mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
134 lines
4.7 KiB
Swift
134 lines
4.7 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift -emit-library -o %t/libGetImageNameHelper.dylib -emit-module %S/Inputs/class_getImageName-helper.swift -Xlinker -install_name -Xlinker @executable_path/libGetImageNameHelper.dylib
|
|
// RUN: %target-codesign %t/libGetImageNameHelper.dylib
|
|
|
|
// RUN: %target-build-swift -g %s -I %t -o %t/main -L %t -lGetImageNameHelper
|
|
// RUN: %target-codesign %t/main
|
|
// RUN: %target-run %t/main %t/libGetImageNameHelper.dylib
|
|
|
|
// REQUIRES: executable_test
|
|
// REQUIRES: objc_interop
|
|
|
|
import Darwin
|
|
import ObjectiveC
|
|
import GetImageNameHelper
|
|
import StdlibUnittest
|
|
|
|
func check(_ cls: AnyClass, in library: String) {
|
|
guard let imageName = class_getImageName(cls) else {
|
|
expectUnreachable("could not find image for \(cls)")
|
|
return
|
|
}
|
|
expectTrue(String(cString: imageName).hasSuffix(library),
|
|
"wrong library for \(cls)")
|
|
}
|
|
|
|
var newOSButCannotUseObjCRuntimeHook = false
|
|
if #available(macOS 10.14, iOS 12, tvOS 12, watchOS 5, *) {
|
|
// The only place these tests will fail is on early versions of the 2018 OSs.
|
|
// The final versions will have 'objc_setHook_getImageName'; anything earlier
|
|
// will be handled by manually overwriting the original implementation of
|
|
// 'class_getImageName'.
|
|
newOSButCannotUseObjCRuntimeHook =
|
|
(nil == dlsym(UnsafeMutableRawPointer(bitPattern: -2),
|
|
"objc_setHook_getImageName"))
|
|
}
|
|
|
|
var testSuite = TestSuite("class_getImageName")
|
|
|
|
testSuite.test("Simple") {
|
|
check(SimpleSwiftObject.self, in: "libGetImageNameHelper.dylib")
|
|
check(SimpleNSObject.self, in: "libGetImageNameHelper.dylib")
|
|
}
|
|
|
|
testSuite.test("Generic")
|
|
.skip(.custom({ newOSButCannotUseObjCRuntimeHook },
|
|
reason: "hook for class_getImageName not present"))
|
|
.code {
|
|
check(GenericSwiftObject<Int>.self, in: "libGetImageNameHelper.dylib")
|
|
check(GenericSwiftObject<NSObject>.self, in: "libGetImageNameHelper.dylib")
|
|
|
|
check(GenericNSObject<Int>.self, in: "libGetImageNameHelper.dylib")
|
|
check(GenericNSObject<NSObject>.self, in: "libGetImageNameHelper.dylib")
|
|
}
|
|
|
|
testSuite.test("GenericAncestry")
|
|
.skip(.custom({ newOSButCannotUseObjCRuntimeHook },
|
|
reason: "hook for class_getImageName not present"))
|
|
.code {
|
|
check(GenericAncestrySwiftObject.self, in: "libGetImageNameHelper.dylib")
|
|
check(GenericAncestryNSObject.self, in: "libGetImageNameHelper.dylib")
|
|
}
|
|
|
|
testSuite.test("Resilient") {
|
|
check(ResilientFieldSwiftObject.self, in: "libGetImageNameHelper.dylib")
|
|
check(ResilientFieldNSObject.self, in: "libGetImageNameHelper.dylib")
|
|
}
|
|
|
|
testSuite.test("ObjC") {
|
|
check(NSObject.self, in: "libobjc.A.dylib")
|
|
}
|
|
|
|
testSuite.test("KVO/Simple") {
|
|
// We use object_getClass in this test to not look through KVO's artificial
|
|
// subclass.
|
|
let obj = SimpleNSObject()
|
|
autoreleasepool {
|
|
let observation = obj.observe(\.observableName) { _, _ in }
|
|
withExtendedLifetime(observation) {
|
|
let theClass = object_getClass(obj)
|
|
precondition(theClass !== SimpleNSObject.self, "no KVO subclass?")
|
|
expectNil(class_getImageName(theClass),
|
|
"should match what happens with NSObject (below)")
|
|
}
|
|
}
|
|
}
|
|
|
|
testSuite.test("KVO/GenericAncestry") {
|
|
// We use object_getClass in this test to not look through KVO's artificial
|
|
// subclass.
|
|
let obj = GenericAncestryNSObject()
|
|
autoreleasepool {
|
|
let observation = obj.observe(\.observableName) { _, _ in }
|
|
withExtendedLifetime(observation) {
|
|
let theClass = object_getClass(obj)
|
|
precondition(theClass !== GenericAncestryNSObject.self, "no KVO subclass?")
|
|
expectNil(class_getImageName(theClass),
|
|
"should match what happens with NSObject (below)")
|
|
}
|
|
}
|
|
}
|
|
|
|
testSuite.test("KVO/ObjC") {
|
|
// We use object_getClass in this test to not look through KVO's artificial
|
|
// subclass.
|
|
let obj = NSObject()
|
|
autoreleasepool {
|
|
let observation = obj.observe(\.description) { _, _ in }
|
|
withExtendedLifetime(observation) {
|
|
let theClass = object_getClass(obj)
|
|
precondition(theClass !== NSObject.self, "no KVO subclass?")
|
|
expectNil(class_getImageName(theClass),
|
|
"should match what happens with the Swift objects (above)")
|
|
}
|
|
}
|
|
}
|
|
|
|
testSuite.test("dynamic") {
|
|
let newClass: AnyClass = objc_allocateClassPair(/*superclass*/NSObject.self,
|
|
"CompletelyDynamic",
|
|
/*extraBytes*/0)!
|
|
objc_registerClassPair(newClass)
|
|
|
|
// We don't actually care what the result is; we just need to not crash.
|
|
_ = class_getImageName(newClass)
|
|
}
|
|
|
|
testSuite.test("nil") {
|
|
// The ObjC runtime should handle this before it even gets to Swift's custom
|
|
// implementation, but just in case.
|
|
expectNil(class_getImageName(nil))
|
|
}
|
|
|
|
runAllTests()
|