Skip to content

Commit ceb703b

Browse files
committed
[test] Add new Set/Dictionary casting tests
1 parent 2bd5da5 commit ceb703b

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

validation-test/stdlib/Dictionary.swift

+15
Original file line numberDiff line numberDiff line change
@@ -3473,6 +3473,21 @@ DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.StringEqualityMismatch") {
34733473
expectTrue(v == 42 || v == 23)
34743474
}
34753475

3476+
DictionaryTestSuite.test("Upcast.StringEqualityMismatch") {
3477+
// Upcasting from NSString to String keys changes their concept of equality,
3478+
// resulting in two equal keys, one of which should be discarded by the
3479+
// downcast. (Along with its associated value.)
3480+
// rdar://problem/35995647
3481+
let d: Dictionary<NSString, NSObject> = [
3482+
"cafe\u{301}": 1 as NSNumber,
3483+
"café": 2 as NSNumber,
3484+
]
3485+
expectEqual(d.count, 2)
3486+
let d2 = d as Dictionary<String, NSObject>
3487+
expectEqual(d2.count, 1)
3488+
}
3489+
3490+
34763491
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.OptionalDowncastFailure") {
34773492
let nsd = NSDictionary(
34783493
objects: [1 as NSNumber, 2 as NSNumber, 3 as NSNumber],

validation-test/stdlib/DictionaryTrapsObjC.swift

+8-2
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,12 @@ DictionaryTraps.test("ForcedVerbatimBridge.Value")
284284
}
285285
}
286286

