| // RUN: %empty-directory(%t) |
| // RUN: %target-build-swift -emit-library -o %t/libSimpleNSObjectSubclass.dylib %S/Inputs/SimpleNSObjectSubclass.swift -Xlinker -install_name -Xlinker @executable_path/libSimpleNSObjectSubclass.dylib |
| // RUN: %target-codesign %t/libSimpleNSObjectSubclass.dylib |
| |
| // RUN: %target-build-swift %s -o %t/main -lSimpleNSObjectSubclass -L%t -import-objc-header %S/Inputs/class_getImageName-static-helper.h |
| // RUN: %target-codesign %t/main |
| // RUN: %target-run %t/main %t/libSimpleNSObjectSubclass.dylib |
| |
| // REQUIRES: executable_test |
| // REQUIRES: objc_interop |
| |
| import Darwin |
| import ObjectiveC |
| // import SimpleNSObjectSubclass // Deliberately omitted in favor of dynamic loads. |
| |
| // Note: The following typealias uses AnyObject instead of AnyClass so that the |
| // function type is trivially bridgeable to Objective-C. (The representation of |
| // AnyClass is not the same as Objective-C's 'Class' type.) |
| typealias GetImageHook = @convention(c) (AnyObject, UnsafeMutablePointer<UnsafePointer<CChar>?>) -> ObjCBool |
| var hook: GetImageHook? |
| |
| func checkThatSwiftHookWasNotInstalled() { |
| // Check that the Swift hook did not get installed. |
| guard let setHookPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), |
| getHookName()) else { |
| // If the version of the ObjC runtime we're using doesn't have the hook, |
| // we're good. |
| return |
| } |
| |
| let setHook = unsafeBitCast(setHookPtr, to: (@convention(c) (GetImageHook, UnsafeMutablePointer<GetImageHook?>) -> Void).self) |
| setHook({ hook!($0, $1) }, &hook) |
| |
| var info: Dl_info = .init() |
| guard 0 != dladdr(unsafeBitCast(hook, to: UnsafeRawPointer.self), &info) else { |
| fatalError("could not get dladdr info for objc_hook_getImageName") |
| } |
| |
| precondition(String(cString: info.dli_fname).hasSuffix("libobjc.A.dylib"), |
| "hook was replaced") |
| } |
| |
| // It's important that this test does not register any Swift classes with the |
| // Objective-C runtime---that's where Swift sets up its custom hook, and we want |
| // to check the behavior /without/ that hook. That includes the buffer types for |
| // String and Array. Therefore, we get C strings directly from a bridging |
| // header. |
| |
| guard let theClass = objc_getClass(getNameOfClassToFind()) as! AnyClass? else { |
| fatalError("could not find class") |
| } |
| |
| guard let imageName = class_getImageName(theClass) else { |
| fatalError("could not find image") |
| } |
| |
| checkThatSwiftHookWasNotInstalled() |
| |
| // Okay, now we can use String. |
| |
| precondition(String(cString: imageName).hasSuffix("libSimpleNSObjectSubclass.dylib"), |
| "found wrong image") |