Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions Sources/Testing/ExitTests/ExitTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ extension ExitTest {
#endif
}

/// The name of the environment variable used to identify the exit test to
/// call in a spawned exit test process.
private static let _idEnvironmentVariableName = "SWT_EXIT_TEST_ID"

/// Call the exit test in the current process.
///
/// This function invokes the closure originally passed to
Expand Down Expand Up @@ -713,6 +717,17 @@ extension ExitTest {
#endif
}

/// The ID of the exit test to run, if any, specified in the environment.
static var environmentIDForEntryPoint: ID? {
guard var idString = Environment.variable(named: Self._idEnvironmentVariableName) else {
return nil
}

return try? idString.withUTF8 { idBuffer in
try JSON.decode(ExitTest.ID.self, from: UnsafeRawBufferPointer(idBuffer))
}
}

/// Find the exit test function specified in the environment of the current
/// process, if any.
///
Expand All @@ -723,21 +738,15 @@ extension ExitTest {
/// `__swiftPMEntryPoint()` function. The effect of using it under other
/// configurations is undefined.
static func findInEnvironmentForEntryPoint() -> Self? {
// Find the ID of the exit test to run, if any, in the environment block.
var id: ExitTest.ID?
if var idString = Environment.variable(named: "SWT_EXIT_TEST_ID") {
// Clear the environment variable. It's an implementation detail and exit
// test code shouldn't be dependent on it. Use ExitTest.current if needed!
Environment.setVariable(nil, named: "SWT_EXIT_TEST_ID")

id = try? idString.withUTF8 { idBuffer in
try JSON.decode(ExitTest.ID.self, from: UnsafeRawBufferPointer(idBuffer))
}
}
guard let id, var result = find(identifiedBy: id) else {
guard let id = environmentIDForEntryPoint, var result = find(identifiedBy: id) else {
return nil
}

// Since an exit test was found, clear the environment variable. It's an
// implementation detail and exit test code shouldn't be dependent on it.
// Use ExitTest.current if needed!
Environment.setVariable(nil, named: Self._idEnvironmentVariableName)

// If an exit test was found, inject back channel handling into its body.
// External tools authors should set up their own back channel mechanisms
// and ensure they're installed before calling ExitTest.callAsFunction().
Expand Down Expand Up @@ -867,7 +876,7 @@ extension ExitTest {
// Insert a specific variable that tells the child process which exit test
// to run.
try JSON.withEncoding(of: exitTest.id) { json in
childEnvironment["SWT_EXIT_TEST_ID"] = String(decoding: json, as: UTF8.self)
childEnvironment[Self._idEnvironmentVariableName] = String(decoding: json, as: UTF8.self)
}

typealias ResultUpdater = @Sendable (inout ExitTest.Result) -> Void
Expand Down