Files
swift-mirror/validation-test/stdlib/Dictionary.swift
Karoy Lorentey d2861f779e [test] Re-add crash tests for getObjects:andKeys:count:
On some platforms, when a new process is started, ARC’s autoreleased return value optimization is expected to fail the first time it is used in each linked dylib. StdlibUnittest takes care of warming up ARC for the stdlib (libswiftCore.dylib), but for Dictionary.swift, we also need to do it for Foundation, or there will be spurious leaks reported for tests immediately following a crash test.

Add the necessary dummy operations to setUp, and re-add the crash tests that were removed in #17862. (As separate tests this time, so they don’t hide leaks in non-crashing test parts.)
2018-07-13 15:32:52 +01:00

4795 lines
138 KiB
Swift

// RUN: %empty-directory(%t)
//
// RUN: %gyb %s -o %t/main.swift
// RUN: if [ %target-runtime == "objc" ]; then \
// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \
// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Dictionary -Xfrontend -disable-access-control; \
// RUN: else \
// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Dictionary -Xfrontend -disable-access-control; \
// RUN: fi
//
// RUN: %line-directive %t/main.swift -- %target-run %t/Dictionary
// REQUIRES: executable_test
#if os(OSX) || os(iOS) || os(tvOS) || os(watchOS)
import Darwin
#else
import Glibc
#endif
import StdlibUnittest
import StdlibCollectionUnittest
#if _runtime(_ObjC)
import Foundation
import StdlibUnittestFoundationExtras
#endif
extension Dictionary {
func _rawIdentifier() -> Int {
return unsafeBitCast(self, to: Int.self)
}
}
// Check that the generic parameters are called 'Key' and 'Value'.
protocol TestProtocol1 {}
extension Dictionary where Key : TestProtocol1, Value : TestProtocol1 {
var _keyValueAreTestProtocol1: Bool {
fatalError("not implemented")
}
}
extension DictionaryIndex where Key : TestProtocol1, Value : TestProtocol1 {
var _keyValueAreTestProtocol1: Bool {
fatalError("not implemented")
}
}
extension DictionaryIterator
where Key : TestProtocol1, Value : TestProtocol1 {
var _keyValueAreTestProtocol1: Bool {
fatalError("not implemented")
}
}
var DictionaryTestSuite = TestSuite("Dictionary")
DictionaryTestSuite.test("AssociatedTypes") {
typealias Collection = Dictionary<MinimalHashableValue, OpaqueValue<Int>>
expectCollectionAssociatedTypes(
collectionType: Collection.self,
iteratorType: DictionaryIterator<MinimalHashableValue, OpaqueValue<Int>>.self,
subSequenceType: Slice<Collection>.self,
indexType: DictionaryIndex<MinimalHashableValue, OpaqueValue<Int>>.self,
indicesType: DefaultIndices<Collection>.self)
}
DictionaryTestSuite.test("sizeof") {
var dict = [1: "meow", 2: "meow"]
#if arch(i386) || arch(arm)
expectEqual(4, MemoryLayout.size(ofValue: dict))
#else
expectEqual(8, MemoryLayout.size(ofValue: dict))
#endif
}
DictionaryTestSuite.test("Index.Hashable") {
let d = [1: "meow", 2: "meow", 3: "meow"]
let e = Dictionary(uniqueKeysWithValues: zip(d.indices, d))
expectEqual(d.count, e.count)
expectNotNil(e[d.startIndex])
}
DictionaryTestSuite.test("valueDestruction") {
var d1 = Dictionary<Int, TestValueTy>()
for i in 100...110 {
d1[i] = TestValueTy(i)
}
var d2 = Dictionary<TestKeyTy, TestValueTy>()
for i in 100...110 {
d2[TestKeyTy(i)] = TestValueTy(i)
}
}
DictionaryTestSuite.test("COW.Smoke") {
var d1 = Dictionary<TestKeyTy, TestValueTy>(minimumCapacity: 10)
let identity1 = d1._rawIdentifier()
d1[TestKeyTy(10)] = TestValueTy(1010)
d1[TestKeyTy(20)] = TestValueTy(1020)
d1[TestKeyTy(30)] = TestValueTy(1030)
var d2 = d1
_fixLifetime(d2)
assert(identity1 == d2._rawIdentifier())
d2[TestKeyTy(40)] = TestValueTy(2040)
assert(identity1 != d2._rawIdentifier())
d1[TestKeyTy(50)] = TestValueTy(1050)
assert(identity1 == d1._rawIdentifier())
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
func getCOWFastDictionary() -> Dictionary<Int, Int> {
var d = Dictionary<Int, Int>(minimumCapacity: 10)
d[10] = 1010
d[20] = 1020
d[30] = 1030
return d
}
func getCOWFastDictionaryWithCOWValues() -> Dictionary<Int, TestValueCOWTy> {
var d = Dictionary<Int, TestValueCOWTy>(minimumCapacity: 10)
d[10] = TestValueCOWTy(1010)
d[20] = TestValueCOWTy(1020)
d[30] = TestValueCOWTy(1030)
return d
}
func getCOWSlowDictionary() -> Dictionary<TestKeyTy, TestValueTy> {
var d = Dictionary<TestKeyTy, TestValueTy>(minimumCapacity: 10)
d[TestKeyTy(10)] = TestValueTy(1010)
d[TestKeyTy(20)] = TestValueTy(1020)
d[TestKeyTy(30)] = TestValueTy(1030)
return d
}
func getCOWSlowEquatableDictionary()
-> Dictionary<TestKeyTy, TestEquatableValueTy> {
var d = Dictionary<TestKeyTy, TestEquatableValueTy>(minimumCapacity: 10)
d[TestKeyTy(10)] = TestEquatableValueTy(1010)
d[TestKeyTy(20)] = TestEquatableValueTy(1020)
d[TestKeyTy(30)] = TestEquatableValueTy(1030)
return d
}
DictionaryTestSuite.test("COW.Fast.IndexesDontAffectUniquenessCheck") {
var d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
let startIndex = d.startIndex
let endIndex = d.endIndex
assert(startIndex != endIndex)
assert(startIndex < endIndex)
assert(startIndex <= endIndex)
assert(!(startIndex >= endIndex))
assert(!(startIndex > endIndex))
assert(identity1 == d._rawIdentifier())
d[40] = 2040
assert(identity1 == d._rawIdentifier())
// Keep indexes alive during the calls above.
_fixLifetime(startIndex)
_fixLifetime(endIndex)
}
DictionaryTestSuite.test("COW.Slow.IndexesDontAffectUniquenessCheck") {
var d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
let startIndex = d.startIndex
let endIndex = d.endIndex
assert(startIndex != endIndex)
assert(startIndex < endIndex)
assert(startIndex <= endIndex)
assert(!(startIndex >= endIndex))
assert(!(startIndex > endIndex))
assert(identity1 == d._rawIdentifier())
d[TestKeyTy(40)] = TestValueTy(2040)
assert(identity1 == d._rawIdentifier())
// Keep indexes alive during the calls above.
_fixLifetime(startIndex)
_fixLifetime(endIndex)
}
DictionaryTestSuite.test("COW.Fast.SubscriptWithIndexDoesNotReallocate") {
let d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
let startIndex = d.startIndex
let empty = startIndex == d.endIndex
assert((d.startIndex < d.endIndex) == !empty)
assert(d.startIndex <= d.endIndex)
assert((d.startIndex >= d.endIndex) == empty)
assert(!(d.startIndex > d.endIndex))
assert(identity1 == d._rawIdentifier())
assert(d[startIndex].1 != 0)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("COW.Slow.SubscriptWithIndexDoesNotReallocate") {
let d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
let startIndex = d.startIndex
let empty = startIndex == d.endIndex
assert((d.startIndex < d.endIndex) == !empty)
assert(d.startIndex <= d.endIndex)
assert((d.startIndex >= d.endIndex) == empty)
assert(!(d.startIndex > d.endIndex))
assert(identity1 == d._rawIdentifier())
assert(d[startIndex].1.value != 0)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("COW.Fast.SubscriptWithKeyDoesNotReallocate")
.code {
var d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
assert(d[10]! == 1010)
assert(identity1 == d._rawIdentifier())
// Insert a new key-value pair.
d[40] = 2040
assert(identity1 == d._rawIdentifier())
assert(d.count == 4)
assert(d[10]! == 1010)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
assert(d[40]! == 2040)
// Overwrite a value in existing binding.
d[10] = 2010
assert(identity1 == d._rawIdentifier())
assert(d.count == 4)
assert(d[10]! == 2010)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
assert(d[40]! == 2040)
// Delete an existing key.
d[10] = nil
assert(identity1 == d._rawIdentifier())
assert(d.count == 3)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
assert(d[40]! == 2040)
// Try to delete a key that does not exist.
d[42] = nil
assert(identity1 == d._rawIdentifier())
assert(d.count == 3)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
assert(d[40]! == 2040)
do {
var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
MinimalHashableValue.timesEqualEqualWasCalled = 0
MinimalHashableValue.timesHashIntoWasCalled = 0
expectNil(d2[MinimalHashableValue(42)])
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
DictionaryTestSuite.test("COW.Slow.SubscriptWithKeyDoesNotReallocate")
.code {
var d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
assert(d[TestKeyTy(10)]!.value == 1010)
assert(identity1 == d._rawIdentifier())
// Insert a new key-value pair.
d[TestKeyTy(40)] = TestValueTy(2040)
assert(identity1 == d._rawIdentifier())
assert(d.count == 4)
assert(d[TestKeyTy(10)]!.value == 1010)
assert(d[TestKeyTy(20)]!.value == 1020)
assert(d[TestKeyTy(30)]!.value == 1030)
assert(d[TestKeyTy(40)]!.value == 2040)
// Overwrite a value in existing binding.
d[TestKeyTy(10)] = TestValueTy(2010)
assert(identity1 == d._rawIdentifier())
assert(d.count == 4)
assert(d[TestKeyTy(10)]!.value == 2010)
assert(d[TestKeyTy(20)]!.value == 1020)
assert(d[TestKeyTy(30)]!.value == 1030)
assert(d[TestKeyTy(40)]!.value == 2040)
// Delete an existing key.
d[TestKeyTy(10)] = nil
assert(identity1 == d._rawIdentifier())
assert(d.count == 3)
assert(d[TestKeyTy(20)]!.value == 1020)
assert(d[TestKeyTy(30)]!.value == 1030)
assert(d[TestKeyTy(40)]!.value == 2040)
// Try to delete a key that does not exist.
d[TestKeyTy(42)] = nil
assert(identity1 == d._rawIdentifier())
assert(d.count == 3)
assert(d[TestKeyTy(20)]!.value == 1020)
assert(d[TestKeyTy(30)]!.value == 1030)
assert(d[TestKeyTy(40)]!.value == 2040)
do {
var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
MinimalHashableClass.timesEqualEqualWasCalled = 0
MinimalHashableClass.timesHashIntoWasCalled = 0
expectNil(d2[MinimalHashableClass(42)])
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
}
}
DictionaryTestSuite.test("COW.Fast.UpdateValueForKeyDoesNotReallocate") {
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
// Insert a new key-value pair.
assert(d1.updateValue(2040, forKey: 40) == .none)
assert(identity1 == d1._rawIdentifier())
assert(d1[40]! == 2040)
// Overwrite a value in existing binding.
assert(d1.updateValue(2010, forKey: 10)! == 1010)
assert(identity1 == d1._rawIdentifier())
assert(d1[10]! == 2010)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Insert a new key-value pair.
d2.updateValue(2040, forKey: 40)
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d1[40] == .none)
assert(d2.count == 4)
assert(d2[10]! == 1010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
assert(d2[40]! == 2040)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Overwrite a value in existing binding.
d2.updateValue(2010, forKey: 10)
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d2.count == 3)
assert(d2[10]! == 2010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Slow.AddDoesNotReallocate") {
do {
var d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
// Insert a new key-value pair.
assert(d1.updateValue(TestValueTy(2040), forKey: TestKeyTy(40)) == nil)
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 4)
assert(d1[TestKeyTy(40)]!.value == 2040)
// Overwrite a value in existing binding.
assert(d1.updateValue(TestValueTy(2010), forKey: TestKeyTy(10))!.value == 1010)
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 4)
assert(d1[TestKeyTy(10)]!.value == 2010)
}
do {
var d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Insert a new key-value pair.
d2.updateValue(TestValueTy(2040), forKey: TestKeyTy(40))
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[TestKeyTy(10)]!.value == 1010)
assert(d1[TestKeyTy(20)]!.value == 1020)
assert(d1[TestKeyTy(30)]!.value == 1030)
assert(d1[TestKeyTy(40)] == nil)
assert(d2.count == 4)
assert(d2[TestKeyTy(10)]!.value == 1010)
assert(d2[TestKeyTy(20)]!.value == 1020)
assert(d2[TestKeyTy(30)]!.value == 1030)
assert(d2[TestKeyTy(40)]!.value == 2040)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Overwrite a value in existing binding.
d2.updateValue(TestValueTy(2010), forKey: TestKeyTy(10))
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[TestKeyTy(10)]!.value == 1010)
assert(d1[TestKeyTy(20)]!.value == 1020)
assert(d1[TestKeyTy(30)]!.value == 1030)
assert(d2.count == 3)
assert(d2[TestKeyTy(10)]!.value == 2010)
assert(d2[TestKeyTy(20)]!.value == 1020)
assert(d2[TestKeyTy(30)]!.value == 1030)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Fast.MergeSequenceDoesNotReallocate")
.code {
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
// Merge some new values.
d1.merge([(40, 2040), (50, 2050)]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 5)
assert(d1[50]! == 2050)
// Merge and overwrite some existing values.
d1.merge([(10, 2010), (60, 2060)]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 6)
assert(d1[10]! == 2010)
assert(d1[60]! == 2060)
// Merge, keeping existing values.
d1.merge([(30, 2030), (70, 2070)]) { x, _ in x }
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 7)
assert(d1[30]! == 1030)
assert(d1[70]! == 2070)
let d2 = d1.merging([(40, 3040), (80, 3080)]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d2.count == 8)
assert(d2[40]! == 3040)
assert(d2[80]! == 3080)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Merge some new values.
d2.merge([(40, 2040), (50, 2050)]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d1[40] == nil)
assert(d2.count == 5)
assert(d2[10]! == 1010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
assert(d2[40]! == 2040)
assert(d2[50]! == 2050)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Merge and overwrite some existing values.
d2.merge([(10, 2010)]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d2.count == 3)
assert(d2[10]! == 2010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Merge, keeping existing values.
d2.merge([(10, 2010)]) { x, _ in x }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d2.count == 3)
assert(d2[10]! == 1010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Fast.MergeDictionaryDoesNotReallocate")
.code {
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
// Merge some new values.
d1.merge([40: 2040, 50: 2050]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 5)
assert(d1[50]! == 2050)
// Merge and overwrite some existing values.
d1.merge([10: 2010, 60: 2060]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 6)
assert(d1[10]! == 2010)
assert(d1[60]! == 2060)
// Merge, keeping existing values.
d1.merge([30: 2030, 70: 2070]) { x, _ in x }
assert(identity1 == d1._rawIdentifier())
assert(d1.count == 7)
assert(d1[30]! == 1030)
assert(d1[70]! == 2070)
let d2 = d1.merging([40: 3040, 80: 3080]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d2.count == 8)
assert(d2[40]! == 3040)
assert(d2[80]! == 3080)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Merge some new values.
d2.merge([40: 2040, 50: 2050]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d1[40] == nil)
assert(d2.count == 5)
assert(d2[10]! == 1010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
assert(d2[40]! == 2040)
assert(d2[50]! == 2050)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Merge and overwrite some existing values.
d2.merge([10: 2010]) { _, y in y }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d2.count == 3)
assert(d2[10]! == 2010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Merge, keeping existing values.
d2.merge([10: 2010]) { x, _ in x }
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d1[20]! == 1020)
assert(d1[30]! == 1030)
assert(d2.count == 3)
assert(d2[10]! == 1010)
assert(d2[20]! == 1020)
assert(d2[30]! == 1030)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Fast.DefaultedSubscriptDoesNotReallocate") {
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
// No mutation on access.
assert(d1[10, default: 0] + 1 == 1011)
assert(d1[40, default: 0] + 1 == 1)
assert(identity1 == d1._rawIdentifier())
assert(d1[10]! == 1010)
// Increment existing in place.
d1[10, default: 0] += 1
assert(identity1 == d1._rawIdentifier())
assert(d1[10]! == 1011)
// Add incremented default value.
d1[40, default: 0] += 1
assert(identity1 == d1._rawIdentifier())
assert(d1[40]! == 1)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// No mutation on access.
assert(d2[10, default: 0] + 1 == 1011)
assert(d2[40, default: 0] + 1 == 1)
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Increment existing in place.
d2[10, default: 0] += 1
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1[10]! == 1010)
assert(d2[10]! == 1011)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
// Add incremented default value.
d2[40, default: 0] += 1
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d1[40] == nil)
assert(d2[40]! == 1)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Fast.DefaultedSubscriptDoesNotCopyValue") {
do {
var d = getCOWFastDictionaryWithCOWValues()
let identityValue30 = d[30]!.baseAddress
// Increment the value without having to reallocate the underlying Base
// instance, as uniquely referenced.
d[30, default: TestValueCOWTy()].value += 1
assert(identityValue30 == d[30]!.baseAddress)
assert(d[30]!.value == 1031)
let value40 = TestValueCOWTy()
let identityValue40 = value40.baseAddress
// Increment the value, reallocating the underlying Base, as not uniquely
// referenced.
d[40, default: value40].value += 1
assert(identityValue40 != d[40]!.baseAddress)
assert(d[40]!.value == 1)
// Keep variables alive.
_fixLifetime(d)
_fixLifetime(value40)
}
}
DictionaryTestSuite.test("COW.Fast.IndexForKeyDoesNotReallocate") {
let d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
// Find an existing key.
do {
let foundIndex1 = d.index(forKey: 10)!
assert(identity1 == d._rawIdentifier())
let foundIndex2 = d.index(forKey: 10)!
assert(foundIndex1 == foundIndex2)
assert(d[foundIndex1].0 == 10)
assert(d[foundIndex1].1 == 1010)
assert(identity1 == d._rawIdentifier())
}
// Try to find a key that is not present.
do {
let foundIndex1 = d.index(forKey: 1111)
assert(foundIndex1 == nil)
assert(identity1 == d._rawIdentifier())
}
do {
let d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
MinimalHashableValue.timesEqualEqualWasCalled = 0
MinimalHashableValue.timesHashIntoWasCalled = 0
expectNil(d2.index(forKey: MinimalHashableValue(42)))
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
DictionaryTestSuite.test("COW.Slow.IndexForKeyDoesNotReallocate") {
let d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
// Find an existing key.
do {
let foundIndex1 = d.index(forKey: TestKeyTy(10))!
assert(identity1 == d._rawIdentifier())
let foundIndex2 = d.index(forKey: TestKeyTy(10))!
assert(foundIndex1 == foundIndex2)
assert(d[foundIndex1].0 == TestKeyTy(10))
assert(d[foundIndex1].1.value == 1010)
assert(identity1 == d._rawIdentifier())
}
// Try to find a key that is not present.
do {
let foundIndex1 = d.index(forKey: TestKeyTy(1111))
assert(foundIndex1 == nil)
assert(identity1 == d._rawIdentifier())
}
do {
let d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
MinimalHashableClass.timesEqualEqualWasCalled = 0
MinimalHashableClass.timesHashIntoWasCalled = 0
expectNil(d2.index(forKey: MinimalHashableClass(42)))
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
}
}
DictionaryTestSuite.test("COW.Fast.RemoveAtDoesNotReallocate")
.code {
do {
var d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
let foundIndex1 = d.index(forKey: 10)!
assert(identity1 == d._rawIdentifier())
assert(d[foundIndex1].0 == 10)
assert(d[foundIndex1].1 == 1010)
let removed = d.remove(at: foundIndex1)
assert(removed.0 == 10)
assert(removed.1 == 1010)
assert(identity1 == d._rawIdentifier())
assert(d.index(forKey: 10) == nil)
}
do {
let d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
let foundIndex1 = d2.index(forKey: 10)!
assert(d2[foundIndex1].0 == 10)
assert(d2[foundIndex1].1 == 1010)
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
let removed = d2.remove(at: foundIndex1)
assert(removed.0 == 10)
assert(removed.1 == 1010)
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d2.index(forKey: 10) == nil)
}
}
DictionaryTestSuite.test("COW.Slow.RemoveAtDoesNotReallocate")
.code {
do {
var d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
let foundIndex1 = d.index(forKey: TestKeyTy(10))!
assert(identity1 == d._rawIdentifier())
assert(d[foundIndex1].0 == TestKeyTy(10))
assert(d[foundIndex1].1.value == 1010)
let removed = d.remove(at: foundIndex1)
assert(removed.0 == TestKeyTy(10))
assert(removed.1.value == 1010)
assert(identity1 == d._rawIdentifier())
assert(d.index(forKey: TestKeyTy(10)) == nil)
}
do {
let d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
let foundIndex1 = d2.index(forKey: TestKeyTy(10))!
assert(d2[foundIndex1].0 == TestKeyTy(10))
assert(d2[foundIndex1].1.value == 1010)
let removed = d2.remove(at: foundIndex1)
assert(removed.0 == TestKeyTy(10))
assert(removed.1.value == 1010)
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
assert(d2.index(forKey: TestKeyTy(10)) == nil)
}
}
DictionaryTestSuite.test("COW.Fast.RemoveValueForKeyDoesNotReallocate")
.code {
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var deleted = d1.removeValue(forKey: 0)
assert(deleted == nil)
assert(identity1 == d1._rawIdentifier())
deleted = d1.removeValue(forKey: 10)
assert(deleted! == 1010)
assert(identity1 == d1._rawIdentifier())
// Keep variables alive.
_fixLifetime(d1)
}
do {
let d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
var deleted = d2.removeValue(forKey: 0)
assert(deleted == nil)
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
deleted = d2.removeValue(forKey: 10)
assert(deleted! == 1010)
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Slow.RemoveValueForKeyDoesNotReallocate")
.code {
do {
var d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
var deleted = d1.removeValue(forKey: TestKeyTy(0))
assert(deleted == nil)
assert(identity1 == d1._rawIdentifier())
deleted = d1.removeValue(forKey: TestKeyTy(10))
assert(deleted!.value == 1010)
assert(identity1 == d1._rawIdentifier())
// Keep variables alive.
_fixLifetime(d1)
}
do {
let d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
var deleted = d2.removeValue(forKey: TestKeyTy(0))
assert(deleted == nil)
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
deleted = d2.removeValue(forKey: TestKeyTy(10))
assert(deleted!.value == 1010)
assert(identity1 == d1._rawIdentifier())
assert(identity1 != d2._rawIdentifier())
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Fast.RemoveAllDoesNotReallocate") {
do {
var d = getCOWFastDictionary()
let originalCapacity = d.capacity
assert(d.count == 3)
assert(d[10]! == 1010)
d.removeAll()
// We cannot assert that identity changed, since the new buffer of smaller
// size can be allocated at the same address as the old one.
let identity1 = d._rawIdentifier()
assert(d.capacity < originalCapacity)
assert(d.count == 0)
assert(d[10] == nil)
d.removeAll()
assert(identity1 == d._rawIdentifier())
assert(d.count == 0)
assert(d[10] == nil)
}
do {
var d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
let originalCapacity = d.capacity
assert(d.count == 3)
assert(d[10]! == 1010)
d.removeAll(keepingCapacity: true)
assert(identity1 == d._rawIdentifier())
assert(d.capacity == originalCapacity)
assert(d.count == 0)
assert(d[10] == nil)
d.removeAll(keepingCapacity: true)
assert(identity1 == d._rawIdentifier())
assert(d.capacity == originalCapacity)
assert(d.count == 0)
assert(d[10] == nil)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
assert(d1.count == 3)
assert(d1[10]! == 1010)
var d2 = d1
d2.removeAll()
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d2.count == 0)
assert(d2[10] == nil)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
let originalCapacity = d1.capacity
assert(d1.count == 3)
assert(d1[10] == 1010)
var d2 = d1
d2.removeAll(keepingCapacity: true)
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert(d1[10]! == 1010)
assert(d2.capacity == originalCapacity)
assert(d2.count == 0)
assert(d2[10] == nil)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Slow.RemoveAllDoesNotReallocate") {
do {
var d = getCOWSlowDictionary()
let originalCapacity = d.capacity
assert(d.count == 3)
assert(d[TestKeyTy(10)]!.value == 1010)
d.removeAll()
// We cannot assert that identity changed, since the new buffer of smaller
// size can be allocated at the same address as the old one.
let identity1 = d._rawIdentifier()
assert(d.capacity < originalCapacity)
assert(d.count == 0)
assert(d[TestKeyTy(10)] == nil)
d.removeAll()
assert(identity1 == d._rawIdentifier())
assert(d.count == 0)
assert(d[TestKeyTy(10)] == nil)
}
do {
var d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
let originalCapacity = d.capacity
assert(d.count == 3)
assert(d[TestKeyTy(10)]!.value == 1010)
d.removeAll(keepingCapacity: true)
assert(identity1 == d._rawIdentifier())
assert(d.capacity == originalCapacity)
assert(d.count == 0)
assert(d[TestKeyTy(10)] == nil)
d.removeAll(keepingCapacity: true)
assert(identity1 == d._rawIdentifier())
assert(d.capacity == originalCapacity)
assert(d.count == 0)
assert(d[TestKeyTy(10)] == nil)
}
do {
var d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
assert(d1.count == 3)
assert(d1[TestKeyTy(10)]!.value == 1010)
var d2 = d1
d2.removeAll()
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert(d1[TestKeyTy(10)]!.value == 1010)
assert(d2.count == 0)
assert(d2[TestKeyTy(10)] == nil)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
do {
var d1 = getCOWSlowDictionary()
let identity1 = d1._rawIdentifier()
let originalCapacity = d1.capacity
assert(d1.count == 3)
assert(d1[TestKeyTy(10)]!.value == 1010)
var d2 = d1
d2.removeAll(keepingCapacity: true)
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert(d1[TestKeyTy(10)]!.value == 1010)
assert(d2.capacity == originalCapacity)
assert(d2.count == 0)
assert(d2[TestKeyTy(10)] == nil)
// Keep variables alive.
_fixLifetime(d1)
_fixLifetime(d2)
}
}
DictionaryTestSuite.test("COW.Fast.CountDoesNotReallocate") {
let d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
assert(d.count == 3)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("COW.Slow.CountDoesNotReallocate") {
let d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
assert(d.count == 3)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("COW.Fast.GenerateDoesNotReallocate") {
let d = getCOWFastDictionary()
let identity1 = d._rawIdentifier()
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
pairs += [(key, value)]
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("COW.Slow.GenerateDoesNotReallocate") {
let d = getCOWSlowDictionary()
let identity1 = d._rawIdentifier()
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
pairs += [(key.value, value.value)]
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("COW.Fast.EqualityTestDoesNotReallocate") {
let d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
var d2 = getCOWFastDictionary()
let identity2 = d2._rawIdentifier()
assert(d1 == d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
d2[40] = 2040
assert(d1 != d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
}
DictionaryTestSuite.test("COW.Slow.EqualityTestDoesNotReallocate") {
let d1 = getCOWSlowEquatableDictionary()
let identity1 = d1._rawIdentifier()
var d2 = getCOWSlowEquatableDictionary()
let identity2 = d2._rawIdentifier()
assert(d1 == d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
d2[TestKeyTy(40)] = TestEquatableValueTy(2040)
assert(d1 != d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
}
//===---
// Keys and Values collection tests.
//===---
DictionaryTestSuite.test("COW.Fast.ValuesAccessDoesNotReallocate") {
var d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
assert([1010, 1020, 1030] == d1.values.sorted())
assert(identity1 == d1._rawIdentifier())
var d2 = d1
assert(identity1 == d2._rawIdentifier())
let i = d2.index(forKey: 10)!
assert(d1.values[i] == 1010)
assert(d1[i] == (10, 1010))
d2.values[i] += 1
assert(d2.values[i] == 1011)
assert(d2[10]! == 1011)
assert(identity1 != d2._rawIdentifier())
assert(d1[10]! == 1010)
assert(identity1 == d1._rawIdentifier())
checkCollection(
Array(d1.values),
d1.values,
stackTrace: SourceLocStack())
{ $0 == $1 }
}
DictionaryTestSuite.test("COW.Fast.KeysAccessDoesNotReallocate") {
let d1 = getCOWFastDictionary()
let identity1 = d1._rawIdentifier()
assert([10, 20, 30] == d1.keys.sorted())
let i = d1.index(forKey: 10)!
assert(d1.keys[i] == 10)
assert(d1[i] == (10, 1010))
assert(identity1 == d1._rawIdentifier())
checkCollection(
Array(d1.keys),
d1.keys,
stackTrace: SourceLocStack())
{ $0 == $1 }
do {
let d2: [MinimalHashableValue : Int] = [
MinimalHashableValue(10): 1010,
MinimalHashableValue(20): 1020,
MinimalHashableValue(30): 1030,
MinimalHashableValue(40): 1040,
MinimalHashableValue(50): 1050,
MinimalHashableValue(60): 1060,
MinimalHashableValue(70): 1070,
MinimalHashableValue(80): 1080,
MinimalHashableValue(90): 1090,
]
// Find the last key in the dictionary
var lastKey: MinimalHashableValue = d2.first!.key
for i in d2.indices { lastKey = d2[i].key }
// firstIndex(where:) - linear search
MinimalHashableValue.timesEqualEqualWasCalled = 0
let j = d2.firstIndex(where: { (k, _) in k == lastKey })!
expectGE(MinimalHashableValue.timesEqualEqualWasCalled, 8)
// index(forKey:) - O(1) bucket + linear search
MinimalHashableValue.timesEqualEqualWasCalled = 0
let k = d2.index(forKey: lastKey)!
expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
// keys.firstIndex(of:) - O(1) bucket + linear search
MinimalHashableValue.timesEqualEqualWasCalled = 0
let l = d2.keys.firstIndex(of: lastKey)!
expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
expectEqual(j, k)
expectEqual(k, l)
}
}
//===---
// Native dictionary tests.
//===---
func helperDeleteThree(_ k1: TestKeyTy, _ k2: TestKeyTy, _ k3: TestKeyTy) {
var d1 = Dictionary<TestKeyTy, TestValueTy>(minimumCapacity: 10)
d1[k1] = TestValueTy(1010)
d1[k2] = TestValueTy(1020)
d1[k3] = TestValueTy(1030)
assert(d1[k1]!.value == 1010)
assert(d1[k2]!.value == 1020)
assert(d1[k3]!.value == 1030)
d1[k1] = nil
assert(d1[k2]!.value == 1020)
assert(d1[k3]!.value == 1030)
d1[k2] = nil
assert(d1[k3]!.value == 1030)
d1[k3] = nil
assert(d1.count == 0)
}
DictionaryTestSuite.test("deleteChainCollision") {
let k1 = TestKeyTy(value: 10, hashValue: 0)
let k2 = TestKeyTy(value: 20, hashValue: 0)
let k3 = TestKeyTy(value: 30, hashValue: 0)
helperDeleteThree(k1, k2, k3)
}
DictionaryTestSuite.test("deleteChainNoCollision") {
let k1 = TestKeyTy(value: 10, hashValue: 0)
let k2 = TestKeyTy(value: 20, hashValue: 1)
let k3 = TestKeyTy(value: 30, hashValue: 2)
helperDeleteThree(k1, k2, k3)
}
DictionaryTestSuite.test("deleteChainCollision2") {
let k1_0 = TestKeyTy(value: 10, hashValue: 0)
let k2_0 = TestKeyTy(value: 20, hashValue: 0)
let k3_2 = TestKeyTy(value: 30, hashValue: 2)
let k4_0 = TestKeyTy(value: 40, hashValue: 0)
let k5_2 = TestKeyTy(value: 50, hashValue: 2)
let k6_0 = TestKeyTy(value: 60, hashValue: 0)
var d = Dictionary<TestKeyTy, TestValueTy>(minimumCapacity: 10)
d[k1_0] = TestValueTy(1010) // in bucket 0
d[k2_0] = TestValueTy(1020) // in bucket 1
d[k3_2] = TestValueTy(1030) // in bucket 2
d[k4_0] = TestValueTy(1040) // in bucket 3
d[k5_2] = TestValueTy(1050) // in bucket 4
d[k6_0] = TestValueTy(1060) // in bucket 5
d[k3_2] = nil
assert(d[k1_0]!.value == 1010)
assert(d[k2_0]!.value == 1020)
assert(d[k3_2] == nil)
assert(d[k4_0]!.value == 1040)
assert(d[k5_2]!.value == 1050)
assert(d[k6_0]!.value == 1060)
}
func uniformRandom(_ max: Int) -> Int {
#if os(Linux)
// SR-685: Can't use arc4random on Linux
return Int(random() % (max + 1))
#else
return Int(arc4random_uniform(UInt32(max)))
#endif
}
func pickRandom<T>(_ a: [T]) -> T {
return a[uniformRandom(a.count)]
}
func product<C1 : Collection, C2 : Collection>(
_ c1: C1, _ c2: C2
) -> [(C1.Iterator.Element, C2.Iterator.Element)] {
var result: [(C1.Iterator.Element, C2.Iterator.Element)] = []
for e1 in c1 {
for e2 in c2 {
result.append((e1, e2))
}
}
return result
}
DictionaryTestSuite.test("deleteChainCollisionRandomized")
.forEach(in: product(1...8, 0...5)) {
(collisionChains, chainOverlap) in
func check(_ d: Dictionary<TestKeyTy, TestValueTy>) {
let keys = Array(d.keys)
for i in 0..<keys.count {
for j in 0..<i {
assert(keys[i] != keys[j])
}
}
for k in keys {
assert(d[k] != nil)
}
}
let chainLength = 7
var knownKeys: [TestKeyTy] = []
func getKey(_ value: Int) -> TestKeyTy {
for k in knownKeys {
if k.value == value {
return k
}
}
let hashValue = uniformRandom(chainLength - chainOverlap) * collisionChains
let k = TestKeyTy(value: value, hashValue: hashValue)
knownKeys += [k]
return k
}
var d = Dictionary<TestKeyTy, TestValueTy>(minimumCapacity: 30)
for _ in 1..<300 {
let key = getKey(uniformRandom(collisionChains * chainLength))
if uniformRandom(chainLength * 2) == 0 {
d[key] = nil
} else {
d[key] = TestValueTy(key.value * 10)
}
check(d)
}
}
DictionaryTestSuite.test("init(dictionaryLiteral:)") {
do {
var empty = Dictionary<Int, Int>()
assert(empty.count == 0)
assert(empty[1111] == nil)
}
do {
var d = Dictionary(dictionaryLiteral: (10, 1010))
assert(d.count == 1)
assert(d[10]! == 1010)
assert(d[1111] == nil)
}
do {
var d = Dictionary(dictionaryLiteral:
(10, 1010), (20, 1020))
assert(d.count == 2)
assert(d[10]! == 1010)
assert(d[20]! == 1020)
assert(d[1111] == nil)
}
do {
var d = Dictionary(dictionaryLiteral:
(10, 1010), (20, 1020), (30, 1030))
assert(d.count == 3)
assert(d[10]! == 1010)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
assert(d[1111] == nil)
}
do {
var d = Dictionary(dictionaryLiteral:
(10, 1010), (20, 1020), (30, 1030), (40, 1040))
assert(d.count == 4)
assert(d[10]! == 1010)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
assert(d[40]! == 1040)
assert(d[1111] == nil)
}
do {
var d: Dictionary<Int, Int> = [ 10: 1010, 20: 1020, 30: 1030 ]
assert(d.count == 3)
assert(d[10]! == 1010)
assert(d[20]! == 1020)
assert(d[30]! == 1030)
}
}
DictionaryTestSuite.test("init(uniqueKeysWithValues:)") {
do {
var d = Dictionary(uniqueKeysWithValues: [(10, 1010), (20, 1020), (30, 1030)])
expectEqual(d.count, 3)
expectEqual(d[10]!, 1010)
expectEqual(d[20]!, 1020)
expectEqual(d[30]!, 1030)
expectNil(d[1111])
}
do {
var d = Dictionary<Int, Int>(uniqueKeysWithValues: EmptyCollection<(Int, Int)>())
expectEqual(d.count, 0)
expectNil(d[1111])
}
do {
expectCrashLater()
_ = Dictionary(uniqueKeysWithValues: [(10, 1010), (20, 1020), (10, 2010)])
}
}
DictionaryTestSuite.test("init(_:uniquingKeysWith:)") {
do {
let d = Dictionary(
[(10, 1010), (20, 1020), (30, 1030), (10, 2010)], uniquingKeysWith: min)
expectEqual(d.count, 3)
expectEqual(d[10]!, 1010)
expectEqual(d[20]!, 1020)
expectEqual(d[30]!, 1030)
expectNil(d[1111])
}
do {
let d = Dictionary(
[(10, 1010), (20, 1020), (30, 1030), (10, 2010)] as [(Int, Int)],
uniquingKeysWith: +)
expectEqual(d.count, 3)
expectEqual(d[10]!, 3020)
expectEqual(d[20]!, 1020)
expectEqual(d[30]!, 1030)
expectNil(d[1111])
}
do {
let d = Dictionary([(10, 1010), (20, 1020), (30, 1030), (10, 2010)]) {
(a, b) in Int("\(a)\(b)")!
}
expectEqual(d.count, 3)
expectEqual(d[10]!, 10102010)
expectEqual(d[20]!, 1020)
expectEqual(d[30]!, 1030)
expectNil(d[1111])
}
do {
let d = Dictionary([(10, 1010), (10, 2010), (10, 3010), (10, 4010)]) { $1 }
expectEqual(d.count, 1)
expectEqual(d[10]!, 4010)
expectNil(d[1111])
}
do {
let d = Dictionary(EmptyCollection<(Int, Int)>(), uniquingKeysWith: min)
expectEqual(d.count, 0)
expectNil(d[1111])
}
struct TE: Error {}
do {
// No duplicate keys, so no error thrown.
let d1 = try Dictionary([(10, 1), (20, 2), (30, 3)]) { (_,_) in throw TE() }
expectEqual(d1.count, 3)
// Duplicate keys, should throw error.
_ = try Dictionary([(10, 1), (10, 2)]) { (_,_) in throw TE() }
_ = assertionFailure()
} catch {
assert(error is TE)
}
}
DictionaryTestSuite.test("init(grouping:by:)") {
let r = 0..<10
let d1 = Dictionary(grouping: r, by: { $0 % 3 })
expectEqual(3, d1.count)
expectEqual([0, 3, 6, 9], d1[0]!)
expectEqual([1, 4, 7], d1[1]!)
expectEqual([2, 5, 8], d1[2]!)
let d2 = Dictionary(grouping: r, by: { $0 })
expectEqual(10, d2.count)
let d3 = Dictionary(grouping: 0..<0, by: { $0 })
expectEqual(0, d3.count)
}
DictionaryTestSuite.test("mapValues(_:)") {
let d1 = [10: 1010, 20: 1020, 30: 1030]
let d2 = d1.mapValues(String.init)
expectEqual(d1.count, d2.count)
expectEqual(d1.keys.first, d2.keys.first)
for (key, _) in d1 {
expectEqual(String(d1[key]!), d2[key]!)
}
do {
let d3: [MinimalHashableValue : Int] = Dictionary(
uniqueKeysWithValues: d1.lazy.map { (MinimalHashableValue($0), $1) })
expectEqual(d3.count, 3)
MinimalHashableValue.timesEqualEqualWasCalled = 0
MinimalHashableValue.timesHashIntoWasCalled = 0
// Calling mapValues shouldn't ever recalculate any hashes.
let d4 = d3.mapValues(String.init)
expectEqual(d4.count, d3.count)
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
DictionaryTestSuite.test("capacity/init(minimumCapacity:)") {
let d0 = Dictionary<String, Int>(minimumCapacity: 0)
expectGE(d0.capacity, 0)
let d1 = Dictionary<String, Int>(minimumCapacity: 1)
expectGE(d1.capacity, 1)
let d3 = Dictionary<String, Int>(minimumCapacity: 3)
expectGE(d3.capacity, 3)
let d4 = Dictionary<String, Int>(minimumCapacity: 4)
expectGE(d4.capacity, 4)
let d10 = Dictionary<String, Int>(minimumCapacity: 10)
expectGE(d10.capacity, 10)
let d100 = Dictionary<String, Int>(minimumCapacity: 100)
expectGE(d100.capacity, 100)
let d1024 = Dictionary<String, Int>(minimumCapacity: 1024)
expectGE(d1024.capacity, 1024)
}
DictionaryTestSuite.test("capacity/reserveCapacity(_:)") {
var d1 = [10: 1010, 20: 1020, 30: 1030]
expectEqual(3, d1.capacity)
d1[40] = 1040
expectEqual(6, d1.capacity)
// Reserving new capacity jumps up to next limit.
d1.reserveCapacity(7)
expectEqual(12, d1.capacity)
// Can reserve right up to a limit.
d1.reserveCapacity(24)
expectEqual(24, d1.capacity)
// Fill up to the limit, no reallocation.
d1.merge(stride(from: 50, through: 240, by: 10).lazy.map { ($0, 1000 + $0) },
uniquingKeysWith: { (_,_) in fatalError() })
expectEqual(24, d1.count)
expectEqual(24, d1.capacity)
d1[250] = 1250
expectEqual(48, d1.capacity)
}
#if _runtime(_ObjC)
//===---
// NSDictionary -> Dictionary bridging tests.
//===---
func getAsNSDictionary(_ d: Dictionary<Int, Int>) -> NSDictionary {
let keys = Array(d.keys.map { TestObjCKeyTy($0) })
let values = Array(d.values.map { TestObjCValueTy($0) })
// Return an `NSMutableDictionary` to make sure that it has a unique
// pointer identity.
return NSMutableDictionary(objects: values, forKeys: keys)
}
func getAsEquatableNSDictionary(_ d: Dictionary<Int, Int>) -> NSDictionary {
let keys = Array(d.keys.map { TestObjCKeyTy($0) })
let values = Array(d.values.map { TestObjCEquatableValueTy($0) })
// Return an `NSMutableDictionary` to make sure that it has a unique
// pointer identity.
return NSMutableDictionary(objects: values, forKeys: keys)
}
func getAsNSMutableDictionary(_ d: Dictionary<Int, Int>) -> NSMutableDictionary {
let keys = Array(d.keys.map { TestObjCKeyTy($0) })
let values = Array(d.values.map { TestObjCValueTy($0) })
return NSMutableDictionary(objects: values, forKeys: keys)
}
func getBridgedVerbatimDictionary() -> Dictionary<NSObject, AnyObject> {
let nsd = getAsNSDictionary([10: 1010, 20: 1020, 30: 1030])
return convertNSDictionaryToDictionary(nsd)
}
func getBridgedVerbatimDictionary(_ d: Dictionary<Int, Int>) -> Dictionary<NSObject, AnyObject> {
let nsd = getAsNSDictionary(d)
return convertNSDictionaryToDictionary(nsd)
}
func getBridgedVerbatimDictionaryAndNSMutableDictionary()
-> (Dictionary<NSObject, AnyObject>, NSMutableDictionary) {
let nsd = getAsNSMutableDictionary([10: 1010, 20: 1020, 30: 1030])
return (convertNSDictionaryToDictionary(nsd), nsd)
}
func getBridgedNonverbatimDictionary() -> Dictionary<TestBridgedKeyTy, TestBridgedValueTy> {
let nsd = getAsNSDictionary([10: 1010, 20: 1020, 30: 1030 ])
return Swift._forceBridgeFromObjectiveC(nsd, Dictionary.self)
}
func getBridgedNonverbatimDictionary(_ d: Dictionary<Int, Int>) -> Dictionary<TestBridgedKeyTy, TestBridgedValueTy> {
let nsd = getAsNSDictionary(d)
return Swift._forceBridgeFromObjectiveC(nsd, Dictionary.self)
}
func getBridgedNonverbatimDictionaryAndNSMutableDictionary()
-> (Dictionary<TestBridgedKeyTy, TestBridgedValueTy>, NSMutableDictionary) {
let nsd = getAsNSMutableDictionary([10: 1010, 20: 1020, 30: 1030])
return (Swift._forceBridgeFromObjectiveC(nsd, Dictionary.self), nsd)
}
func getBridgedVerbatimEquatableDictionary(_ d: Dictionary<Int, Int>) -> Dictionary<NSObject, TestObjCEquatableValueTy> {
let nsd = getAsEquatableNSDictionary(d)
return convertNSDictionaryToDictionary(nsd)
}
func getBridgedNonverbatimEquatableDictionary(_ d: Dictionary<Int, Int>) -> Dictionary<TestBridgedKeyTy, TestBridgedEquatableValueTy> {
let nsd = getAsEquatableNSDictionary(d)
return Swift._forceBridgeFromObjectiveC(nsd, Dictionary.self)
}
func getHugeBridgedVerbatimDictionaryHelper() -> NSDictionary {
let keys = (1...32).map { TestObjCKeyTy($0) }
let values = (1...32).map { TestObjCValueTy(1000 + $0) }
return NSMutableDictionary(objects: values, forKeys: keys)
}
func getHugeBridgedVerbatimDictionary() -> Dictionary<NSObject, AnyObject> {
let nsd = getHugeBridgedVerbatimDictionaryHelper()
return convertNSDictionaryToDictionary(nsd)
}
func getHugeBridgedNonverbatimDictionary() -> Dictionary<TestBridgedKeyTy, TestBridgedValueTy> {
let nsd = getHugeBridgedVerbatimDictionaryHelper()
return Swift._forceBridgeFromObjectiveC(nsd, Dictionary.self)
}
/// A mock dictionary that stores its keys and values in parallel arrays, which
/// allows it to return inner pointers to the keys array in fast enumeration.
@objc
class ParallelArrayDictionary : NSDictionary {
struct Keys {
var key0: AnyObject = TestObjCKeyTy(10)
var key1: AnyObject = TestObjCKeyTy(20)
var key2: AnyObject = TestObjCKeyTy(30)
var key3: AnyObject = TestObjCKeyTy(40)
}
var keys = [ Keys() ]
var value: AnyObject = TestObjCValueTy(1111)
override init() {
super.init()
}
override init(
objects: UnsafePointer<AnyObject>?,
forKeys keys: UnsafePointer<NSCopying>?,
count: Int) {
super.init(objects: objects, forKeys: keys, count: count)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) not implemented by ParallelArrayDictionary")
}
@objc(copyWithZone:)
override func copy(with zone: NSZone?) -> Any {
// Ensure that copying this dictionary does not produce a CoreFoundation
// object.
return self
}
override func countByEnumerating(
with state: UnsafeMutablePointer<NSFastEnumerationState>,
objects: AutoreleasingUnsafeMutablePointer<AnyObject?>,
count: Int
) -> Int {
var theState = state.pointee
if theState.state == 0 {
theState.state = 1
theState.itemsPtr = AutoreleasingUnsafeMutablePointer(keys._baseAddressIfContiguous)
theState.mutationsPtr = _fastEnumerationStorageMutationsPtr
state.pointee = theState
return 4
}
return 0
}
override func object(forKey aKey: Any) -> Any? {
return value
}
override var count: Int {
return 4
}
}
func getParallelArrayBridgedVerbatimDictionary() -> Dictionary<NSObject, AnyObject> {
let nsd: NSDictionary = ParallelArrayDictionary()
return convertNSDictionaryToDictionary(nsd)
}
func getParallelArrayBridgedNonverbatimDictionary() -> Dictionary<TestBridgedKeyTy, TestBridgedValueTy> {
let nsd: NSDictionary = ParallelArrayDictionary()
return Swift._forceBridgeFromObjectiveC(nsd, Dictionary.self)
}
@objc
class CustomImmutableNSDictionary : NSDictionary {
init(_privateInit: ()) {
super.init()
}
override init() {
expectUnreachable()
super.init()
}
override init(
objects: UnsafePointer<AnyObject>?,
forKeys keys: UnsafePointer<NSCopying>?,
count: Int) {
expectUnreachable()
super.init(objects: objects, forKeys: keys, count: count)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) not implemented by CustomImmutableNSDictionary")
}
@objc(copyWithZone:)
override func copy(with zone: NSZone?) -> Any {
CustomImmutableNSDictionary.timesCopyWithZoneWasCalled += 1
return self
}
override func object(forKey aKey: Any) -> Any? {
CustomImmutableNSDictionary.timesObjectForKeyWasCalled += 1
return getAsNSDictionary([10: 1010, 20: 1020, 30: 1030]).object(forKey: aKey)
}
override func keyEnumerator() -> NSEnumerator {
CustomImmutableNSDictionary.timesKeyEnumeratorWasCalled += 1
return getAsNSDictionary([10: 1010, 20: 1020, 30: 1030]).keyEnumerator()
}
override var count: Int {
CustomImmutableNSDictionary.timesCountWasCalled += 1
return 3
}
static var timesCopyWithZoneWasCalled = 0
static var timesObjectForKeyWasCalled = 0
static var timesKeyEnumeratorWasCalled = 0
static var timesCountWasCalled = 0
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.DictionaryIsCopied") {
let (d, nsd) = getBridgedVerbatimDictionaryAndNSMutableDictionary()
assert(isCocoaDictionary(d))
// Find an existing key.
do {
let kv = d[d.index(forKey: TestObjCKeyTy(10))!]
assert(kv.0 == TestObjCKeyTy(10))
assert((kv.1 as! TestObjCValueTy).value == 1010)
}
// Delete the key from the NSMutableDictionary.
assert(nsd[TestObjCKeyTy(10)] != nil)
nsd.removeObject(forKey: TestObjCKeyTy(10))
assert(nsd[TestObjCKeyTy(10)] == nil)
// Find an existing key, again.
do {
let kv = d[d.index(forKey: TestObjCKeyTy(10))!]
assert(kv.0 == TestObjCKeyTy(10))
assert((kv.1 as! TestObjCValueTy).value == 1010)
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.DictionaryIsCopied") {
let (d, nsd) = getBridgedNonverbatimDictionaryAndNSMutableDictionary()
assert(isNativeDictionary(d))
// Find an existing key.
do {
let kv = d[d.index(forKey: TestBridgedKeyTy(10))!]
assert(kv.0 == TestBridgedKeyTy(10))
assert(kv.1.value == 1010)
}
// Delete the key from the NSMutableDictionary.
assert(nsd[TestBridgedKeyTy(10) as NSCopying] != nil)
nsd.removeObject(forKey: TestBridgedKeyTy(10) as NSCopying)
assert(nsd[TestBridgedKeyTy(10) as NSCopying] == nil)
// Find an existing key, again.
do {
let kv = d[d.index(forKey: TestBridgedKeyTy(10))!]
assert(kv.0 == TestBridgedKeyTy(10))
assert(kv.1.value == 1010)
}
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.NSDictionaryIsRetained") {
let nsd: NSDictionary =
NSDictionary(dictionary:
getAsNSDictionary([10: 1010, 20: 1020, 30: 1030]))
let d: [NSObject : AnyObject] = convertNSDictionaryToDictionary(nsd)
let bridgedBack: NSDictionary = convertDictionaryToNSDictionary(d)
expectEqual(
unsafeBitCast(nsd, to: Int.self),
unsafeBitCast(bridgedBack, to: Int.self))
_fixLifetime(nsd)
_fixLifetime(d)
_fixLifetime(bridgedBack)
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.NSDictionaryIsCopied") {
let nsd: NSDictionary =
NSDictionary(dictionary:
getAsNSDictionary([10: 1010, 20: 1020, 30: 1030]))
let d: [TestBridgedKeyTy : TestBridgedValueTy] =
convertNSDictionaryToDictionary(nsd)
let bridgedBack: NSDictionary = convertDictionaryToNSDictionary(d)
expectNotEqual(
unsafeBitCast(nsd, to: Int.self),
unsafeBitCast(bridgedBack, to: Int.self))
_fixLifetime(nsd)
_fixLifetime(d)
_fixLifetime(bridgedBack)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.ImmutableDictionaryIsRetained") {
let nsd: NSDictionary = CustomImmutableNSDictionary(_privateInit: ())
CustomImmutableNSDictionary.timesCopyWithZoneWasCalled = 0
CustomImmutableNSDictionary.timesObjectForKeyWasCalled = 0
CustomImmutableNSDictionary.timesKeyEnumeratorWasCalled = 0
CustomImmutableNSDictionary.timesCountWasCalled = 0
let d: [NSObject : AnyObject] = convertNSDictionaryToDictionary(nsd)
expectEqual(1, CustomImmutableNSDictionary.timesCopyWithZoneWasCalled)
expectEqual(0, CustomImmutableNSDictionary.timesObjectForKeyWasCalled)
expectEqual(0, CustomImmutableNSDictionary.timesKeyEnumeratorWasCalled)
expectEqual(0, CustomImmutableNSDictionary.timesCountWasCalled)
let bridgedBack: NSDictionary = convertDictionaryToNSDictionary(d)
expectEqual(
unsafeBitCast(nsd, to: Int.self),
unsafeBitCast(bridgedBack, to: Int.self))
_fixLifetime(nsd)
_fixLifetime(d)
_fixLifetime(bridgedBack)
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.ImmutableDictionaryIsCopied") {
let nsd: NSDictionary = CustomImmutableNSDictionary(_privateInit: ())
CustomImmutableNSDictionary.timesCopyWithZoneWasCalled = 0
CustomImmutableNSDictionary.timesObjectForKeyWasCalled = 0
CustomImmutableNSDictionary.timesKeyEnumeratorWasCalled = 0
CustomImmutableNSDictionary.timesCountWasCalled = 0
TestBridgedValueTy.bridgeOperations = 0
let d: [TestBridgedKeyTy : TestBridgedValueTy] =
convertNSDictionaryToDictionary(nsd)
expectEqual(0, CustomImmutableNSDictionary.timesCopyWithZoneWasCalled)
expectEqual(3, CustomImmutableNSDictionary.timesObjectForKeyWasCalled)
expectEqual(1, CustomImmutableNSDictionary.timesKeyEnumeratorWasCalled)
expectNotEqual(0, CustomImmutableNSDictionary.timesCountWasCalled)
expectEqual(3, TestBridgedValueTy.bridgeOperations)
let bridgedBack: NSDictionary = convertDictionaryToNSDictionary(d)
expectNotEqual(
unsafeBitCast(nsd, to: Int.self),
unsafeBitCast(bridgedBack, to: Int.self))
_fixLifetime(nsd)
_fixLifetime(d)
_fixLifetime(bridgedBack)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.IndexForKey") {
let d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
// Find an existing key.
do {
var kv = d[d.index(forKey: TestObjCKeyTy(10))!]
assert(kv.0 == TestObjCKeyTy(10))
assert((kv.1 as! TestObjCValueTy).value == 1010)
kv = d[d.index(forKey: TestObjCKeyTy(20))!]
assert(kv.0 == TestObjCKeyTy(20))
assert((kv.1 as! TestObjCValueTy).value == 1020)
kv = d[d.index(forKey: TestObjCKeyTy(30))!]
assert(kv.0 == TestObjCKeyTy(30))
assert((kv.1 as! TestObjCValueTy).value == 1030)
}
// Try to find a key that does not exist.
assert(d.index(forKey: TestObjCKeyTy(40)) == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.IndexForKey") {
let d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
// Find an existing key.
do {
var kv = d[d.index(forKey: TestBridgedKeyTy(10))!]
assert(kv.0 == TestBridgedKeyTy(10))
assert(kv.1.value == 1010)
kv = d[d.index(forKey: TestBridgedKeyTy(20))!]
assert(kv.0 == TestBridgedKeyTy(20))
assert(kv.1.value == 1020)
kv = d[d.index(forKey: TestBridgedKeyTy(30))!]
assert(kv.0 == TestBridgedKeyTy(30))
assert(kv.1.value == 1030)
}
// Try to find a key that does not exist.
assert(d.index(forKey: TestBridgedKeyTy(40)) == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.SubscriptWithIndex") {
let d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let startIndex = d.startIndex
let endIndex = d.endIndex
assert(startIndex != endIndex)
assert(startIndex < endIndex)
assert(startIndex <= endIndex)
assert(!(startIndex >= endIndex))
assert(!(startIndex > endIndex))
assert(identity1 == d._rawIdentifier())
var pairs = Array<(Int, Int)>()
for i in d.indices {
let (key, value) = d[i]
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs += [kv]
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
assert(identity1 == d._rawIdentifier())
// Keep indexes alive during the calls above.
_fixLifetime(startIndex)
_fixLifetime(endIndex)
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.SubscriptWithIndex") {
let d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let startIndex = d.startIndex
let endIndex = d.endIndex
assert(startIndex != endIndex)
assert(startIndex < endIndex)
assert(startIndex <= endIndex)
assert(!(startIndex >= endIndex))
assert(!(startIndex > endIndex))
assert(identity1 == d._rawIdentifier())
var pairs = Array<(Int, Int)>()
for i in d.indices {
let (key, value) = d[i]
let kv = (key.value, value.value)
pairs += [kv]
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
assert(identity1 == d._rawIdentifier())
// Keep indexes alive during the calls above.
_fixLifetime(startIndex)
_fixLifetime(endIndex)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.SubscriptWithIndex_Empty") {
let d = getBridgedVerbatimDictionary([:])
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let startIndex = d.startIndex
let endIndex = d.endIndex
assert(startIndex == endIndex)
assert(!(startIndex < endIndex))
assert(startIndex <= endIndex)
assert(startIndex >= endIndex)
assert(!(startIndex > endIndex))
assert(identity1 == d._rawIdentifier())
// Keep indexes alive during the calls above.
_fixLifetime(startIndex)
_fixLifetime(endIndex)
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.SubscriptWithIndex_Empty") {
let d = getBridgedNonverbatimDictionary([:])
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let startIndex = d.startIndex
let endIndex = d.endIndex
assert(startIndex == endIndex)
assert(!(startIndex < endIndex))
assert(startIndex <= endIndex)
assert(startIndex >= endIndex)
assert(!(startIndex > endIndex))
assert(identity1 == d._rawIdentifier())
// Keep indexes alive during the calls above.
_fixLifetime(startIndex)
_fixLifetime(endIndex)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.SubscriptWithKey") {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
// Read existing key-value pairs.
var v = d[TestObjCKeyTy(10)] as! TestObjCValueTy
assert(v.value == 1010)
v = d[TestObjCKeyTy(20)] as! TestObjCValueTy
assert(v.value == 1020)
v = d[TestObjCKeyTy(30)] as! TestObjCValueTy
assert(v.value == 1030)
assert(identity1 == d._rawIdentifier())
// Insert a new key-value pair.
d[TestObjCKeyTy(40)] = TestObjCValueTy(2040)
let identity2 = d._rawIdentifier()
assert(identity1 != identity2)
assert(isNativeDictionary(d))
assert(d.count == 4)
v = d[TestObjCKeyTy(10)] as! TestObjCValueTy
assert(v.value == 1010)
v = d[TestObjCKeyTy(20)] as! TestObjCValueTy
assert(v.value == 1020)
v = d[TestObjCKeyTy(30)] as! TestObjCValueTy
assert(v.value == 1030)
v = d[TestObjCKeyTy(40)] as! TestObjCValueTy
assert(v.value == 2040)
// Overwrite value in existing binding.
d[TestObjCKeyTy(10)] = TestObjCValueTy(2010)
assert(identity2 == d._rawIdentifier())
assert(isNativeDictionary(d))
assert(d.count == 4)
v = d[TestObjCKeyTy(10)] as! TestObjCValueTy
assert(v.value == 2010)
v = d[TestObjCKeyTy(20)] as! TestObjCValueTy
assert(v.value == 1020)
v = d[TestObjCKeyTy(30)] as! TestObjCValueTy
assert(v.value == 1030)
v = d[TestObjCKeyTy(40)] as! TestObjCValueTy
assert(v.value == 2040)
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.SubscriptWithKey") {
var d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
// Read existing key-value pairs.
var v = d[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = d[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = d[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
assert(identity1 == d._rawIdentifier())
// Insert a new key-value pair.
d[TestBridgedKeyTy(40)] = TestBridgedValueTy(2040)
let identity2 = d._rawIdentifier()
// Storage identity may or may not change depending on allocation behavior.
// (d is eagerly bridged to a regular uniquely referenced native Dictionary.)
//assert(identity1 != identity2)
assert(isNativeDictionary(d))
assert(d.count == 4)
v = d[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = d[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = d[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
v = d[TestBridgedKeyTy(40)]
assert(v!.value == 2040)
// Overwrite value in existing binding.
d[TestBridgedKeyTy(10)] = TestBridgedValueTy(2010)
assert(identity2 == d._rawIdentifier())
assert(isNativeDictionary(d))
assert(d.count == 4)
v = d[TestBridgedKeyTy(10)]
assert(v!.value == 2010)
v = d[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = d[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
v = d[TestBridgedKeyTy(40)]
assert(v!.value == 2040)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.UpdateValueForKey") {
// Insert a new key-value pair.
do {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let oldValue: AnyObject? =
d.updateValue(TestObjCValueTy(2040), forKey: TestObjCKeyTy(40))
assert(oldValue == nil)
let identity2 = d._rawIdentifier()
assert(identity1 != identity2)
assert(isNativeDictionary(d))
assert(d.count == 4)
assert((d[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
assert((d[TestObjCKeyTy(20)] as! TestObjCValueTy).value == 1020)
assert((d[TestObjCKeyTy(30)] as! TestObjCValueTy).value == 1030)
assert((d[TestObjCKeyTy(40)] as! TestObjCValueTy).value == 2040)
}
// Overwrite a value in existing binding.
do {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let oldValue: AnyObject? =
d.updateValue(TestObjCValueTy(2010), forKey: TestObjCKeyTy(10))
assert((oldValue as! TestObjCValueTy).value == 1010)
let identity2 = d._rawIdentifier()
assert(identity1 != identity2)
assert(isNativeDictionary(d))
assert(d.count == 3)
assert((d[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 2010)
assert((d[TestObjCKeyTy(20)] as! TestObjCValueTy).value == 1020)
assert((d[TestObjCKeyTy(30)] as! TestObjCValueTy).value == 1030)
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.UpdateValueForKey") {
// Insert a new key-value pair.
do {
var d = getBridgedNonverbatimDictionary()
// let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let oldValue =
d.updateValue(TestBridgedValueTy(2040), forKey: TestBridgedKeyTy(40))
assert(oldValue == nil)
// let identity2 = d._rawIdentifier()
// Storage identity may or may not change depending on allocation behavior.
// (d is eagerly bridged to a regular uniquely referenced native Dictionary.)
//assert(identity1 != identity2)
assert(isNativeDictionary(d))
assert(d.count == 4)
assert(d[TestBridgedKeyTy(10)]!.value == 1010)
assert(d[TestBridgedKeyTy(20)]!.value == 1020)
assert(d[TestBridgedKeyTy(30)]!.value == 1030)
assert(d[TestBridgedKeyTy(40)]!.value == 2040)
}
// Overwrite a value in existing binding.
do {
var d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let oldValue =
d.updateValue(TestBridgedValueTy(2010), forKey: TestBridgedKeyTy(10))!
assert(oldValue.value == 1010)
let identity2 = d._rawIdentifier()
assert(identity1 == identity2)
assert(isNativeDictionary(d))
assert(d.count == 3)
assert(d[TestBridgedKeyTy(10)]!.value == 2010)
assert(d[TestBridgedKeyTy(20)]!.value == 1020)
assert(d[TestBridgedKeyTy(30)]!.value == 1030)
}
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.RemoveAt") {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let foundIndex1 = d.index(forKey: TestObjCKeyTy(10))!
assert(d[foundIndex1].0 == TestObjCKeyTy(10))
assert((d[foundIndex1].1 as! TestObjCValueTy).value == 1010)
assert(identity1 == d._rawIdentifier())
let removedElement = d.remove(at: foundIndex1)
assert(identity1 != d._rawIdentifier())
assert(isNativeDictionary(d))
assert(removedElement.0 == TestObjCKeyTy(10))
assert((removedElement.1 as! TestObjCValueTy).value == 1010)
assert(d.count == 2)
assert(d.index(forKey: TestObjCKeyTy(10)) == nil)
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAt")
.code {
var d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let foundIndex1 = d.index(forKey: TestBridgedKeyTy(10))!
assert(d[foundIndex1].0 == TestBridgedKeyTy(10))
assert(d[foundIndex1].1.value == 1010)
assert(identity1 == d._rawIdentifier())
let removedElement = d.remove(at: foundIndex1)
assert(identity1 == d._rawIdentifier())
assert(isNativeDictionary(d))
assert(removedElement.0 == TestObjCKeyTy(10) as TestBridgedKeyTy)
assert(removedElement.1.value == 1010)
assert(d.count == 2)
assert(d.index(forKey: TestBridgedKeyTy(10)) == nil)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.RemoveValueForKey") {
do {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
var deleted: AnyObject? = d.removeValue(forKey: TestObjCKeyTy(0))
assert(deleted == nil)
assert(identity1 == d._rawIdentifier())
assert(isCocoaDictionary(d))
deleted = d.removeValue(forKey: TestObjCKeyTy(10))
assert((deleted as! TestObjCValueTy).value == 1010)
let identity2 = d._rawIdentifier()
assert(identity1 != identity2)
assert(isNativeDictionary(d))
assert(d.count == 2)
assert(d[TestObjCKeyTy(10)] == nil)
assert((d[TestObjCKeyTy(20)] as! TestObjCValueTy).value == 1020)
assert((d[TestObjCKeyTy(30)] as! TestObjCValueTy).value == 1030)
assert(identity2 == d._rawIdentifier())
}
do {
var d1 = getBridgedVerbatimDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(isCocoaDictionary(d1))
assert(isCocoaDictionary(d2))
var deleted: AnyObject? = d2.removeValue(forKey: TestObjCKeyTy(0))
assert(deleted == nil)
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
assert(isCocoaDictionary(d1))
assert(isCocoaDictionary(d2))
deleted = d2.removeValue(forKey: TestObjCKeyTy(10))
assert((deleted as! TestObjCValueTy).value == 1010)
let identity2 = d2._rawIdentifier()
assert(identity1 != identity2)
assert(isCocoaDictionary(d1))
assert(isNativeDictionary(d2))
assert(d2.count == 2)
assert((d1[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
assert((d1[TestObjCKeyTy(20)] as! TestObjCValueTy).value == 1020)
assert((d1[TestObjCKeyTy(30)] as! TestObjCValueTy).value == 1030)
assert(identity1 == d1._rawIdentifier())
assert(d2[TestObjCKeyTy(10)] == nil)
assert((d2[TestObjCKeyTy(20)] as! TestObjCValueTy).value == 1020)
assert((d2[TestObjCKeyTy(30)] as! TestObjCValueTy).value == 1030)
assert(identity2 == d2._rawIdentifier())
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveValueForKey")
.code {
do {
var d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
var deleted = d.removeValue(forKey: TestBridgedKeyTy(0))
assert(deleted == nil)
assert(identity1 == d._rawIdentifier())
assert(isNativeDictionary(d))
deleted = d.removeValue(forKey: TestBridgedKeyTy(10))
assert(deleted!.value == 1010)
let identity2 = d._rawIdentifier()
assert(identity1 == identity2)
assert(isNativeDictionary(d))
assert(d.count == 2)
assert(d[TestBridgedKeyTy(10)] == nil)
assert(d[TestBridgedKeyTy(20)]!.value == 1020)
assert(d[TestBridgedKeyTy(30)]!.value == 1030)
assert(identity2 == d._rawIdentifier())
}
do {
var d1 = getBridgedNonverbatimDictionary()
let identity1 = d1._rawIdentifier()
var d2 = d1
assert(isNativeDictionary(d1))
assert(isNativeDictionary(d2))
var deleted = d2.removeValue(forKey: TestBridgedKeyTy(0))
assert(deleted == nil)
assert(identity1 == d1._rawIdentifier())
assert(identity1 == d2._rawIdentifier())
assert(isNativeDictionary(d1))
assert(isNativeDictionary(d2))
deleted = d2.removeValue(forKey: TestBridgedKeyTy(10))
assert(deleted!.value == 1010)
let identity2 = d2._rawIdentifier()
assert(identity1 != identity2)
assert(isNativeDictionary(d1))
assert(isNativeDictionary(d2))
assert(d2.count == 2)
assert(d1[TestBridgedKeyTy(10)]!.value == 1010)
assert(d1[TestBridgedKeyTy(20)]!.value == 1020)
assert(d1[TestBridgedKeyTy(30)]!.value == 1030)
assert(identity1 == d1._rawIdentifier())
assert(d2[TestBridgedKeyTy(10)] == nil)
assert(d2[TestBridgedKeyTy(20)]!.value == 1020)
assert(d2[TestBridgedKeyTy(30)]!.value == 1030)
assert(identity2 == d2._rawIdentifier())
}
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.RemoveAll") {
do {
var d = getBridgedVerbatimDictionary([:])
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
assert(d.count == 0)
d.removeAll()
assert(identity1 == d._rawIdentifier())
assert(d.count == 0)
}
do {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let originalCapacity = d.count
assert(d.count == 3)
assert((d[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
d.removeAll()
assert(identity1 != d._rawIdentifier())
assert(d.capacity < originalCapacity)
assert(d.count == 0)
assert(d[TestObjCKeyTy(10)] == nil)
}
do {
var d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
let originalCapacity = d.count
assert(d.count == 3)
assert((d[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
d.removeAll(keepingCapacity: true)
assert(identity1 != d._rawIdentifier())
assert(d.capacity >= originalCapacity)
assert(d.count == 0)
assert(d[TestObjCKeyTy(10)] == nil)
}
do {
var d1 = getBridgedVerbatimDictionary()
let identity1 = d1._rawIdentifier()
assert(isCocoaDictionary(d1))
let originalCapacity = d1.count
assert(d1.count == 3)
assert((d1[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
var d2 = d1
d2.removeAll()
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert((d1[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
assert(d2.capacity < originalCapacity)
assert(d2.count == 0)
assert(d2[TestObjCKeyTy(10)] == nil)
}
do {
var d1 = getBridgedVerbatimDictionary()
let identity1 = d1._rawIdentifier()
assert(isCocoaDictionary(d1))
let originalCapacity = d1.count
assert(d1.count == 3)
assert((d1[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
var d2 = d1
d2.removeAll(keepingCapacity: true)
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert((d1[TestObjCKeyTy(10)] as! TestObjCValueTy).value == 1010)
assert(d2.capacity >= originalCapacity)
assert(d2.count == 0)
assert(d2[TestObjCKeyTy(10)] == nil)
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAll") {
do {
var d = getBridgedNonverbatimDictionary([:])
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
assert(d.count == 0)
d.removeAll()
assert(identity1 == d._rawIdentifier())
assert(d.count == 0)
}
do {
var d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let originalCapacity = d.count
assert(d.count == 3)
assert(d[TestBridgedKeyTy(10)]!.value == 1010)
d.removeAll()
assert(identity1 != d._rawIdentifier())
assert(d.capacity < originalCapacity)
assert(d.count == 0)
assert(d[TestBridgedKeyTy(10)] == nil)
}
do {
var d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
let originalCapacity = d.count
assert(d.count == 3)
assert(d[TestBridgedKeyTy(10)]!.value == 1010)
d.removeAll(keepingCapacity: true)
assert(identity1 == d._rawIdentifier())
assert(d.capacity >= originalCapacity)
assert(d.count == 0)
assert(d[TestBridgedKeyTy(10)] == nil)
}
do {
let d1 = getBridgedNonverbatimDictionary()
let identity1 = d1._rawIdentifier()
assert(isNativeDictionary(d1))
let originalCapacity = d1.count
assert(d1.count == 3)
assert(d1[TestBridgedKeyTy(10)]!.value == 1010)
var d2 = d1
d2.removeAll()
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert(d1[TestBridgedKeyTy(10)]!.value == 1010)
assert(d2.capacity < originalCapacity)
assert(d2.count == 0)
assert(d2[TestBridgedKeyTy(10)] == nil)
}
do {
let d1 = getBridgedNonverbatimDictionary()
let identity1 = d1._rawIdentifier()
assert(isNativeDictionary(d1))
let originalCapacity = d1.count
assert(d1.count == 3)
assert(d1[TestBridgedKeyTy(10)]!.value == 1010)
var d2 = d1
d2.removeAll(keepingCapacity: true)
let identity2 = d2._rawIdentifier()
assert(identity1 == d1._rawIdentifier())
assert(identity2 != identity1)
assert(d1.count == 3)
assert(d1[TestBridgedKeyTy(10)]!.value == 1010)
assert(d2.capacity >= originalCapacity)
assert(d2.count == 0)
assert(d2[TestBridgedKeyTy(10)] == nil)
}
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.Count") {
let d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
assert(d.count == 3)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.Count") {
let d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
assert(d.count == 3)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.Generate") {
let d = getBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.Generate") {
let d = getBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = (key.value, value.value)
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.Generate_Empty") {
let d = getBridgedVerbatimDictionary([:])
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
var iter = d.makeIterator()
// Cannot write code below because of
// <rdar://problem/16811736> Optional tuples are broken as optionals regarding == comparison
// assert(iter.next() == .none)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_Empty") {
let d = getBridgedNonverbatimDictionary([:])
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
var iter = d.makeIterator()
// Cannot write code below because of
// <rdar://problem/16811736> Optional tuples are broken as optionals regarding == comparison
// assert(iter.next() == .none)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.Generate_Huge") {
let d = getHugeBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
var expectedPairs = Array<(Int, Int)>()
for i in 1...32 {
expectedPairs += [(i, 1000 + i)]
}
assert(equalsUnordered(pairs, expectedPairs))
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_Huge") {
let d = getHugeBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = (key.value, value.value)
pairs.append(kv)
}
var expectedPairs = Array<(Int, Int)>()
for i in 1...32 {
expectedPairs += [(i, 1000 + i)]
}
assert(equalsUnordered(pairs, expectedPairs))
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.Generate_ParallelArray") {
autoreleasepoolIfUnoptimizedReturnAutoreleased {
// Add an autorelease pool because ParallelArrayDictionary autoreleases
// values in objectForKey.
let d = getParallelArrayBridgedVerbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isCocoaDictionary(d))
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
let expectedPairs = [ (10, 1111), (20, 1111), (30, 1111), (40, 1111) ]
assert(equalsUnordered(pairs, expectedPairs))
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_ParallelArray") {
autoreleasepoolIfUnoptimizedReturnAutoreleased {
// Add an autorelease pool because ParallelArrayDictionary autoreleases
// values in objectForKey.
let d = getParallelArrayBridgedNonverbatimDictionary()
let identity1 = d._rawIdentifier()
assert(isNativeDictionary(d))
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = (key.value, value.value)
pairs.append(kv)
}
let expectedPairs = [ (10, 1111), (20, 1111), (30, 1111), (40, 1111) ]
assert(equalsUnordered(pairs, expectedPairs))
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(identity1 == d._rawIdentifier())
}
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.EqualityTest_Empty") {
let d1 = getBridgedVerbatimEquatableDictionary([:])
let identity1 = d1._rawIdentifier()
assert(isCocoaDictionary(d1))
var d2 = getBridgedVerbatimEquatableDictionary([:])
var identity2 = d2._rawIdentifier()
assert(isCocoaDictionary(d2))
// We can't check that `identity1 != identity2` because Foundation might be
// returning the same singleton NSDictionary for empty dictionaries.
assert(d1 == d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
d2[TestObjCKeyTy(10)] = TestObjCEquatableValueTy(2010)
assert(isNativeDictionary(d2))
assert(identity2 != d2._rawIdentifier())
identity2 = d2._rawIdentifier()
assert(d1 != d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.EqualityTest_Empty") {
let d1 = getBridgedNonverbatimEquatableDictionary([:])
let identity1 = d1._rawIdentifier()
assert(isNativeDictionary(d1))
var d2 = getBridgedNonverbatimEquatableDictionary([:])
let identity2 = d2._rawIdentifier()
assert(isNativeDictionary(d2))
assert(identity1 != identity2)
assert(d1 == d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
d2[TestBridgedKeyTy(10)] = TestBridgedEquatableValueTy(2010)
assert(isNativeDictionary(d2))
assert(identity2 == d2._rawIdentifier())
assert(d1 != d2)
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.EqualityTest_Small") {
func helper(_ nd1: Dictionary<Int, Int>, _ nd2: Dictionary<Int, Int>, _ expectedEq: Bool) {
let d1 = getBridgedVerbatimEquatableDictionary(nd1)
let identity1 = d1._rawIdentifier()
assert(isCocoaDictionary(d1))
var d2 = getBridgedVerbatimEquatableDictionary(nd2)
var identity2 = d2._rawIdentifier()
assert(isCocoaDictionary(d2))
do {
let eq1 = (d1 == d2)
assert(eq1 == expectedEq)
let eq2 = (d2 == d1)
assert(eq2 == expectedEq)
let neq1 = (d1 != d2)
assert(neq1 != expectedEq)
let neq2 = (d2 != d1)
assert(neq2 != expectedEq)
}
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
d2[TestObjCKeyTy(1111)] = TestObjCEquatableValueTy(1111)
d2[TestObjCKeyTy(1111)] = nil
assert(isNativeDictionary(d2))
assert(identity2 != d2._rawIdentifier())
identity2 = d2._rawIdentifier()
do {
let eq1 = (d1 == d2)
assert(eq1 == expectedEq)
let eq2 = (d2 == d1)
assert(eq2 == expectedEq)
let neq1 = (d1 != d2)
assert(neq1 != expectedEq)
let neq2 = (d2 != d1)
assert(neq2 != expectedEq)
}
assert(identity1 == d1._rawIdentifier())
assert(identity2 == d2._rawIdentifier())
}
helper([:], [:], true)
helper([10: 1010],
[10: 1010],
true)
helper([10: 1010, 20: 1020],
[10: 1010, 20: 1020],
true)
helper([10: 1010, 20: 1020, 30: 1030],
[10: 1010, 20: 1020, 30: 1030],
true)
helper([10: 1010, 20: 1020, 30: 1030],
[10: 1010, 20: 1020, 1111: 1030],
false)
helper([10: 1010, 20: 1020, 30: 1030],
[10: 1010, 20: 1020, 30: 1111],
false)
helper([10: 1010, 20: 1020, 30: 1030],
[10: 1010, 20: 1020],
false)
helper([10: 1010, 20: 1020, 30: 1030],
[10: 1010],
false)
helper([10: 1010, 20: 1020, 30: 1030],
[:],
false)
helper([10: 1010, 20: 1020, 30: 1030],
[10: 1010, 20: 1020, 30: 1030, 40: 1040],
false)
}
DictionaryTestSuite.test("BridgedFromObjC.Verbatim.ArrayOfDictionaries") {
let nsa = NSMutableArray()
for i in 0..<3 {
nsa.add(
getAsNSDictionary([10: 1010 + i, 20: 1020 + i, 30: 1030 + i]))
}
var a = nsa as [AnyObject] as! [Dictionary<NSObject, AnyObject>]
for i in 0..<3 {
let d = a[i]
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
let expectedPairs = [ (10, 1010 + i), (20, 1020 + i), (30, 1030 + i) ]
assert(equalsUnordered(pairs, expectedPairs))
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.ArrayOfDictionaries") {
let nsa = NSMutableArray()
for i in 0..<3 {
nsa.add(
getAsNSDictionary([10: 1010 + i, 20: 1020 + i, 30: 1030 + i]))
}
var a = nsa as [AnyObject] as! [Dictionary<TestBridgedKeyTy, TestBridgedValueTy>]
for i in 0..<3 {
let d = a[i]
var iter = d.makeIterator()
var pairs = Array<(Int, Int)>()
while let (key, value) = iter.next() {
let kv = (key.value, value.value)
pairs.append(kv)
}
let expectedPairs = [ (10, 1010 + i), (20, 1020 + i), (30, 1030 + i) ]
assert(equalsUnordered(pairs, expectedPairs))
}
}
DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.StringEqualityMismatch") {
// NSString's isEqual(_:) implementation is stricter than Swift's String, so
// Dictionary values bridged over from Objective-C may have duplicate keys.
// rdar://problem/35995647
let cafe1 = "Cafe\u{301}" as NSString
let cafe2 = "Café" as NSString
let nsd = NSMutableDictionary()
nsd.setObject(42, forKey: cafe1)
nsd.setObject(23, forKey: cafe2)
expectEqual(2, nsd.count)
expectTrue((42 as NSNumber).isEqual(nsd.object(forKey: cafe1)))
expectTrue((23 as NSNumber).isEqual(nsd.object(forKey: cafe2)))
let d = convertNSDictionaryToDictionary(nsd) as [String: Int]
expectEqual(1, d.count)
expectEqual(d["Cafe\u{301}"], d["Café"])
let v = d["Café"]
expectTrue(v == 42 || v == 23)
}
//===---
// Dictionary -> NSDictionary bridging tests.
//
// Key and Value are bridged verbatim.
//===---
DictionaryTestSuite.test("BridgedToObjC.Verbatim.Count") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
assert(d.count == 3)
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.ObjectForKey") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
var v: AnyObject? = d.object(forKey: TestObjCKeyTy(10)).map { $0 as AnyObject }
expectEqual(1010, (v as! TestObjCValueTy).value)
let idValue10 = unsafeBitCast(v, to: UInt.self)
v = d.object(forKey: TestObjCKeyTy(20)).map { $0 as AnyObject }
expectEqual(1020, (v as! TestObjCValueTy).value)
let idValue20 = unsafeBitCast(v, to: UInt.self)
v = d.object(forKey: TestObjCKeyTy(30)).map { $0 as AnyObject }
expectEqual(1030, (v as! TestObjCValueTy).value)
let idValue30 = unsafeBitCast(v, to: UInt.self)
expectNil(d.object(forKey: TestObjCKeyTy(40)))
// NSDictionary can store mixed key types. Swift's Dictionary is typed, but
// when bridged to NSDictionary, it should behave like one, and allow queries
// for mismatched key types.
expectNil(d.object(forKey: TestObjCInvalidKeyTy()))
for _ in 0..<3 {
expectEqual(idValue10, unsafeBitCast(
d.object(forKey: TestObjCKeyTy(10)).map { $0 as AnyObject }, to: UInt.self))
expectEqual(idValue20, unsafeBitCast(
d.object(forKey: TestObjCKeyTy(20)).map { $0 as AnyObject }, to: UInt.self))
expectEqual(idValue30, unsafeBitCast(
d.object(forKey: TestObjCKeyTy(30)).map { $0 as AnyObject }, to: UInt.self))
}
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.NextObject") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
var capturedIdentityPairs = Array<(UInt, UInt)>()
for _ in 0..<3 {
let enumerator = d.keyEnumerator()
var dataPairs = Array<(Int, Int)>()
var identityPairs = Array<(UInt, UInt)>()
while let key = enumerator.nextObject() {
let keyObj = key as AnyObject
let value: AnyObject = d.object(forKey: keyObj)! as AnyObject
let dataPair =
((keyObj as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
dataPairs.append(dataPair)
let identityPair =
(unsafeBitCast(keyObj, to: UInt.self),
unsafeBitCast(value, to: UInt.self))
identityPairs.append(identityPair)
}
expectTrue(
equalsUnordered(dataPairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
if capturedIdentityPairs.isEmpty {
capturedIdentityPairs = identityPairs
} else {
expectTrue(equalsUnordered(capturedIdentityPairs, identityPairs))
}
assert(enumerator.nextObject() == nil)
assert(enumerator.nextObject() == nil)
assert(enumerator.nextObject() == nil)
}
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.NextObject_Empty") {
let d = getBridgedEmptyNSDictionary()
let enumerator = d.keyEnumerator()
assert(enumerator.nextObject() == nil)
assert(enumerator.nextObject() == nil)
assert(enumerator.nextObject() == nil)
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.FastEnumeration.UseFromSwift") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
checkDictionaryFastEnumerationFromSwift(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d.keyEnumerator() },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.FastEnumeration.UseFromObjC") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
checkDictionaryFastEnumerationFromObjC(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d.keyEnumerator() },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.FastEnumeration_Empty") {
let d = getBridgedEmptyNSDictionary()
checkDictionaryFastEnumerationFromSwift(
[], d, { d.keyEnumerator() },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
checkDictionaryFastEnumerationFromObjC(
[], d, { d.keyEnumerator() },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromSwift") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
checkDictionaryFastEnumerationFromSwift(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromObjC") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
checkDictionaryFastEnumerationFromObjC(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration_Empty") {
let d = getBridgedEmptyNSDictionary()
checkDictionaryFastEnumerationFromSwift(
[], d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
checkDictionaryFastEnumerationFromObjC(
[], d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
}
/// Check for buffer overruns/underruns in Swift's
/// `-[NSDictionary getObjects:andKeys:count:]` implementations.
func checkGetObjectsAndKeys(
_ dictionary: NSDictionary,
count: Int,
file: String = #file,
line: UInt = #line) {
let canary = NSObject()
let storageSize = 2 * max(count, dictionary.count) + 2
// Create buffers for storing keys and values at +0 refcounts,
// then call getObjects:andKeys:count: via a shim in
// StdlibUnittestFoundationExtras.
typealias UnmanagedPointer = UnsafeMutablePointer<Unmanaged<AnyObject>>
let keys = UnmanagedPointer.allocate(capacity: storageSize)
keys.initialize(repeating: Unmanaged.passUnretained(canary), count: storageSize)
let values = UnmanagedPointer.allocate(capacity: storageSize)
values.initialize(repeating: Unmanaged.passUnretained(canary), count: storageSize)
keys.withMemoryRebound(to: AnyObject.self, capacity: storageSize) { k in
values.withMemoryRebound(to: AnyObject.self, capacity: storageSize) { v in
dictionary.available_getObjects(
AutoreleasingUnsafeMutablePointer(v),
andKeys: AutoreleasingUnsafeMutablePointer(k),
count: count)
}
}
// Check results.
for i in 0 ..< storageSize {
let key = keys[i].takeUnretainedValue()
let value = values[i].takeUnretainedValue()
if i < min(count, dictionary.count) {
expectTrue(
key !== canary,
"""
Buffer underrun at offset \(i) with count \(count):
keys[\(i)] was left unchanged
""",
file: file, line: line)
expectTrue(
value !== canary,
"""
Buffer underrun at offset \(i) with count \(count):
values[\(i)] was left unchanged
""",
file: file, line: line)
if key !== canary, value !== canary {
autoreleasepoolIfUnoptimizedReturnAutoreleased {
// We need an autorelease pool because objectForKey returns
// autoreleased values.
expectTrue(
value === dictionary.object(forKey: key) as AnyObject,
"""
Inconsistency at offset \(i) with count \(count):
values[\(i)] does not match value for keys[\(i)]
""",
file: file, line: line)
}
}
} else {
expectTrue(
key === canary,
"""
Buffer overrun at offset \(i) with count \(count):
keys[\(i)] was overwritten with value \(key)
""",
file: file, line: line)
expectTrue(
value === canary,
"""
Buffer overrun at offset \(i) with count \(count):
values[\(i)] was overwritten with value \(key)
""",
file: file, line: line)
}
}
keys.deinitialize(count: storageSize) // noop
keys.deallocate()
values.deinitialize(count: storageSize) // noop
values.deallocate()
withExtendedLifetime(canary) {}
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.getObjects:andKeys:count:") {
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
for count in 0 ..< d.count + 2 {
checkGetObjectsAndKeys(d, count: count)
}
}
DictionaryTestSuite.test("BridgedToObjC.Verbatim.getObjects:andKeys:count:/InvalidCount") {
expectCrashLater()
let d = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
checkGetObjectsAndKeys(d, count: -1)
}
//===---
// Dictionary -> NSDictionary bridging tests.
//
// Key type and value type are bridged non-verbatim.
//===---
DictionaryTestSuite.test("BridgedToObjC.KeyValue_ValueTypesCustomBridged") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
let enumerator = d.keyEnumerator()
var pairs = Array<(Int, Int)>()
while let key = enumerator.nextObject() {
let value: AnyObject = d.object(forKey: key)! as AnyObject
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Custom.KeyEnumerator.FastEnumeration.UseFromSwift") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
checkDictionaryFastEnumerationFromSwift(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d.keyEnumerator() },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Custom.KeyEnumerator.FastEnumeration.UseFromSwift.Partial") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged(
numElements: 9)
checkDictionaryEnumeratorPartialFastEnumerationFromSwift(
[ (10, 1010), (20, 1020), (30, 1030), (40, 1040), (50, 1050),
(60, 1060), (70, 1070), (80, 1080), (90, 1090) ],
d, maxFastEnumerationItems: 5,
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (9, 9))
}
DictionaryTestSuite.test("BridgedToObjC.Custom.KeyEnumerator.FastEnumeration.UseFromObjC") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
checkDictionaryFastEnumerationFromObjC(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d.keyEnumerator() },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromSwift") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
checkDictionaryFastEnumerationFromSwift(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromObjC") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
checkDictionaryFastEnumerationFromObjC(
[ (10, 1010), (20, 1020), (30, 1030) ],
d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("BridgedToObjC.Custom.FastEnumeration_Empty") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged(
numElements: 0)
checkDictionaryFastEnumerationFromSwift(
[], d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
checkDictionaryFastEnumerationFromObjC(
[], d, { d },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
}
DictionaryTestSuite.test("BridgedToObjC.Custom.getObjects:andKeys:count:") {
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
for count in 0 ..< d.count + 2 {
checkGetObjectsAndKeys(d, count: count)
}
}
DictionaryTestSuite.test("BridgedToObjC.Custom.getObjects:andKeys:count:/InvalidCount") {
expectCrashLater()
let d = getBridgedNSDictionaryOfKeyValue_ValueTypesCustomBridged()
checkGetObjectsAndKeys(d, count: -1)
}
func getBridgedNSDictionaryOfKey_ValueTypeCustomBridged() -> NSDictionary {
assert(!_isBridgedVerbatimToObjectiveC(TestBridgedKeyTy.self))
assert(_isBridgedVerbatimToObjectiveC(TestObjCValueTy.self))
var d = Dictionary<TestBridgedKeyTy, TestObjCValueTy>()
d[TestBridgedKeyTy(10)] = TestObjCValueTy(1010)
d[TestBridgedKeyTy(20)] = TestObjCValueTy(1020)
d[TestBridgedKeyTy(30)] = TestObjCValueTy(1030)
let bridged = convertDictionaryToNSDictionary(d)
assert(isNativeNSDictionary(bridged))
return bridged
}
DictionaryTestSuite.test("BridgedToObjC.Key_ValueTypeCustomBridged") {
let d = getBridgedNSDictionaryOfKey_ValueTypeCustomBridged()
let enumerator = d.keyEnumerator()
var pairs = Array<(Int, Int)>()
while let key = enumerator.nextObject() {
let value: AnyObject = d.object(forKey: key)! as AnyObject
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
func getBridgedNSDictionaryOfValue_ValueTypeCustomBridged() -> NSDictionary {
assert(_isBridgedVerbatimToObjectiveC(TestObjCKeyTy.self))
assert(!_isBridgedVerbatimToObjectiveC(TestBridgedValueTy.self))
var d = Dictionary<TestObjCKeyTy, TestBridgedValueTy>()
d[TestObjCKeyTy(10)] = TestBridgedValueTy(1010)
d[TestObjCKeyTy(20)] = TestBridgedValueTy(1020)
d[TestObjCKeyTy(30)] = TestBridgedValueTy(1030)
let bridged = convertDictionaryToNSDictionary(d)
assert(isNativeNSDictionary(bridged))
return bridged
}
DictionaryTestSuite.test("BridgedToObjC.Value_ValueTypeCustomBridged") {
let d = getBridgedNSDictionaryOfValue_ValueTypeCustomBridged()
let enumerator = d.keyEnumerator()
var pairs = Array<(Int, Int)>()
while let key = enumerator.nextObject() {
let value: AnyObject = d.object(forKey: key)! as AnyObject
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
expectAutoreleasedKeysAndValues(unopt: (3, 3))
}
//===---
// NSDictionary -> Dictionary -> NSDictionary bridging tests.
//===---
func getRoundtripBridgedNSDictionary() -> NSDictionary {
let keys = [ 10, 20, 30 ].map { TestObjCKeyTy($0) }
let values = [ 1010, 1020, 1030 ].map { TestObjCValueTy($0) }
let nsd = NSDictionary(objects: values, forKeys: keys)
let d: Dictionary<NSObject, AnyObject> = convertNSDictionaryToDictionary(nsd)
let bridgedBack = convertDictionaryToNSDictionary(d)
assert(isCocoaNSDictionary(bridgedBack))
// FIXME: this should be true.
//assert(unsafeBitCast(nsd, Int.self) == unsafeBitCast(bridgedBack, Int.self))
return bridgedBack
}
DictionaryTestSuite.test("BridgingRoundtrip") {
let d = getRoundtripBridgedNSDictionary()
let enumerator = d.keyEnumerator()
var pairs = Array<(key: Int, value: Int)>()
while let key = enumerator.nextObject() {
let value: AnyObject = d.object(forKey: key)! as AnyObject
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
expectEqualsUnordered([ (10, 1010), (20, 1020), (30, 1030) ], pairs)
}
//===---
// NSDictionary -> Dictionary implicit conversion.
//===---
DictionaryTestSuite.test("NSDictionaryToDictionaryConversion") {
let keys = [ 10, 20, 30 ].map { TestObjCKeyTy($0) }
let values = [ 1010, 1020, 1030 ].map { TestObjCValueTy($0) }
let nsd = NSDictionary(objects: values, forKeys: keys)
let d: Dictionary = nsd as Dictionary
var pairs = Array<(Int, Int)>()
for (key, value) in d {
let kv = ((key as! TestObjCKeyTy).value, (value as! TestObjCValueTy).value)
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
}
DictionaryTestSuite.test("DictionaryToNSDictionaryConversion") {
var d = Dictionary<TestObjCKeyTy, TestObjCValueTy>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
checkDictionaryFastEnumerationFromSwift(
[ (10, 1010), (20, 1020), (30, 1030) ],
d as NSDictionary, { d as NSDictionary },
{ ($0 as! TestObjCKeyTy).value },
{ ($0 as! TestObjCValueTy).value })
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
//===---
// Dictionary upcasts
//===---
DictionaryTestSuite.test("DictionaryUpcastEntryPoint") {
var d = Dictionary<TestObjCKeyTy, TestObjCValueTy>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
var dAsAnyObject: Dictionary<NSObject, AnyObject> = _dictionaryUpCast(d)
assert(dAsAnyObject.count == 3)
var v: AnyObject? = dAsAnyObject[TestObjCKeyTy(10)]
assert((v! as! TestObjCValueTy).value == 1010)
v = dAsAnyObject[TestObjCKeyTy(20)]
assert((v! as! TestObjCValueTy).value == 1020)
v = dAsAnyObject[TestObjCKeyTy(30)]
assert((v! as! TestObjCValueTy).value == 1030)
}
DictionaryTestSuite.test("DictionaryUpcast") {
var d = Dictionary<TestObjCKeyTy, TestObjCValueTy>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
var dAsAnyObject: Dictionary<NSObject, AnyObject> = d
assert(dAsAnyObject.count == 3)
var v: AnyObject? = dAsAnyObject[TestObjCKeyTy(10)]
assert((v! as! TestObjCValueTy).value == 1010)
v = dAsAnyObject[TestObjCKeyTy(20)]
assert((v! as! TestObjCValueTy).value == 1020)
v = dAsAnyObject[TestObjCKeyTy(30)]
assert((v! as! TestObjCValueTy).value == 1030)
}
DictionaryTestSuite.test("DictionaryUpcastBridgedEntryPoint") {
var d = Dictionary<TestBridgedKeyTy, TestBridgedValueTy>(minimumCapacity: 32)
d[TestBridgedKeyTy(10)] = TestBridgedValueTy(1010)
d[TestBridgedKeyTy(20)] = TestBridgedValueTy(1020)
d[TestBridgedKeyTy(30)] = TestBridgedValueTy(1030)
do {
var dOO: Dictionary<NSObject, AnyObject> = _dictionaryBridgeToObjectiveC(d)
assert(dOO.count == 3)
var v: AnyObject? = dOO[TestObjCKeyTy(10)]
assert((v! as! TestBridgedValueTy).value == 1010)
v = dOO[TestObjCKeyTy(20)]
assert((v! as! TestBridgedValueTy).value == 1020)
v = dOO[TestObjCKeyTy(30)]
assert((v! as! TestBridgedValueTy).value == 1030)
}
do {
var dOV: Dictionary<NSObject, TestBridgedValueTy>
= _dictionaryBridgeToObjectiveC(d)
assert(dOV.count == 3)
var v = dOV[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dOV[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dOV[TestObjCKeyTy(30)]
assert(v!.value == 1030)
}
do {
var dVO: Dictionary<TestBridgedKeyTy, AnyObject>
= _dictionaryBridgeToObjectiveC(d)
assert(dVO.count == 3)
var v: AnyObject? = dVO[TestBridgedKeyTy(10)]
assert((v! as! TestBridgedValueTy).value == 1010)
v = dVO[TestBridgedKeyTy(20)]
assert((v! as! TestBridgedValueTy).value == 1020)
v = dVO[TestBridgedKeyTy(30)]
assert((v! as! TestBridgedValueTy).value == 1030)
}
}
DictionaryTestSuite.test("DictionaryUpcastBridged") {
var d = Dictionary<TestBridgedKeyTy, TestBridgedValueTy>(minimumCapacity: 32)
d[TestBridgedKeyTy(10)] = TestBridgedValueTy(1010)
d[TestBridgedKeyTy(20)] = TestBridgedValueTy(1020)
d[TestBridgedKeyTy(30)] = TestBridgedValueTy(1030)
do {
var dOO = d as Dictionary<NSObject, AnyObject>
assert(dOO.count == 3)
var v: AnyObject? = dOO[TestObjCKeyTy(10)]
assert((v! as! TestBridgedValueTy).value == 1010)
v = dOO[TestObjCKeyTy(20)]
assert((v! as! TestBridgedValueTy).value == 1020)
v = dOO[TestObjCKeyTy(30)]
assert((v! as! TestBridgedValueTy).value == 1030)
}
do {
var dOV = d as Dictionary<NSObject, TestBridgedValueTy>
assert(dOV.count == 3)
var v = dOV[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dOV[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dOV[TestObjCKeyTy(30)]
assert(v!.value == 1030)
}
do {
var dVO = d as Dictionary<TestBridgedKeyTy, AnyObject>
assert(dVO.count == 3)
var v: AnyObject? = dVO[TestBridgedKeyTy(10)]
assert((v! as! TestBridgedValueTy).value == 1010)
v = dVO[TestBridgedKeyTy(20)]
assert((v! as! TestBridgedValueTy).value == 1020)
v = dVO[TestBridgedKeyTy(30)]
assert((v! as! TestBridgedValueTy).value == 1030)
}
}
//===---
// Dictionary downcasts
//===---
DictionaryTestSuite.test("DictionaryDowncastEntryPoint") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
let dCC: Dictionary<TestObjCKeyTy, TestObjCValueTy> = _dictionaryDownCast(d)
assert(dCC.count == 3)
var v = dCC[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCC[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCC[TestObjCKeyTy(30)]
assert(v!.value == 1030)
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("DictionaryDowncast") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
let dCC = d as! Dictionary<TestObjCKeyTy, TestObjCValueTy>
assert(dCC.count == 3)
var v = dCC[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCC[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCC[TestObjCKeyTy(30)]
assert(v!.value == 1030)
expectAutoreleasedKeysAndValues(unopt: (0, 3))
}
DictionaryTestSuite.test("DictionaryDowncastConditionalEntryPoint") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
if let dCC
= _dictionaryDownCastConditional(d) as Dictionary<TestObjCKeyTy, TestObjCValueTy>? {
assert(dCC.count == 3)
var v = dCC[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCC[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCC[TestObjCKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Unsuccessful downcast
d["hello" as NSString] = 17 as NSNumber
if let _
= _dictionaryDownCastConditional(d) as Dictionary<TestObjCKeyTy, TestObjCValueTy>? {
assert(false)
}
}
DictionaryTestSuite.test("DictionaryDowncastConditional") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
if let dCC = d as? Dictionary<TestObjCKeyTy, TestObjCValueTy> {
assert(dCC.count == 3)
var v = dCC[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCC[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCC[TestObjCKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Unsuccessful downcast
d["hello" as NSString] = 17 as NSNumber
if d is Dictionary<TestObjCKeyTy, TestObjCValueTy> {
assert(false)
}
}
DictionaryTestSuite.test("DictionaryBridgeFromObjectiveCEntryPoint") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
let dCV: Dictionary<TestObjCKeyTy, TestBridgedValueTy>
= _dictionaryBridgeFromObjectiveC(d)
do {
assert(dCV.count == 3)
var v = dCV[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCV[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCV[TestObjCKeyTy(30)]
assert(v!.value == 1030)
}
// Successful downcast.
let dVC: Dictionary<TestBridgedKeyTy, TestObjCValueTy>
= _dictionaryBridgeFromObjectiveC(d)
do {
assert(dVC.count == 3)
var v = dVC[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVC[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVC[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
}
// Successful downcast.
let dVV: Dictionary<TestBridgedKeyTy, TestBridgedValueTy>
= _dictionaryBridgeFromObjectiveC(d)
do {
assert(dVV.count == 3)
var v = dVV[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVV[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVV[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
}
}
DictionaryTestSuite.test("DictionaryBridgeFromObjectiveC") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
let dCV = d as! Dictionary<TestObjCKeyTy, TestBridgedValueTy>
do {
assert(dCV.count == 3)
var v = dCV[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCV[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCV[TestObjCKeyTy(30)]
assert(v!.value == 1030)
}
// Successful downcast.
let dVC = d as! Dictionary<TestBridgedKeyTy, TestObjCValueTy>
do {
assert(dVC.count == 3)
var v = dVC[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVC[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVC[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
}
// Successful downcast.
let dVV = d as! Dictionary<TestBridgedKeyTy, TestBridgedValueTy>
do {
assert(dVV.count == 3)
var v = dVV[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVV[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVV[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
}
}
DictionaryTestSuite.test("DictionaryBridgeFromObjectiveCConditionalEntryPoint") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
if let dCV
= _dictionaryBridgeFromObjectiveCConditional(d) as
Dictionary<TestObjCKeyTy, TestBridgedValueTy>? {
assert(dCV.count == 3)
var v = dCV[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCV[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCV[TestObjCKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Successful downcast.
if let dVC
= _dictionaryBridgeFromObjectiveCConditional(d) as Dictionary<TestBridgedKeyTy, TestObjCValueTy>? {
assert(dVC.count == 3)
var v = dVC[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVC[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVC[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Successful downcast.
if let dVV
= _dictionaryBridgeFromObjectiveCConditional(d) as Dictionary<TestBridgedKeyTy, TestBridgedValueTy>? {
assert(dVV.count == 3)
var v = dVV[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVV[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVV[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Unsuccessful downcasts
d["hello" as NSString] = 17 as NSNumber
if let _
= _dictionaryBridgeFromObjectiveCConditional(d) as Dictionary<TestObjCKeyTy, TestBridgedValueTy>?{
assert(false)
}
if let _
= _dictionaryBridgeFromObjectiveCConditional(d) as Dictionary<TestBridgedKeyTy, TestObjCValueTy>?{
assert(false)
}
if let _
= _dictionaryBridgeFromObjectiveCConditional(d) as Dictionary<TestBridgedKeyTy, TestBridgedValueTy>?{
assert(false)
}
}
DictionaryTestSuite.test("DictionaryBridgeFromObjectiveCConditional") {
var d = Dictionary<NSObject, AnyObject>(minimumCapacity: 32)
d[TestObjCKeyTy(10)] = TestObjCValueTy(1010)
d[TestObjCKeyTy(20)] = TestObjCValueTy(1020)
d[TestObjCKeyTy(30)] = TestObjCValueTy(1030)
// Successful downcast.
if let dCV = d as? Dictionary<TestObjCKeyTy, TestBridgedValueTy> {
assert(dCV.count == 3)
var v = dCV[TestObjCKeyTy(10)]
assert(v!.value == 1010)
v = dCV[TestObjCKeyTy(20)]
assert(v!.value == 1020)
v = dCV[TestObjCKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Successful downcast.
if let dVC = d as? Dictionary<TestBridgedKeyTy, TestObjCValueTy> {
assert(dVC.count == 3)
var v = dVC[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVC[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVC[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Successful downcast.
if let dVV = d as? Dictionary<TestBridgedKeyTy, TestBridgedValueTy> {
assert(dVV.count == 3)
var v = dVV[TestBridgedKeyTy(10)]
assert(v!.value == 1010)
v = dVV[TestBridgedKeyTy(20)]
assert(v!.value == 1020)
v = dVV[TestBridgedKeyTy(30)]
assert(v!.value == 1030)
} else {
assert(false)
}
// Unsuccessful downcasts
d["hello" as NSString] = 17 as NSNumber
if d is Dictionary<TestObjCKeyTy, TestBridgedValueTy> {
assert(false)
}
if d is Dictionary<TestBridgedKeyTy, TestObjCValueTy> {
assert(false)
}
if d is Dictionary<TestBridgedKeyTy, TestBridgedValueTy> {
assert(false)
}
}
#endif // _runtime(_ObjC)
//===---
// Tests for APIs implemented strictly based on public interface. We only need
// to test them once, not for every storage type.
//===---
func getDerivedAPIsDictionary() -> Dictionary<Int, Int> {
var d = Dictionary<Int, Int>(minimumCapacity: 10)
d[10] = 1010
d[20] = 1020
d[30] = 1030
return d
}
var DictionaryDerivedAPIs = TestSuite("DictionaryDerivedAPIs")
DictionaryDerivedAPIs.test("isEmpty") {
do {
let empty = Dictionary<Int, Int>()
expectTrue(empty.isEmpty)
}
do {
let d = getDerivedAPIsDictionary()
expectFalse(d.isEmpty)
}
}
#if _runtime(_ObjC)
@objc
class MockDictionaryWithCustomCount : NSDictionary {
init(count: Int) {
self._count = count
super.init()
}
override init() {
expectUnreachable()
super.init()
}
override init(
objects: UnsafePointer<AnyObject>?,
forKeys keys: UnsafePointer<NSCopying>?,
count: Int) {
expectUnreachable()
super.init(objects: objects, forKeys: keys, count: count)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) not implemented by MockDictionaryWithCustomCount")
}
@objc(copyWithZone:)
override func copy(with zone: NSZone?) -> Any {
// Ensure that copying this dictionary produces an object of the same
// dynamic type.
return self
}
override func object(forKey aKey: Any) -> Any? {
expectUnreachable()
return NSObject()
}
override var count: Int {
MockDictionaryWithCustomCount.timesCountWasCalled += 1
return _count
}
var _count: Int = 0
static var timesCountWasCalled = 0
}
func getMockDictionaryWithCustomCount(count: Int)
-> Dictionary<NSObject, AnyObject> {
return MockDictionaryWithCustomCount(count: count) as Dictionary
}
func callGenericIsEmpty<C : Collection>(_ collection: C) -> Bool {
return collection.isEmpty
}
DictionaryDerivedAPIs.test("isEmpty/ImplementationIsCustomized") {
do {
let d = getMockDictionaryWithCustomCount(count: 0)
MockDictionaryWithCustomCount.timesCountWasCalled = 0
expectTrue(d.isEmpty)
expectEqual(1, MockDictionaryWithCustomCount.timesCountWasCalled)
}
do {
let d = getMockDictionaryWithCustomCount(count: 0)
MockDictionaryWithCustomCount.timesCountWasCalled = 0
expectTrue(callGenericIsEmpty(d))
expectEqual(1, MockDictionaryWithCustomCount.timesCountWasCalled)
}
do {
let d = getMockDictionaryWithCustomCount(count: 4)
MockDictionaryWithCustomCount.timesCountWasCalled = 0
expectFalse(d.isEmpty)
expectEqual(1, MockDictionaryWithCustomCount.timesCountWasCalled)
}
do {
let d = getMockDictionaryWithCustomCount(count: 4)
MockDictionaryWithCustomCount.timesCountWasCalled = 0
expectFalse(callGenericIsEmpty(d))
expectEqual(1, MockDictionaryWithCustomCount.timesCountWasCalled)
}
}
#endif // _runtime(_ObjC)
DictionaryDerivedAPIs.test("keys") {
do {
let empty = Dictionary<Int, Int>()
let keys = Array(empty.keys)
expectTrue(equalsUnordered(keys, []))
}
do {
let d = getDerivedAPIsDictionary()
let keys = Array(d.keys)
expectTrue(equalsUnordered(keys, [ 10, 20, 30 ]))
}
}
DictionaryDerivedAPIs.test("values") {
do {
let empty = Dictionary<Int, Int>()
let values = Array(empty.values)
expectTrue(equalsUnordered(values, []))
}
do {
var d = getDerivedAPIsDictionary()
var values = Array(d.values)
expectTrue(equalsUnordered(values, [ 1010, 1020, 1030 ]))
d[11] = 1010
values = Array(d.values)
expectTrue(equalsUnordered(values, [ 1010, 1010, 1020, 1030 ]))
}
}
#if _runtime(_ObjC)
var ObjCThunks = TestSuite("ObjCThunks")
class ObjCThunksHelper : NSObject {
@objc dynamic func acceptArrayBridgedVerbatim(_ array: [TestObjCValueTy]) {
expectEqual(10, array[0].value)
expectEqual(20, array[1].value)
expectEqual(30, array[2].value)
}
@objc dynamic func acceptArrayBridgedNonverbatim(_ array: [TestBridgedValueTy]) {
// Cannot check elements because doing so would bridge them.
expectEqual(3, array.count)
}
@objc dynamic func returnArrayBridgedVerbatim() -> [TestObjCValueTy] {
return [ TestObjCValueTy(10), TestObjCValueTy(20),
TestObjCValueTy(30) ]
}
@objc dynamic func returnArrayBridgedNonverbatim() -> [TestBridgedValueTy] {
return [ TestBridgedValueTy(10), TestBridgedValueTy(20),
TestBridgedValueTy(30) ]
}
@objc dynamic func acceptDictionaryBridgedVerbatim(
_ d: [TestObjCKeyTy : TestObjCValueTy]) {
expectEqual(3, d.count)
expectEqual(1010, d[TestObjCKeyTy(10)]!.value)
expectEqual(1020, d[TestObjCKeyTy(20)]!.value)
expectEqual(1030, d[TestObjCKeyTy(30)]!.value)
}
@objc dynamic func acceptDictionaryBridgedNonverbatim(
_ d: [TestBridgedKeyTy : TestBridgedValueTy]) {
expectEqual(3, d.count)
// Cannot check elements because doing so would bridge them.
}
@objc dynamic func returnDictionaryBridgedVerbatim() ->
[TestObjCKeyTy : TestObjCValueTy] {
return [
TestObjCKeyTy(10): TestObjCValueTy(1010),
TestObjCKeyTy(20): TestObjCValueTy(1020),
TestObjCKeyTy(30): TestObjCValueTy(1030),
]
}
@objc dynamic func returnDictionaryBridgedNonverbatim() ->
[TestBridgedKeyTy : TestBridgedValueTy] {
return [
TestBridgedKeyTy(10): TestBridgedValueTy(1010),
TestBridgedKeyTy(20): TestBridgedValueTy(1020),
TestBridgedKeyTy(30): TestBridgedValueTy(1030),
]
}
}
ObjCThunks.test("Array/Accept") {
let helper = ObjCThunksHelper()
do {
helper.acceptArrayBridgedVerbatim(
[ TestObjCValueTy(10), TestObjCValueTy(20), TestObjCValueTy(30) ])
}
do {
TestBridgedValueTy.bridgeOperations = 0
helper.acceptArrayBridgedNonverbatim(
[ TestBridgedValueTy(10), TestBridgedValueTy(20),
TestBridgedValueTy(30) ])
expectEqual(0, TestBridgedValueTy.bridgeOperations)
}
}
ObjCThunks.test("Array/Return") {
let helper = ObjCThunksHelper()
do {
let a = helper.returnArrayBridgedVerbatim()
expectEqual(10, a[0].value)
expectEqual(20, a[1].value)
expectEqual(30, a[2].value)
}
do {
TestBridgedValueTy.bridgeOperations = 0
let a = helper.returnArrayBridgedNonverbatim()
expectEqual(0, TestBridgedValueTy.bridgeOperations)
TestBridgedValueTy.bridgeOperations = 0
expectEqual(10, a[0].value)
expectEqual(20, a[1].value)
expectEqual(30, a[2].value)
expectEqual(0, TestBridgedValueTy.bridgeOperations)
}
}
ObjCThunks.test("Dictionary/Accept") {
let helper = ObjCThunksHelper()
do {
helper.acceptDictionaryBridgedVerbatim(
[ TestObjCKeyTy(10): TestObjCValueTy(1010),
TestObjCKeyTy(20): TestObjCValueTy(1020),
TestObjCKeyTy(30): TestObjCValueTy(1030) ])
}
do {
TestBridgedKeyTy.bridgeOperations = 0
TestBridgedValueTy.bridgeOperations = 0
helper.acceptDictionaryBridgedNonverbatim(
[ TestBridgedKeyTy(10): TestBridgedValueTy(1010),
TestBridgedKeyTy(20): TestBridgedValueTy(1020),
TestBridgedKeyTy(30): TestBridgedValueTy(1030) ])
expectEqual(0, TestBridgedKeyTy.bridgeOperations)
expectEqual(0, TestBridgedValueTy.bridgeOperations)
}
}
ObjCThunks.test("Dictionary/Return") {
let helper = ObjCThunksHelper()
do {
let d = helper.returnDictionaryBridgedVerbatim()
expectEqual(3, d.count)
expectEqual(1010, d[TestObjCKeyTy(10)]!.value)
expectEqual(1020, d[TestObjCKeyTy(20)]!.value)
expectEqual(1030, d[TestObjCKeyTy(30)]!.value)
}
do {
TestBridgedKeyTy.bridgeOperations = 0
TestBridgedValueTy.bridgeOperations = 0
let d = helper.returnDictionaryBridgedNonverbatim()
expectEqual(0, TestBridgedKeyTy.bridgeOperations)
expectEqual(0, TestBridgedValueTy.bridgeOperations)
TestBridgedKeyTy.bridgeOperations = 0
TestBridgedValueTy.bridgeOperations = 0
expectEqual(3, d.count)
expectEqual(1010, d[TestBridgedKeyTy(10)]!.value)
expectEqual(1020, d[TestBridgedKeyTy(20)]!.value)
expectEqual(1030, d[TestBridgedKeyTy(30)]!.value)
expectEqual(0, TestBridgedKeyTy.bridgeOperations)
expectEqual(0, TestBridgedValueTy.bridgeOperations)
}
}
#endif // _runtime(_ObjC)
//===---
// Check that iterators traverse a snapshot of the collection.
//===---
DictionaryTestSuite.test("mutationDoesNotAffectIterator/subscript/store") {
var dict = getDerivedAPIsDictionary()
let iter = dict.makeIterator()
dict[10] = 1011
expectEqualsUnordered(
[ (10, 1010), (20, 1020), (30, 1030) ],
Array(IteratorSequence(iter)))
}
DictionaryTestSuite.test("mutationDoesNotAffectIterator/removeValueForKey,1") {
var dict = getDerivedAPIsDictionary()
let iter = dict.makeIterator()
expectOptionalEqual(1010, dict.removeValue(forKey: 10))
expectEqualsUnordered(
[ (10, 1010), (20, 1020), (30, 1030) ],
Array(IteratorSequence(iter)))
}
DictionaryTestSuite.test("mutationDoesNotAffectIterator/removeValueForKey,all") {
var dict = getDerivedAPIsDictionary()
let iter = dict.makeIterator()
expectOptionalEqual(1010, dict.removeValue(forKey: 10))
expectOptionalEqual(1020, dict.removeValue(forKey: 20))
expectOptionalEqual(1030, dict.removeValue(forKey: 30))
expectEqualsUnordered(
[ (10, 1010), (20, 1020), (30, 1030) ],
Array(IteratorSequence(iter)))
}
DictionaryTestSuite.test(
"mutationDoesNotAffectIterator/removeAll,keepingCapacity=false") {
var dict = getDerivedAPIsDictionary()
let iter = dict.makeIterator()
dict.removeAll(keepingCapacity: false)
expectEqualsUnordered(
[ (10, 1010), (20, 1020), (30, 1030) ],
Array(IteratorSequence(iter)))
}
DictionaryTestSuite.test(
"mutationDoesNotAffectIterator/removeAll,keepingCapacity=true") {
var dict = getDerivedAPIsDictionary()
let iter = dict.makeIterator()
dict.removeAll(keepingCapacity: true)
expectEqualsUnordered(
[ (10, 1010), (20, 1020), (30, 1030) ],
Array(IteratorSequence(iter)))
}
//===---
// Misc tests.
//===---
DictionaryTestSuite.test("misc") {
do {
// Dictionary literal
var dict = ["Hello": 1, "World": 2]
// Insertion
dict["Swift"] = 3
// Access
expectOptionalEqual(1, dict["Hello"])
expectOptionalEqual(2, dict["World"])
expectOptionalEqual(3, dict["Swift"])
expectNil(dict["Universe"])
// Overwriting existing value
dict["Hello"] = 0
expectOptionalEqual(0, dict["Hello"])
expectOptionalEqual(2, dict["World"])
expectOptionalEqual(3, dict["Swift"])
expectNil(dict["Universe"])
}
do {
// Dictionaries with other types
var d = [ 1.2: 1, 2.6: 2 ]
d[3.3] = 3
expectOptionalEqual(1, d[1.2])
expectOptionalEqual(2, d[2.6])
expectOptionalEqual(3, d[3.3])
}
do {
var d = Dictionary<String, Int>(minimumCapacity: 13)
d["one"] = 1
d["two"] = 2
d["three"] = 3
d["four"] = 4
d["five"] = 5
expectOptionalEqual(1, d["one"])
expectOptionalEqual(2, d["two"])
expectOptionalEqual(3, d["three"])
expectOptionalEqual(4, d["four"])
expectOptionalEqual(5, d["five"])
// Iterate over (key, value) tuples as a silly copy
var d3 = Dictionary<String,Int>(minimumCapacity: 13)
for (k, v) in d {
d3[k] = v
}
expectOptionalEqual(1, d3["one"])
expectOptionalEqual(2, d3["two"])
expectOptionalEqual(3, d3["three"])
expectOptionalEqual(4, d3["four"])
expectOptionalEqual(5, d3["five"])
expectEqual(3, d.values[d.keys.firstIndex(of: "three")!])
expectEqual(4, d.values[d.keys.firstIndex(of: "four")!])
expectEqual(3, d3.values[d3.keys.firstIndex(of: "three")!])
expectEqual(4, d3.values[d3.keys.firstIndex(of: "four")!])
}
}
#if _runtime(_ObjC)
DictionaryTestSuite.test("dropsBridgedCache") {
// rdar://problem/18544533
// Previously this code would segfault due to a double free in the Dictionary
// implementation.
// This test will only fail in address sanitizer.
var dict = [0:10]
do {
let bridged: NSDictionary = dict as NSDictionary
expectEqual(10, bridged[0 as NSNumber] as! Int)
}
dict[0] = 11
do {
let bridged: NSDictionary = dict as NSDictionary
expectEqual(11, bridged[0 as NSNumber] as! Int)
}
}
DictionaryTestSuite.test("getObjects:andKeys:count:") {
let native = [1: "one", 2: "two"] as Dictionary<Int, String>
let d = native as NSDictionary
let keys = UnsafeMutableBufferPointer(
start: UnsafeMutablePointer<NSNumber>.allocate(capacity: 2), count: 2)
let values = UnsafeMutableBufferPointer(
start: UnsafeMutablePointer<NSString>.allocate(capacity: 2), count: 2)
let kp = AutoreleasingUnsafeMutablePointer<AnyObject?>(keys.baseAddress!)
let vp = AutoreleasingUnsafeMutablePointer<AnyObject?>(values.baseAddress!)
let null: AutoreleasingUnsafeMutablePointer<AnyObject?>? = nil
let expectedKeys: [NSNumber]
let expectedValues: [NSString]
if native.first?.key == 1 {
expectedKeys = [1, 2]
expectedValues = ["one", "two"]
} else {
expectedKeys = [2, 1]
expectedValues = ["two", "one"]
}
d.available_getObjects(null, andKeys: null, count: 2) // don't segfault
d.available_getObjects(null, andKeys: kp, count: 2)
expectEqual(expectedKeys, Array(keys))
d.available_getObjects(vp, andKeys: null, count: 2)
expectEqual(expectedValues, Array(values))
d.available_getObjects(vp, andKeys: kp, count: 2)
expectEqual(expectedKeys, Array(keys))
expectEqual(expectedValues, Array(values))
}
#endif
DictionaryTestSuite.test("popFirst") {
// Empty
do {
var d = [Int: Int]()
let popped = d.popFirst()
expectNil(popped)
}
do {
var popped = [(Int, Int)]()
var d: [Int: Int] = [
1010: 1010,
2020: 2020,
3030: 3030,
]
let expected = [(1010, 1010), (2020, 2020), (3030, 3030)]
while let element = d.popFirst() {
popped.append(element)
}
// Note that removing an element may reorder remaining items, so we
// can't compare ordering here.
popped.sort(by: { $0.0 < $1.0 })
expectEqualSequence(expected, popped) {
(lhs: (Int, Int), rhs: (Int, Int)) -> Bool in
lhs.0 == rhs.0 && lhs.1 == rhs.1
}
expectTrue(d.isEmpty)
}
}
DictionaryTestSuite.test("removeAt") {
// Test removing from the startIndex, the middle, and the end of a dictionary.
for i in 1...3 {
var d: [Int: Int] = [
10: 1010,
20: 2020,
30: 3030,
]
let removed = d.remove(at: d.index(forKey: i*10)!)
expectEqual(i*10, removed.0)
expectEqual(i*1010, removed.1)
expectEqual(2, d.count)
expectNil(d.index(forKey: i))
let origKeys: [Int] = [10, 20, 30]
expectEqual(origKeys.filter { $0 != (i*10) }, d.keys.sorted())
}
}
DictionaryTestSuite.test("localHashSeeds") {
// With global hashing, copying elements in hash order between hash tables
// can become quadratic. (See https://bugs.swift.org/browse/SR-3268)
//
// We defeat this by mixing the local storage capacity into the global hash
// seed, thereby breaking the correlation between bucket indices across
// hash tables with different sizes.
//
// Verify this works by copying a small sampling of elements near the
// beginning of a large Dictionary into a smaller one. If the elements end up
// in the same order in the smaller Dictionary, then that indicates we do not
// use size-dependent seeding.
let count = 100_000
// Set a large table size to reduce frequency/length of collision chains.
var large = [Int: Int](minimumCapacity: 4 * count)
for i in 1 ..< count {
large[i] = 2 * i
}
let bunch = count / 100 // 1 percent's worth of elements
// Copy two bunches of elements into another dictionary that's half the size
// of the first. We start after the initial bunch because the hash table may
// begin with collided elements wrapped over from the end, and these would be
// sorted into irregular slots in the smaller table.
let slice = large.prefix(3 * bunch).dropFirst(bunch)
var small = [Int: Int](minimumCapacity: large.capacity / 2)
expectLT(small.capacity, large.capacity)
for (key, value) in slice {
small[key] = value
}
// Compare the second halves of the new dictionary and the slice. Ignore the
// first halves; the first few elements may not be in the correct order if we
// happened to start copying from the middle of a collision chain.
let smallKeys = small.dropFirst(bunch).map { $0.key }
let sliceKeys = slice.dropFirst(bunch).map { $0.key }
// If this test fails, there is a problem with local hash seeding.
expectFalse(smallKeys.elementsEqual(sliceKeys))
}
DictionaryTestSuite.test("Hashable") {
let d1: [Dictionary<Int, String>] = [
[1: "meow", 2: "meow", 3: "meow"],
[1: "meow", 2: "meow", 3: "mooo"],
[1: "meow", 2: "meow", 4: "meow"],
[1: "meow", 2: "meow", 4: "mooo"]]
checkHashable(d1, equalityOracle: { $0 == $1 })
let d2: [Dictionary<Int, Dictionary<Int, String>>] = [
[1: [2: "meow"]],
[2: [1: "meow"]],
[2: [2: "meow"]],
[1: [1: "meow"]],
[2: [2: "mooo"]],
[2: [:]],
[:]]
checkHashable(d2, equalityOracle: { $0 == $1 })
// Dictionary should hash itself in a way that ensures instances get correctly
// delineated even when they are nested in other commutative collections.
// These are different Sets, so they should produce different hashes:
let remix: [Set<Dictionary<String, Int>>] = [
[["Blanche": 1, "Rose": 2], ["Dorothy": 3, "Sophia": 4]],
[["Blanche": 1, "Dorothy": 3], ["Rose": 2, "Sophia": 4]],
[["Blanche": 1, "Sophia": 4], ["Rose": 2, "Dorothy": 3]]
]
checkHashable(remix, equalityOracle: { $0 == $1 })
// Dictionary ordering is not guaranteed to be consistent across equal
// instances. In particular, ordering is highly sensitive to the size of the
// allocated storage buffer. Generate a few copies of the same dictionary with
// different capacities, and verify that they compare and hash the same.
var variants: [Dictionary<String, Int>] = []
for i in 4 ..< 12 {
var set: Dictionary<String, Int> = [
"one": 1, "two": 2,
"three": 3, "four": 4,
"five": 5, "six": 6]
set.reserveCapacity(1 << i)
variants.append(set)
}
checkHashable(variants, equalityOracle: { _, _ in true })
}
DictionaryTestSuite.setUp {
#if _runtime(_ObjC)
// Exercise ARC's autoreleased return value optimization in Foundation.
//
// On some platforms, when a new process is started, the optimization is
// expected to fail the first time it is used in each linked
// dylib. StdlibUnittest takes care of warming up ARC for the stdlib
// (libswiftCore.dylib), but for this particular test we also need to do it
// for Foundation, or there will be spurious leaks reported for tests
// immediately following a crash test.
//
// <rdar://problem/42069800> stdlib tests: expectCrashLater() interferes with
// counting autoreleased live objects
let d = NSDictionary(objects: [1 as NSNumber], forKeys: [1 as NSNumber])
_ = d.object(forKey: 1 as NSNumber)
#endif
resetLeaksOfDictionaryKeysValues()
#if _runtime(_ObjC)
resetLeaksOfObjCDictionaryKeysValues()
#endif
}
DictionaryTestSuite.tearDown {
expectNoLeaksOfDictionaryKeysValues()
#if _runtime(_ObjC)
expectNoLeaksOfObjCDictionaryKeysValues()
#endif
}
runAllTests()