| // RUN: %empty-directory(%t) |
| // |
| // RUN: %target-clang %S/Inputs/Mirror/Mirror.mm -c -o %t/Mirror.mm.o -g |
| // RUN: %target-build-swift -parse-stdlib -Xfrontend -disable-access-control -module-name a -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o %s -o %t.out |
| // RUN: %target-run %t.out |
| // REQUIRES: executable_test |
| // REQUIRES: objc_interop |
| |
| import Swift |
| import StdlibUnittest |
| |
| |
| import Foundation |
| import CoreGraphics |
| import SwiftShims |
| import MirrorObjC |
| |
| var nsObjectCanaryCount = 0 |
| @objc class NSObjectCanary : NSObject { |
| override init() { |
| nsObjectCanaryCount += 1 |
| } |
| deinit { |
| nsObjectCanaryCount -= 1 |
| } |
| } |
| |
| struct NSObjectCanaryStruct { |
| var ref = NSObjectCanary() |
| } |
| |
| var swiftObjectCanaryCount = 0 |
| class SwiftObjectCanary { |
| init() { |
| swiftObjectCanaryCount += 1 |
| } |
| deinit { |
| swiftObjectCanaryCount -= 1 |
| } |
| } |
| |
| struct SwiftObjectCanaryStruct { |
| var ref = SwiftObjectCanary() |
| } |
| |
| @objc class ClassA { |
| init(value: Int) { |
| self.value = value |
| } |
| |
| var value: Int |
| } |
| |
| struct BridgedValueType : _ObjectiveCBridgeable { |
| init(value: Int) { |
| self.value = value |
| } |
| |
| func _bridgeToObjectiveC() -> ClassA { |
| return ClassA(value: value) |
| } |
| |
| static func _forceBridgeFromObjectiveC( |
| _ x: ClassA, |
| result: inout BridgedValueType? |
| ) { |
| assert(x.value % 2 == 0, "not bridged to Objective-C") |
| result = BridgedValueType(value: x.value) |
| } |
| |
| static func _conditionallyBridgeFromObjectiveC( |
| _ x: ClassA, |
| result: inout BridgedValueType? |
| ) -> Bool { |
| if x.value % 2 == 0 { |
| result = BridgedValueType(value: x.value) |
| return true |
| } |
| |
| result = nil |
| return false |
| } |
| |
| static func _unconditionallyBridgeFromObjectiveC(_ source: ClassA?) |
| -> BridgedValueType { |
| var result: BridgedValueType? |
| _forceBridgeFromObjectiveC(source!, result: &result) |
| return result! |
| } |
| |
| var value: Int |
| var canaryRef = SwiftObjectCanary() |
| } |
| |
| struct BridgedLargeValueType : _ObjectiveCBridgeable { |
| init(value: Int) { |
| value0 = value |
| value1 = value |
| value2 = value |
| value3 = value |
| value4 = value |
| value5 = value |
| value6 = value |
| value7 = value |
| } |
| |
| func _bridgeToObjectiveC() -> ClassA { |
| assert(value == value0) |
| return ClassA(value: value0) |
| } |
| |
| static func _forceBridgeFromObjectiveC( |
| _ x: ClassA, |
| result: inout BridgedLargeValueType? |
| ) { |
| assert(x.value % 2 == 0, "not bridged to Objective-C") |
| result = BridgedLargeValueType(value: x.value) |
| } |
| |
| static func _conditionallyBridgeFromObjectiveC( |
| _ x: ClassA, |
| result: inout BridgedLargeValueType? |
| ) -> Bool { |
| if x.value % 2 == 0 { |
| result = BridgedLargeValueType(value: x.value) |
| return true |
| } |
| |
| result = nil |
| return false |
| } |
| |
| static func _unconditionallyBridgeFromObjectiveC(_ source: ClassA?) |
| -> BridgedLargeValueType { |
| var result: BridgedLargeValueType? |
| _forceBridgeFromObjectiveC(source!, result: &result) |
| return result! |
| } |
| |
| var value: Int { |
| let x = value0 |
| assert(value0 == x && value1 == x && value2 == x && value3 == x && |
| value4 == x && value5 == x && value6 == x && value7 == x) |
| return x |
| } |
| |
| var (value0, value1, value2, value3): (Int, Int, Int, Int) |
| var (value4, value5, value6, value7): (Int, Int, Int, Int) |
| var canaryRef = SwiftObjectCanary() |
| } |
| |
| class BridgedVerbatimRefType { |
| var value: Int = 42 |
| var canaryRef = SwiftObjectCanary() |
| } |
| |
| func withSwiftObjectCanary<T>( |
| _ createValue: () -> T, |
| _ check: (T) -> Void, |
| file: String = #file, line: UInt = #line |
| ) { |
| let stackTrace = SourceLocStack(SourceLoc(file, line)) |
| |
| swiftObjectCanaryCount = 0 |
| autoreleasepool { |
| var valueWithCanary = createValue() |
| expectEqual(1, swiftObjectCanaryCount, stackTrace: stackTrace) |
| check(valueWithCanary) |
| } |
| expectEqual(0, swiftObjectCanaryCount, stackTrace: stackTrace) |
| } |
| |
| var Runtime = TestSuite("Runtime") |
| |
| func _isClassOrObjCExistential_Opaque<T>(_ x: T.Type) -> Bool { |
| return _isClassOrObjCExistential(_opaqueIdentity(x)) |
| } |
| |
| Runtime.test("_isClassOrObjCExistential") { |
| expectTrue(_isClassOrObjCExistential(NSObjectCanary.self)) |
| expectTrue(_isClassOrObjCExistential_Opaque(NSObjectCanary.self)) |
| |
| expectFalse(_isClassOrObjCExistential(NSObjectCanaryStruct.self)) |
| expectFalse(_isClassOrObjCExistential_Opaque(NSObjectCanaryStruct.self)) |
| |
| expectTrue(_isClassOrObjCExistential(SwiftObjectCanary.self)) |
| expectTrue(_isClassOrObjCExistential_Opaque(SwiftObjectCanary.self)) |
| |
| expectFalse(_isClassOrObjCExistential(SwiftObjectCanaryStruct.self)) |
| expectFalse(_isClassOrObjCExistential_Opaque(SwiftObjectCanaryStruct.self)) |
| |
| typealias SwiftClosure = () -> () |
| expectFalse(_isClassOrObjCExistential(SwiftClosure.self)) |
| expectFalse(_isClassOrObjCExistential_Opaque(SwiftClosure.self)) |
| |
| typealias ObjCClosure = @convention(block) () -> () |
| expectTrue(_isClassOrObjCExistential(ObjCClosure.self)) |
| expectTrue(_isClassOrObjCExistential_Opaque(ObjCClosure.self)) |
| |
| expectTrue(_isClassOrObjCExistential(CFArray.self)) |
| expectTrue(_isClassOrObjCExistential_Opaque(CFArray.self)) |
| |
| expectTrue(_isClassOrObjCExistential(CFArray.self)) |
| expectTrue(_isClassOrObjCExistential_Opaque(CFArray.self)) |
| |
| expectTrue(_isClassOrObjCExistential(AnyObject.self)) |
| expectTrue(_isClassOrObjCExistential_Opaque(AnyObject.self)) |
| |
| // AnyClass == AnyObject.Type |
| expectFalse(_isClassOrObjCExistential(AnyClass.self)) |
| expectFalse(_isClassOrObjCExistential_Opaque(AnyClass.self)) |
| |
| expectFalse(_isClassOrObjCExistential(AnyObject.Protocol.self)) |
| expectFalse(_isClassOrObjCExistential_Opaque(AnyObject.Protocol.self)) |
| |
| expectFalse(_isClassOrObjCExistential(NSObjectCanary.Type.self)) |
| expectFalse(_isClassOrObjCExistential_Opaque(NSObjectCanary.Type.self)) |
| } |
| |
| Runtime.test("_canBeClass") { |
| expectEqual(1, _canBeClass(NSObjectCanary.self)) |
| expectEqual(0, _canBeClass(NSObjectCanaryStruct.self)) |
| |
| typealias ObjCClosure = @convention(block) () -> () |
| expectEqual(1, _canBeClass(ObjCClosure.self)) |
| |
| expectEqual(1, _canBeClass(CFArray.self)) |
| } |
| |
| Runtime.test("bridgeToObjectiveC") { |
| expectEqual(42, (_bridgeAnythingToObjectiveC(BridgedValueType(value: 42)) as! ClassA).value) |
| |
| expectEqual(42, (_bridgeAnythingToObjectiveC(BridgedLargeValueType(value: 42)) as! ClassA).value) |
| |
| var bridgedVerbatimRef = BridgedVerbatimRefType() |
| expectTrue(_bridgeAnythingToObjectiveC(bridgedVerbatimRef) === bridgedVerbatimRef) |
| } |
| |
| Runtime.test("bridgeToObjectiveC/NoLeak") { |
| withSwiftObjectCanary( |
| { BridgedValueType(value: 42) }, |
| { expectEqual(42, (_bridgeAnythingToObjectiveC($0) as! ClassA).value) }) |
| |
| withSwiftObjectCanary( |
| { BridgedLargeValueType(value: 42) }, |
| { expectEqual(42, (_bridgeAnythingToObjectiveC($0) as! ClassA).value) }) |
| |
| withSwiftObjectCanary( |
| { BridgedVerbatimRefType() }, |
| { expectTrue(_bridgeAnythingToObjectiveC($0) === $0) }) |
| } |
| |
| Runtime.test("forceBridgeFromObjectiveC") { |
| |
| // Bridge back using BridgedValueType. |
| expectNil(_conditionallyBridgeFromObjectiveC( |
| ClassA(value: 21), BridgedValueType.self)) |
| |
| expectEqual(42, _forceBridgeFromObjectiveC( |
| ClassA(value: 42), BridgedValueType.self).value) |
| expectEqual(42, _conditionallyBridgeFromObjectiveC( |
| ClassA(value: 42), BridgedValueType.self)!.value) |
| |
| expectNil(_conditionallyBridgeFromObjectiveC( |
| BridgedVerbatimRefType(), BridgedValueType.self)) |
| |
| // Bridge back using BridgedLargeValueType. |
| expectNil(_conditionallyBridgeFromObjectiveC( |
| ClassA(value: 21), BridgedLargeValueType.self)) |
| |
| expectEqual(42, _forceBridgeFromObjectiveC( |
| ClassA(value: 42), BridgedLargeValueType.self).value) |
| expectEqual(42, _conditionallyBridgeFromObjectiveC( |
| ClassA(value: 42), BridgedLargeValueType.self)!.value) |
| |
| expectNil(_conditionallyBridgeFromObjectiveC( |
| BridgedVerbatimRefType(), BridgedLargeValueType.self)) |
| |
| // Bridge back using BridgedVerbatimRefType. |
| expectNil(_conditionallyBridgeFromObjectiveC( |
| ClassA(value: 21), BridgedVerbatimRefType.self)) |
| |
| expectNil(_conditionallyBridgeFromObjectiveC( |
| ClassA(value: 42), BridgedVerbatimRefType.self)) |
| |
| var bridgedVerbatimRef = BridgedVerbatimRefType() |
| expectTrue(_forceBridgeFromObjectiveC( |
| bridgedVerbatimRef, BridgedVerbatimRefType.self) === bridgedVerbatimRef) |
| expectTrue(_conditionallyBridgeFromObjectiveC( |
| bridgedVerbatimRef, BridgedVerbatimRefType.self)! === bridgedVerbatimRef) |
| } |
| |
| |
| Runtime.test("isBridgedToObjectiveC") { |
| expectTrue(_isBridgedToObjectiveC(BridgedValueType)) |
| expectTrue(_isBridgedToObjectiveC(BridgedVerbatimRefType)) |
| } |
| |
| Runtime.test("isBridgedVerbatimToObjectiveC") { |
| expectFalse(_isBridgedVerbatimToObjectiveC(BridgedValueType)) |
| expectTrue(_isBridgedVerbatimToObjectiveC(BridgedVerbatimRefType)) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| |
| class SomeClass {} |
| @objc class SomeObjCClass {} |
| class SomeNSObjectSubclass : NSObject {} |
| |
| Runtime.test("typeName") { |
| expectEqual("a.SomeObjCClass", _typeName(SomeObjCClass.self)) |
| expectEqual("a.SomeNSObjectSubclass", _typeName(SomeNSObjectSubclass.self)) |
| expectEqual("NSObject", _typeName(NSObject.self)) |
| |
| var a : Any = SomeObjCClass() |
| expectEqual("a.SomeObjCClass", _typeName(type(of: a))) |
| |
| a = SomeNSObjectSubclass() |
| expectEqual("a.SomeNSObjectSubclass", _typeName(type(of: a))) |
| |
| a = NSObject() |
| expectEqual("NSObject", _typeName(type(of: a))) |
| } |
| |
| class GenericClass<T> {} |
| class MultiGenericClass<T, U> {} |
| struct GenericStruct<T> {} |
| enum GenericEnum<T> {} |
| |
| struct PlainStruct {} |
| enum PlainEnum {} |
| |
| protocol ProtocolA {} |
| protocol ProtocolB {} |
| |
| Runtime.test("Generic class ObjC runtime names") { |
| expectEqual("_TtGC1a12GenericClassSi_", |
| NSStringFromClass(GenericClass<Int>.self)) |
| expectEqual("_TtGC1a12GenericClassVS_11PlainStruct_", |
| NSStringFromClass(GenericClass<PlainStruct>.self)) |
| expectEqual("_TtGC1a12GenericClassOS_9PlainEnum_", |
| NSStringFromClass(GenericClass<PlainEnum>.self)) |
| expectEqual("_TtGC1a12GenericClassTVS_11PlainStructOS_9PlainEnumS1___", |
| NSStringFromClass(GenericClass<(PlainStruct, PlainEnum, PlainStruct)>.self)) |
| expectEqual("_TtGC1a12GenericClassMVS_11PlainStruct_", |
| NSStringFromClass(GenericClass<PlainStruct.Type>.self)) |
| expectEqual("_TtGC1a12GenericClassFMVS_11PlainStructS1__", |
| NSStringFromClass(GenericClass<(PlainStruct.Type) -> PlainStruct>.self)) |
| |
| expectEqual("_TtGC1a12GenericClassFzMVS_11PlainStructS1__", |
| NSStringFromClass(GenericClass<(PlainStruct.Type) throws -> PlainStruct>.self)) |
| expectEqual("_TtGC1a12GenericClassFTVS_11PlainStructROS_9PlainEnum_Si_", |
| NSStringFromClass(GenericClass<(PlainStruct, inout PlainEnum) -> Int>.self)) |
| |
| expectEqual("_TtGC1a12GenericClassPS_9ProtocolA__", |
| NSStringFromClass(GenericClass<ProtocolA>.self)) |
| expectEqual("_TtGC1a12GenericClassPS_9ProtocolAS_9ProtocolB__", |
| NSStringFromClass(GenericClass<ProtocolA & ProtocolB>.self)) |
| expectEqual("_TtGC1a12GenericClassPMPS_9ProtocolAS_9ProtocolB__", |
| NSStringFromClass(GenericClass<(ProtocolA & ProtocolB).Type>.self)) |
| expectEqual("_TtGC1a12GenericClassMPS_9ProtocolAS_9ProtocolB__", |
| NSStringFromClass(GenericClass<(ProtocolB & ProtocolA).Protocol>.self)) |
| |
| expectEqual("_TtGC1a12GenericClassCSo7CFArray_", |
| NSStringFromClass(GenericClass<CFArray>.self)) |
| expectEqual("_TtGC1a12GenericClassVSC7Decimal_", |
| NSStringFromClass(GenericClass<Decimal>.self)) |
| expectEqual("_TtGC1a12GenericClassCSo8NSObject_", |
| NSStringFromClass(GenericClass<NSObject>.self)) |
| expectEqual("_TtGC1a12GenericClassCSo8NSObject_", |
| NSStringFromClass(GenericClass<NSObject>.self)) |
| expectEqual("_TtGC1a12GenericClassPSo9NSCopying__", |
| NSStringFromClass(GenericClass<NSCopying>.self)) |
| expectEqual("_TtGC1a12GenericClassPSo9NSCopyingS_9ProtocolAS_9ProtocolB__", |
| NSStringFromClass(GenericClass<ProtocolB & NSCopying & ProtocolA>.self)) |
| |
| expectEqual("_TtGC1a12GenericClassXcCS_9SomeClassS_9ProtocolA__", |
| NSStringFromClass(GenericClass<ProtocolA & SomeClass>.self)) |
| expectEqual("_TtGC1a12GenericClassPS_9ProtocolAs9AnyObject__", |
| NSStringFromClass(GenericClass<ProtocolA & AnyObject>.self)) |
| expectEqual("_TtGC1a12GenericClassPs9AnyObject__", |
| NSStringFromClass(GenericClass<AnyObject>.self)) |
| |
| expectEqual("_TtGC1a17MultiGenericClassGVS_13GenericStructSi_GOS_11GenericEnumGS2_Si___", |
| NSStringFromClass(MultiGenericClass<GenericStruct<Int>, |
| GenericEnum<GenericEnum<Int>>>.self)) |
| } |
| |
| Runtime.test("typeByName") { |
| // Make sure we don't crash if we have foreign classes in the |
| // table -- those don't have NominalTypeDescriptors |
| print(CFArray.self) |
| expectTrue(_typeByName("a.SomeClass") == SomeClass.self) |
| expectTrue(_typeByName("DoesNotExist") == nil) |
| } |
| |
| Runtime.test("casting AnyObject to class metatypes") { |
| do { |
| var ao: AnyObject = SomeClass.self |
| expectTrue(ao as? Any.Type == SomeClass.self) |
| expectTrue(ao as? AnyClass == SomeClass.self) |
| expectTrue(ao as? SomeClass.Type == SomeClass.self) |
| } |
| |
| do { |
| var ao : AnyObject = SomeNSObjectSubclass() |
| expectTrue(ao as? Any.Type == nil) |
| expectTrue(ao as? AnyClass == nil) |
| |
| ao = SomeNSObjectSubclass.self |
| expectTrue(ao as? Any.Type == SomeNSObjectSubclass.self) |
| expectTrue(ao as? AnyClass == SomeNSObjectSubclass.self) |
| expectTrue(ao as? SomeNSObjectSubclass.Type == SomeNSObjectSubclass.self) |
| } |
| |
| do { |
| var a : Any = SomeNSObjectSubclass() |
| expectTrue(a as? Any.Type == nil) |
| expectTrue(a as? AnyClass == nil) |
| } |
| |
| do { |
| var nso: NSObject = SomeNSObjectSubclass() |
| expectTrue(nso as? AnyClass == nil) |
| |
| nso = (SomeNSObjectSubclass.self as AnyObject) as! NSObject |
| expectTrue(nso as? Any.Type == SomeNSObjectSubclass.self) |
| expectTrue(nso as? AnyClass == SomeNSObjectSubclass.self) |
| expectTrue(nso as? SomeNSObjectSubclass.Type == SomeNSObjectSubclass.self) |
| } |
| } |
| |
| var RuntimeFoundationWrappers = TestSuite("RuntimeFoundationWrappers") |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSObject_isEqual/NoLeak") { |
| nsObjectCanaryCount = 0 |
| autoreleasepool { |
| let a = NSObjectCanary() |
| let b = NSObjectCanary() |
| expectEqual(2, nsObjectCanaryCount) |
| _stdlib_NSObject_isEqual(a, b) |
| } |
| expectEqual(0, nsObjectCanaryCount) |
| } |
| |
| var nsStringCanaryCount = 0 |
| @objc class NSStringCanary : NSString { |
| override init() { |
| nsStringCanaryCount += 1 |
| super.init() |
| } |
| required init(coder: NSCoder) { |
| fatalError("don't call this initializer") |
| } |
| required init(itemProviderData data: Data, typeIdentifier: String) throws { |
| fatalError("don't call this initializer") |
| } |
| deinit { |
| nsStringCanaryCount -= 1 |
| } |
| @objc override var length: Int { |
| return 0 |
| } |
| @objc override func character(at index: Int) -> unichar { |
| fatalError("out-of-bounds access") |
| } |
| } |
| |
| RuntimeFoundationWrappers.test( |
| "_stdlib_compareNSStringDeterministicUnicodeCollation/NoLeak" |
| ) { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| let b = NSStringCanary() |
| expectEqual(2, nsStringCanaryCount) |
| _stdlib_compareNSStringDeterministicUnicodeCollation(a, b) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test( |
| "_stdlib_compareNSStringDeterministicUnicodeCollationPtr/NoLeak" |
| ) { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| let b = NSStringCanary() |
| expectEqual(2, nsStringCanaryCount) |
| let ptrA = unsafeBitCast(a, to: OpaquePointer.self) |
| let ptrB = unsafeBitCast(b, to: OpaquePointer.self) |
| _stdlib_compareNSStringDeterministicUnicodeCollationPointer(ptrA, ptrB) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHashValue/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_NSStringHashValue(a, true) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHashValueNonASCII/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_NSStringHashValue(a, false) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHashValuePointer/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| let ptrA = unsafeBitCast(a, to: OpaquePointer.self) |
| _stdlib_NSStringHashValuePointer(ptrA, true) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHashValuePointerNonASCII/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| let ptrA = unsafeBitCast(a, to: OpaquePointer.self) |
| _stdlib_NSStringHashValuePointer(ptrA, false) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHasPrefixNFDPointer/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| let b = NSStringCanary() |
| expectEqual(2, nsStringCanaryCount) |
| let ptrA = unsafeBitCast(a, to: OpaquePointer.self) |
| let ptrB = unsafeBitCast(b, to: OpaquePointer.self) |
| _stdlib_NSStringHasPrefixNFDPointer(ptrA, ptrB) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHasSuffixNFDPointer/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| let b = NSStringCanary() |
| expectEqual(2, nsStringCanaryCount) |
| let ptrA = unsafeBitCast(a, to: OpaquePointer.self) |
| let ptrB = unsafeBitCast(b, to: OpaquePointer.self) |
| _stdlib_NSStringHasSuffixNFDPointer(ptrA, ptrB) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHasPrefixNFD/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| let b = NSStringCanary() |
| expectEqual(2, nsStringCanaryCount) |
| _stdlib_NSStringHasPrefixNFD(a, b) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringHasSuffixNFD/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| let b = NSStringCanary() |
| expectEqual(2, nsStringCanaryCount) |
| _stdlib_NSStringHasSuffixNFD(a, b) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringLowercaseString/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_NSStringLowercaseString(a) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_NSStringUppercaseString/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_NSStringUppercaseString(a) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_CFStringCreateCopy/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_binary_CFStringCreateCopy(a) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_CFStringGetLength/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_binary_CFStringGetLength(a) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("_stdlib_CFStringGetCharactersPtr/NoLeak") { |
| nsStringCanaryCount = 0 |
| autoreleasepool { |
| let a = NSStringCanary() |
| expectEqual(1, nsStringCanaryCount) |
| _stdlib_binary_CFStringGetCharactersPtr(a) |
| } |
| expectEqual(0, nsStringCanaryCount) |
| } |
| |
| RuntimeFoundationWrappers.test("bridgedNSArray") { |
| var c = [NSObject]() |
| autoreleasepool { |
| let a = [NSObject]() |
| let b = a as NSArray |
| c = b as! [NSObject] |
| } |
| c.append(NSObject()) |
| // expect no crash. |
| } |
| |
| var Reflection = TestSuite("Reflection") |
| |
| class SwiftFooMoreDerivedObjCClass : FooMoreDerivedObjCClass { |
| let first: Int = 123 |
| let second: String = "abc" |
| } |
| |
| Reflection.test("Class/ObjectiveCBase/Default") { |
| do { |
| let value = SwiftFooMoreDerivedObjCClass() |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "▿ This is FooObjCClass #0\n" + |
| " - super: FooMoreDerivedObjCClass\n" + |
| " - super: FooDerivedObjCClass\n" + |
| " - super: FooObjCClass\n" + |
| " - super: NSObject\n" + |
| " - first: 123\n" + |
| " - second: \"abc\"\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| protocol SomeNativeProto {} |
| @objc protocol SomeObjCProto {} |
| extension SomeClass: SomeObjCProto {} |
| |
| Reflection.test("MetatypeMirror") { |
| do { |
| let concreteClassMetatype = SomeClass.self |
| let expectedSomeClass = "- a.SomeClass #0\n" |
| let objcProtocolMetatype: SomeObjCProto.Type = SomeClass.self |
| var output = "" |
| dump(objcProtocolMetatype, to: &output) |
| expectEqual(expectedSomeClass, output) |
| |
| let objcProtocolConcreteMetatype = SomeObjCProto.self |
| let expectedObjCProtocolConcrete = "- a.SomeObjCProto #0\n" |
| output = "" |
| dump(objcProtocolConcreteMetatype, to: &output) |
| expectEqual(expectedObjCProtocolConcrete, output) |
| |
| let compositionConcreteMetatype = (SomeNativeProto & SomeObjCProto).self |
| let expectedComposition = "- a.SomeNativeProto & a.SomeObjCProto #0\n" |
| output = "" |
| dump(compositionConcreteMetatype, to: &output) |
| expectEqual(expectedComposition, output) |
| |
| let objcDefinedProtoType = NSObjectProtocol.self |
| expectEqual(String(describing: objcDefinedProtoType), "NSObject") |
| } |
| } |
| |
| Reflection.test("CGPoint") { |
| var output = "" |
| dump(CGPoint(x: 1.25, y: 2.75), to: &output) |
| |
| let expected = |
| "▿ (1.25, 2.75)\n" + |
| " - x: 1.25\n" + |
| " - y: 2.75\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("CGSize") { |
| var output = "" |
| dump(CGSize(width: 1.25, height: 2.75), to: &output) |
| |
| let expected = |
| "▿ (1.25, 2.75)\n" + |
| " - width: 1.25\n" + |
| " - height: 2.75\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("CGRect") { |
| var output = "" |
| dump( |
| CGRect( |
| origin: CGPoint(x: 1.25, y: 2.25), |
| size: CGSize(width: 10.25, height: 11.75)), |
| to: &output) |
| |
| let expected = |
| "▿ (1.25, 2.25, 10.25, 11.75)\n" + |
| " ▿ origin: (1.25, 2.25)\n" + |
| " - x: 1.25\n" + |
| " - y: 2.25\n" + |
| " ▿ size: (10.25, 11.75)\n" + |
| " - width: 10.25\n" + |
| " - height: 11.75\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("Unmanaged/nil") { |
| var output = "" |
| var optionalURL: Unmanaged<CFURL>? |
| dump(optionalURL, to: &output) |
| |
| let expected = "- nil\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("Unmanaged/not-nil") { |
| var output = "" |
| var optionalURL: Unmanaged<CFURL>? = |
| Unmanaged.passRetained(CFURLCreateWithString(nil, "http://llvm.org/" as CFString, nil)) |
| dump(optionalURL, to: &output) |
| |
| let expected = |
| "▿ Optional(Swift.Unmanaged<__ObjC.CFURL>(_value: http://llvm.org/))\n" + |
| " ▿ some: Swift.Unmanaged<__ObjC.CFURL>\n" + |
| " - _value: http://llvm.org/ #0\n" + |
| " - super: NSObject\n" |
| |
| expectEqual(expected, output) |
| |
| optionalURL!.release() |
| } |
| |
| Reflection.test("TupleMirror/NoLeak") { |
| do { |
| nsObjectCanaryCount = 0 |
| autoreleasepool { |
| var tuple = (1, NSObjectCanary()) |
| expectEqual(1, nsObjectCanaryCount) |
| var output = "" |
| dump(tuple, to: &output) |
| } |
| expectEqual(0, nsObjectCanaryCount) |
| } |
| do { |
| nsObjectCanaryCount = 0 |
| autoreleasepool { |
| var tuple = (1, NSObjectCanaryStruct()) |
| expectEqual(1, nsObjectCanaryCount) |
| var output = "" |
| dump(tuple, to: &output) |
| } |
| expectEqual(0, nsObjectCanaryCount) |
| } |
| do { |
| swiftObjectCanaryCount = 0 |
| autoreleasepool { |
| var tuple = (1, SwiftObjectCanary()) |
| expectEqual(1, swiftObjectCanaryCount) |
| var output = "" |
| dump(tuple, to: &output) |
| } |
| expectEqual(0, swiftObjectCanaryCount) |
| } |
| do { |
| swiftObjectCanaryCount = 0 |
| autoreleasepool { |
| var tuple = (1, SwiftObjectCanaryStruct()) |
| expectEqual(1, swiftObjectCanaryCount) |
| var output = "" |
| dump(tuple, to: &output) |
| } |
| expectEqual(0, swiftObjectCanaryCount) |
| } |
| } |
| |
| class TestArtificialSubclass: NSObject { |
| dynamic var foo = "foo" |
| } |
| |
| var KVOHandle = 0 |
| |
| Reflection.test("Name of metatype of artificial subclass") { |
| let obj = TestArtificialSubclass() |
| |
| expectEqual("\(type(of: obj))", "TestArtificialSubclass") |
| expectEqual(String(describing: type(of: obj)), "TestArtificialSubclass") |
| expectEqual(String(reflecting: type(of: obj)), "a.TestArtificialSubclass") |
| |
| // Trigger the creation of a KVO subclass for TestArtificialSubclass. |
| obj.addObserver(obj, forKeyPath: "foo", options: [.new], context: &KVOHandle) |
| expectEqual("\(type(of: obj))", "TestArtificialSubclass") |
| expectEqual(String(describing: type(of: obj)), "TestArtificialSubclass") |
| expectEqual(String(reflecting: type(of: obj)), "a.TestArtificialSubclass") |
| obj.removeObserver(obj, forKeyPath: "foo") |
| |
| expectEqual("\(type(of: obj))", "TestArtificialSubclass") |
| expectEqual(String(describing: type(of: obj)), "TestArtificialSubclass") |
| expectEqual(String(reflecting: type(of: obj)), "a.TestArtificialSubclass") |
| } |
| |
| @objc class StringConvertibleInDebugAndOtherwise : NSObject { |
| override var description: String { return "description" } |
| override var debugDescription: String { return "debugDescription" } |
| } |
| |
| Reflection.test("NSObject is properly CustomDebugStringConvertible") { |
| let object = StringConvertibleInDebugAndOtherwise() |
| expectEqual(String(reflecting: object), object.debugDescription) |
| } |
| |
| Reflection.test("NSRange QuickLook") { |
| let rng = NSRange(location:Int.min, length:5) |
| let ql = PlaygroundQuickLook(reflecting: rng) |
| switch ql { |
| case .range(let loc, let len): |
| expectEqual(loc, Int64(Int.min)) |
| expectEqual(len, 5) |
| default: |
| expectUnreachable("PlaygroundQuickLook for NSRange did not match Range") |
| } |
| } |
| |
| class SomeSubclass : SomeClass {} |
| |
| var ObjCConformsToProtocolTestSuite = TestSuite("ObjCConformsToProtocol") |
| |
| ObjCConformsToProtocolTestSuite.test("cast/instance") { |
| expectTrue(SomeClass() is SomeObjCProto) |
| expectTrue(SomeSubclass() is SomeObjCProto) |
| } |
| |
| ObjCConformsToProtocolTestSuite.test("cast/metatype") { |
| expectTrue(SomeClass.self is SomeObjCProto.Type) |
| expectTrue(SomeSubclass.self is SomeObjCProto.Type) |
| } |
| |
| runAllTests() |