287-
DictionaryTraps.test("Downcast1") {
287+
DictionaryTraps.test("Downcast.Verbatim")
288+
.skip(.custom(
289+
{ _isFastAssertConfiguration() },
290+
reason: "this trap is not guaranteed to happen in -Ounchecked"))
291+
.crashOutputMatches("Could not cast value of type")
292+
.code {
288293
let d: Dictionary<NSObject, NSObject> = [ TestObjCKeyTy(10): NSObject(),
289294
NSObject() : NSObject() ]
290295
let d2: Dictionary<TestObjCKeyTy, NSObject> = _dictionaryDownCast(d)
@@ -296,10 +301,11 @@ DictionaryTraps.test("Downcast1") {
296301
for (_, _) in d2 { }
297302
}
298303

299-
DictionaryTraps.test("Downcast2")
304+
DictionaryTraps.test("Downcast.NonVerbatimBridged")
300305
.skip(.custom(
301306
{ _isFastAssertConfiguration() },
302307
reason: "this trap is not guaranteed to happen in -Ounchecked"))
308+
.crashOutputMatches("Could not cast value of type")
303309
.code {
304310
let d: Dictionary<NSObject, NSObject> = [ TestObjCKeyTy(10): NSObject(),
305311
NSObject() : NSObject() ]

validation-test/stdlib/Set.swift

+112
Original file line numberDiff line numberDiff line change
@@ -4714,4 +4714,116 @@ SetTestSuite.test("ForcedVerbatimBridge.Trap.NSNumber")
47144714
}
47154715
#endif
47164716

4717+
#if _runtime(_ObjC)
4718+
SetTestSuite.test("ForcedVerbatimDowncast.Trap.String")
4719+
.skip(.custom(
4720+
{ _isFastAssertConfiguration() },
4721+
reason: "this trap is not guaranteed to happen in -Ounchecked"))
4722+
.crashOutputMatches("Could not cast value of type")
4723+
.code {
4724+
let s1: Set<NSObject> = [
4725+
"Gordon" as NSString,
4726+
"William" as NSString,
4727+
"Katherine" as NSString,
4728+
"Lynn" as NSString,
4729+
"Brian" as NSString,
4730+
1756 as NSNumber]
4731+
// With the ObjC runtime, the verbatim downcast is O(1); it performs no
4732+
// runtime checks.
4733+
let s2 = s1 as! Set<NSString>
4734+
// Element access goes through the bridged path and performs forced downcasts.
4735+
// This is where the odd numeric value is caught.
4736+
expectCrashLater()
4737+
for string in s2 {
4738+
_ = string
4739+
}
4740+
}
4741+
#endif
4742+
4743+
#if _runtime(_ObjC)
4744+
SetTestSuite.test("ForcedVerbatimDowncast.Trap.Int")
4745+
.skip(.custom(
4746+
{ _isFastAssertConfiguration() },
4747+
reason: "this trap is not guaranteed to happen in -Ounchecked"))
4748+
.crashOutputMatches("Could not cast value of type")
4749+
.code {
4750+
let s1: Set<NSObject> = [
4751+
4 as NSNumber,
4752+
8 as NSNumber,
4753+
15 as NSNumber,
4754+
16 as NSNumber,
4755+
23 as NSNumber,
4756+
42 as NSNumber,
4757+
"John" as NSString]
4758+
// With the ObjC runtime, the verbatim downcast is O(1); it performs no
4759+
// runtime checks.
4760+
let s2 = s1 as! Set<NSNumber>
4761+
expectCrashLater()
4762+
// Element access goes through the bridged path and performs forced downcasts.
4763+
// This is where the odd string value is caught.
4764+
for string in s2 {
4765+
_ = string
4766+
}
4767+
}
4768+
#endif
4769+
4770+
#if _runtime(_ObjC)
4771+
SetTestSuite.test("ForcedBridgingNonverbatimDowncast.Trap.String")
4772+
.skip(.custom(
4773+
{ _isFastAssertConfiguration() },
4774+
reason: "this trap is not guaranteed to happen in -Ounchecked"))
4775+
.crashOutputMatches("Could not cast value of type")
4776+
.code {
4777+
let s1: Set<NSObject> = [
4778+
"Gordon" as NSString,
4779+
"William" as NSString,
4780+
"Katherine" as NSString,
4781+
"Lynn" as NSString,
4782+
"Brian" as NSString,
4783+
1756 as NSNumber]
4784+
expectCrashLater()
4785+
// Nonverbatim downcasts are greedy and they trap immediately.
4786+
let s2 = s1 as! Set<String>
4787+
_ = s2.contains("Gordon")
4788+
}
4789+
#endif
4790+
4791+
#if _runtime(_ObjC)
4792+
SetTestSuite.test("ForcedBridgingNonverbatimDowncast.Trap.Int")
4793+
.skip(.custom(
4794+
{ _isFastAssertConfiguration() },
4795+
reason: "this trap is not guaranteed to happen in -Ounchecked"))
4796+
.crashOutputMatches("Could not cast value of type")
4797+
.code {
4798+
let s1: Set<NSObject> = [
4799+
4 as NSNumber,
4800+
8 as NSNumber,
4801+
15 as NSNumber,
4802+
16 as NSNumber,
4803+
23 as NSNumber,
4804+
42 as NSNumber,
4805+
"John" as NSString]
4806+
expectCrashLater()
4807+
// Nonverbatim downcasts are greedy and they trap immediately.
4808+
let s2 = s1 as! Set<Int>
4809+
_ = s2.contains(23)
4810+
}
4811+
#endif
4812+
4813+
#if _runtime(_ObjC)
4814+
SetTestSuite.test("Upcast.StringEqualityMismatch") {
4815+
// Upcasting from NSString to String keys changes their concept of equality,
4816+
// resulting in two equal keys, one of which should be discarded by the
4817+
// downcast. (Along with its associated value.)
4818+
// rdar://problem/35995647
4819+
let s: Set<NSString> = [
4820+
"cafe\u{301}",
4821+
"café"
4822+
]
4823+
expectEqual(s.count, 2)
4824+
let s2 = s as Set<String>
4825+
expectEqual(s2.count, 1)
4826+
}
4827+
#endif
4828+
47174829
runAllTests()

0 commit comments

Comments
 (0)