| // 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-codesign %t.out |
| // RUN: %target-run %t.out |
| // REQUIRES: executable_test |
| |
| import Swift |
| import StdlibUnittest |
| import SwiftShims |
| |
| #if canImport(Darwin) |
| import Darwin |
| #elseif canImport(Glibc) |
| import Glibc |
| #elseif os(Windows) |
| import MSVCRT |
| import WinSDK |
| #else |
| #error("Unsupported platform") |
| #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") { |
| let someP1Value = StructConformsToP1() |
| let someP1Value2 = Struct2ConformsToP1(StructConformsToP1()) |
| let someNotP1Value = StructDoesNotConformToP1() |
| let someP2Value = Struct3ConformsToP2() |
| let someP2Value2 = Struct4ConformsToP2(Struct3ConformsToP2()) |
| let someP1Ref = ClassConformsToP1() |
| let someP1Ref2 = Class2ConformsToP1(ClassConformsToP1()) |
| let 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 } |
| |
| _ = 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("$sSdD")) |
| 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("$s1x1aAA3FooCyADyADySiSiGADySiSiGGADyADySiSiGADySiSiGGGvp")) |
| expectEqual("Foobar", _stdlib_demangleName("$s13__lldb_expr_46FoobarCD")) |
| } |
| |
| if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) { |
| Runtime.test("demangleTruncate") { |
| // Swift.Int requires 10 bytes to be fully demangled. |
| let buffer = UnsafeMutableBufferPointer<Int8>.allocate(capacity: 10) |
| |
| defer { buffer.deallocate() } |
| |
| // Set last byte to a custom number, that way when we call swift_demangle |
| // the last byte should be unchanged rather than it being set to 0. |
| buffer[buffer.count - 1] = 16 |
| |
| // Only give 9 bytes though to exercise that swift_demangle doesn't write past |
| // the buffer. |
| var bufferSize = UInt(buffer.count - 1) |
| |
| let mangled = "$sSi" |
| |
| mangled.utf8CString.withUnsafeBufferPointer { |
| _ = _stdlib_demangleImpl( |
| mangledName: $0.baseAddress, |
| mangledNameLength: UInt($0.count - 1), |
| outputBuffer: buffer.baseAddress, |
| outputBufferSize: &bufferSize, |
| flags: 0 |
| ) |
| } |
| |
| expectEqual(String(cString: buffer.baseAddress!), "Swift.In") |
| expectEqual(bufferSize, 10) |
| expectEqual(buffer[buffer.count - 1], 16) |
| } |
| } |
| |
| % for optionality in ['', '?']: |
| Runtime.test("_stdlib_atomicCompareExchangeStrongPtr") { |
| typealias IntPtr = UnsafeMutablePointer<Int> |
| let origP1: IntPtr${optionality} = IntPtr(bitPattern: 0x10101010)! |
| let origP2: IntPtr${optionality} = IntPtr(bitPattern: 0x20202020)! |
| let 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 { |
| let 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") { |
| let offsetof_SwiftError_typeMetadata = pointerToSwiftCoreSymbol(name: "_swift_lldb_offsetof_SwiftError_typeMetadata")! |
| let sizeof_SwiftError = pointerToSwiftCoreSymbol(name: "_swift_lldb_sizeof_SwiftError")! |
| |
| #if canImport(Darwin) |
| #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) || os(Android) || os(Windows) || os(OpenBSD) |
| 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) |
| } |
| |
| |
| class Brilliant { |
| let first: Int |
| let second: String |
| |
| init(_ fst: Int, _ snd: String) { |
| self.first = fst |
| self.second = snd |
| } |
| } |
| |
| 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) |
| |
| } |
| |
| class C: Q1 & Codable { } |
| |
| Reflection.test("multiprotocolTypes") { |
| // [SR-8158]: Printing type(of: Codable & Protocol type ) EXC_BAD_ACCESS |
| // This use of String(reflecting:) exercises a previously incorrect cast in |
| // NonFixedExistentialMetatypeBox::Container::getNumWitnessTables. |
| let obj: Q1 & Codable = C() |
| let t = type(of: obj) |
| let x = String(reflecting: t) |
| expectEqual("a.C", x) |
| } |
| |
| |
| var BitTwiddlingTestSuite = TestSuite("BitTwiddling") |
| |
| BitTwiddlingTestSuite.test("_pointerSize") { |
| #if arch(i386) || arch(arm) |
| expectEqual(4, MemoryLayout<Optional<AnyObject>>.size) |
| #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) |
| expectEqual(8, MemoryLayout<Optional<AnyObject>>.size) |
| #else |
| fatalError("implement") |
| #endif |
| } |
| |
| 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)) |
| } |
| |
| var AvailabilityVersionsTestSuite = TestSuite("AvailabilityVersions") |
| |
| AvailabilityVersionsTestSuite.test("_stdlib_isOSVersionAtLeast") { |
| func isAtLeastOS(_ major: Int, _ minor: Int, _ patch: Int) -> Bool { |
| return Bool(_builtinBooleanLiteral: _stdlib_isOSVersionAtLeast( |
| major._builtinWordValue, |
| minor._builtinWordValue, |
| patch._builtinWordValue)) |
| } |
| |
| // _stdlib_isOSVersionAtLeast is broken for |
| // watchOS. rdar://problem/20234735 |
| #if canImport(Darwin) |
| // 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)) |
| |
| // When using a runtime that's not part of the OS, 9999 is a special version |
| // that's always available. The _swift_classIsSwiftMask symbol is absent in OS |
| // libraries, so detect based on that. |
| let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2) |
| let _swift_classIsSwiftMaskPtr = dlsym(RTLD_DEFAULT, "_swift_classIsSwiftMask") |
| if _swift_classIsSwiftMaskPtr != nil { |
| expectTrue(isAtLeastOS(9999, 0, 0)) |
| } |
| #endif |
| } |
| |
| runAllTests() |
| |