Skip to content

Commit 3c092d0

Browse files
committed
Create helper to post test events to fallback event handler
As part of the strategy for enabling interoperability, unhandled issues can be turned into events and sent to the fallback event handler. Also link against the _TestingInterop framework/library (depending on the platform), which provides a function to lookup the currently installed fallback event handler.
1 parent 00c0b1b commit 3c092d0

File tree

5 files changed

+90
-4
lines changed

5 files changed

+90
-4
lines changed

Package.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,20 @@ let package = Package(
142142
exclude: ["CMakeLists.txt", "Testing.swiftcrossimport"],
143143
cxxSettings: .packageSettings,
144144
swiftSettings: .packageSettings + .enableLibraryEvolution(),
145-
linkerSettings: [
146-
.linkedLibrary("execinfo", .when(platforms: [.custom("freebsd"), .openbsd]))
147-
]
145+
linkerSettings: {
146+
var result = [LinkerSetting]()
147+
result += [
148+
.linkedLibrary("execinfo", .when(platforms: [.custom("freebsd"), .openbsd]))
149+
]
150+
#if compiler(>=6.3)
151+
result += [
152+
.linkedFramework("_TestingInterop", .whenApple()),
153+
.linkedLibrary("_TestingInterop", .whenApple(false)),
154+
]
155+
#endif
156+
157+
return result
158+
}()
148159
),
149160
.testTarget(
150161
name: "TestingTests",

Sources/Testing/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_library(Testing
3131
Attachments/Attachment.swift
3232
Events/Clock.swift
3333
Events/Event.swift
34+
Events/Event+FallbackHandler.swift
3435
Events/Recorder/Event.AdvancedConsoleOutputRecorder.swift
3536
Events/Recorder/Event.ConsoleOutputRecorder.swift
3637
Events/Recorder/Event.HumanReadableOutputRecorder.swift
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// This source file is part of the Swift.org open source project
3+
//
4+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
5+
// Licensed under Apache License v2.0 with Runtime Library Exception
6+
//
7+
// See https://swift.org/LICENSE.txt for license information
8+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
//
10+
11+
private import _TestingInternals
12+
13+
extension Event {
14+
private static let _fallbackEventHandler: FallbackEventHandler? = {
15+
_swift_testing_getFallbackEventHandler()
16+
}()
17+
18+
/// Post this event to the currently-installed fallback event handler.
19+
///
20+
/// - Parameters:
21+
/// - context: The context associated with this event.
22+
///
23+
/// - Returns: Whether or not the fallback event handler was invoked. If the
24+
/// currently-installed handler belongs to the testing library, returns
25+
/// `false`.
26+
borrowing func postToFallbackHandler(in context: borrowing Context) -> Bool {
27+
#if canImport(_TestingInterop)
28+
guard let fallbackEventHandler = Self._fallbackEventHandler else {
29+
return false
30+
}
31+
32+
// Encode the event as JSON and pass it to the handler.
33+
let encodeAndInvoke = ABI.CurrentVersion.eventHandler(encodeAsJSONLines: false) {
34+
recordJSON in
35+
fallbackEventHandler(
36+
String(describing: ABI.CurrentVersion.versionNumber),
37+
recordJSON.baseAddress!,
38+
recordJSON.count,
39+
nil
40+
)
41+
}
42+
encodeAndInvoke(self, context)
43+
return true
44+
#else
45+
return false
46+
#endif
47+
}
48+
}

Sources/_TestingInternals/include/Stubs.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,32 @@ static int swt_setfdflags(int fd, int flags) {
180180
}
181181
#endif
182182

183+
// __SWIFT_COMPILER_VERSION is a packed value. The comparison below is >= 6.3
184+
#if __SWIFT_COMPILER_VERSION >= 6003000000000 && !SWT_NO_INTEROP
185+
186+
/// A type describing a fallback event handler that testing API can invoke as an
187+
/// alternate method of reporting test events to the current test runner.
188+
/// Shadows the type with the same name in _TestingInterop.
189+
///
190+
/// - Parameters:
191+
/// - recordJSONSchemaVersionNumber: The JSON schema version used to encode
192+
/// the event record.
193+
/// - recordJSONBaseAddress: A pointer to the first byte of the encoded event.
194+
/// - recordJSONByteCount: The size of the encoded event in bytes.
195+
/// - reserved: Reserved for future use.
196+
typedef void (* FallbackEventHandler)(const char *recordJSONSchemaVersionNumber,
197+
const void *recordJSONBaseAddress,
198+
long recordJSONByteCount,
199+
const void *_Nullable reserved);
200+
201+
/// Get the current fallback event handler.
202+
/// Shadows the function with the same name in _TestingInterop.
203+
///
204+
/// - Returns: The currently-set handler function, if any.
205+
SWT_EXTERN FallbackEventHandler _Nullable _swift_testing_getFallbackEventHandler(void);
206+
207+
#endif
208+
183209
SWT_ASSUME_NONNULL_END
184210

185211
#endif

Sources/_TestingInterop/FallbackEventHandler.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
//
1010

11-
#if !SWT_NO_INTEROP
11+
#if compiler(>=6.3) && !SWT_NO_INTEROP
1212
#if SWT_TARGET_OS_APPLE && !SWT_NO_OS_UNFAIR_LOCK && !hasFeature(Embedded)
1313
private import _TestingInternals
1414
#else

0 commit comments

Comments
 (0)