mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Implements SE-0055: https://github.com/apple/swift-evolution/blob/master/proposals/0055-optional-unsafe-pointers.md - Add NULL as an extra inhabitant of Builtin.RawPointer (currently hardcoded to 0 rather than being target-dependent). - Import non-object pointers as Optional/IUO when nullable/null_unspecified (like everything else). - Change the type checker's *-to-pointer conversions to handle a layer of optional. - Use 'AutoreleasingUnsafeMutablePointer<NSError?>?' as the type of error parameters exported to Objective-C. - Drop NilLiteralConvertible conformance for all pointer types. - Update the standard library and then all the tests. I've decided to leave this commit only updating existing tests; any new tests will come in the following commits. (That may mean some additional implementation work to follow.) The other major piece that's missing here is migration. I'm hoping we get a lot of that with Swift 1.1's work for optional object references, but I still need to investigate.
1145 lines
36 KiB
Plaintext
1145 lines
36 KiB
Plaintext
// RUN: rm -rf %t
|
|
// RUN: mkdir -p %t
|
|
//
|
|
// RUN: %S/../../utils/gyb %s -o %t/main.swift
|
|
// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o
|
|
// RUN: %S/../../utils/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: %S/../../utils/line-directive %t/main.swift -- %target-run %t/Array
|
|
// REQUIRES: executable_test
|
|
|
|
// XFAIL: linux
|
|
|
|
import Darwin
|
|
import StdlibUnittest
|
|
import StdlibCollectionUnittest
|
|
|
|
|
|
import StdlibUnittestFoundationExtras
|
|
import Foundation
|
|
|
|
%{
|
|
all_array_types = ['ContiguousArray', 'ArraySlice', 'Array']
|
|
}%
|
|
|
|
extension Array {
|
|
var identity: UnsafePointer<Void> {
|
|
return self._buffer.identity
|
|
}
|
|
}
|
|
|
|
extension ArraySlice {
|
|
var identity: UnsafePointer<Void> {
|
|
return self._buffer.identity
|
|
}
|
|
}
|
|
|
|
extension ContiguousArray {
|
|
var identity: UnsafePointer<Void> {
|
|
return self._buffer.identity
|
|
}
|
|
}
|
|
|
|
var ArrayTestSuite = TestSuite("Array")
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// COW tests
|
|
// FIXME: incomplete.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
func withInoutInt(_ x: inout Int, body: (x: inout Int) -> Void) {
|
|
body(x: &x)
|
|
}
|
|
|
|
func withInoutT<T>(_ x: inout T, body: (x: inout T) -> Void) {
|
|
body(x: &x)
|
|
}
|
|
|
|
% for element_type in ['TestValueTy', 'TestBridgedValueTy']:
|
|
% for array_type in all_array_types:
|
|
|
|
ArrayTestSuite.test("${array_type}<${element_type}>/subscript(_: Int)/COW") {
|
|
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.identity
|
|
var identityInner = a[0].identity
|
|
|
|
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.identity, stackTrace: stackTrace)
|
|
expectEqual(identityInner, a[0].identity, stackTrace: stackTrace)
|
|
% else:
|
|
expectEqual(identityOuter, a.identity, stackTrace: stackTrace)
|
|
|
|
// Should not reallocate storage.
|
|
expectEqual(identityInner, a[0].identity, 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") {
|
|
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.identity
|
|
var identityInner = a[0].identity
|
|
|
|
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.identity, stackTrace: stackTrace)
|
|
expectEqual(identityInner, a[0].identity, stackTrace: stackTrace)
|
|
% else:
|
|
expectEqual(identityOuter, a.identity, 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].identity, stackTrace: stackTrace)
|
|
identityInner = a[0].identity
|
|
% 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.identity)
|
|
expectNotEqual(identityInner, a[0].identity)
|
|
identityInner = a[0].identity
|
|
|
|
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.identity)
|
|
expectNotEqual(identityInner, a[0].identity)
|
|
identityInner = a[0].identity
|
|
|
|
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)
|
|
}
|
|
|
|
% end
|
|
% end
|
|
|
|
// 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?) -> AnyObject {
|
|
CustomImmutableNSArray.timesCopyWithZoneWasCalled += 1
|
|
return self
|
|
}
|
|
|
|
@objc
|
|
override func object(at index: Int) -> AnyObject {
|
|
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! 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") {
|
|
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)
|
|
expectEqual(10, (v as! TestObjCValueTy).value)
|
|
let idValue0 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a.object(at: 1)
|
|
expectEqual(20, (v as! TestObjCValueTy).value)
|
|
let idValue1 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a.object(at: 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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), 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>(allocatingCapacity: 16)
|
|
a.getObjects(
|
|
AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<0))
|
|
expectCrashLater()
|
|
a.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>(allocatingCapacity: 16)
|
|
a.getObjects(
|
|
AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<3))
|
|
expectCrashLater()
|
|
a.getObjects(
|
|
AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(indexRange))
|
|
}
|
|
}
|
|
|
|
ArrayTestSuite.test("BridgedToObjC/Verbatim/getObjects") {
|
|
let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3)
|
|
let buffer = UnsafeMutablePointer<AnyObject>(allocatingCapacity: 16)
|
|
a.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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), to: UInt.self))
|
|
}
|
|
|
|
buffer.deallocateCapacity(3)
|
|
_fixLifetime(a)
|
|
|
|
expectAutoreleasedKeysAndValues(unopt: (0, 3))
|
|
}
|
|
|
|
ArrayTestSuite.test("BridgedToObjC/Verbatim/copyWithZone") {
|
|
let a = getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3)
|
|
let copy: AnyObject = a.copy(with: nil)
|
|
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]
|
|
expectEqual(10, (v as! TestObjCValueTy).value)
|
|
let idValue0 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a[1]
|
|
expectEqual(20, (v as! TestObjCValueTy).value)
|
|
let idValue1 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a[2]
|
|
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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), to: UInt.self))
|
|
|
|
expectAutoreleasedKeysAndValues(unopt: (0, 3))
|
|
}
|
|
|
|
ArrayTestSuite.test("BridgedToObjC/Verbatim/BridgeBack/Adopt") {
|
|
// Bridge back to native array.
|
|
var native: [TestObjCValueTy] = convertNSArrayToArray(
|
|
getBridgedNSArrayOfRefTypeVerbatimBridged(numElements: 3))
|
|
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)
|
|
expectEqual(10, (v as! TestObjCValueTy).value)
|
|
let idValue0 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a.object(at: 1)
|
|
expectEqual(20, (v as! TestObjCValueTy).value)
|
|
let idValue1 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a.object(at: 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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), 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>(allocatingCapacity: 16)
|
|
a.getObjects(
|
|
AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<0))
|
|
expectCrashLater()
|
|
a.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>(allocatingCapacity: 16)
|
|
a.getObjects(
|
|
AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(0..<3))
|
|
expectCrashLater()
|
|
a.getObjects(
|
|
AutoreleasingUnsafeMutablePointer(buffer), range: NSRange(indexRange))
|
|
}
|
|
}
|
|
|
|
ArrayTestSuite.test("BridgedToObjC/Custom/getObjects") {
|
|
let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3)
|
|
let buffer = UnsafeMutablePointer<AnyObject>(allocatingCapacity: 16)
|
|
a.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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), to: UInt.self))
|
|
}
|
|
|
|
buffer.deallocateCapacity(3)
|
|
_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)
|
|
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]
|
|
expectEqual(10, (v as! TestObjCValueTy).value)
|
|
let idValue0 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a[1]
|
|
expectEqual(20, (v as! TestObjCValueTy).value)
|
|
let idValue1 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a[2]
|
|
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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), to: UInt.self))
|
|
|
|
expectAutoreleasedKeysAndValues(unopt: (0, 3))
|
|
}
|
|
|
|
ArrayTestSuite.test("BridgedToObjC/Custom/BridgeBack/Reallocate") {
|
|
let a = getBridgedNSArrayOfValueTypeCustomBridged(numElements: 3)
|
|
|
|
var v: AnyObject = a[0]
|
|
expectEqual(10, (v as! TestObjCValueTy).value)
|
|
let idValue0 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a[1]
|
|
expectEqual(20, (v as! TestObjCValueTy).value)
|
|
let idValue1 = unsafeBitCast(v, to: UInt.self)
|
|
|
|
v = a[2]
|
|
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), to: UInt.self))
|
|
expectEqual(idValue1, unsafeBitCast(a.object(at: 1), to: UInt.self))
|
|
expectEqual(idValue2, unsafeBitCast(a.object(at: 2), 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()
|
|
}
|
|
}
|
|
|
|
runAllTests()
|
|
|