@@ -1100,6 +1100,170 @@ 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
+ Expected to decode String but found number instead
1117
+ Path: [0]/address/city/birds/[1]/name
1118
+ """# ,
1119
+ fromDecodingError: DecodingError . typeMismatch (
1120
+ String . self,
1121
+ DecodingError . Context (
1122
+ codingPath: [ 0 , " address " , " city " , " birds " , 1 , " name " ] as [ GenericCodingKey ] ,
1123
+ debugDescription: " Expected to decode String but found number instead "
1124
+ )
1125
+ )
1126
+ )
1127
+ }
1128
+
1129
+ func test_decodingError_typeMismatch_nonNilUnderlyingError( ) {
1130
+ expectErrorDescription (
1131
+ #"""
1132
+ Expected to decode String but found number instead
1133
+ Underlying error: GenericError(name: "some generic error goes here")
1134
+ Path: [0]/address/[1]/street
1135
+ """# ,
1136
+ fromDecodingError: DecodingError . typeMismatch (
1137
+ String . self,
1138
+ DecodingError . Context (
1139
+ codingPath: [ 0 , " address " , 1 , " street " ] as [ GenericCodingKey ] ,
1140
+ debugDescription: " Expected to decode String but found number instead " ,
1141
+ underlyingError: GenericError ( name: " some generic error goes here " )
1142
+ )
1143
+ )
1144
+ )
1145
+ }
1146
+
1147
+ func test_decodingError_valueNotFound_nilUnderlyingError( ) {
1148
+ expectErrorDescription (
1149
+ #"""
1150
+ Cannot get value of type String -- found null value instead
1151
+ Path: [0]/firstName
1152
+ """# ,
1153
+ fromDecodingError: DecodingError . valueNotFound (
1154
+ String . self,
1155
+ DecodingError . Context (
1156
+ codingPath: [ 0 , " firstName " ] as [ GenericCodingKey ] ,
1157
+ debugDescription: " Cannot get value of type String -- found null value instead "
1158
+ )
1159
+ )
1160
+ )
1161
+ }
1162
+
1163
+ func test_decodingError_valueNotFound_nonNilUnderlyingError( ) {
1164
+ expectErrorDescription (
1165
+ #"""
1166
+ Cannot get value of type String -- found null value instead
1167
+ Underlying error: GenericError(name: "these aren\'t the droids you\'re looking for")
1168
+ Path: [0]/firstName
1169
+ """# ,
1170
+ fromDecodingError: DecodingError . valueNotFound (
1171
+ String . self,
1172
+ DecodingError . Context (
1173
+ codingPath: [ 0 , " firstName " ] as [ GenericCodingKey ] ,
1174
+ debugDescription: " Cannot get value of type String -- found null value instead " ,
1175
+ underlyingError: GenericError ( name: " these aren't the droids you're looking for " )
1176
+ )
1177
+ )
1178
+ )
1179
+ }
1180
+
1181
+ func test_decodingError_keyNotFound_nilUnderlyingError( ) {
1182
+ expectErrorDescription (
1183
+ #"""
1184
+ No value associated with key name ("name")
1185
+ Path: [0]/address/city
1186
+ """# ,
1187
+ fromDecodingError: DecodingError . keyNotFound (
1188
+ GenericCodingKey ( stringValue: " name " ) ,
1189
+ DecodingError . Context (
1190
+ codingPath: [ 0 , " address " , " city " ] as [ GenericCodingKey ] ,
1191
+ debugDescription: #"""
1192
+ No value associated with key name ("name")
1193
+ """#
1194
+ )
1195
+ )
1196
+ )
1197
+ }
1198
+
1199
+ func test_decodingError_keyNotFound_nonNilUnderlyingError( ) {
1200
+ expectErrorDescription (
1201
+ #"""
1202
+ No value associated with key name ("name")
1203
+ Underlying error: GenericError(name: "hey, who turned out the lights?")
1204
+ Path: [0]/address/city
1205
+ """# ,
1206
+ fromDecodingError: DecodingError . keyNotFound (
1207
+ GenericCodingKey ( stringValue: " name " ) ,
1208
+ DecodingError . Context (
1209
+ codingPath: [ 0 , " address " , " city " ] as [ GenericCodingKey ] ,
1210
+ debugDescription: #"""
1211
+ No value associated with key name ("name")
1212
+ """# ,
1213
+ underlyingError: GenericError ( name: " hey, who turned out the lights? " )
1214
+ )
1215
+ )
1216
+ )
1217
+ }
1218
+
1219
+ func test_decodingError_dataCorrupted_emptyCodingPath( ) {
1220
+ expectErrorDescription (
1221
+ #"""
1222
+ The given data was not valid JSON
1223
+ Underlying error: Error Domain=NSCocoaErrorDomain Code=3840 "Unexpected character 'a' around line 5, column 10." UserInfo={NSJSONSerializationErrorIndex=81, NSDebugDescription=Unexpected character 'a' around line 5, column 10.}
1224
+ """# ,
1225
+ fromDecodingError: DecodingError . dataCorrupted (
1226
+ DecodingError . Context (
1227
+ codingPath: [ ] as [ GenericCodingKey ] , // sometimes empty when generated by JSONDecoder
1228
+ debugDescription: " The given data was not valid JSON " ,
1229
+ // Real-world example error from JSONDecoder, although it does not correspond to the given codingPath in this test
1230
+ underlyingError: NSError (
1231
+ domain: NSCocoaErrorDomain,
1232
+ code: 3840 ,
1233
+ userInfo: [
1234
+ " NSJSONSerializationErrorIndex " : 81 ,
1235
+ " NSDebugDescription " : " Unexpected character 'a' around line 5, column 10. " ,
1236
+ ]
1237
+ )
1238
+ )
1239
+ )
1240
+ )
1241
+ }
1242
+
1243
+ func test_decodingError_dataCorrupted_nonEmptyCodingPath( ) {
1244
+ expectErrorDescription (
1245
+ #"""
1246
+ The given data was not valid JSON
1247
+ Underlying error: Error Domain=NSCocoaErrorDomain Code=3840 "Unexpected character 'a' around line 5, column 10." UserInfo={NSJSONSerializationErrorIndex=81, NSDebugDescription=Unexpected character 'a' around line 5, column 10.}
1248
+ Path: first/second/[2]
1249
+ """# ,
1250
+ fromDecodingError: DecodingError . dataCorrupted (
1251
+ DecodingError . Context (
1252
+ codingPath: [ " first " , " second " , 2 ] as [ GenericCodingKey ] ,
1253
+ debugDescription: " The given data was not valid JSON " ,
1254
+ // Real-world example error from JSONDecoder, although it does not correspond to the given codingPath in this test
1255
+ underlyingError: NSError (
1256
+ domain: NSCocoaErrorDomain,
1257
+ code: 3840 ,
1258
+ userInfo: [
1259
+ " NSJSONSerializationErrorIndex " : 81 ,
1260
+ " NSDebugDescription " : " Unexpected character 'a' around line 5, column 10. " ,
1261
+ ]
1262
+ )
1263
+ )
1264
+ )
1265
+ )
1266
+ }
1103
1267
}
1104
1268
1105
1269
// MARK: - Helper Types
@@ -1118,6 +1282,18 @@ struct GenericCodingKey: CodingKey {
1118
1282
}
1119
1283
}
1120
1284
1285
+ extension GenericCodingKey : ExpressibleByStringLiteral {
1286
+ init ( stringLiteral: String ) {
1287
+ self . init ( stringValue: stringLiteral)
1288
+ }
1289
+ }
1290
+
1291
+ extension GenericCodingKey : ExpressibleByIntegerLiteral {
1292
+ init ( integerLiteral: Int ) {
1293
+ self . init ( intValue: integerLiteral)
1294
+ }
1295
+ }
1296
+
1121
1297
struct TopLevelWrapper < T> : Codable , Equatable where T : Codable , T : Equatable {
1122
1298
let value : T
1123
1299
@@ -1130,6 +1306,10 @@ struct TopLevelWrapper<T> : Codable, Equatable where T : Codable, T : Equatable
1130
1306
}
1131
1307
}
1132
1308
1309
+ struct GenericError : Error {
1310
+ let name : String
1311
+ }
1312
+
1133
1313
// MARK: - Tests
1134
1314
1135
1315
#if !FOUNDATION_XCTEST
@@ -1183,6 +1363,14 @@ var tests = [
1183
1363
" test_URL_Plist " : TestCodable . test_URL_Plist,
1184
1364
" test_UUID_JSON " : TestCodable . test_UUID_JSON,
1185
1365
" test_UUID_Plist " : TestCodable . test_UUID_Plist,
1366
+ " test_decodingError_typeMismatch_nilUnderlyingError " : TestCodable . test_decodingError_typeMismatch_nilUnderlyingError,
1367
+ " test_decodingError_typeMismatch_nonNilUnderlyingError " : TestCodable . test_decodingError_typeMismatch_nonNilUnderlyingError,
1368
+ " test_decodingError_valueNotFound_nilUnderlyingError " : TestCodable . test_decodingError_valueNotFound_nilUnderlyingError,
1369
+ " test_decodingError_valueNotFound_nonNilUnderlyingError " : TestCodable . test_decodingError_valueNotFound_nonNilUnderlyingError,
1370
+ " test_decodingError_keyNotFound_nilUnderlyingError " : TestCodable . test_decodingError_keyNotFound_nilUnderlyingError,
1371
+ " test_decodingError_keyNotFound_nonNilUnderlyingError " : TestCodable . test_decodingError_keyNotFound_nonNilUnderlyingError,
1372
+ " test_decodingError_dataCorrupted_emptyCodingPath " : TestCodable . test_decodingError_dataCorrupted_emptyCodingPath,
1373
+ " test_decodingError_dataCorrupted_nonEmptyCodingPath " : TestCodable . test_decodingError_dataCorrupted_nonEmptyCodingPath,
1186
1374
]
1187
1375
1188
1376
#if os(macOS)
0 commit comments