| // 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/Array -Xfrontend -disable-access-control; \ |
| // RUN: else \ |
| // RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Array -Xfrontend -disable-access-control; \ |
| // RUN: fi |
| // RUN: %line-directive %t/main.swift -- %target-run %t/Array |
| // REQUIRES: executable_test |
| |
| import StdlibUnittest |
| import StdlibCollectionUnittest |
| |
| |
| %{ |
| all_array_types = ['ContiguousArray', 'ArraySlice', 'Array'] |
| }% |
| |
| %for Self in all_array_types: |
| extension ${Self} { |
| typealias _BufferID = UnsafeRawPointer? |
| var _bufferID: _BufferID { |
| return unsafeBitCast(_owner, to: _BufferID.self) |
| } |
| } |
| %end |
| |
| var ArrayTestSuite = TestSuite("Array") |
| |
| //===----------------------------------------------------------------------===// |
| // COW tests |
| // FIXME: incomplete. |
| //===----------------------------------------------------------------------===// |
| |
| func withInoutInt(_ x: inout Int, body: (_ x: inout Int) -> Void) { |
| body(&x) |
| } |
| |
| func withInoutT<T>(_ x: inout T, body: (_ x: inout T) -> Void) { |
| body(&x) |
| } |
| |
| % for element_type in ['TestValueTy', 'TestBridgedValueTy']: |
| % for array_type in all_array_types: |
| % if element_type == 'TestBridgedValueTy': |
| #if _runtime(_ObjC) |
| % end |
| |
| ArrayTestSuite.test("${array_type}<${element_type}>/subscript(_: Int)/COW") |
| .code { |
| var a: ${array_type}<${array_type}<${element_type}>> = [[ |
| ${element_type}(10), ${element_type}(20), ${element_type}(30), |
| ${element_type}(40), ${element_type}(50), ${element_type}(60), |
| ${element_type}(70) |
| ]] |
| let identityOuter = a._bufferID |
| var identityInner = a[0]._bufferID |
| |
| func checkIdentity(_ stackTrace: SourceLocStack) { |
| % if element_type == 'TestValueTy': |
| // Does not reallocate storage because we changed a property based on a |
| // reference; array storage was not changed. Writeback of the inner array |
| // does not happen. |
| expectEqual(identityOuter, a._bufferID, stackTrace: stackTrace) |
| expectEqual(identityInner, a[0]._bufferID, stackTrace: stackTrace) |
| % else: |
| expectEqual(identityOuter, a._bufferID, stackTrace: stackTrace) |
| |
| // Should not reallocate storage. |
| expectEqual(identityInner, a[0]._bufferID, stackTrace: stackTrace) |
| % end |
| } |
| |
| // Mutating through a subscript expression. |
| a[0][0] = ${element_type}(1010) |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| a[0][1].value = 1020 |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutT(&a) { |
| (x: inout ${array_type}<${array_type}<${element_type}>>) in |
| x[0][2].value += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutT(&a[0]) { |
| (x: inout ${array_type}<${element_type}>) in |
| x[3].value += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| // This will reallocate storage unless Array uses addressors for subscript. |
| //withInoutT(&a[0][4]) { |
| // (x: inout ${element_type}) in |
| // x.value += 1000 |
| //} |
| |
| // FIXME: both of these lines crash the compiler. |
| // <rdar://problem/18439579> Passing an expression based on addressors as |
| // 'inout' crashes SILGen |
| //withInoutT(&a[0][5].value, { $0 += 1000 }) |
| //withInoutInt(&a[0][6].value, { $0 += 1000 }) |
| |
| // Don't change the last element. |
| |
| expectEqual(1010, a[0][0].value) |
| expectEqual(1020, a[0][1].value) |
| expectEqual(1030, a[0][2].value) |
| expectEqual(1040, a[0][3].value) |
| expectEqual(50, a[0][4].value) |
| expectEqual(60, a[0][5].value) |
| expectEqual(70, a[0][6].value) |
| } |
| |
| ArrayTestSuite.test("${array_type}<${element_type}>/subscript(_: Range<Int>)/COW") |
| .code { |
| var a: ${array_type}<${array_type}<${element_type}>> = [[ |
| ${element_type}(10), ${element_type}(20), ${element_type}(30), |
| ${element_type}(40), ${element_type}(50), ${element_type}(60), |
| ${element_type}(70), ${element_type}(80), ${element_type}(90), |
| ]] |
| let identityOuter = a._bufferID |
| var identityInner = a[0]._bufferID |
| |
| func checkIdentity(_ stackTrace: SourceLocStack) { |
| % if element_type == 'TestValueTy': |
| // Does not reallocate storage because we changed a property based on a |
| // reference; array storage was not changed. |
| expectEqual(identityOuter, a._bufferID, stackTrace: stackTrace) |
| expectEqual(identityInner, a[0]._bufferID, stackTrace: stackTrace) |
| % else: |
| expectEqual(identityOuter, a._bufferID, stackTrace: stackTrace) |
| // Writeback happens in subscript(Range<Int>), but array notices that the new |
| // value did not change. |
| // Another writeback happens in Array.subscript(Int), but this is not what we |
| // want. |
| expectNotEqual(identityInner, a[0]._bufferID, stackTrace: stackTrace) |
| identityInner = a[0]._bufferID |
| % end |
| } |
| |
| // Mutating through a subscript expression. |
| a[0..<1][0][0] = ${element_type}(1010) |
| |
| // Reallocates storage because of the writeback in Array.subscript(Int). |
| expectEqual(identityOuter, a._bufferID) |
| expectNotEqual(identityInner, a[0]._bufferID) |
| identityInner = a[0]._bufferID |
| |
| a[0..<1][0][1].value = 1020 |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutT(&a) { |
| (x: inout ${array_type}<${array_type}<${element_type}>>) in |
| x[0..<1][0][2].value += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutT(&a[0..<1]) { |
| (x: inout ArraySlice<${array_type}<${element_type}>>) in |
| x[0][3].value += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutT(&a[0..<1][0]) { |
| (x: inout ${array_type}<${element_type}>) in |
| x[4].value += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutT(&a[0..<1][0][5]) { |
| (x: inout ${element_type}) in |
| x.value += 1000 |
| } |
| |
| // Reallocates storage because of the writeback in Array.subscript(Int) |
| // (writeback is being requested for the array element even though it is not |
| // needed). |
| expectEqual(identityOuter, a._bufferID) |
| expectNotEqual(identityInner, a[0]._bufferID) |
| identityInner = a[0]._bufferID |
| |
| withInoutT(&a[0..<1][0][6].value) { |
| (x: inout Int) in |
| x += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| withInoutInt(&a[0..<1][0][7].value) { |
| (x: inout Int) in |
| x += 1000 |
| } |
| |
| checkIdentity(SourceLocStack().withCurrentLoc()) |
| |
| // Don't change the last element. |
| |
| expectEqual(1010, a[0][0].value) |
| expectEqual(1020, a[0][1].value) |
| expectEqual(1030, a[0][2].value) |
| expectEqual(1040, a[0][3].value) |
| expectEqual(1050, a[0][4].value) |
| expectEqual(1060, a[0][5].value) |
| expectEqual(1070, a[0][6].value) |
| expectEqual(1080, a[0][7].value) |
| expectEqual(90, a[0][8].value) |
| } |
| |
| % if element_type == 'TestBridgedValueTy': |
| #endif // _runtime(_ObjC) |
| % end |
| % end |
| % end |
| |
| #if _runtime(_ObjC) |
| import Darwin |
| import StdlibUnittestFoundationExtras |
| import Foundation |
| |
| // FIXME: all the tests below are applicable to ArraySlice, too. |
| |
| //===----------------------------------------------------------------------===// |
| // NSArray -> Array bridging tests |
| // FIXME: incomplete. |
| //===----------------------------------------------------------------------===// |
| |
| func isNativeArray<Element>(_ a: Array<Element>) -> Bool { |
| return a._hoistableIsNativeTypeChecked() |
| } |
| |
| func isCocoaArray<Element>(_ a: Array<Element>) -> Bool { |
| return !isNativeArray(a) |
| } |
| |
| func getAsImmutableNSArray(_ a: Array<Int>) -> NSArray { |
| var elements = a.map { TestObjCValueTy($0) as AnyObject } |
| return NSArray(objects: &elements, count: elements.count) |
| } |
| |
| func getAsNSArray(_ a: Array<Int>) -> NSArray { |
| // Return an `NSMutableArray` to make sure that it has a unique |
| // pointer identity. |
| return getAsNSMutableArray(a) |
| } |
| |
| func getAsNSMutableArray(_ a: Array<Int>) -> NSMutableArray { |
| let result = NSMutableArray() |
| for element in a { |
| result.add(TestObjCValueTy(element)) |
| } |
| return result |
| } |
| |
| @objc |
| class CustomImmutableNSArray : NSArray { |
| init(_privateInit: ()) { |
| super.init() |
| } |
| |
| override init() { |
| expectUnreachable() |
| super.init() |
| } |
| |
| override init(objects: UnsafePointer<AnyObject>?, count: Int) { |
| super.init(objects: objects, count: count) |
| } |
| |
| required init(coder aDecoder: NSCoder) { |
| fatalError("init(coder:) not implemented by CustomImmutableNSArray") |
| } |
| |
| @objc(copyWithZone:) |
| override func copy(with zone: NSZone?) -> Any { |
| CustomImmutableNSArray.timesCopyWithZoneWasCalled += 1 |
| return self |
| } |
| |
| @objc |
| override func object(at index: Int) -> Any { |
| CustomImmutableNSArray.timesObjectAtIndexWasCalled += 1 |
| return _data[index] |
| } |
| |
| @objc |
| override var count: Int { |
| CustomImmutableNSArray.timesCountWasCalled += 1 |
| return _data.count |
| } |
| |
| @objc |
| 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(_data._baseAddressIfContiguous) |
| theState.mutationsPtr = _fastEnumerationStorageMutationsPtr |
| state.pointee = theState |
| return _data.count |
| } |
| return 0 |
| } |
| |
| let _data = [ 10, 20, 30 ].map { TestObjCValueTy($0) } |
| |
| static var timesCopyWithZoneWasCalled = 0 |
| static var timesObjectAtIndexWasCalled = 0 |
| static var timesCountWasCalled = 0 |
| } |
| |
| ArrayTestSuite.test("BridgedFromObjC.Verbatim.BridgeUsingAs") { |
| do { |
| let source = [ 10, 20, 30 ] |
| let nsa = getAsNSArray(source) |
| var result = nsa as Array |
| expectTrue(isCocoaArray(result)) |
| expectType(Array<AnyObject>.self, &result) |
| checkSequence(source.map { TestObjCValueTy($0) as AnyObject }, result) { |
| ($0 as! TestObjCValueTy).value == ($1 as! TestObjCValueTy).value |
| } |
| } |
| do { |
| let source = [ 10, 20, 30 ] |
| let nsa = getAsNSArray(source) |
| var result = nsa as! Array<TestObjCValueTy> |
| expectTrue(isCocoaArray(result)) |
| expectType(Array<TestObjCValueTy>.self, &result) |
| checkSequence(source.map { TestObjCValueTy($0) }, result) { |
| $0.value == $1.value |
| } |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.BridgeUsingAs") { |
| let source = [ 10, 20, 30 ] |
| let nsa = getAsNSArray(source) |
| var result = nsa as! Array<TestBridgedValueTy> |
| expectTrue(isNativeArray(result)) |
| expectType(Array<TestBridgedValueTy>.self, &result) |
| checkSequence(source.map { TestBridgedValueTy($0) }, result) { |
| $0.value == $1.value |
| } |
| } |
| |
| |
| ArrayTestSuite.test("BridgedFromObjC.Verbatim.ArrayIsCopied") { |
| let source = [ 10, 20, 30 ] |
| let nsa = getAsNSMutableArray(source) |
| let result = nsa as Array<AnyObject> |
| expectTrue(isCocoaArray(result)) |
| |
| // Delete the value from NSMutableArray. |
| expectEqual(20, (nsa[1] as! TestObjCValueTy).value) |
| nsa.removeObject(at: 1) |
| expectEqual(30, (nsa[1] as! TestObjCValueTy).value) |
| |
| // Check that the Array is not affected. |
| expectEqual(20, result[1].value) |
| } |
| |
| ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.ArrayIsCopied") { |
| let source = [ 10, 20, 30 ] |
| let nsa = getAsNSMutableArray(source) |
| var result = nsa as AnyObject as! Array<TestBridgedValueTy> |
| expectTrue(isNativeArray(result)) |
| |
| // Delete the value from NSMutableArray. |
| expectEqual(20, (nsa[1] as! TestObjCValueTy).value) |
| nsa.removeObject(at: 1) |
| expectEqual(30, (nsa[1] as! TestObjCValueTy).value) |
| |
| // Check that the Array is not affected. |
| expectEqual(20, result[1].value) |
| } |
| |
| |
| ArrayTestSuite.test("BridgedFromObjC.Verbatim.NSArrayIsRetained") { |
| let nsa = NSArray(array: getAsNSArray([ 10, 20, 30 ])) |
| var a: Array<AnyObject> = convertNSArrayToArray(nsa) |
| var bridgedBack: NSArray = convertArrayToNSArray(a) |
| |
| expectEqual( |
| unsafeBitCast(nsa, to: Int.self), |
| unsafeBitCast(bridgedBack, to: Int.self)) |
| |
| _fixLifetime(nsa) |
| _fixLifetime(a) |
| _fixLifetime(bridgedBack) |
| } |
| |
| ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.NSArrayIsCopied") { |
| let nsa = NSArray(array: getAsNSArray([ 10, 20, 30 ])) |
| var a: Array<TestBridgedValueTy> = convertNSArrayToArray(nsa) |
| var bridgedBack: NSArray = convertArrayToNSArray(a) |
| |
| expectNotEqual( |
| unsafeBitCast(nsa, to: Int.self), |
| unsafeBitCast(bridgedBack, to: Int.self)) |
| |
| _fixLifetime(nsa) |
| _fixLifetime(a) |
| _fixLifetime(bridgedBack) |
| } |
| |
| |
| ArrayTestSuite.test("BridgedFromObjC.Verbatim.ImmutableArrayIsRetained") { |
| let nsa: NSArray = CustomImmutableNSArray(_privateInit: ()) |
| |
| CustomImmutableNSArray.timesCopyWithZoneWasCalled = 0 |
| CustomImmutableNSArray.timesObjectAtIndexWasCalled = 0 |
| CustomImmutableNSArray.timesCountWasCalled = 0 |
| let a: Array<AnyObject> = convertNSArrayToArray(nsa) |
| expectEqual(1, CustomImmutableNSArray.timesCopyWithZoneWasCalled) |
| expectEqual(0, CustomImmutableNSArray.timesObjectAtIndexWasCalled) |
| expectEqual(0, CustomImmutableNSArray.timesCountWasCalled) |
| |
| let bridgedBack: NSArray = convertArrayToNSArray(a) |
| |
| expectEqual( |
| unsafeBitCast(nsa, to: Int.self), |
| unsafeBitCast(bridgedBack, to: Int.self)) |
| |
| _fixLifetime(nsa) |
| _fixLifetime(a) |
| _fixLifetime(bridgedBack) |
| } |
| |
| ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.ImmutableArrayIsCopied") |
| .skip(.iOSAny("<rdar://problem/33926468>")) |
| .skip(.tvOSAny("<rdar://problem/33926468>")) |
| .code { |
| let nsa: NSArray = CustomImmutableNSArray(_privateInit: ()) |
| |
| CustomImmutableNSArray.timesCopyWithZoneWasCalled = 0 |
| CustomImmutableNSArray.timesObjectAtIndexWasCalled = 0 |
| CustomImmutableNSArray.timesCountWasCalled = 0 |
| TestBridgedValueTy.bridgeOperations = 0 |
| var a: Array<TestBridgedValueTy> = [] |
| |
| // FIXME: bridging shouldn't dump array contents into the autorelease pool. |
| autoreleasepoolIfUnoptimizedReturnAutoreleased { |
| a = convertNSArrayToArray(nsa) |
| expectEqual(1, CustomImmutableNSArray.timesCopyWithZoneWasCalled) |
| expectEqual(3, CustomImmutableNSArray.timesObjectAtIndexWasCalled) |
| expectNotEqual(0, CustomImmutableNSArray.timesCountWasCalled) |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| let bridgedBack: NSArray = convertArrayToNSArray(a) |
| |
| expectNotEqual( |
| unsafeBitCast(nsa, to: Int.self), |
| unsafeBitCast(bridgedBack, to: Int.self)) |
| |
| _fixLifetime(nsa) |
| _fixLifetime(a) |
| _fixLifetime(bridgedBack) |
| } |
| |
| // FIXME: test API calls on the BridgedFromObjC arrays. |
| |
| //===----------------------------------------------------------------------===// |
| // Array -> NSArray bridging tests |
| // |
| // Element is bridged verbatim. |
| // |
| // FIXME: incomplete. |
| //===----------------------------------------------------------------------===// |
| |
| ArrayTestSuite.test("BridgedToObjC.Verbatim.BridgeUsingAs") { |
| let source = [ 10, 20, 30 ].map { TestObjCValueTy($0) } |
| let result = source as NSArray |
| expectTrue(isNativeNSArray(result)) |
| expectEqual(3, result.count) |
| autoreleasepoolIfUnoptimizedReturnAutoreleased { |
| expectEqual(10, (result[0] as! TestObjCValueTy).value) |
| expectEqual(20, (result[1] as! TestObjCValueTy).value) |
| expectEqual(30, (result[2] as! TestObjCValueTy).value) |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/count/empty") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 0) |
| expectEqual(0, a.count) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/count") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged() |
| expectEqual(3, a.count) |
| } |
| |
| for index in [ -100, -1, 0, 1, 100 ] { |
| ArrayTestSuite.test( |
| "BridgedToObjC/Verbatim/objectAtIndex/empty/trap/\(index)") |
| .crashOutputMatches("Array index out of range") |
| .code { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 0) |
| expectCrashLater() |
| a.object(at: index) |
| } |
| } |
| |
| for index in [ -100, -1, 3, 4, 100 ] { |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/objectAtIndex/trap/\(index)") |
| .crashOutputMatches("Array index out of range") |
| .code { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| expectCrashLater() |
| a.object(at: index) |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/objectAtIndex") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| |
| var v: AnyObject = a.object(at: 0) as AnyObject |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a.object(at: 1) as AnyObject |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a.object(at: 2) as AnyObject |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| for i in 0..<3 { |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| } |
| |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| for indexRange in [ |
| -2..<(-2), 1..<1, |
| 0..<4, -2..<(-1), -1..<2, 0..<1, 2..<4, 4..<5 |
| ] as [Range<Int>] { |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/getObjects/empty/trap/\(indexRange)") |
| .crashOutputMatches("Array index out of range") |
| .code { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged( |
| numElements: 0, capacity: 16) |
| let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: 16) |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<0)) |
| expectCrashLater() |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(indexRange)) |
| } |
| } |
| |
| for indexRange in [ 0..<4, -2..<(-1), -1..<2, 2..<4, 4..<5 ] as [Range<Int>] { |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/getObjects/trap/\(indexRange)") |
| .crashOutputMatches("Array index out of range") |
| .code { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged( |
| numElements: 3, capacity: 16) |
| let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: 16) |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<3)) |
| expectCrashLater() |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(indexRange)) |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/getObjects") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: 16) |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<3)) |
| |
| var v: AnyObject = buffer[0] |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = buffer[1] |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = buffer[2] |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| for i in 0..<3 { |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| } |
| |
| buffer.deallocate() |
| _fixLifetime(a) |
| |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/copyWithZone") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| let copy: AnyObject = a.copy(with: nil) as AnyObject |
| expectEqual( |
| unsafeBitCast(a, to: UInt.self), unsafeBitCast(copy, to: UInt.self)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/FastEnumeration/UseFromSwift/Empty") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 0) |
| |
| checkArrayFastEnumerationFromSwift( |
| [], a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/FastEnumeration/UseFromSwift/3") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromSwift( |
| [ 10, 20, 30 ], |
| a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/FastEnumeration/UseFromSwift/7") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 7) |
| |
| checkArrayFastEnumerationFromSwift( |
| [ 10, 20, 30, 40, 50, 60, 70 ], |
| a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/FastEnumeration/UseFromObjC/Empty") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 0) |
| |
| checkArrayFastEnumerationFromObjC( |
| [], a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/FastEnumeration/UseFromObjC") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromObjC( |
| [ 10, 20, 30 ], |
| a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/ObjectEnumerator/FastEnumeration/UseFromSwift/Empty") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 0) |
| |
| checkArrayFastEnumerationFromSwift( |
| [], a, { a.objectEnumerator() }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/ObjectEnumerator/FastEnumeration/UseFromSwift") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromSwift( |
| [ 10, 20, 30 ], |
| a, { a.objectEnumerator() }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/ObjectEnumerator/FastEnumeration/UseFromSwift/Partial") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 9) |
| |
| checkArrayEnumeratorPartialFastEnumerationFromSwift( |
| [ 10, 20, 30, 40, 50, 60, 70, 80, 90 ], |
| a, maxFastEnumerationItems: 5, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/ObjectEnumerator/FastEnumeration/UseFromObjC") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromObjC( |
| [ 10, 20, 30 ], |
| a, { a.objectEnumerator() }, |
| { ($0 as! TestObjCValueTy).value }) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/BridgeBack/Reallocate") { |
| let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) |
| |
| var v: AnyObject = a[0] as AnyObject |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a[1] as AnyObject |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a[2] as AnyObject |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| // Bridge back to native array. |
| var native: [TestObjCValueTy] = convertNSArrayToArray(a) |
| native[0] = TestObjCValueTy(110) |
| native[1] = TestObjCValueTy(120) |
| native[2] = TestObjCValueTy(130) |
| native.append(TestObjCValueTy(140)) |
| |
| // Ensure that the compiler does not elide mutation of the native array. |
| _blackHole(native) |
| |
| // Check that mutating the native array did not affect the bridged array. |
| expectEqual(3, a.count) |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Verbatim/BridgeBack/Adopt") { |
| // Bridge back to native array. |
| var native: [TestObjCValueTy] = |
| getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3) as! Array |
| |
| let identity1 = unsafeBitCast(native, to: UInt.self) |
| |
| // Mutate elements, but don't change count. |
| native[0] = TestObjCValueTy(110) |
| native[1] = TestObjCValueTy(120) |
| native[2] = TestObjCValueTy(130) |
| |
| // Expect no reallocations. |
| expectEqual(identity1, unsafeBitCast(native, to: UInt.self)) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Array -> NSArray bridging tests |
| // |
| // Element is bridged non-verbatim. |
| // |
| // FIXME: incomplete. |
| //===----------------------------------------------------------------------===// |
| |
| ArrayTestSuite.test("BridgedToObjC.Nonverbatim.BridgeUsingAs") { |
| let source = [ 10, 20, 30 ].map { TestBridgedValueTy($0) } |
| var result = source as NSArray |
| expectTrue(isNativeNSArray(result)) |
| expectEqual(3, result.count) |
| autoreleasepoolIfUnoptimizedReturnAutoreleased { |
| expectEqual(10, (result[0] as! TestBridgedValueTy).value) |
| expectEqual(20, (result[1] as! TestBridgedValueTy).value) |
| expectEqual(30, (result[2] as! TestBridgedValueTy).value) |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/count/empty") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 0) |
| expectEqual(0, a.count) |
| |
| expectEqual(0, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/count") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged() |
| expectEqual(3, a.count) |
| |
| expectEqual(0, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| for index in [ -100, -1, 0, 1, 100 ] { |
| ArrayTestSuite.test( |
| "BridgedToObjC/Custom/objectAtIndex/empty/trap/\(index)") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 0) |
| expectCrashLater() |
| a.object(at: index) |
| } |
| } |
| |
| for index in [ -100, -1, 3, 4, 100 ] { |
| ArrayTestSuite.test("BridgedToObjC/Custom/objectAtIndex/trap/\(index)") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| expectCrashLater() |
| a.object(at: index) |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/objectAtIndex") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| var v: AnyObject = a.object(at: 0) as AnyObject |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a.object(at: 1) as AnyObject |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a.object(at: 2) as AnyObject |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| for i in 0..<3 { |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| } |
| |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| for indexRange in [ |
| -2..<(-2), 1..<1, |
| 0..<4, -2..<(-1), -1..<2, 0..<1, 2..<4, 4..<5 |
| ] as [Range<Int>] { |
| ArrayTestSuite.test("BridgedToObjC/Custom/getObjects/empty/trap/\(indexRange)") |
| .crashOutputMatches("Array index out of range") |
| .code { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged( |
| numElements: 0, capacity: 16) |
| let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: 16) |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<0)) |
| expectCrashLater() |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(indexRange)) |
| } |
| } |
| |
| for indexRange in [ 0..<4, -2..<(-1), -1..<2, 2..<4, 4..<5 ] as [Range<Int>] { |
| ArrayTestSuite.test("BridgedToObjC/Custom/getObjects/trap/\(indexRange)") |
| .crashOutputMatches("Array index out of range") |
| .code { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged( |
| numElements: 3, capacity: 16) |
| let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: 16) |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<3)) |
| expectCrashLater() |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(indexRange)) |
| } |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/getObjects") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: 16) |
| a.available_getObjects( |
| AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<3)) |
| |
| var v: AnyObject = buffer[0] |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = buffer[1] |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = buffer[2] |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| for i in 0..<3 { |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| } |
| |
| buffer.deallocate() |
| _fixLifetime(a) |
| |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/copyWithZone") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| let copy: AnyObject = a.copy(with: nil) as AnyObject |
| expectEqual( |
| unsafeBitCast(a, to: UInt.self), |
| unsafeBitCast(copy, to: UInt.self)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/FastEnumeration/UseFromSwift/Empty") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 0) |
| |
| checkArrayFastEnumerationFromSwift( |
| [], a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(0, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/FastEnumeration/UseFromSwift/3") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromSwift( |
| [ 10, 20, 30 ], |
| a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/FastEnumeration/UseFromSwift/7") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 7) |
| |
| checkArrayFastEnumerationFromSwift( |
| [ 10, 20, 30, 40, 50, 60, 70 ], |
| a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(7, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/FastEnumeration/UseFromObjC/Empty") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 0) |
| |
| checkArrayFastEnumerationFromObjC( |
| [], a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(0, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/FastEnumeration/UseFromObjC") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromObjC( |
| [ 10, 20, 30 ], |
| a, { a }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/ObjectEnumerator/FastEnumeration/UseFromSwift/Empty") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 0) |
| |
| checkArrayFastEnumerationFromSwift( |
| [], a, { a.objectEnumerator() }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(0, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/ObjectEnumerator/FastEnumeration/UseFromSwift") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromSwift( |
| [ 10, 20, 30 ], |
| a, { a.objectEnumerator() }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/ObjectEnumerator/FastEnumeration/UseFromSwift/Partial") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 9) |
| |
| checkArrayEnumeratorPartialFastEnumerationFromSwift( |
| [ 10, 20, 30, 40, 50, 60, 70, 80, 90 ], |
| a, maxFastEnumerationItems: 5, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(9, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/ObjectEnumerator/FastEnumeration/UseFromObjC") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| checkArrayFastEnumerationFromObjC( |
| [ 10, 20, 30 ], |
| a, { a.objectEnumerator() }, |
| { ($0 as! TestObjCValueTy).value }) |
| |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/BridgeBack/Cast") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| var v: AnyObject = a[0] as AnyObject |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a[1] as AnyObject |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a[2] as AnyObject |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| // Bridge back to native array with a cast. |
| var native: [TestObjCValueTy] = convertNSArrayToArray(a) |
| native[0] = TestObjCValueTy(110) |
| native[1] = TestObjCValueTy(120) |
| native[2] = TestObjCValueTy(130) |
| native.append(TestObjCValueTy(140)) |
| |
| // Ensure that the compiler does not elide mutation of the native array. |
| _blackHole(native) |
| |
| // Check that mutating the native array did not affect the bridged array. |
| expectEqual(3, a.count) |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/BridgeBack/Reallocate") { |
| let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3) |
| |
| var v: AnyObject = a[0] as AnyObject |
| expectEqual(10, (v as! TestObjCValueTy).value) |
| let idValue0 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a[1] as AnyObject |
| expectEqual(20, (v as! TestObjCValueTy).value) |
| let idValue1 = unsafeBitCast(v, to: UInt.self) |
| |
| v = a[2] as AnyObject |
| expectEqual(30, (v as! TestObjCValueTy).value) |
| let idValue2 = unsafeBitCast(v, to: UInt.self) |
| |
| // Bridge back to native array. |
| var native: [TestBridgedValueTy] = convertNSArrayToArray(a) |
| native[0] = TestBridgedValueTy(110) |
| native[1] = TestBridgedValueTy(120) |
| native[2] = TestBridgedValueTy(130) |
| native.append(TestBridgedValueTy(140)) |
| |
| // Ensure that the compiler does not elide mutation of the native array. |
| _blackHole(native) |
| |
| // Check that mutating the native array did not affect the bridged array. |
| expectEqual(3, a.count) |
| expectEqual(idValue0, unsafeBitCast(a.object(at: 0) as AnyObject, to: UInt.self)) |
| expectEqual(idValue1, unsafeBitCast(a.object(at: 1) as AnyObject, to: UInt.self)) |
| expectEqual(idValue2, unsafeBitCast(a.object(at: 2) as AnyObject, to: UInt.self)) |
| |
| expectAutoreleasedKeysAndValues(unopt: (0, 3)) |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC/Custom/BridgeBack/Adopt") { |
| // Bridge back to native array. |
| var native: [TestBridgedValueTy] = convertNSArrayToArray( |
| getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3)) |
| let identity1 = unsafeBitCast(native, to: UInt.self) |
| |
| // Mutate elements, but don't change count. |
| native[0] = TestBridgedValueTy(110) |
| native[1] = TestBridgedValueTy(120) |
| native[2] = TestBridgedValueTy(130) |
| |
| // Expect no reallocations. |
| expectEqual(identity1, unsafeBitCast(native, to: UInt.self)) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // NSArray -> Array -> NSArray bridging tests. |
| //===----------------------------------------------------------------------===// |
| |
| ArrayTestSuite.test("BridgedToObjC.Verbatim.RoundtripThroughSwiftArray") { |
| % for (MiddleType, AsCast) in [ |
| % ('Array<AnyObject>', 'as'), |
| % ('Array<TestObjCValueTy>', 'as!'), |
| % ]: |
| do { |
| let nsa: NSArray = getAsImmutableNSArray([ 10, 20, 30 ]) |
| let a: ${MiddleType} = convertNSArrayToArray(nsa) |
| let bridgedBack = convertArrayToNSArray(a) |
| |
| expectEqual( |
| unsafeBitCast(nsa, to: Int.self), |
| unsafeBitCast(bridgedBack, to: Int.self)) |
| |
| _fixLifetime(nsa) |
| _fixLifetime(a) |
| _fixLifetime(bridgedBack) |
| } |
| do { |
| let nsa: NSArray = getAsImmutableNSArray([ 10, 20, 30 ]) |
| let a = nsa ${AsCast} ${MiddleType} |
| let bridgedBack: NSArray = a as NSArray |
| |
| expectEqual( |
| unsafeBitCast(nsa, to: Int.self), |
| unsafeBitCast(bridgedBack, to: Int.self)) |
| |
| _fixLifetime(nsa) |
| _fixLifetime(a) |
| _fixLifetime(bridgedBack) |
| } |
| % end |
| } |
| |
| ArrayTestSuite.test("BridgedToObjC.Nonverbatim.RoundtripThroughSwiftArray") { |
| do { |
| TestBridgedValueTy.bridgeOperations = 0 |
| let nsa: NSArray = getAsImmutableNSArray([ 10, 20, 30 ]) |
| let a: Array<TestBridgedValueTy> = convertNSArrayToArray(nsa) |
| let bridgedBack = convertArrayToNSArray(a) |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| do { |
| TestBridgedValueTy.bridgeOperations = 0 |
| let nsa: NSArray = getAsImmutableNSArray([ 10, 20, 30 ]) |
| let a = nsa as! Array<TestBridgedValueTy> |
| let bridgedBack: NSArray = a as NSArray |
| expectEqual(3, TestBridgedValueTy.bridgeOperations) |
| } |
| } |
| |
| ArrayTestSuite.setUp { |
| resetLeaksOfDictionaryKeysValues() |
| resetLeaksOfObjCDictionaryKeysValues() |
| TestBridgedValueTy.bridgeOperations = 0 |
| } |
| |
| ArrayTestSuite.tearDown { |
| if _isDebugAssertConfiguration() { |
| // The return autorelease optimization does not happen reliable. |
| expectNoLeaksOfDictionaryKeysValues() |
| expectNoLeaksOfObjCDictionaryKeysValues() |
| } |
| } |
| |
| #endif // _runtime(_ObjC) |
| |
| runAllTests() |