Skip to content

Commit 50a70a9

Browse files
authored
Revert #9 (#11)
* Revert #9 Fixes #10. * wip
1 parent eafd792 commit 50a70a9

File tree

1 file changed

+79
-57
lines changed

1 file changed

+79
-57
lines changed
Lines changed: 79 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,77 @@
1-
#if canImport(ObjectiveC)
2-
import Foundation
3-
1+
#if DEBUG
2+
#if canImport(ObjectiveC)
3+
import Foundation
4+
5+
/// This function generates a failure immediately and unconditionally.
6+
///
7+
/// Dynamically creates and records an `XCTIssue` under the hood that captures the source code
8+
/// context of the caller. Useful for defining assertion helpers that fail in indirect code
9+
/// paths, where the `file` and `line` of the failure have not been realized.
10+
///
11+
/// - Parameter message: An optional description of the assertion, for inclusion in test
12+
/// results.
13+
public func XCTFail(_ message: String = "") {
14+
if let XCTestObservationCenter = NSClassFromString("XCTestObservationCenter")
15+
as Any as? NSObjectProtocol,
16+
String(describing: XCTestObservationCenter) != "<null>",
17+
let shared = XCTestObservationCenter.perform(Selector(("sharedTestObservationCenter")))?
18+
.takeUnretainedValue(),
19+
let observers = shared.perform(Selector(("observers")))?
20+
.takeUnretainedValue() as? [AnyObject],
21+
let observer =
22+
observers
23+
.first(where: { NSStringFromClass(type(of: $0)) == "XCTestMisuseObserver" }),
24+
let currentTestCase = observer.perform(Selector(("currentTestCase")))?
25+
.takeUnretainedValue(),
26+
let XCTIssue = NSClassFromString("XCTIssue")
27+
as Any as? NSObjectProtocol,
28+
let alloc = XCTIssue.perform(NSSelectorFromString("alloc"))?
29+
.takeUnretainedValue(),
30+
let issue =
31+
alloc
32+
.perform(
33+
Selector(("initWithType:compactDescription:")),
34+
with: 0,
35+
with: message.isEmpty ? "failed" : message
36+
)?
37+
.takeUnretainedValue()
38+
{
39+
_ = currentTestCase.perform(Selector(("recordIssue:")), with: issue)
40+
return
41+
}
42+
}
43+
44+
/// This function generates a failure immediately and unconditionally.
45+
///
46+
/// Dynamically calls `XCTFail` with the given file and line. Useful for defining assertion
47+
/// helpers that have the source code context at hand and want to highlight the direct caller
48+
/// of the helper.
49+
///
50+
/// - Parameter message: An optional description of the assertion, for inclusion in test
51+
/// results.
52+
public func XCTFail(_ message: String = "", file: StaticString, line: UInt) {
53+
guard let _XCTFailureHandler = _XCTFailureHandler
54+
else { return }
55+
56+
_XCTFailureHandler(nil, true, "\(file)", line, "\(message.isEmpty ? "failed" : message)", nil)
57+
}
58+
59+
private typealias XCTFailureHandler = @convention(c) (
60+
AnyObject?, Bool, UnsafePointer<CChar>, UInt, String, String?
61+
) -> Void
62+
private let XCTest = NSClassFromString("XCTest")
63+
.flatMap(Bundle.init(for:))
64+
.flatMap { $0.executablePath }
65+
.flatMap { dlopen($0, RTLD_NOW) }
66+
private let _XCTFailureHandler =
67+
XCTest
68+
.flatMap { dlsym($0, "_XCTFailureHandler") }
69+
.map { unsafeBitCast($0, to: XCTFailureHandler.self) }
70+
#else
71+
// NB: It seems to be safe to import XCTest on Linux
72+
@_exported import func XCTest.XCTFail
73+
#endif
74+
#else
475
/// This function generates a failure immediately and unconditionally.
576
///
677
/// Dynamically creates and records an `XCTIssue` under the hood that captures the source code
@@ -9,64 +80,15 @@
980
///
1081
/// - Parameter message: An optional description of the assertion, for inclusion in test
1182
/// results.
12-
public func XCTFail(_ message: String = "") {
13-
if let XCTestObservationCenter = NSClassFromString("XCTestObservationCenter")
14-
as Any as? NSObjectProtocol,
15-
String(describing: XCTestObservationCenter) != "<null>",
16-
let shared = XCTestObservationCenter.perform(Selector(("sharedTestObservationCenter")))?
17-
.takeUnretainedValue(),
18-
let observers = shared.perform(Selector(("observers")))?
19-
.takeUnretainedValue() as? [AnyObject],
20-
let observer =
21-
observers
22-
.first(where: { NSStringFromClass(type(of: $0)) == "XCTestMisuseObserver" }),
23-
let currentTestCase = observer.perform(Selector(("currentTestCase")))?
24-
.takeUnretainedValue(),
25-
let XCTIssue = NSClassFromString("XCTIssue")
26-
as Any as? NSObjectProtocol,
27-
let alloc = XCTIssue.perform(NSSelectorFromString("alloc"))?
28-
.takeUnretainedValue(),
29-
let issue =
30-
alloc
31-
.perform(
32-
Selector(("initWithType:compactDescription:")),
33-
with: 0,
34-
with: message.isEmpty ? "failed" : message
35-
)?
36-
.takeUnretainedValue()
37-
{
38-
_ = currentTestCase.perform(Selector(("recordIssue:")), with: issue)
39-
return
40-
}
41-
}
83+
public func XCTFail(_ message: String = "") {}
4284

4385
/// This function generates a failure immediately and unconditionally.
4486
///
45-
/// Dynamically calls `XCTFail` with the given file and line. Useful for defining assertion
46-
/// helpers that have the source code context at hand and want to highlight the direct caller
47-
/// of the helper.
87+
/// Dynamically creates and records an `XCTIssue` under the hood that captures the source code
88+
/// context of the caller. Useful for defining assertion helpers that fail in indirect code
89+
/// paths, where the `file` and `line` of the failure have not been realized.
4890
///
4991
/// - Parameter message: An optional description of the assertion, for inclusion in test
5092
/// results.
51-
public func XCTFail(_ message: String = "", file: StaticString, line: UInt) {
52-
guard let _XCTFailureHandler = _XCTFailureHandler
53-
else { return }
54-
55-
_XCTFailureHandler(nil, true, "\(file)", line, "\(message.isEmpty ? "failed" : message)", nil)
56-
}
57-
58-
private typealias XCTFailureHandler = @convention(c) (
59-
AnyObject?, Bool, UnsafePointer<CChar>, UInt, String, String?
60-
) -> Void
61-
private let XCTest = NSClassFromString("XCTest")
62-
.flatMap(Bundle.init(for:))
63-
.flatMap { $0.executablePath }
64-
.flatMap { dlopen($0, RTLD_NOW) }
65-
private let _XCTFailureHandler =
66-
XCTest
67-
.flatMap { dlsym($0, "_XCTFailureHandler") }
68-
.map { unsafeBitCast($0, to: XCTFailureHandler.self) }
69-
#else
70-
// NB: It seems to be safe to import XCTest on Linux
71-
@_exported import func XCTest.XCTFail
93+
public func XCTFail(_ message: String = "", file: StaticString, line: UInt) {}
7294
#endif

0 commit comments

Comments
 (0)