mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
The core definitions of CGPoint and other types were pushed down from CoreGraphics to CoreFoundation. This test indirectly depends on the conformance of those types to CustomReflectable, but nothing in the test was using those conformances explicitly and so libswiftCoreGraphics would not be auto-linked when the test is compiled at a high enough deployment target. Use the conformances directly to force linkage. Resolves rdar://121343931
826 lines
25 KiB
Swift
826 lines
25 KiB
Swift
// 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 -Xfrontend -disable-deserialization-safety
|
|
// RUN: %target-codesign %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)
|
|
}
|
|
|
|
// Hack to ensure the CustomReflectable conformance is used directly by the test
|
|
// in case it comes from a library that would otherwise not be autolinked.
|
|
@inline(never)
|
|
func assertCustomReflectable<T: CustomReflectable>(_ t: T) {}
|
|
|
|
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.self))
|
|
expectTrue(_isBridgedToObjectiveC(BridgedVerbatimRefType.self))
|
|
}
|
|
|
|
Runtime.test("isBridgedVerbatimToObjectiveC") {
|
|
expectFalse(_isBridgedVerbatimToObjectiveC(BridgedValueType.self))
|
|
expectTrue(_isBridgedVerbatimToObjectiveC(BridgedVerbatimRefType.self))
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
protocol SomeNativeProto {}
|
|
|
|
class SomeClass {}
|
|
@objc class SomeObjCClass {}
|
|
|
|
class SomeNSObjectSubclass : NSObject, SomeNativeProto {}
|
|
extension SomeNativeProto {
|
|
// https://github.com/apple/swift/issues/43154
|
|
func expectSelfTypeNameEqual(to typeName: String) {
|
|
expectEqual(typeName, _typeName(type(of: self)))
|
|
}
|
|
}
|
|
|
|
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)))
|
|
|
|
SomeNSObjectSubclass().expectSelfTypeNameEqual(to: "a.SomeNSObjectSubclass")
|
|
}
|
|
|
|
class GenericClass<T> {}
|
|
class MultiGenericClass<T, U> {}
|
|
struct GenericStruct<T> {}
|
|
enum GenericEnum<T> {}
|
|
|
|
struct PlainStruct {}
|
|
enum PlainEnum {}
|
|
|
|
protocol ProtocolA {}
|
|
protocol ProtocolB {}
|
|
|
|
class OuterClass {
|
|
|
|
private class PrivateGeneric<T, U> {
|
|
class InnerGeneric<X> {
|
|
class Inner { }
|
|
}
|
|
}
|
|
|
|
static func getPrivateGenericName() -> String {
|
|
return NSStringFromClass(OuterClass.PrivateGeneric<Int, Bool>.self)
|
|
}
|
|
static func getInnerGenericName() -> String {
|
|
return NSStringFromClass(OuterClass.PrivateGeneric<Int, Bool>.InnerGeneric<Float>.self)
|
|
}
|
|
static func getInnerName() -> String {
|
|
return NSStringFromClass(OuterClass.PrivateGeneric<Int, Bool>.InnerGeneric<Float>.Inner.self)
|
|
}
|
|
}
|
|
|
|
// The private discriminator is not deterministic.
|
|
// Replace it with a constant string.
|
|
func removePrivateDiscriminator(_ symbol: String) -> String {
|
|
let regexp = try! NSRegularExpression(pattern: "P[0-9]+\\$[0-9a-f]+")
|
|
let range = NSRange(0..<symbol.count)
|
|
return regexp.stringByReplacingMatches(in: symbol, range: range, withTemplate: "XXX")
|
|
}
|
|
|
|
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("_TtGC1a12GenericClassaSo10CFArrayRef_",
|
|
NSStringFromClass(GenericClass<CFArray>.self))
|
|
expectEqual("_TtGC1a12GenericClassaSo9NSDecimal_",
|
|
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))
|
|
|
|
expectEqual("_TtGCC1a10OuterClassXXXPrivateGeneric_SiSb_",
|
|
removePrivateDiscriminator(OuterClass.getPrivateGenericName()))
|
|
expectEqual("_TtGCCC1a10OuterClassXXXPrivateGeneric12InnerGeneric_SiSb_Sf_",
|
|
removePrivateDiscriminator(OuterClass.getInnerGenericName()))
|
|
expectEqual("_TtGCCCC1a10OuterClassXXXPrivateGeneric12InnerGeneric5Inner_SiSb_Sf__",
|
|
removePrivateDiscriminator(OuterClass.getInnerName()))
|
|
}
|
|
|
|
@objc protocol P {}
|
|
struct AnyObjStruct<T: AnyObject> {}
|
|
|
|
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)
|
|
expectTrue(_typeByName("1a12AnyObjStructVyAA1P_pG") == AnyObjStruct<P>.self)
|
|
}
|
|
|
|
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_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)
|
|
}
|
|
}
|
|
|
|
@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 = ""
|
|
let point = CGPoint(x: 1.25, y: 2.75)
|
|
assertCustomReflectable(point)
|
|
dump(point, 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 = ""
|
|
let size = CGSize(width: 1.25, height: 2.75)
|
|
assertCustomReflectable(size)
|
|
dump(size, 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 = ""
|
|
let rect = CGRect(
|
|
origin: CGPoint(x: 1.25, y: 2.25),
|
|
size: CGSize(width: 10.25, height: 11.75))
|
|
assertCustomReflectable(rect)
|
|
dump(rect, 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<__C.CFURLRef>(_value: http://llvm.org/))\n" +
|
|
" ▿ some: Swift.Unmanaged<__C.CFURLRef>\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)
|
|
}
|
|
}
|
|
|
|
@objc @objcMembers 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_Native : NSObject {
|
|
override var description: String { return "description" }
|
|
override var debugDescription: String { return "debugDescription" }
|
|
}
|
|
|
|
Reflection.test("NSObject is properly CustomDebugStringConvertible") {
|
|
let objectNative = StringConvertibleInDebugAndOtherwise_Native()
|
|
let objectObjC = StringConvertibleInDebugAndOtherwise_ObjC()
|
|
|
|
expectEqual(String(reflecting: objectNative), objectNative.debugDescription)
|
|
expectEqual(String(reflecting: objectObjC), objectObjC.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)
|
|
}
|
|
|
|
// https://github.com/apple/swift/issues/49905
|
|
|
|
extension Optional where Wrapped == NSData {
|
|
private class Inner {
|
|
}
|
|
|
|
var asInner: Inner {
|
|
return Inner()
|
|
}
|
|
}
|
|
|
|
var RuntimeClassNamesTestSuite = TestSuite("runtime class names")
|
|
|
|
RuntimeClassNamesTestSuite.test("private class nested in same-type-constrained extension") {
|
|
let base: NSData? = nil
|
|
let util = base.asInner
|
|
|
|
let clazz = unsafeBitCast(type(of: util), to: NSObject.self)
|
|
let desc = clazz.description
|
|
expectEqual("_TtCE1a", desc.prefix(7))
|
|
expectEqual("Inner", desc.suffix(5))
|
|
}
|
|
|
|
runAllTests()
|