| // RUN: %empty-directory(%t) |
| // |
| // RUN: %gyb %s -o %t/Runtime.swift |
| // RUN: %target-build-swift -parse-stdlib -module-name a %t/Runtime.swift -o %t.out |
| // RUN: %target-run %t.out |
| // REQUIRES: executable_test |
| |
| import Swift |
| import StdlibUnittest |
| import SwiftShims |
| |
| #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) |
| import Darwin |
| #elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) |
| import Glibc |
| #endif |
| |
| @_silgen_name("swift_demangle") |
| public |
| func _stdlib_demangleImpl( |
| mangledName: UnsafePointer<CChar>?, |
| mangledNameLength: UInt, |
| outputBuffer: UnsafeMutablePointer<CChar>?, |
| outputBufferSize: UnsafeMutablePointer<UInt>?, |
| flags: UInt32 |
| ) -> UnsafeMutablePointer<CChar>? |
| |
| func _stdlib_demangleName(_ mangledName: String) -> String { |
| return mangledName.utf8CString.withUnsafeBufferPointer { |
| (mangledNameUTF8CStr) in |
| |
| let demangledNamePtr = _stdlib_demangleImpl( |
| mangledName: mangledNameUTF8CStr.baseAddress, |
| mangledNameLength: UInt(mangledNameUTF8CStr.count - 1), |
| outputBuffer: nil, |
| outputBufferSize: nil, |
| flags: 0) |
| |
| if let demangledNamePtr = demangledNamePtr { |
| let demangledName = String(cString: demangledNamePtr) |
| _swift_stdlib_free(demangledNamePtr) |
| return demangledName |
| } |
| return mangledName |
| } |
| } |
| |
| var swiftObjectCanaryCount = 0 |
| class SwiftObjectCanary { |
| init() { |
| swiftObjectCanaryCount += 1 |
| } |
| deinit { |
| swiftObjectCanaryCount -= 1 |
| } |
| } |
| |
| struct SwiftObjectCanaryStruct { |
| var ref = SwiftObjectCanary() |
| } |
| |
| var Runtime = TestSuite("Runtime") |
| |
| Runtime.test("_canBeClass") { |
| expectEqual(1, _canBeClass(SwiftObjectCanary.self)) |
| expectEqual(0, _canBeClass(SwiftObjectCanaryStruct.self)) |
| |
| typealias SwiftClosure = () -> () |
| expectEqual(0, _canBeClass(SwiftClosure.self)) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| |
| // The protocol should be defined in the standard library, otherwise the cast |
| // does not work. |
| typealias P1 = CustomReflectable |
| typealias P2 = CustomStringConvertible |
| protocol Q1 {} |
| |
| extension P1 { |
| var success: Bool { |
| print(String(describing: customMirror)) |
| return String(describing: customMirror) == "Mirror for ()" |
| } |
| } |
| |
| // A small struct that can be stored inline in an opaque buffer. |
| struct StructConformsToP1 : CustomReflectable, Q1 { |
| var customMirror: Mirror { |
| return Mirror(reflecting: ()) |
| } |
| } |
| |
| // A small struct that can be stored inline in an opaque buffer. |
| struct Struct2ConformsToP1<T : CustomReflectable> : CustomReflectable, Q1 { |
| init(_ value: T) { |
| self.value = value |
| } |
| var customMirror: Mirror { |
| return value.customMirror |
| } |
| var value: T |
| } |
| |
| // A large struct that cannot be stored inline in an opaque buffer. |
| struct Struct3ConformsToP2 : CustomStringConvertible, Q1 { |
| var a: UInt64 = 10 |
| var b: UInt64 = 20 |
| var c: UInt64 = 30 |
| var d: UInt64 = 40 |
| |
| var description: String { |
| // Don't rely on string interpolation, it uses the casts that we are trying |
| // to test. |
| var result = "" |
| result += _uint64ToString(a) + " " |
| result += _uint64ToString(b) + " " |
| result += _uint64ToString(c) + " " |
| result += _uint64ToString(d) |
| return result |
| } |
| } |
| |
| // A large struct that cannot be stored inline in an opaque buffer. |
| struct Struct4ConformsToP2<T : CustomStringConvertible> : CustomStringConvertible, Q1 { |
| var value: T |
| var e: UInt64 = 50 |
| var f: UInt64 = 60 |
| var g: UInt64 = 70 |
| var h: UInt64 = 80 |
| |
| init(_ value: T) { |
| self.value = value |
| } |
| |
| var description: String { |
| // Don't rely on string interpolation, it uses the casts that we are trying |
| // to test. |
| var result = value.description + " " |
| result += _uint64ToString(e) + " " |
| result += _uint64ToString(f) + " " |
| result += _uint64ToString(g) + " " |
| result += _uint64ToString(h) |
| return result |
| } |
| } |
| |
| struct StructDoesNotConformToP1 : Q1 {} |
| |
| class ClassConformsToP1 : CustomReflectable, Q1 { |
| var customMirror: Mirror { |
| return Mirror(reflecting: ()) |
| } |
| } |
| |
| class Class2ConformsToP1<T : CustomReflectable> : CustomReflectable, Q1 { |
| init(_ value: T) { |
| self.value = [value] |
| } |
| var customMirror: Mirror { |
| return value[0].customMirror |
| } |
| // FIXME: should be "var value: T", but we don't support it now. |
| var value: Array<T> |
| } |
| |
| class ClassDoesNotConformToP1 : Q1 {} |
| |
| Runtime.test("dynamicCasting with as") { |
| var someP1Value = StructConformsToP1() |
| var someP1Value2 = Struct2ConformsToP1(StructConformsToP1()) |
| var someNotP1Value = StructDoesNotConformToP1() |
| var someP2Value = Struct3ConformsToP2() |
| var someP2Value2 = Struct4ConformsToP2(Struct3ConformsToP2()) |
| var someP1Ref = ClassConformsToP1() |
| var someP1Ref2 = Class2ConformsToP1(ClassConformsToP1()) |
| var someNotP1Ref = ClassDoesNotConformToP1() |
| |
| expectTrue(someP1Value is P1) |
| expectTrue(someP1Value2 is P1) |
| expectFalse(someNotP1Value is P1) |
| expectTrue(someP2Value is P2) |
| expectTrue(someP2Value2 is P2) |
| expectTrue(someP1Ref is P1) |
| expectTrue(someP1Ref2 is P1) |
| expectFalse(someNotP1Ref is P1) |
| |
| expectTrue(someP1Value as P1 is P1) |
| expectTrue(someP1Value2 as P1 is P1) |
| expectTrue(someP2Value as P2 is P2) |
| expectTrue(someP2Value2 as P2 is P2) |
| expectTrue(someP1Ref as P1 is P1) |
| |
| expectTrue(someP1Value as Q1 is P1) |
| expectTrue(someP1Value2 as Q1 is P1) |
| expectFalse(someNotP1Value as Q1 is P1) |
| expectTrue(someP2Value as Q1 is P2) |
| expectTrue(someP2Value2 as Q1 is P2) |
| expectTrue(someP1Ref as Q1 is P1) |
| expectTrue(someP1Ref2 as Q1 is P1) |
| expectFalse(someNotP1Ref as Q1 is P1) |
| |
| expectTrue(someP1Value as Any is P1) |
| expectTrue(someP1Value2 as Any is P1) |
| expectFalse(someNotP1Value as Any is P1) |
| expectTrue(someP2Value as Any is P2) |
| expectTrue(someP2Value2 as Any is P2) |
| expectTrue(someP1Ref as Any is P1) |
| expectTrue(someP1Ref2 as Any is P1) |
| expectFalse(someNotP1Ref as Any is P1) |
| |
| expectTrue(someP1Ref as AnyObject is P1) |
| expectTrue(someP1Ref2 as AnyObject is P1) |
| expectFalse(someNotP1Ref as AnyObject is P1) |
| |
| expectTrue((someP1Value as P1).success) |
| expectTrue((someP1Value2 as P1).success) |
| expectEqual("10 20 30 40", (someP2Value as P2).description) |
| expectEqual("10 20 30 40 50 60 70 80", (someP2Value2 as P2).description) |
| |
| expectTrue((someP1Ref as P1).success) |
| expectTrue((someP1Ref2 as P1).success) |
| |
| expectTrue(((someP1Value as Q1) as! P1).success) |
| expectTrue(((someP1Value2 as Q1) as! P1).success) |
| expectEqual("10 20 30 40", ((someP2Value as Q1) as! P2).description) |
| expectEqual("10 20 30 40 50 60 70 80", |
| ((someP2Value2 as Q1) as! P2).description) |
| expectTrue(((someP1Ref as Q1) as! P1).success) |
| expectTrue(((someP1Ref2 as Q1) as! P1).success) |
| |
| expectTrue(((someP1Value as Any) as! P1).success) |
| expectTrue(((someP1Value2 as Any) as! P1).success) |
| expectEqual("10 20 30 40", ((someP2Value as Any) as! P2).description) |
| expectEqual("10 20 30 40 50 60 70 80", |
| ((someP2Value2 as Any) as! P2).description) |
| expectTrue(((someP1Ref as Any) as! P1).success) |
| expectTrue(((someP1Ref2 as Any) as! P1).success) |
| |
| expectTrue(((someP1Ref as AnyObject) as! P1).success) |
| |
| expectNil((someNotP1Value as? P1)) |
| expectNil((someNotP1Ref as? P1)) |
| |
| expectTrue(((someP1Value as Q1) as? P1)!.success) |
| expectTrue(((someP1Value2 as Q1) as? P1)!.success) |
| expectNil(((someNotP1Value as Q1) as? P1)) |
| expectEqual("10 20 30 40", ((someP2Value as Q1) as? P2)!.description) |
| expectEqual("10 20 30 40 50 60 70 80", |
| ((someP2Value2 as Q1) as? P2)!.description) |
| expectTrue(((someP1Ref as Q1) as? P1)!.success) |
| expectTrue(((someP1Ref2 as Q1) as? P1)!.success) |
| expectNil(((someNotP1Ref as Q1) as? P1)) |
| |
| expectTrue(((someP1Value as Any) as? P1)!.success) |
| expectTrue(((someP1Value2 as Any) as? P1)!.success) |
| expectNil(((someNotP1Value as Any) as? P1)) |
| expectEqual("10 20 30 40", ((someP2Value as Any) as? P2)!.description) |
| expectEqual("10 20 30 40 50 60 70 80", |
| ((someP2Value2 as Any) as? P2)!.description) |
| expectTrue(((someP1Ref as Any) as? P1)!.success) |
| expectTrue(((someP1Ref2 as Any) as? P1)!.success) |
| expectNil(((someNotP1Ref as Any) as? P1)) |
| |
| expectTrue(((someP1Ref as AnyObject) as? P1)!.success) |
| expectTrue(((someP1Ref2 as AnyObject) as? P1)!.success) |
| expectNil(((someNotP1Ref as AnyObject) as? P1)) |
| |
| let doesThrow: (Int) throws -> Int = { $0 } |
| let doesNotThrow: (String) -> String = { $0 } |
| |
| var any: Any = doesThrow |
| |
| expectTrue(doesThrow as Any is (Int) throws -> Int) |
| expectFalse(doesThrow as Any is (String) throws -> Int) |
| expectFalse(doesThrow as Any is (String) throws -> String) |
| expectFalse(doesThrow as Any is (Int) throws -> String) |
| expectFalse(doesThrow as Any is (Int) -> Int) |
| expectFalse(doesThrow as Any is (String) throws -> String) |
| expectFalse(doesThrow as Any is (String) -> String) |
| expectTrue(doesNotThrow as Any is (String) throws -> String) |
| expectTrue(doesNotThrow as Any is (String) -> String) |
| expectFalse(doesNotThrow as Any is (Int) -> String) |
| expectFalse(doesNotThrow as Any is (Int) -> Int) |
| expectFalse(doesNotThrow as Any is (String) -> Int) |
| expectFalse(doesNotThrow as Any is (Int) throws -> Int) |
| expectFalse(doesNotThrow as Any is (Int) -> Int) |
| } |
| |
| extension Int { |
| class ExtensionClassConformsToP2 : P2 { |
| var description: String { return "abc" } |
| } |
| |
| fileprivate class PrivateExtensionClassConformsToP2 : P2 { |
| var description: String { return "def" } |
| } |
| } |
| |
| Runtime.test("dynamic cast to existential with cross-module extensions") { |
| let internalObj = Int.ExtensionClassConformsToP2() |
| let privateObj = Int.PrivateExtensionClassConformsToP2() |
| |
| expectTrue(internalObj is P2) |
| expectTrue(privateObj is P2) |
| } |
| |
| class SomeClass {} |
| struct SomeStruct {} |
| enum SomeEnum { |
| case A |
| init() { self = .A } |
| } |
| |
| Runtime.test("typeName") { |
| expectEqual("a.SomeClass", _typeName(SomeClass.self)) |
| expectEqual("a.SomeStruct", _typeName(SomeStruct.self)) |
| expectEqual("a.SomeEnum", _typeName(SomeEnum.self)) |
| expectEqual("Any.Protocol", _typeName(Any.Protocol.self)) |
| expectEqual("Swift.AnyObject.Protocol", _typeName(AnyObject.Protocol.self)) |
| expectEqual("Swift.AnyObject.Type.Protocol", _typeName(AnyClass.Protocol.self)) |
| expectEqual("Swift.Optional<Swift.AnyObject>.Type", _typeName((AnyObject?).Type.self)) |
| |
| var a: Any = SomeClass() |
| expectEqual("a.SomeClass", _typeName(type(of: a))) |
| |
| a = SomeStruct() |
| expectEqual("a.SomeStruct", _typeName(type(of: a))) |
| |
| a = SomeEnum() |
| expectEqual("a.SomeEnum", _typeName(type(of: a))) |
| |
| a = AnyObject.self |
| expectEqual("Swift.AnyObject.Protocol", _typeName(type(of: a))) |
| |
| a = AnyClass.self |
| expectEqual("Swift.AnyObject.Type.Protocol", _typeName(type(of: a))) |
| |
| a = (AnyObject?).self |
| expectEqual("Swift.Optional<Swift.AnyObject>.Type", |
| _typeName(type(of: a))) |
| |
| a = Any.self |
| expectEqual("Any.Protocol", _typeName(type(of: a))) |
| } |
| |
| class SomeSubclass : SomeClass {} |
| |
| protocol SomeProtocol {} |
| class SomeConformingClass : SomeProtocol {} |
| class SomeConformingSubclass : SomeConformingClass {} |
| class UnicodeCläss {} |
| |
| Runtime.test("typeByName") { |
| expectTrue(_typeByName("a.SomeClass") == SomeClass.self) |
| expectTrue(_typeByName("a.SomeSubclass") == SomeSubclass.self) |
| // name lookup will be via protocol conformance table |
| expectTrue(_typeByName("a.SomeConformingClass") == SomeConformingClass.self) |
| expectTrue(_typeByName("a.UnicodeCläss") == UnicodeCläss.self) |
| } |
| |
| Runtime.test("demangleName") { |
| expectEqual("", _stdlib_demangleName("")) |
| expectEqual("abc", _stdlib_demangleName("abc")) |
| expectEqual("\0", _stdlib_demangleName("\0")) |
| expectEqual("Swift.Double", _stdlib_demangleName("_T0SdD")) |
| expectEqual("x.a : x.Foo<x.Foo<x.Foo<Swift.Int, Swift.Int>, x.Foo<Swift.Int, Swift.Int>>, x.Foo<x.Foo<Swift.Int, Swift.Int>, x.Foo<Swift.Int, Swift.Int>>>", |
| _stdlib_demangleName("_T01x1aAA3FooCyADyADySiSiGADySiSiGGADyADySiSiGADySiSiGGGvp")) |
| expectEqual("Foobar", _stdlib_demangleName("_T013__lldb_expr_46FoobarCD")) |
| } |
| |
| % for optionality in ['', '?']: |
| Runtime.test("_stdlib_atomicCompareExchangeStrongPtr") { |
| typealias IntPtr = UnsafeMutablePointer<Int> |
| var origP1: IntPtr${optionality} = IntPtr(bitPattern: 0x10101010)! |
| var origP2: IntPtr${optionality} = IntPtr(bitPattern: 0x20202020)! |
| var origP3: IntPtr${optionality} = IntPtr(bitPattern: 0x30303030)! |
| |
| do { |
| var object = origP1 |
| var expected = origP1 |
| let r = _stdlib_atomicCompareExchangeStrongPtr( |
| object: &object, expected: &expected, desired: origP2) |
| expectTrue(r) |
| expectEqual(origP2, object) |
| expectEqual(origP1, expected) |
| } |
| do { |
| var object = origP1 |
| var expected = origP2 |
| let r = _stdlib_atomicCompareExchangeStrongPtr( |
| object: &object, expected: &expected, desired: origP3) |
| expectFalse(r) |
| expectEqual(origP1, object) |
| expectEqual(origP1, expected) |
| } |
| |
| struct FooStruct { |
| var i: Int |
| var object: IntPtr${optionality} |
| var expected: IntPtr${optionality} |
| |
| init(object: IntPtr${optionality}, expected: IntPtr${optionality}) { |
| self.i = 0 |
| self.object = object |
| self.expected = expected |
| } |
| } |
| do { |
| var foo = FooStruct(object: origP1, expected: origP1) |
| let r = _stdlib_atomicCompareExchangeStrongPtr( |
| object: &foo.object, expected: &foo.expected, desired: origP2) |
| expectTrue(r) |
| expectEqual(origP2, foo.object) |
| expectEqual(origP1, foo.expected) |
| } |
| do { |
| var foo = FooStruct(object: origP1, expected: origP2) |
| let r = _stdlib_atomicCompareExchangeStrongPtr( |
| object: &foo.object, expected: &foo.expected, desired: origP3) |
| expectFalse(r) |
| expectEqual(origP1, foo.object) |
| expectEqual(origP1, foo.expected) |
| } |
| } |
| % end |
| |
| Runtime.test("casting AnyObject to class metatypes") { |
| do { |
| var ao: AnyObject = SomeClass() |
| expectTrue(ao as? Any.Type == nil) |
| expectTrue(ao as? AnyClass == nil) |
| } |
| |
| do { |
| var a: Any = SomeClass() |
| expectTrue(a as? Any.Type == nil) |
| expectTrue(a as? AnyClass == nil) |
| |
| a = SomeClass.self |
| expectTrue(a as? Any.Type == SomeClass.self) |
| expectTrue(a as? AnyClass == SomeClass.self) |
| expectTrue(a as? SomeClass.Type == SomeClass.self) |
| } |
| } |
| |
| func wantonlyWrapInAny<T>(_ x: T) -> Any { |
| return x |
| } |
| |
| // Because `type(of: x)` and `T.self` have the same type `T.Type` in |
| // a <T>(x: T) context, both operations must produce the concrete protocol |
| // type value when `T` is bound to an existential type `P`. |
| func castWithAbstractionBarrier<T>(_ x: T) -> ( |
| staticWithConcreteType: T.Type, |
| dynamicWithConcreteType: T.Type, |
| staticWithErasedType: Any.Type, |
| dynamicWithErasedType: Any.Type, |
| dynamicExistentialWithErasedType: Any.Type, |
| dynamicDoubleWrappedExistentialWithErasedType: Any.Type |
| ) { |
| return ( |
| staticWithConcreteType: T.self, |
| dynamicWithConcreteType: type(of: x), |
| staticWithErasedType: T.self, |
| dynamicWithErasedType: type(of: x), |
| dynamicExistentialWithErasedType: type(of: x as Any), |
| dynamicDoubleWrappedExistentialWithErasedType: |
| type(of: wantonlyWrapInAny(wantonlyWrapInAny(x))) |
| ) |
| } |
| |
| Runtime.test("abstraction barrier on casting generic param bound to existential") { |
| let c: SomeConformingClass = SomeConformingSubclass() |
| let x: SomeProtocol = c |
| let (staticWithConcreteType, |
| dynamicWithConcreteType, |
| staticWithErasedType, |
| dynamicWithErasedType, |
| dynamicExistentialWithErasedType, |
| dynamicDoubleWrappedExistentialWithErasedType) |
| = castWithAbstractionBarrier(x) |
| |
| expectTrue(staticWithConcreteType == SomeProtocol.self) |
| expectTrue(dynamicWithConcreteType == SomeProtocol.self) |
| expectTrue(staticWithErasedType == SomeProtocol.self) |
| expectTrue(dynamicWithErasedType == SomeProtocol.self) |
| |
| // type(of: x as Any) can be a proper existential type cast |
| expectTrue(dynamicExistentialWithErasedType == SomeConformingSubclass.self) |
| expectTrue(dynamicDoubleWrappedExistentialWithErasedType |
| == SomeConformingSubclass.self) |
| } |
| |
| class Malkovich: Malkovichable { |
| var malkovich: String { return "malkovich" } |
| } |
| protocol Malkovichable: class { |
| var malkovich: String { get } |
| } |
| |
| struct GenericStructWithReferenceStorage<T> { |
| var a: T |
| unowned(safe) var unownedConcrete: Malkovich |
| unowned(unsafe) var unmanagedConcrete: Malkovich |
| weak var weakConcrete: Malkovich? |
| |
| unowned(safe) var unownedProto: Malkovichable |
| unowned(unsafe) var unmanagedProto: Malkovichable |
| weak var weakProto: Malkovichable? |
| } |
| |
| func exerciseReferenceStorageInGenericContext<T>( |
| _ x: GenericStructWithReferenceStorage<T>, |
| forceCopy y: GenericStructWithReferenceStorage<T> |
| ) { |
| expectEqual(x.unownedConcrete.malkovich, "malkovich") |
| expectEqual(x.unmanagedConcrete.malkovich, "malkovich") |
| expectEqual(x.weakConcrete!.malkovich, "malkovich") |
| expectEqual(x.unownedProto.malkovich, "malkovich") |
| expectEqual(x.unmanagedProto.malkovich, "malkovich") |
| expectEqual(x.weakProto!.malkovich, "malkovich") |
| |
| expectEqual(y.unownedConcrete.malkovich, "malkovich") |
| expectEqual(y.unmanagedConcrete.malkovich, "malkovich") |
| expectEqual(y.weakConcrete!.malkovich, "malkovich") |
| expectEqual(y.unownedProto.malkovich, "malkovich") |
| expectEqual(y.unmanagedProto.malkovich, "malkovich") |
| expectEqual(y.weakProto!.malkovich, "malkovich") |
| } |
| |
| Runtime.test("Struct layout with reference storage types") { |
| let malkovich = Malkovich() |
| |
| let x = GenericStructWithReferenceStorage(a: malkovich, |
| unownedConcrete: malkovich, |
| unmanagedConcrete: malkovich, |
| weakConcrete: malkovich, |
| unownedProto: malkovich, |
| unmanagedProto: malkovich, |
| weakProto: malkovich) |
| exerciseReferenceStorageInGenericContext(x, forceCopy: x) |
| |
| expectEqual(x.unownedConcrete.malkovich, "malkovich") |
| expectEqual(x.unmanagedConcrete.malkovich, "malkovich") |
| expectEqual(x.weakConcrete!.malkovich, "malkovich") |
| expectEqual(x.unownedProto.malkovich, "malkovich") |
| expectEqual(x.unmanagedProto.malkovich, "malkovich") |
| expectEqual(x.weakProto!.malkovich, "malkovich") |
| |
| // Make sure malkovich lives long enough. |
| print(malkovich) |
| } |
| |
| Runtime.test("SwiftError layout constants for LLDB") { |
| #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) |
| let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2) |
| #elseif os(Linux) |
| let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0) |
| #else |
| _UnimplementedError() |
| #endif |
| |
| let offsetof_SwiftError_typeMetadata = |
| dlsym(RTLD_DEFAULT, "_swift_lldb_offsetof_SwiftError_typeMetadata")! |
| let sizeof_SwiftError = |
| dlsym(RTLD_DEFAULT, "_swift_lldb_sizeof_SwiftError")! |
| #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) |
| #if arch(i386) || arch(arm) |
| expectEqual(20, offsetof_SwiftError_typeMetadata.load(as: UInt.self)) |
| expectEqual(36, sizeof_SwiftError.load(as: UInt.self)) |
| #else |
| expectEqual(40, offsetof_SwiftError_typeMetadata.load(as: UInt.self)) |
| expectEqual(72, sizeof_SwiftError.load(as: UInt.self)) |
| #endif |
| #elseif os(Linux) |
| expectEqual(16, offsetof_SwiftError_typeMetadata.load(as: UInt.self)) |
| expectEqual(32, sizeof_SwiftError.load(as: UInt.self)) |
| #else |
| _UnimplementedError() |
| #endif |
| } |
| |
| var Reflection = TestSuite("Reflection") |
| |
| func wrap1 (_ x: Any) -> Any { return x } |
| func wrap2<T>(_ x: T) -> Any { return wrap1(x) } |
| func wrap3 (_ x: Any) -> Any { return wrap2(x) } |
| func wrap4<T>(_ x: T) -> Any { return wrap3(x) } |
| func wrap5 (_ x: Any) -> Any { return wrap4(x) } |
| |
| class JustNeedAMetatype {} |
| |
| Reflection.test("nested existential containers") { |
| let wrapped = wrap5(JustNeedAMetatype.self) |
| expectEqual("\(wrapped)", "JustNeedAMetatype") |
| } |
| |
| Reflection.test("dumpToAStream") { |
| var output = "" |
| dump([ 42, 4242 ], to: &output) |
| expectEqual("â–¿ 2 elements\n - 42\n - 4242\n", output) |
| } |
| |
| struct StructWithDefaultMirror { |
| let s: String |
| |
| init (_ s: String) { |
| self.s = s |
| } |
| } |
| |
| Reflection.test("Struct/NonGeneric/DefaultMirror") { |
| do { |
| var output = "" |
| dump(StructWithDefaultMirror("123"), to: &output) |
| expectEqual("â–¿ a.StructWithDefaultMirror\n - s: \"123\"\n", output) |
| } |
| |
| do { |
| // Build a String around an interpolation as a way of smoke-testing that |
| // the internal _Mirror implementation gets memory management right. |
| var output = "" |
| dump(StructWithDefaultMirror("\(456)"), to: &output) |
| expectEqual("â–¿ a.StructWithDefaultMirror\n - s: \"456\"\n", output) |
| } |
| |
| expectEqual( |
| .`struct`, |
| Mirror(reflecting: StructWithDefaultMirror("")).displayStyle) |
| } |
| |
| struct GenericStructWithDefaultMirror<T, U> { |
| let first: T |
| let second: U |
| } |
| |
| Reflection.test("Struct/Generic/DefaultMirror") { |
| do { |
| var value = GenericStructWithDefaultMirror<Int, [Any?]>( |
| first: 123, |
| second: ["abc", 456, 789.25]) |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ a.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" + |
| " - first: 123\n" + |
| " â–¿ second: 3 elements\n" + |
| " â–¿ Optional(\"abc\")\n" + |
| " - some: \"abc\"\n" + |
| " â–¿ Optional(456)\n" + |
| " - some: 456\n" + |
| " â–¿ Optional(789.25)\n" + |
| " - some: 789.25\n" |
| |
| expectEqual(expected, output) |
| |
| } |
| } |
| |
| enum NoPayloadEnumWithDefaultMirror { |
| case A, ß |
| } |
| |
| Reflection.test("Enum/NoPayload/DefaultMirror") { |
| do { |
| let value: [NoPayloadEnumWithDefaultMirror] = |
| [.A, .ß] |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 2 elements\n" + |
| " - a.NoPayloadEnumWithDefaultMirror.A\n" + |
| " - a.NoPayloadEnumWithDefaultMirror.ß\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| enum SingletonNonGenericEnumWithDefaultMirror { |
| case OnlyOne(Int) |
| } |
| |
| Reflection.test("Enum/SingletonNonGeneric/DefaultMirror") { |
| do { |
| let value = SingletonNonGenericEnumWithDefaultMirror.OnlyOne(5) |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ a.SingletonNonGenericEnumWithDefaultMirror.OnlyOne\n" + |
| " - OnlyOne: 5\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| enum SingletonGenericEnumWithDefaultMirror<T> { |
| case OnlyOne(T) |
| } |
| |
| Reflection.test("Enum/SingletonGeneric/DefaultMirror") { |
| do { |
| let value = SingletonGenericEnumWithDefaultMirror.OnlyOne("IIfx") |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ a.SingletonGenericEnumWithDefaultMirror<Swift.String>.OnlyOne\n" + |
| " - OnlyOne: \"IIfx\"\n" |
| |
| expectEqual(expected, output) |
| } |
| expectEqual(0, LifetimeTracked.instances) |
| do { |
| let value = SingletonGenericEnumWithDefaultMirror.OnlyOne( |
| LifetimeTracked(0)) |
| expectEqual(1, LifetimeTracked.instances) |
| var output = "" |
| dump(value, to: &output) |
| } |
| expectEqual(0, LifetimeTracked.instances) |
| } |
| |
| enum SinglePayloadNonGenericEnumWithDefaultMirror { |
| case Cat |
| case Dog |
| case Volleyball(String, Int) |
| } |
| |
| Reflection.test("Enum/SinglePayloadNonGeneric/DefaultMirror") { |
| do { |
| let value: [SinglePayloadNonGenericEnumWithDefaultMirror] = |
| [.Cat, |
| .Dog, |
| .Volleyball("Wilson", 2000)] |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 3 elements\n" + |
| " - a.SinglePayloadNonGenericEnumWithDefaultMirror.Cat\n" + |
| " - a.SinglePayloadNonGenericEnumWithDefaultMirror.Dog\n" + |
| " â–¿ a.SinglePayloadNonGenericEnumWithDefaultMirror.Volleyball\n" + |
| " â–¿ Volleyball: (2 elements)\n" + |
| " - .0: \"Wilson\"\n" + |
| " - .1: 2000\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| enum SinglePayloadGenericEnumWithDefaultMirror<T, U> { |
| case Well |
| case Faucet |
| case Pipe(T, U) |
| } |
| |
| Reflection.test("Enum/SinglePayloadGeneric/DefaultMirror") { |
| do { |
| let value: [SinglePayloadGenericEnumWithDefaultMirror<Int, [Int]>] = |
| [.Well, |
| .Faucet, |
| .Pipe(408, [415])] |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 3 elements\n" + |
| " - a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Well\n" + |
| " - a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Faucet\n" + |
| " â–¿ a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Pipe\n" + |
| " â–¿ Pipe: (2 elements)\n" + |
| " - .0: 408\n" + |
| " â–¿ .1: 1 element\n" + |
| " - 415\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| enum MultiPayloadTagBitsNonGenericEnumWithDefaultMirror { |
| case Plus |
| case SE30 |
| case Classic(mhz: Int) |
| case Performa(model: Int) |
| } |
| |
| Reflection.test("Enum/MultiPayloadTagBitsNonGeneric/DefaultMirror") { |
| do { |
| let value: [MultiPayloadTagBitsNonGenericEnumWithDefaultMirror] = |
| [.Plus, |
| .SE30, |
| .Classic(mhz: 16), |
| .Performa(model: 220)] |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 4 elements\n" + |
| " - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" + |
| " - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" + |
| " â–¿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" + |
| " - Classic: 16\n" + |
| " â–¿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" + |
| " - Performa: 220\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| class Floppy { |
| let capacity: Int |
| |
| init(capacity: Int) { self.capacity = capacity } |
| } |
| |
| class CDROM { |
| let capacity: Int |
| |
| init(capacity: Int) { self.capacity = capacity } |
| } |
| |
| enum MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror { |
| case MacWrite |
| case MacPaint |
| case FileMaker |
| case ClarisWorks(floppy: Floppy) |
| case HyperCard(cdrom: CDROM) |
| } |
| |
| Reflection.test("Enum/MultiPayloadSpareBitsNonGeneric/DefaultMirror") { |
| do { |
| let value: [MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror] = |
| [.MacWrite, |
| .MacPaint, |
| .FileMaker, |
| .ClarisWorks(floppy: Floppy(capacity: 800)), |
| .HyperCard(cdrom: CDROM(capacity: 600))] |
| |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 5 elements\n" + |
| " - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacWrite\n" + |
| " - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" + |
| " - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" + |
| " â–¿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" + |
| " â–¿ ClarisWorks: a.Floppy #0\n" + |
| " - capacity: 800\n" + |
| " â–¿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" + |
| " â–¿ HyperCard: a.CDROM #1\n" + |
| " - capacity: 600\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| enum MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror { |
| case MacWrite |
| case MacPaint |
| case FileMaker |
| case ClarisWorks(floppy: Bool) |
| case HyperCard(cdrom: Bool) |
| } |
| |
| Reflection.test("Enum/MultiPayloadTagBitsSmallNonGeneric/DefaultMirror") { |
| do { |
| let value: [MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror] = |
| [.MacWrite, |
| .MacPaint, |
| .FileMaker, |
| .ClarisWorks(floppy: true), |
| .HyperCard(cdrom: false)] |
| |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 5 elements\n" + |
| " - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacWrite\n" + |
| " - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" + |
| " - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" + |
| " â–¿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" + |
| " - ClarisWorks: true\n" + |
| " â–¿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" + |
| " - HyperCard: false\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| enum MultiPayloadGenericEnumWithDefaultMirror<T, U> { |
| case IIe |
| case IIgs |
| case Centris(ram: T) |
| case Quadra(hdd: U) |
| case PowerBook170 |
| case PowerBookDuo220 |
| } |
| |
| Reflection.test("Enum/MultiPayloadGeneric/DefaultMirror") { |
| do { |
| let value: [MultiPayloadGenericEnumWithDefaultMirror<Int, String>] = |
| [.IIe, |
| .IIgs, |
| .Centris(ram: 4096), |
| .Quadra(hdd: "160MB"), |
| .PowerBook170, |
| .PowerBookDuo220] |
| |
| var output = "" |
| dump(value, to: &output) |
| |
| let expected = |
| "â–¿ 6 elements\n" + |
| " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" + |
| " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" + |
| " â–¿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" + |
| " - Centris: 4096\n" + |
| " â–¿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" + |
| " - Quadra: \"160MB\"\n" + |
| " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" + |
| " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n" |
| |
| expectEqual(expected, output) |
| } |
| expectEqual(0, LifetimeTracked.instances) |
| do { |
| let value = MultiPayloadGenericEnumWithDefaultMirror<LifetimeTracked, |
| LifetimeTracked> |
| .Quadra(hdd: LifetimeTracked(0)) |
| expectEqual(1, LifetimeTracked.instances) |
| var output = "" |
| dump(value, to: &output) |
| } |
| expectEqual(0, LifetimeTracked.instances) |
| } |
| |
| enum Foo<T> { |
| indirect case Foo(Int) |
| case Bar(T) |
| } |
| |
| enum List<T> { |
| case Nil |
| indirect case Cons(first: T, rest: List<T>) |
| } |
| |
| Reflection.test("Enum/IndirectGeneric/DefaultMirror") { |
| let x = Foo<String>.Foo(22) |
| let y = Foo<String>.Bar("twenty-two") |
| |
| expectEqual("\(x)", "Foo(22)") |
| expectEqual("\(y)", "Bar(\"twenty-two\")") |
| |
| let list = List.Cons(first: 0, rest: .Cons(first: 1, rest: .Nil)) |
| expectEqual("Cons(first: 0, rest: a.List<Swift.Int>.Cons(first: 1, rest: a.List<Swift.Int>.Nil))", |
| "\(list)") |
| } |
| |
| class Brilliant : CustomReflectable { |
| let first: Int |
| let second: String |
| |
| init(_ fst: Int, _ snd: String) { |
| self.first = fst |
| self.second = snd |
| } |
| |
| var customMirror: Mirror { |
| return Mirror(self, children: ["first": first, "second": second, "self": self]) |
| } |
| } |
| |
| /// Subclasses inherit their parents' custom mirrors. |
| class Irradiant : Brilliant { |
| init() { |
| super.init(400, "") |
| } |
| } |
| |
| Reflection.test("CustomMirror") { |
| do { |
| var output = "" |
| dump(Brilliant(123, "four five six"), to: &output) |
| |
| let expected = |
| "â–¿ a.Brilliant #0\n" + |
| " - first: 123\n" + |
| " - second: \"four five six\"\n" + |
| " â–¿ self: a.Brilliant #0\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var output = "" |
| dump(Brilliant(123, "four five six"), to: &output, maxDepth: 0) |
| expectEqual("â–¹ a.Brilliant #0\n", output) |
| } |
| |
| do { |
| var output = "" |
| dump(Brilliant(123, "four five six"), to: &output, maxItems: 3) |
| |
| let expected = |
| "â–¿ a.Brilliant #0\n" + |
| " - first: 123\n" + |
| " - second: \"four five six\"\n" + |
| " (1 more child)\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var output = "" |
| dump(Brilliant(123, "four five six"), to: &output, maxItems: 2) |
| |
| let expected = |
| "â–¿ a.Brilliant #0\n" + |
| " - first: 123\n" + |
| " (2 more children)\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var output = "" |
| dump(Brilliant(123, "four five six"), to: &output, maxItems: 1) |
| |
| let expected = |
| "â–¿ a.Brilliant #0\n" + |
| " (3 children)\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("ObjectIdentifier/Hashable,Comparable") { |
| // Check that object identifiers are unique to class instances. |
| let a = Brilliant(1, "") |
| let b = Brilliant(2, "") |
| let c = Brilliant(3, "") |
| |
| checkHashable( |
| [a, b, c].map(ObjectIdentifier.init), |
| equalityOracle: { $0 == $1 }) |
| |
| // Comparable |
| func isComparable<X : Comparable>(_ x: X) {} |
| isComparable(ObjectIdentifier(a)) |
| // Check the ObjectIdentifier created is stable |
| expectTrue( |
| (ObjectIdentifier(a) < ObjectIdentifier(b)) |
| != (ObjectIdentifier(a) > ObjectIdentifier(b))) |
| expectFalse( |
| ObjectIdentifier(a) >= ObjectIdentifier(b) |
| && ObjectIdentifier(a) <= ObjectIdentifier(b)) |
| |
| // Check that ordering is transitive. |
| expectEqual( |
| [ ObjectIdentifier(a), ObjectIdentifier(b), ObjectIdentifier(c) ].sorted(), |
| [ ObjectIdentifier(c), ObjectIdentifier(b), ObjectIdentifier(a) ].sorted()) |
| } |
| |
| Reflection.test("ObjectIdentifier/CustomDebugStringConvertible") { |
| let obj1 = Brilliant(1, "") |
| let obj2 = Brilliant(2, "") |
| |
| let oi1 = ObjectIdentifier(obj1) |
| let oi2 = ObjectIdentifier(obj2) |
| |
| expectEqual(String(reflecting: oi1), String(reflecting: oi1)) |
| expectNotEqual(String(reflecting: oi1), String(reflecting: oi2)) |
| |
| let p1 = UnsafeRawPointer(bitPattern: UInt(bitPattern: oi1))! |
| expectPrinted("ObjectIdentifier(\(p1))", oi1) |
| let p2 = UnsafeRawPointer(bitPattern: Int(bitPattern: oi1))! |
| expectPrinted("ObjectIdentifier(\(p2))", oi1) |
| |
| } |
| |
| Reflection.test("CustomMirrorIsInherited") { |
| do { |
| var output = "" |
| dump(Irradiant(), to: &output) |
| |
| let expected = |
| "â–¿ a.Brilliant #0\n" + |
| " - first: 400\n" + |
| " - second: \"\"\n" + |
| " â–¿ self: a.Brilliant #0\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| protocol SomeNativeProto {} |
| extension Int: SomeNativeProto {} |
| |
| Reflection.test("MetatypeMirror") { |
| do { |
| var output = "" |
| let concreteMetatype = Int.self |
| dump(concreteMetatype, to: &output) |
| |
| let expectedInt = "- Swift.Int #0\n" |
| expectEqual(expectedInt, output) |
| |
| let anyMetatype: Any.Type = Int.self |
| output = "" |
| dump(anyMetatype, to: &output) |
| expectEqual(expectedInt, output) |
| |
| let nativeProtocolMetatype: SomeNativeProto.Type = Int.self |
| output = "" |
| dump(nativeProtocolMetatype, to: &output) |
| expectEqual(expectedInt, output) |
| |
| let concreteClassMetatype = SomeClass.self |
| let expectedSomeClass = "- a.SomeClass #0\n" |
| output = "" |
| dump(concreteClassMetatype, to: &output) |
| expectEqual(expectedSomeClass, output) |
| |
| let nativeProtocolConcreteMetatype = SomeNativeProto.self |
| let expectedNativeProtocolConcrete = "- a.SomeNativeProto #0\n" |
| output = "" |
| dump(nativeProtocolConcreteMetatype, to: &output) |
| expectEqual(expectedNativeProtocolConcrete, output) |
| } |
| } |
| |
| Reflection.test("TupleMirror") { |
| do { |
| var output = "" |
| let tuple = |
| (Brilliant(384, "seven six eight"), StructWithDefaultMirror("nine")) |
| dump(tuple, to: &output) |
| |
| let expected = |
| "â–¿ (2 elements)\n" + |
| " â–¿ .0: a.Brilliant #0\n" + |
| " - first: 384\n" + |
| " - second: \"seven six eight\"\n" + |
| " â–¿ self: a.Brilliant #0\n" + |
| " â–¿ .1: a.StructWithDefaultMirror\n" + |
| " - s: \"nine\"\n" |
| |
| expectEqual(expected, output) |
| |
| expectEqual(.tuple, Mirror(reflecting: tuple).displayStyle) |
| } |
| |
| do { |
| // A tuple of stdlib types with mirrors. |
| var output = "" |
| let tuple = (1, 2.5, false, "three") |
| dump(tuple, to: &output) |
| |
| let expected = |
| "â–¿ (4 elements)\n" + |
| " - .0: 1\n" + |
| " - .1: 2.5\n" + |
| " - .2: false\n" + |
| " - .3: \"three\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // A nested tuple. |
| var output = "" |
| let tuple = (1, ("Hello", "World")) |
| dump(tuple, to: &output) |
| |
| let expected = |
| "â–¿ (2 elements)\n" + |
| " - .0: 1\n" + |
| " â–¿ .1: (2 elements)\n" + |
| " - .0: \"Hello\"\n" + |
| " - .1: \"World\"\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| class DullClass {} |
| |
| Reflection.test("ClassReflection") { |
| expectEqual(.`class`, Mirror(reflecting: DullClass()).displayStyle) |
| } |
| |
| Reflection.test("String/Mirror") { |
| do { |
| var output = "" |
| dump("", to: &output) |
| |
| let expected = |
| "- \"\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+0061 LATIN SMALL LETTER A |
| // U+304B HIRAGANA LETTER KA |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| // U+1F425 FRONT-FACING BABY CHICK |
| var output = "" |
| dump("\u{61}\u{304b}\u{3099}\u{1f425}", to: &output) |
| |
| let expected = |
| "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("String.UTF8View/Mirror") { |
| // U+0061 LATIN SMALL LETTER A |
| // U+304B HIRAGANA LETTER KA |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| var output = "" |
| dump("\u{61}\u{304b}\u{3099}".utf8, to: &output) |
| |
| let expected = |
| "â–¿ UTF8View(\"\u{61}\u{304b}\u{3099}\")\n" + |
| " - 97\n" + |
| " - 227\n" + |
| " - 129\n" + |
| " - 139\n" + |
| " - 227\n" + |
| " - 130\n" + |
| " - 153\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("String.UTF16View/Mirror") { |
| // U+0061 LATIN SMALL LETTER A |
| // U+304B HIRAGANA LETTER KA |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| // U+1F425 FRONT-FACING BABY CHICK |
| var output = "" |
| dump("\u{61}\u{304b}\u{3099}\u{1f425}".utf16, to: &output) |
| |
| let expected = |
| "â–¿ StringUTF16(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" + |
| " - 97\n" + |
| " - 12363\n" + |
| " - 12441\n" + |
| " - 55357\n" + |
| " - 56357\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("String.UnicodeScalarView/Mirror") { |
| // U+0061 LATIN SMALL LETTER A |
| // U+304B HIRAGANA LETTER KA |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| // U+1F425 FRONT-FACING BABY CHICK |
| var output = "" |
| dump("\u{61}\u{304b}\u{3099}\u{1f425}".unicodeScalars, to: &output) |
| |
| let expected = |
| "â–¿ StringUnicodeScalarView(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" + |
| " - \"\u{61}\"\n" + |
| " - \"\\u{304B}\"\n" + |
| " - \"\\u{3099}\"\n" + |
| " - \"\\u{0001F425}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("Character/Mirror") { |
| do { |
| // U+0061 LATIN SMALL LETTER A |
| let input: Character = "\u{61}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\u{61}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+304B HIRAGANA LETTER KA |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| let input: Character = "\u{304b}\u{3099}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\u{304b}\u{3099}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+1F425 FRONT-FACING BABY CHICK |
| let input: Character = "\u{1f425}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\u{1f425}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("UnicodeScalar") { |
| do { |
| // U+0061 LATIN SMALL LETTER A |
| let input: UnicodeScalar = "\u{61}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\u{61}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+304B HIRAGANA LETTER KA |
| let input: UnicodeScalar = "\u{304b}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\\u{304B}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| let input: UnicodeScalar = "\u{3099}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\\u{3099}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+1F425 FRONT-FACING BABY CHICK |
| let input: UnicodeScalar = "\u{1f425}" |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- \"\\u{0001F425}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("Bool") { |
| do { |
| var output = "" |
| dump(false, to: &output) |
| |
| let expected = |
| "- false\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var output = "" |
| dump(true, to: &output) |
| |
| let expected = |
| "- true\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| // FIXME: these tests should cover Float80. |
| // FIXME: these tests should be automatically generated from the list of |
| // available floating point types. |
| Reflection.test("Float") { |
| do { |
| var output = "" |
| dump(Float.nan, to: &output) |
| |
| let expected = |
| "- nan\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var output = "" |
| dump(Float.infinity, to: &output) |
| |
| let expected = |
| "- inf\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var input: Float = 42.125 |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- 42.125\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("Double") { |
| do { |
| var output = "" |
| dump(Double.nan, to: &output) |
| |
| let expected = |
| "- nan\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var output = "" |
| dump(Double.infinity, to: &output) |
| |
| let expected = |
| "- inf\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| var input: Double = 42.125 |
| var output = "" |
| dump(input, to: &output) |
| |
| let expected = |
| "- 42.125\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| // A struct type and class type whose NominalTypeDescriptor.FieldNames |
| // data is exactly eight bytes long. FieldNames data of exactly |
| // 4 or 8 or 16 bytes was once miscompiled on arm64. |
| struct EightByteFieldNamesStruct { |
| let abcdef = 42 |
| } |
| class EightByteFieldNamesClass { |
| let abcdef = 42 |
| } |
| |
| Reflection.test("FieldNamesBug") { |
| do { |
| let expected = |
| "â–¿ a.EightByteFieldNamesStruct\n" + |
| " - abcdef: 42\n" |
| var output = "" |
| dump(EightByteFieldNamesStruct(), to: &output) |
| expectEqual(expected, output) |
| } |
| |
| do { |
| let expected = |
| "â–¿ a.EightByteFieldNamesClass #0\n" + |
| " - abcdef: 42\n" |
| var output = "" |
| dump(EightByteFieldNamesClass(), to: &output) |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("MirrorMirror") { |
| var object = 1 |
| var mirror = Mirror(reflecting: object) |
| var mirrorMirror = Mirror(reflecting: mirror) |
| |
| expectEqual(0, mirrorMirror.children.count) |
| } |
| |
| Reflection.test("OpaquePointer/null") { |
| // Don't crash on null pointers. rdar://problem/19708338 |
| let pointer: OpaquePointer? = nil |
| let mirror = Mirror(reflecting: pointer) |
| expectEqual(0, mirror.children.count) |
| } |
| |
| Reflection.test("StaticString/Mirror") { |
| do { |
| var output = "" |
| dump("" as StaticString, to: &output) |
| |
| let expected = |
| "- \"\"\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| do { |
| // U+0061 LATIN SMALL LETTER A |
| // U+304B HIRAGANA LETTER KA |
| // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK |
| // U+1F425 FRONT-FACING BABY CHICK |
| var output = "" |
| dump("\u{61}\u{304b}\u{3099}\u{1f425}" as StaticString, to: &output) |
| |
| let expected = |
| "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n" |
| |
| expectEqual(expected, output) |
| } |
| } |
| |
| Reflection.test("DictionaryIterator/Mirror") { |
| let d: [MinimalHashableValue : OpaqueValue<Int>] = |
| [ MinimalHashableValue(0) : OpaqueValue(0) ] |
| |
| var output = "" |
| dump(d.makeIterator(), to: &output) |
| |
| let expected = |
| "- Swift.DictionaryIterator<StdlibUnittest.MinimalHashableValue, StdlibUnittest.OpaqueValue<Swift.Int>>\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| Reflection.test("SetIterator/Mirror") { |
| let s: Set<MinimalHashableValue> = [ MinimalHashableValue(0)] |
| |
| var output = "" |
| dump(s.makeIterator(), to: &output) |
| |
| let expected = |
| "- Swift.SetIterator<StdlibUnittest.MinimalHashableValue>\n" |
| |
| expectEqual(expected, output) |
| } |
| |
| var BitTwiddlingTestSuite = TestSuite("BitTwiddling") |
| |
| func computeCountLeadingZeroes(_ x: Int64) -> Int64 { |
| var x = x |
| var r: Int64 = 64 |
| while x != 0 { |
| x >>= 1 |
| r -= 1 |
| } |
| return r |
| } |
| |
| BitTwiddlingTestSuite.test("_pointerSize") { |
| #if arch(i386) || arch(arm) |
| expectEqual(4, MemoryLayout<Optional<AnyObject>>.size) |
| #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) |
| expectEqual(8, MemoryLayout<Optional<AnyObject>>.size) |
| #else |
| fatalError("implement") |
| #endif |
| } |
| |
| BitTwiddlingTestSuite.test("_countLeadingZeros") { |
| for i in Int64(0)..<1000 { |
| expectEqual(computeCountLeadingZeroes(i), _countLeadingZeros(i)) |
| } |
| expectEqual(0, _countLeadingZeros(Int64.min)) |
| } |
| |
| BitTwiddlingTestSuite.test("_isPowerOf2/Int") { |
| func asInt(_ a: Int) -> Int { return a } |
| |
| expectFalse(_isPowerOf2(asInt(-1025))) |
| expectFalse(_isPowerOf2(asInt(-1024))) |
| expectFalse(_isPowerOf2(asInt(-1023))) |
| expectFalse(_isPowerOf2(asInt(-4))) |
| expectFalse(_isPowerOf2(asInt(-3))) |
| expectFalse(_isPowerOf2(asInt(-2))) |
| expectFalse(_isPowerOf2(asInt(-1))) |
| expectFalse(_isPowerOf2(asInt(0))) |
| expectTrue(_isPowerOf2(asInt(1))) |
| expectTrue(_isPowerOf2(asInt(2))) |
| expectFalse(_isPowerOf2(asInt(3))) |
| expectTrue(_isPowerOf2(asInt(1024))) |
| #if arch(i386) || arch(arm) |
| // Not applicable to 32-bit architectures. |
| #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) |
| expectTrue(_isPowerOf2(asInt(0x8000_0000))) |
| #else |
| fatalError("implement") |
| #endif |
| expectFalse(_isPowerOf2(Int.min)) |
| expectFalse(_isPowerOf2(Int.max)) |
| } |
| |
| BitTwiddlingTestSuite.test("_isPowerOf2/UInt") { |
| func asUInt(_ a: UInt) -> UInt { return a } |
| |
| expectFalse(_isPowerOf2(asUInt(0))) |
| expectTrue(_isPowerOf2(asUInt(1))) |
| expectTrue(_isPowerOf2(asUInt(2))) |
| expectFalse(_isPowerOf2(asUInt(3))) |
| expectTrue(_isPowerOf2(asUInt(1024))) |
| expectTrue(_isPowerOf2(asUInt(0x8000_0000))) |
| expectFalse(_isPowerOf2(UInt.max)) |
| } |
| |
| BitTwiddlingTestSuite.test("_floorLog2") { |
| expectEqual(_floorLog2(1), 0) |
| expectEqual(_floorLog2(8), 3) |
| expectEqual(_floorLog2(15), 3) |
| expectEqual(_floorLog2(Int64.max), 62) // 63 minus 1 for sign bit. |
| } |
| |
| var AvailabilityVersionsTestSuite = TestSuite("AvailabilityVersions") |
| |
| AvailabilityVersionsTestSuite.test("lexicographic_compare") { |
| func version( |
| _ major: Int, |
| _ minor: Int, |
| _ patch: Int |
| ) -> _SwiftNSOperatingSystemVersion { |
| return _SwiftNSOperatingSystemVersion( |
| majorVersion: major, |
| minorVersion: minor, |
| patchVersion: patch |
| ) |
| } |
| |
| checkComparable(.eq, version(0, 0, 0), version(0, 0, 0)) |
| |
| checkComparable(.lt, version(0, 0, 0), version(0, 0, 1)) |
| checkComparable(.lt, version(0, 0, 0), version(0, 1, 0)) |
| checkComparable(.lt, version(0, 0, 0), version(1, 0, 0)) |
| |
| checkComparable(.lt, version(10, 9, 0), version(10, 10, 0)) |
| checkComparable(.lt, version(10, 9, 11), version(10, 10, 0)) |
| checkComparable(.lt, version(10, 10, 3), version(10, 11, 0)) |
| |
| checkComparable(.lt, version(8, 3, 0), version(9, 0, 0)) |
| |
| checkComparable(.lt, version(0, 11, 0), version(10, 10, 4)) |
| checkComparable(.lt, version(0, 10, 0), version(10, 10, 4)) |
| checkComparable(.lt, version(3, 2, 1), version(4, 3, 2)) |
| checkComparable(.lt, version(1, 2, 3), version(2, 3, 1)) |
| |
| checkComparable(.eq, version(10, 11, 12), version(10, 11, 12)) |
| |
| checkEquatable(true, version(1, 2, 3), version(1, 2, 3)) |
| checkEquatable(false, version(1, 2, 3), version(1, 2, 42)) |
| checkEquatable(false, version(1, 2, 3), version(1, 42, 3)) |
| checkEquatable(false, version(1, 2, 3), version(42, 2, 3)) |
| } |
| |
| AvailabilityVersionsTestSuite.test("_stdlib_isOSVersionAtLeast") { |
| func isAtLeastOS(_ major: Int, _ minor: Int, _ patch: Int) -> Bool { |
| return _getBool(_stdlib_isOSVersionAtLeast(major._builtinWordValue, |
| minor._builtinWordValue, |
| patch._builtinWordValue)) |
| } |
| |
| // _stdlib_isOSVersionAtLeast is broken for |
| // watchOS. rdar://problem/20234735 |
| #if os(OSX) || os(iOS) || os(tvOS) || os(watchOS) |
| // This test assumes that no version component on an OS we test upon |
| // will ever be greater than 1066 and that every major version will always |
| // be greater than 1. |
| expectFalse(isAtLeastOS(1066, 0, 0)) |
| expectTrue(isAtLeastOS(0, 1066, 0)) |
| expectTrue(isAtLeastOS(0, 0, 1066)) |
| #endif |
| } |
| |
| runAllTests() |
| |