@@ -1100,6 +1100,152 @@ 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
+ This is where the debug description goes
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: " This is where the debug description goes "
1124
+ )
1125
+ )
1126
+ )
1127
+ }
1128
+
1129
+ func test_decodingError_typeMismatch_nonNilUnderlyingError( ) {
1130
+ expectErrorDescription (
1131
+ #"""
1132
+ Some debug description
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: " Some debug description " ,
1141
+ underlyingError: GenericError ( name: " some generic error goes here " )
1142
+ )
1143
+ )
1144
+ )
1145
+ }
1146
+
1147
+ func test_decodingError_valueNotFound_nilUnderlyingError( ) {
1148
+ expectErrorDescription (
1149
+ #"""
1150
+ Description for debugging purposes
1151
+ Path: [0]/firstName
1152
+ """# ,
1153
+ fromDecodingError: DecodingError . valueNotFound (
1154
+ String . self,
1155
+ DecodingError . Context (
1156
+ codingPath: [ 0 , " firstName " ] as [ GenericCodingKey ] ,
1157
+ debugDescription: " Description for debugging purposes "
1158
+ )
1159
+ )
1160
+ )
1161
+ }
1162
+
1163
+ func test_decodingError_valueNotFound_nonNilUnderlyingError( ) {
1164
+ expectErrorDescription (
1165
+ #"""
1166
+ Here is the debug description for value-not-found
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: " Here is the debug description for value-not-found " ,
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
+ How would you describe your relationship with your debugger?
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: " How would you describe your relationship with your debugger? "
1192
+ )
1193
+ )
1194
+ )
1195
+ }
1196
+
1197
+ func test_decodingError_keyNotFound_nonNilUnderlyingError( ) {
1198
+ expectErrorDescription (
1199
+ #"""
1200
+ No value associated with key name ("name")
1201
+ Underlying error: GenericError(name: "hey, who turned out the lights?")
1202
+ Path: [0]/address/city
1203
+ """# ,
1204
+ fromDecodingError: DecodingError . keyNotFound (
1205
+ GenericCodingKey ( stringValue: " name " ) ,
1206
+ DecodingError . Context (
1207
+ codingPath: [ 0 , " address " , " city " ] as [ GenericCodingKey ] ,
1208
+ debugDescription: #"""
1209
+ No value associated with key name ("name")
1210
+ """# ,
1211
+ underlyingError: GenericError ( name: " hey, who turned out the lights? " )
1212
+ )
1213
+ )
1214
+ )
1215
+ }
1216
+
1217
+ func test_decodingError_dataCorrupted_emptyCodingPath( ) {
1218
+ expectErrorDescription (
1219
+ #"""
1220
+ The given data was not valid JSON
1221
+ Underlying error: GenericError(name: "just some data corruption")
1222
+ """# ,
1223
+ fromDecodingError: DecodingError . dataCorrupted (
1224
+ DecodingError . Context (
1225
+ codingPath: [ ] as [ GenericCodingKey ] , // sometimes empty when generated by JSONDecoder
1226
+ debugDescription: " The given data was not valid JSON " ,
1227
+ underlyingError: GenericError ( name: " just some data corruption " )
1228
+ )
1229
+ )
1230
+ )
1231
+ }
1232
+
1233
+ func test_decodingError_dataCorrupted_nonEmptyCodingPath( ) {
1234
+ expectErrorDescription (
1235
+ #"""
1236
+ There was apparently some data corruption!
1237
+ Underlying error: GenericError(name: "This data corruption is getting out of hand")
1238
+ Path: first/second/[2]
1239
+ """# ,
1240
+ fromDecodingError: DecodingError . dataCorrupted (
1241
+ DecodingError . Context (
1242
+ codingPath: [ " first " , " second " , 2 ] as [ GenericCodingKey ] ,
1243
+ debugDescription: " There was apparently some data corruption! " ,
1244
+ underlyingError: GenericError ( name: " This data corruption is getting out of hand " )
1245
+ )
1246
+ )
1247
+ )
1248
+ }
1103
1249
}
1104
1250
1105
1251
// MARK: - Helper Types
@@ -1118,6 +1264,18 @@ struct GenericCodingKey: CodingKey {
1118
1264
}
1119
1265
}
1120
1266
1267
+ extension GenericCodingKey : ExpressibleByStringLiteral {
1268
+ init ( stringLiteral: String ) {
1269
+ self . init ( stringValue: stringLiteral)
1270
+ }
1271
+ }
1272
+
1273
+ extension GenericCodingKey : ExpressibleByIntegerLiteral {
1274
+ init ( integerLiteral: Int ) {
1275
+ self . init ( intValue: integerLiteral)
1276
+ }
1277
+ }
1278
+
1121
1279
struct TopLevelWrapper < T> : Codable , Equatable where T : Codable , T : Equatable {
1122
1280
let value : T
1123
1281
@@ -1130,6 +1288,10 @@ struct TopLevelWrapper<T> : Codable, Equatable where T : Codable, T : Equatable
1130
1288
}
1131
1289
}
1132
1290
1291
+ struct GenericError : Error {
1292
+ let name : String
1293
+ }
1294
+
1133
1295
// MARK: - Tests
1134
1296
1135
1297
#if !FOUNDATION_XCTEST
@@ -1183,6 +1345,14 @@ var tests = [
1183
1345
" test_URL_Plist " : TestCodable . test_URL_Plist,
1184
1346
" test_UUID_JSON " : TestCodable . test_UUID_JSON,
1185
1347
" test_UUID_Plist " : TestCodable . test_UUID_Plist,
1348
+ " test_decodingError_typeMismatch_nilUnderlyingError " : TestCodable . test_decodingError_typeMismatch_nilUnderlyingError,
1349
+ " test_decodingError_typeMismatch_nonNilUnderlyingError " : TestCodable . test_decodingError_typeMismatch_nonNilUnderlyingError,
1350
+ " test_decodingError_valueNotFound_nilUnderlyingError " : TestCodable . test_decodingError_valueNotFound_nilUnderlyingError,
1351
+ " test_decodingError_valueNotFound_nonNilUnderlyingError " : TestCodable . test_decodingError_valueNotFound_nonNilUnderlyingError,
1352
+ " test_decodingError_keyNotFound_nilUnderlyingError " : TestCodable . test_decodingError_keyNotFound_nilUnderlyingError,
1353
+ " test_decodingError_keyNotFound_nonNilUnderlyingError " : TestCodable . test_decodingError_keyNotFound_nonNilUnderlyingError,
1354
+ " test_decodingError_dataCorrupted_emptyCodingPath " : TestCodable . test_decodingError_dataCorrupted_emptyCodingPath,
1355
+ " test_decodingError_dataCorrupted_nonEmptyCodingPath " : TestCodable . test_decodingError_dataCorrupted_nonEmptyCodingPath,
1186
1356
]
1187
1357
1188
1358
#if os(macOS)
0 commit comments