@@ -1100,6 +1100,237 @@ class TestCodable : TestCodableSuper {
1100
1100
expectRoundTripEqualityThroughPlist ( for: UUIDCodingWrapper ( uuid) , lineNumber: testLine)
1101
1101
}
1102
1102
}
1103
+
1104
+ // MARK: - DecodingError
1105
+ func expectErrorDescription(
1106
+ _ expectedErrorDescription: String ,
1107
+ fromDecodingError error: DecodingError ,
1108
+ lineNumber: UInt = #line
1109
+ ) {
1110
+ expectEqual ( String ( describing: error) , expectedErrorDescription, " Unexpectedly wrong error: \( error) " , line: lineNumber)
1111
+ }
1112
+
1113
+ func test_decodingError_typeMismatch_nilUnderlyingError( ) {
1114
+ expectErrorDescription (
1115
+ #"""
1116
+ Type mismatch: expected value of type String.
1117
+ Debug description: This is where the debug description goes
1118
+ Path: [0]/address/city/birds/[1]/name
1119
+ """# ,
1120
+ fromDecodingError: DecodingError . typeMismatch (
1121
+ String . self,
1122
+ DecodingError . Context (
1123
+ codingPath: [ 0 , " address " , " city " , " birds " , 1 , " name " ] as [ GenericCodingKey ] ,
1124
+ debugDescription: " This is where the debug description goes "
1125
+ )
1126
+ )
1127
+ )
1128
+ }
1129
+
1130
+ func test_decodingError_typeMismatch_nonNilUnderlyingError( ) {
1131
+ expectErrorDescription (
1132
+ #"""
1133
+ Type mismatch: expected value of type String.
1134
+ Debug description: Some debug description
1135
+ Underlying error: GenericError(name: "some generic error goes here")
1136
+ Path: [0]/address/[1]/street
1137
+ """# ,
1138
+ fromDecodingError: DecodingError . typeMismatch (
1139
+ String . self,
1140
+ DecodingError . Context (
1141
+ codingPath: [ 0 , " address " , 1 , " street " ] as [ GenericCodingKey ] ,
1142
+ debugDescription: " Some debug description " ,
1143
+ underlyingError: GenericError ( name: " some generic error goes here " )
1144
+ )
1145
+ )
1146
+ )
1147
+ }
1148
+
1149
+ func test_decodingError_valueNotFound_nilUnderlyingError( ) {
1150
+ expectErrorDescription (
1151
+ #"""
1152
+ Expected value of type String but found null instead.
1153
+ Debug description: Description for debugging purposes
1154
+ Path: [0]/firstName
1155
+ """# ,
1156
+ fromDecodingError: DecodingError . valueNotFound (
1157
+ String . self,
1158
+ DecodingError . Context (
1159
+ codingPath: [ 0 , " firstName " ] as [ GenericCodingKey ] ,
1160
+ debugDescription: " Description for debugging purposes "
1161
+ )
1162
+ )
1163
+ )
1164
+ }
1165
+
1166
+ func test_decodingError_valueNotFound_nonNilUnderlyingError( ) {
1167
+ expectErrorDescription (
1168
+ #"""
1169
+ Expected value of type Int but found null instead.
1170
+ Debug description: Here is the debug description for value-not-found
1171
+ Underlying error: GenericError(name: "these aren\'t the droids you\'re looking for")
1172
+ Path: [0]/population
1173
+ """# ,
1174
+ fromDecodingError: DecodingError . valueNotFound (
1175
+ Int . self,
1176
+ DecodingError . Context (
1177
+ codingPath: [ 0 , " population " ] as [ GenericCodingKey ] ,
1178
+ debugDescription: " Here is the debug description for value-not-found " ,
1179
+ underlyingError: GenericError ( name: " these aren't the droids you're looking for " )
1180
+ )
1181
+ )
1182
+ )
1183
+ }
1184
+
1185
+ func test_decodingError_keyNotFound_nilUnderlyingError( ) {
1186
+ expectErrorDescription (
1187
+ #"""
1188
+ Key 'name' not found in keyed decoding container.
1189
+ Debug description: How would you describe your relationship with your debugger?
1190
+ Path: [0]/address/city
1191
+ """# ,
1192
+ fromDecodingError: DecodingError . keyNotFound (
1193
+ GenericCodingKey ( stringValue: " name " ) ,
1194
+ DecodingError . Context (
1195
+ codingPath: [ 0 , " address " , " city " ] as [ GenericCodingKey ] ,
1196
+ debugDescription: " How would you describe your relationship with your debugger? "
1197
+ )
1198
+ )
1199
+ )
1200
+ }
1201
+
1202
+ func test_decodingError_keyNotFound_nonNilUnderlyingError( ) {
1203
+ expectErrorDescription (
1204
+ #"""
1205
+ Key 'name' not found in keyed decoding container.
1206
+ Debug description: Just some info to help you out
1207
+ Underlying error: GenericError(name: "hey, who turned out the lights?")
1208
+ Path: [0]/address/city
1209
+ """# ,
1210
+ fromDecodingError: DecodingError . keyNotFound (
1211
+ GenericCodingKey ( stringValue: " name " ) ,
1212
+ DecodingError . Context (
1213
+ codingPath: [ 0 , " address " , " city " ] as [ GenericCodingKey ] ,
1214
+ debugDescription: " Just some info to help you out " ,
1215
+ underlyingError: GenericError ( name: " hey, who turned out the lights? " )
1216
+ )
1217
+ )
1218
+ )
1219
+ }
1220
+
1221
+ func test_decodingError_dataCorrupted_emptyCodingPath( ) {
1222
+ expectErrorDescription (
1223
+ #"""
1224
+ Data was corrupted.
1225
+ Debug description: The given data was not valid JSON
1226
+ Underlying error: GenericError(name: "just some data corruption")
1227
+ """# ,
1228
+ fromDecodingError: DecodingError . dataCorrupted (
1229
+ DecodingError . Context (
1230
+ codingPath: [ ] as [ GenericCodingKey ] , // sometimes empty when generated by JSONDecoder
1231
+ debugDescription: " The given data was not valid JSON " ,
1232
+ underlyingError: GenericError ( name: " just some data corruption " )
1233
+ )
1234
+ )
1235
+ )
1236
+ }
1237
+
1238
+ func test_decodingError_dataCorrupted_nonEmptyCodingPath( ) {
1239
+ expectErrorDescription (
1240
+ #"""
1241
+ Data was corrupted.
1242
+ Debug description: There was apparently some data corruption!
1243
+ Underlying error: GenericError(name: "This data corruption is getting out of hand")
1244
+ Path: first/second/[2]
1245
+ """# ,
1246
+ fromDecodingError: DecodingError . dataCorrupted (
1247
+ DecodingError . Context (
1248
+ codingPath: [ " first " , " second " , 2 ] as [ GenericCodingKey ] ,
1249
+ debugDescription: " There was apparently some data corruption! " ,
1250
+ underlyingError: GenericError ( name: " This data corruption is getting out of hand " )
1251
+ )
1252
+ )
1253
+ )
1254
+ }
1255
+
1256
+ // MARK: - EncodingError
1257
+ func expectErrorDescription(
1258
+ _ expectedErrorDescription: String ,
1259
+ fromEncodingError error: EncodingError ,
1260
+ lineNumber: UInt = #line
1261
+ ) {
1262
+ expectEqual ( String ( describing: error) , expectedErrorDescription, " Unexpectedly wrong error: \( error) " , line: lineNumber)
1263
+ }
1264
+
1265
+ func test_encodingError_invalidValue_emptyCodingPath_nilUnderlyingError( ) {
1266
+ expectErrorDescription (
1267
+ #"""
1268
+ Invalid value: 123 (Int)
1269
+ You cannot do that!
1270
+ """# ,
1271
+ fromEncodingError: EncodingError . invalidValue (
1272
+ 123 as Int ,
1273
+ EncodingError . Context (
1274
+ codingPath: [ ] as [ GenericCodingKey ] ,
1275
+ debugDescription: " You cannot do that! "
1276
+ )
1277
+ )
1278
+ )
1279
+ }
1280
+
1281
+ func test_encodingError_invalidValue_nonEmptyCodingPath_nilUnderlyingError( ) {
1282
+ expectErrorDescription (
1283
+ #"""
1284
+ Invalid value: 234 (Int)
1285
+ You cannot do that!
1286
+ Path: first/second/[2]
1287
+ """# ,
1288
+ fromEncodingError: EncodingError . invalidValue (
1289
+ 234 as Int ,
1290
+ EncodingError . Context (
1291
+ codingPath: [ " first " , " second " , 2 ] as [ GenericCodingKey ] ,
1292
+ debugDescription: " You cannot do that! "
1293
+ )
1294
+ )
1295
+ )
1296
+ }
1297
+
1298
+ func test_encodingError_invalidValue_emptyCodingPath_nonNilUnderlyingError( ) {
1299
+ expectErrorDescription (
1300
+ #"""
1301
+ Invalid value: 345 (Int)
1302
+ You cannot do that!
1303
+ Underlying error: GenericError(name: "You really cannot do that")
1304
+ """# ,
1305
+ fromEncodingError: EncodingError . invalidValue (
1306
+ 345 as Int ,
1307
+ EncodingError . Context (
1308
+ codingPath: [ ] as [ GenericCodingKey ] ,
1309
+ debugDescription: " You cannot do that! " ,
1310
+ underlyingError: GenericError ( name: " You really cannot do that " )
1311
+ )
1312
+ )
1313
+ )
1314
+ }
1315
+
1316
+ func test_encodingError_invalidValue_nonEmptyCodingPath_nonNilUnderlyingError( ) {
1317
+ expectErrorDescription (
1318
+ #"""
1319
+ Invalid value: 456 (Int)
1320
+ You cannot do that!
1321
+ Underlying error: GenericError(name: "You really cannot do that")
1322
+ Path: first/second/[2]
1323
+ """# ,
1324
+ fromEncodingError: EncodingError . invalidValue (
1325
+ 456 as Int ,
1326
+ EncodingError . Context (
1327
+ codingPath: [ " first " , " second " , 2 ] as [ GenericCodingKey ] ,
1328
+ debugDescription: " You cannot do that! " ,
1329
+ underlyingError: GenericError ( name: " You really cannot do that " )
1330
+ )
1331
+ )
1332
+ )
1333
+ }
1103
1334
}
1104
1335
1105
1336
// MARK: - Helper Types
@@ -1118,6 +1349,18 @@ struct GenericCodingKey: CodingKey {
1118
1349
}
1119
1350
}
1120
1351
1352
+ extension GenericCodingKey : ExpressibleByStringLiteral {
1353
+ init ( stringLiteral: String ) {
1354
+ self . init ( stringValue: stringLiteral)
1355
+ }
1356
+ }
1357
+
1358
+ extension GenericCodingKey : ExpressibleByIntegerLiteral {
1359
+ init ( integerLiteral: Int ) {
1360
+ self . init ( intValue: integerLiteral)
1361
+ }
1362
+ }
1363
+
1121
1364
struct TopLevelWrapper < T> : Codable , Equatable where T : Codable , T : Equatable {
1122
1365
let value : T
1123
1366
@@ -1130,6 +1373,10 @@ struct TopLevelWrapper<T> : Codable, Equatable where T : Codable, T : Equatable
1130
1373
}
1131
1374
}
1132
1375
1376
+ struct GenericError : Error {
1377
+ let name : String
1378
+ }
1379
+
1133
1380
// MARK: - Tests
1134
1381
1135
1382
#if !FOUNDATION_XCTEST
@@ -1183,6 +1430,18 @@ var tests = [
1183
1430
" test_URL_Plist " : TestCodable . test_URL_Plist,
1184
1431
" test_UUID_JSON " : TestCodable . test_UUID_JSON,
1185
1432
" test_UUID_Plist " : TestCodable . test_UUID_Plist,
1433
+ " test_decodingError_typeMismatch_nilUnderlyingError " : TestCodable . test_decodingError_typeMismatch_nilUnderlyingError,
1434
+ " test_decodingError_typeMismatch_nonNilUnderlyingError " : TestCodable . test_decodingError_typeMismatch_nonNilUnderlyingError,
1435
+ " test_decodingError_valueNotFound_nilUnderlyingError " : TestCodable . test_decodingError_valueNotFound_nilUnderlyingError,
1436
+ " test_decodingError_valueNotFound_nonNilUnderlyingError " : TestCodable . test_decodingError_valueNotFound_nonNilUnderlyingError,
1437
+ " test_decodingError_keyNotFound_nilUnderlyingError " : TestCodable . test_decodingError_keyNotFound_nilUnderlyingError,
1438
+ " test_decodingError_keyNotFound_nonNilUnderlyingError " : TestCodable . test_decodingError_keyNotFound_nonNilUnderlyingError,
1439
+ " test_decodingError_dataCorrupted_emptyCodingPath " : TestCodable . test_decodingError_dataCorrupted_emptyCodingPath,
1440
+ " test_decodingError_dataCorrupted_nonEmptyCodingPath " : TestCodable . test_decodingError_dataCorrupted_nonEmptyCodingPath,
1441
+ " test_encodingError_invalidValue_emptyCodingPath_nilUnderlyingError " : TestCodable . test_encodingError_invalidValue_emptyCodingPath_nilUnderlyingError,
1442
+ " test_encodingError_invalidValue_nonEmptyCodingPath_nilUnderlyingError " : TestCodable . test_encodingError_invalidValue_nonEmptyCodingPath_nilUnderlyingError,
1443
+ " test_encodingError_invalidValue_emptyCodingPath_nonNilUnderlyingError " : TestCodable . test_encodingError_invalidValue_emptyCodingPath_nonNilUnderlyingError,
1444
+ " test_encodingError_invalidValue_nonEmptyCodingPath_nonNilUnderlyingError " : TestCodable . test_encodingError_invalidValue_nonEmptyCodingPath_nonNilUnderlyingError,
1186
1445
]
1187
1446
1188
1447
#if os(macOS)
0 commit comments