mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This reverts commit 2262bd579a.
This information isn't necessary for field descriptor lookup,
after all. It's only the fields that need to have generic information,
which is already in the field descriptor.
883 lines
25 KiB
Swift
883 lines
25 KiB
Swift
// 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<T> : _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<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") {
|
|
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<Int>(value: 42)) as! ClassA).value)
|
|
|
|
expectEmpty(_bridgeToObjectiveC(ConditionallyBridgedValueType<String>(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<Int>(value: 42) },
|
|
{ expectEqual(42, (_bridgeToObjectiveC($0) as! ClassA).value) })
|
|
|
|
withSwiftObjectCanary(
|
|
{ ConditionallyBridgedValueType<String>(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<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<protocol<ProtocolA, ProtocolB>>.self))
|
|
expectEqual("_TtGC1a12GenericClassPMPS_9ProtocolAS_9ProtocolB__",
|
|
NSStringFromClass(GenericClass<protocol<ProtocolA, ProtocolB>.Type>.self))
|
|
expectEqual("_TtGC1a12GenericClassMPS_9ProtocolAS_9ProtocolB__",
|
|
NSStringFromClass(GenericClass<protocol<ProtocolB, ProtocolA>.Protocol>.self))
|
|
|
|
expectEqual("_TtGC1a12GenericClassCSo7CFArray_",
|
|
NSStringFromClass(GenericClass<CFArray>.self))
|
|
expectEqual("_TtGC1a12GenericClassVSC9NSDecimal_",
|
|
NSStringFromClass(GenericClass<NSDecimal>.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<protocol<ProtocolB, NSCopying, ProtocolA>>.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")
|
|
}
|
|
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<SomeNativeProto, SomeObjCProto>
|
|
let compositionConcreteMetatype = Composition.self
|
|
let expectedComposition = "- protocol<a.SomeNativeProto, a.SomeObjCProto> #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<CFURL>? = nil
|
|
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/", 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()
|