// RUN: rm -rf %t && mkdir %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 // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif 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 NotBridgedValueType { // Keep it pointer-sized. var canaryRef = SwiftObjectCanary() } struct BridgedValueType : _ObjectiveCBridgeable { init(value: Int) { self.value = value } static func _getObjectiveCType() -> Any.Type { return ClassA.self } func _bridgeToObjectiveC() -> ClassA { return ClassA(value: value) } static func _isBridgedToObjectiveC() -> Bool { return true } 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 } 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 } static func _getObjectiveCType() -> Any.Type { return ClassA.self } func _bridgeToObjectiveC() -> ClassA { assert(value == value0) return ClassA(value: value0) } static func _isBridgedToObjectiveC() -> Bool { return true } 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 } 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() } struct ConditionallyBridgedValueType : _ObjectiveCBridgeable { init(value: Int) { self.value = value } static func _getObjectiveCType() -> Any.Type { return ClassA.self } func _bridgeToObjectiveC() -> ClassA { return ClassA(value: value) } static func _forceBridgeFromObjectiveC( x: ClassA, result: inout ConditionallyBridgedValueType? ) { assert(x.value % 2 == 0, "not bridged from Objective-C") result = ConditionallyBridgedValueType(value: x.value) } static func _conditionallyBridgeFromObjectiveC( x: ClassA, result: inout ConditionallyBridgedValueType? ) -> Bool { if x.value % 2 == 0 { result = ConditionallyBridgedValueType(value: x.value) return true } result = nil return false } static func _isBridgedToObjectiveC() -> Bool { return ((T.self as Any) as? String.Type) == nil } var value: Int var canaryRef = SwiftObjectCanary() } class BridgedVerbatimRefType { var value: Int = 42 var canaryRef = SwiftObjectCanary() } func withSwiftObjectCanary( 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(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") { expectEmpty(_bridgeToObjectiveC(NotBridgedValueType())) expectEqual(42, (_bridgeToObjectiveC(BridgedValueType(value: 42)) as! ClassA).value) expectEqual(42, (_bridgeToObjectiveC(BridgedLargeValueType(value: 42)) as! ClassA).value) expectEqual(42, (_bridgeToObjectiveC(ConditionallyBridgedValueType(value: 42)) as! ClassA).value) expectEmpty(_bridgeToObjectiveC(ConditionallyBridgedValueType(value: 42))) var bridgedVerbatimRef = BridgedVerbatimRefType() expectTrue(_bridgeToObjectiveC(bridgedVerbatimRef) === bridgedVerbatimRef) } Runtime.test("bridgeToObjectiveC/NoLeak") { withSwiftObjectCanary( { NotBridgedValueType() }, { expectEmpty(_bridgeToObjectiveC($0)) }) withSwiftObjectCanary( { BridgedValueType(value: 42) }, { expectEqual(42, (_bridgeToObjectiveC($0) as! ClassA).value) }) withSwiftObjectCanary( { BridgedLargeValueType(value: 42) }, { expectEqual(42, (_bridgeToObjectiveC($0) as! ClassA).value) }) withSwiftObjectCanary( { ConditionallyBridgedValueType(value: 42) }, { expectEqual(42, (_bridgeToObjectiveC($0) as! ClassA).value) }) withSwiftObjectCanary( { ConditionallyBridgedValueType(value: 42) }, { expectEmpty(_bridgeToObjectiveC($0)) }) withSwiftObjectCanary( { BridgedVerbatimRefType() }, { expectTrue(_bridgeToObjectiveC($0) === $0) }) } Runtime.test("forceBridgeFromObjectiveC") { // Bridge back using NotBridgedValueType. expectEmpty(_conditionallyBridgeFromObjectiveC( ClassA(value: 21), NotBridgedValueType.self)) expectEmpty(_conditionallyBridgeFromObjectiveC( ClassA(value: 42), NotBridgedValueType.self)) expectEmpty(_conditionallyBridgeFromObjectiveC( BridgedVerbatimRefType(), NotBridgedValueType.self)) // Bridge back using BridgedValueType. expectEmpty(_conditionallyBridgeFromObjectiveC( ClassA(value: 21), BridgedValueType.self)) expectEqual(42, _forceBridgeFromObjectiveC( ClassA(value: 42), BridgedValueType.self).value) expectEqual(42, _conditionallyBridgeFromObjectiveC( ClassA(value: 42), BridgedValueType.self)!.value) expectEmpty(_conditionallyBridgeFromObjectiveC( BridgedVerbatimRefType(), BridgedValueType.self)) // Bridge back using BridgedLargeValueType. expectEmpty(_conditionallyBridgeFromObjectiveC( ClassA(value: 21), BridgedLargeValueType.self)) expectEqual(42, _forceBridgeFromObjectiveC( ClassA(value: 42), BridgedLargeValueType.self).value) expectEqual(42, _conditionallyBridgeFromObjectiveC( ClassA(value: 42), BridgedLargeValueType.self)!.value) expectEmpty(_conditionallyBridgeFromObjectiveC( BridgedVerbatimRefType(), BridgedLargeValueType.self)) // Bridge back using BridgedVerbatimRefType. expectEmpty(_conditionallyBridgeFromObjectiveC( ClassA(value: 21), BridgedVerbatimRefType.self)) expectEmpty(_conditionallyBridgeFromObjectiveC( ClassA(value: 42), BridgedVerbatimRefType.self)) var bridgedVerbatimRef = BridgedVerbatimRefType() expectTrue(_forceBridgeFromObjectiveC( bridgedVerbatimRef, BridgedVerbatimRefType.self) === bridgedVerbatimRef) expectTrue(_conditionallyBridgeFromObjectiveC( bridgedVerbatimRef, BridgedVerbatimRefType.self)! === bridgedVerbatimRef) } Runtime.test("isBridgedToObjectiveC") { expectFalse(_isBridgedToObjectiveC(NotBridgedValueType)) expectTrue(_isBridgedToObjectiveC(BridgedValueType)) expectTrue(_isBridgedToObjectiveC(BridgedVerbatimRefType)) } Runtime.test("isBridgedVerbatimToObjectiveC") { expectFalse(_isBridgedVerbatimToObjectiveC(NotBridgedValueType)) 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(a.dynamicType)) a = SomeNSObjectSubclass() expectEqual("a.SomeNSObjectSubclass", _typeName(a.dynamicType)) a = NSObject() expectEqual("NSObject", _typeName(a.dynamicType)) } class GenericClass {} class MultiGenericClass {} struct GenericStruct {} enum GenericEnum {} struct PlainStruct {} enum PlainEnum {} protocol ProtocolA {} protocol ProtocolB {} Runtime.test("Generic class ObjC runtime names") { expectEqual("_TtGC1a12GenericClassSi_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassVS_11PlainStruct_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassOS_9PlainEnum_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassTVS_11PlainStructOS_9PlainEnumS1___", NSStringFromClass(GenericClass<(PlainStruct, PlainEnum, PlainStruct)>.self)) expectEqual("_TtGC1a12GenericClassMVS_11PlainStruct_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassFMVS_11PlainStructS1__", NSStringFromClass(GenericClass PlainStruct>.self)) expectEqual("_TtGC1a12GenericClassFzMVS_11PlainStructS1__", NSStringFromClass(GenericClass PlainStruct>.self)) expectEqual("_TtGC1a12GenericClassFTVS_11PlainStructROS_9PlainEnum_Si_", NSStringFromClass(GenericClass<(PlainStruct, inout PlainEnum) -> Int>.self)) expectEqual("_TtGC1a12GenericClassPS_9ProtocolA__", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassPS_9ProtocolAS_9ProtocolB__", NSStringFromClass(GenericClass>.self)) expectEqual("_TtGC1a12GenericClassPMPS_9ProtocolAS_9ProtocolB__", NSStringFromClass(GenericClass.Type>.self)) expectEqual("_TtGC1a12GenericClassMPS_9ProtocolAS_9ProtocolB__", NSStringFromClass(GenericClass.Protocol>.self)) expectEqual("_TtGC1a12GenericClassCSo7CFArray_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassVSC9NSDecimal_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassCSo8NSObject_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassCSo8NSObject_", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassPSo9NSCopying__", NSStringFromClass(GenericClass.self)) expectEqual("_TtGC1a12GenericClassPSo9NSCopyingS_9ProtocolAS_9ProtocolB__", NSStringFromClass(GenericClass>.self)) expectEqual("_TtGC1a17MultiGenericClassGVS_13GenericStructSi_GOS_11GenericEnumGS2_Si___", NSStringFromClass(MultiGenericClass, GenericEnum>>.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") } 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_NSStringNFDHashValue/NoLeak") { nsStringCanaryCount = 0 autoreleasepool { let a = NSStringCanary() expectEqual(1, nsStringCanaryCount) _stdlib_NSStringNFDHashValue(a) } expectEqual(0, nsStringCanaryCount) } RuntimeFoundationWrappers.test("_stdlib_NSStringASCIIHashValue/NoLeak") { nsStringCanaryCount = 0 autoreleasepool { let a = NSStringCanary() expectEqual(1, nsStringCanaryCount) _stdlib_NSStringASCIIHashValue(a) } 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) typealias Composition = protocol let compositionConcreteMetatype = Composition.self let expectedComposition = "- protocol #0\n" output = "" dump(compositionConcreteMetatype, to: &output) expectEqual(expectedComposition, output) let objcDefinedProtoType = NSObjectProtocol.self expectEqual(String(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? = nil dump(optionalURL, to: &output) let expected = "- nil\n" expectEqual(expected, output) } Reflection.test("Unmanaged/not-nil") { var output = "" var optionalURL: Unmanaged? = Unmanaged.passRetained(CFURLCreateWithString(nil, "http://llvm.org/", 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() // Trigger the creation of a KVO subclass for TestArtificialSubclass. obj.addObserver(obj, forKeyPath: "foo", options: [.new], context: &KVOHandle) obj.removeObserver(obj, forKeyPath: "foo") expectEqual("\(obj.dynamicType)", "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()