diff --git a/Sources/Testing/ABI/ABI.swift b/Sources/Testing/ABI/ABI.swift index 1707953a0..7a33970fc 100644 --- a/Sources/Testing/ABI/ABI.swift +++ b/Sources/Testing/ABI/ABI.swift @@ -45,7 +45,8 @@ extension ABI { /// The current supported ABI version (ignoring any experimental versions.) typealias CurrentVersion = v0 - /// The highest supported ABI version (including any experimental versions.) + /// The highest defined and supported ABI version (including any experimental + /// versions.) typealias HighestVersion = v6_3 #if !hasFeature(Embedded) @@ -93,6 +94,39 @@ extension ABI { #endif } +/// The value of the environment variable flag which enables experimental event +/// stream fields, if any. +private let _shouldIncludeExperimentalFlags = Environment.flag(named: "SWT_EXPERIMENTAL_EVENT_STREAM_FIELDS_ENABLED") + +extension ABI.Version { + /// Whether or not experimental fields should be included when using this + /// ABI version. + /// + /// The value of this property is `true` if any of the following conditions + /// are satisfied: + /// + /// - The version number is less than 6.3. This is to preserve compatibility + /// with existing clients before the inclusion of experimental fields became + /// opt-in starting in 6.3. + /// - The version number is greater than or equal to 6.3 and the environment + /// variable flag `SWT_EXPERIMENTAL_EVENT_STREAM_FIELDS_ENABLED` is set to a + /// true value. + /// - The version number is greater than or equal to that of ``ABI/ExperimentalVersion``. + /// + /// Otherwise, the value of this property is `false`. + static var includesExperimentalFields: Bool { + switch versionNumber { + case ABI.ExperimentalVersion.versionNumber...: + true + case ABI.v6_3.versionNumber...: + _shouldIncludeExperimentalFlags == true + default: + // Maintain behavior for pre-6.3 versions. + true + } + } +} + // MARK: - Concrete ABI versions extension ABI { @@ -125,6 +159,14 @@ extension ABI { VersionNumber(6, 3) } } + + /// A namespace and type representing the ABI version whose symbols are + /// considered experimental. + enum ExperimentalVersion: Sendable, Version { + static var versionNumber: VersionNumber { + VersionNumber(99, 0) + } + } } /// A namespace for ABI version 0 symbols. diff --git a/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift b/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift index 73e7db2ac..c9683f927 100644 --- a/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift +++ b/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift @@ -98,8 +98,12 @@ extension ABI { instant = EncodedInstant(encoding: event.instant) self.messages = messages.map(EncodedMessage.init) testID = event.testID.map(EncodedTest.ID.init) - if eventContext.test?.isParameterized == true { - _testCase = eventContext.testCase.map(EncodedTestCase.init) + + // Experimental fields + if V.includesExperimentalFields { + if eventContext.test?.isParameterized == true { + _testCase = eventContext.testCase.map(EncodedTestCase.init) + } } } } diff --git a/Sources/Testing/ABI/Encoded/ABI.EncodedIssue.swift b/Sources/Testing/ABI/Encoded/ABI.EncodedIssue.swift index c1e3c12fd..c593a68a5 100644 --- a/Sources/Testing/ABI/Encoded/ABI.EncodedIssue.swift +++ b/Sources/Testing/ABI/Encoded/ABI.EncodedIssue.swift @@ -72,12 +72,14 @@ extension ABI { isFailure = issue.isFailure } - // Experimental - if let backtrace = issue.sourceContext.backtrace { - _backtrace = EncodedBacktrace(encoding: backtrace, in: eventContext) - } - if let error = issue.error { - _error = EncodedError(encoding: error, in: eventContext) + // Experimental fields + if V.includesExperimentalFields { + if let backtrace = issue.sourceContext.backtrace { + _backtrace = EncodedBacktrace(encoding: backtrace, in: eventContext) + } + if let error = issue.error { + _error = EncodedError(encoding: error, in: eventContext) + } } } } diff --git a/Sources/Testing/ABI/Encoded/ABI.EncodedTest.swift b/Sources/Testing/ABI/Encoded/ABI.EncodedTest.swift index 11c309e83..43a1b615b 100644 --- a/Sources/Testing/ABI/Encoded/ABI.EncodedTest.swift +++ b/Sources/Testing/ABI/Encoded/ABI.EncodedTest.swift @@ -76,10 +76,6 @@ extension ABI { /// The tags associated with the test. /// /// - Warning: Tags are not yet part of the JSON schema. - /// - /// @Metadata { - /// @Available("Swift Testing ABI", introduced: 6.3) - /// } var _tags: [String]? init(encoding test: borrowing Test) { @@ -87,18 +83,19 @@ extension ABI { kind = .suite } else { kind = .function - let testIsParameterized = test.isParameterized - isParameterized = testIsParameterized - if testIsParameterized { - _testCases = test.uncheckedTestCases?.map(EncodedTestCase.init(encoding:)) - } + isParameterized = test.isParameterized } name = test.name displayName = test.displayName sourceLocation = test.sourceLocation id = ID(encoding: test.id) - if V.versionNumber >= ABI.v6_3.versionNumber { + // Experimental fields + if V.includesExperimentalFields { + if isParameterized == true { + _testCases = test.uncheckedTestCases?.map(EncodedTestCase.init(encoding:)) + } + let tags = test.tags if !tags.isEmpty { _tags = tags.map(String.init(describing:)) diff --git a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift index a97d33c9e..727d91632 100644 --- a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift @@ -57,10 +57,10 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha // Check for experimental console output flag if Environment.flag(named: "SWT_ENABLE_EXPERIMENTAL_CONSOLE_OUTPUT") == true { // Use experimental AdvancedConsoleOutputRecorder - var advancedOptions = Event.AdvancedConsoleOutputRecorder.Options() + var advancedOptions = Event.AdvancedConsoleOutputRecorder.Options() advancedOptions.base = .for(.stderr) - let eventRecorder = Event.AdvancedConsoleOutputRecorder(options: advancedOptions) { string in + let eventRecorder = Event.AdvancedConsoleOutputRecorder(options: advancedOptions) { string in try? FileHandle.stderr.write(string) } diff --git a/Sources/Testing/ExitTests/ExitTest.swift b/Sources/Testing/ExitTests/ExitTest.swift index 904d3a40a..f1421ee2b 100644 --- a/Sources/Testing/ExitTests/ExitTest.swift +++ b/Sources/Testing/ExitTests/ExitTest.swift @@ -541,10 +541,9 @@ extension ABI { /// The ABI version to use for encoding and decoding events sent over the back /// channel. /// - /// The back channel always uses the latest ABI version (even if experimental) - /// since both the producer and consumer use this exact version of the testing - /// library. - fileprivate typealias BackChannelVersion = v6_3 + /// The back channel always uses the experimental ABI version since both the + /// producer and consumer use this exact version of the testing library. + fileprivate typealias BackChannelVersion = ExperimentalVersion } @_spi(ForToolsIntegrationOnly) diff --git a/Tests/TestingTests/SwiftPMTests.swift b/Tests/TestingTests/SwiftPMTests.swift index 672e34a03..e61c3b237 100644 --- a/Tests/TestingTests/SwiftPMTests.swift +++ b/Tests/TestingTests/SwiftPMTests.swift @@ -376,7 +376,7 @@ struct SwiftPMTests { } #expect(testRecords.count == 1) for testRecord in testRecords { - if version.versionNumber >= ABI.v6_3.versionNumber { + if version.includesExperimentalFields { #expect(testRecord._tags != nil) } else { #expect(testRecord._tags == nil)