Skip to content

Commit 414cd10

Browse files
authored
Return the ABI entry point from swt_copyABIEntryPoint_v0() normally. (#389)
This PR changes the calling convention of `swt_copyABIEntryPoint_v0()` to return a pointer to the ABI entry point rather than passing it back through an out-parameter. The previous signature was an attempt to allow using `withUnsafeTemporaryAllocation()` (to avoid a heap allocation) but that's a premature optimization and makes the function harder to use. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent a2bf9a2 commit 414cd10

File tree

2 files changed

+18
-21
lines changed

2 files changed

+18
-21
lines changed

Sources/Testing/EntryPoints/ABIEntryPoint.swift

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
///
2929
/// - Warning: This function's signature and the structure of its JSON inputs
3030
/// and outputs have not been finalized yet.
31-
@_spi(ForToolsIntegrationOnly)
31+
@_spi(Experimental) @_spi(ForToolsIntegrationOnly)
3232
public typealias ABIEntryPoint_v0 = @Sendable (
3333
_ argumentsJSON: UnsafeRawBufferPointer?,
3434
_ eventHandler: @escaping @Sendable (_ eventAndContextJSON: UnsafeRawBufferPointer) -> Void
@@ -37,36 +37,35 @@ public typealias ABIEntryPoint_v0 = @Sendable (
3737
/// Get the entry point to the testing library used by tools that want to remain
3838
/// version-agnostic regarding the testing library.
3939
///
40-
/// - Parameters:
41-
/// - outEntryPoint: Uninitialized memory large enough to hold an instance of
42-
/// ``ABIEntryPoint_v0``. On return, a pointer to an instance of that type
43-
/// representing the ABI-stable entry point to the testing library. The
44-
/// caller owns this memory and is responsible for deinitializing and
45-
/// deallocating it when done.
40+
/// - Returns: A pointer to an instance of ``ABIEntryPoint_v0`` representing the
41+
/// ABI-stable entry point to the testing library. The caller owns this memory
42+
/// and is responsible for deinitializing and deallocating it when done.
4643
///
4744
/// This function can be used by tools that do not link directly to the testing
4845
/// library and wish to invoke tests in a binary that has been loaded into the
4946
/// current process. The function is emitted into the binary under the name
5047
/// `"swt_copyABIEntryPoint_v0"` and can be dynamically looked up at runtime
5148
/// using `dlsym()` or a platform equivalent.
5249
///
53-
/// The function stored at `outEntryPoint` can be thought of as equivalent to
50+
/// The returned function can be thought of as equivalent to
5451
/// `swift test --experimental-event-stream-output` except that, instead of
5552
/// streaming events to a named pipe or file, it streams them to a callback.
5653
///
5754
/// - Warning: This function's signature and the structure of its JSON inputs
5855
/// and outputs have not been finalized yet.
5956
@_cdecl("swt_copyABIEntryPoint_v0")
60-
@usableFromInline
61-
func abiEntryPoint_v0(_ outEntryPoint: UnsafeMutableRawPointer) {
62-
outEntryPoint.initializeMemory(as: ABIEntryPoint_v0.self) { argumentsJSON, eventHandler in
57+
@_spi(Experimental) @_spi(ForToolsIntegrationOnly)
58+
public func copyABIEntryPoint_v0() -> UnsafeMutableRawPointer {
59+
let result = UnsafeMutablePointer<ABIEntryPoint_v0>.allocate(capacity: 1)
60+
result.initialize { argumentsJSON, eventHandler in
6361
let args = try! argumentsJSON.map { argumentsJSON in
6462
try JSON.decode(__CommandLineArguments_v0.self, from: argumentsJSON)
6563
}
6664

6765
let eventHandler = eventHandlerForStreamingEvents_v0(to: eventHandler)
6866
return await entryPoint(passing: args, eventHandler: eventHandler)
6967
}
68+
return .init(result)
7069
}
7170
#endif
7271

Tests/TestingTests/ABIEntryPointTests.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,26 @@
88
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
//
1010

11-
#if canImport(Foundation) && !SWT_NO_DYNAMIC_LINKING && !SWT_NO_ABI_ENTRY_POINT
11+
#if canImport(Foundation) && !SWT_NO_ABI_ENTRY_POINT
1212
@testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing
1313
private import TestingInternals
1414

1515
@Suite("ABI entry point tests")
1616
struct ABIEntryPointTests {
1717
@Test func v0() async throws {
18-
// Get the ABI entry point.
19-
#if os(Linux)
20-
// The standard Linux linker does not allow exporting symbols from
18+
#if !os(Linux) && !SWT_NO_DYNAMIC_LINKING
19+
// Get the ABI entry point by dynamically looking it up at runtime.
20+
//
21+
// NOTE: The standard Linux linker does not allow exporting symbols from
2122
// executables, so dlsym() does not let us find this function on that
2223
// platform when built as an executable rather than a dynamic library.
23-
let copyABIEntryPoint = abiEntryPoint_v0
24-
#else
25-
let copyABIEntryPoint = try #require(
24+
let copyABIEntryPoint_v0 = try #require(
2625
swt_getFunctionWithName(nil, "swt_copyABIEntryPoint_v0").map {
27-
unsafeBitCast($0, to: (@convention(c) (UnsafeMutableRawPointer) -> Void).self)
26+
unsafeBitCast($0, to: (@convention(c) () -> UnsafeMutableRawPointer).self)
2827
}
2928
)
3029
#endif
31-
let abiEntryPoint = UnsafeMutablePointer<ABIEntryPoint_v0>.allocate(capacity: 1)
32-
copyABIEntryPoint(abiEntryPoint)
30+
let abiEntryPoint = copyABIEntryPoint_v0().assumingMemoryBound(to: ABIEntryPoint_v0.self)
3331
defer {
3432
abiEntryPoint.deinitialize(count: 1)
3533
abiEntryPoint.deallocate()

0 commit comments

Comments
 (0)