From a52b10d959288a603a96521df942637b625787cf Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 4 Dec 2025 15:54:23 -0500 Subject: [PATCH 1/4] Bump `ABI.CurrentVersion` to 6.3 and ensure minor variances in JSON version numbers are permitted. This PR ensures that the JSON schema version 6.3 is considered "supported" in Swift Testing 6.3. As well, it suppresses a thrown error when the `version` field of a JSON record is slightly higher than the expected schema. For example, if we ask Swift Testing the ABI version corresponding to `VersionNumber(6, 3, 1)`, we'll get back `v6_3`, but then if we try to decode a JSON record whose `version` field equals `"6.3.1"`, we'll throw a version mismatch error. This error is now suppressed unless the versions really do mismatch. --- Sources/Testing/ABI/ABI.Record.swift | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Sources/Testing/ABI/ABI.Record.swift b/Sources/Testing/ABI/ABI.Record.swift index 40a8d4bc3..2c101ec40 100644 --- a/Sources/Testing/ABI/ABI.Record.swift +++ b/Sources/Testing/ABI/ABI.Record.swift @@ -70,8 +70,17 @@ extension ABI.Record: Codable { init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - let versionNumber = try container.decode(VersionNumber.self, forKey: .version) - if versionNumber != V.versionNumber { + func validateVersionNumber(_ versionNumber: VersionNumber) throws { + if versionNumber == V.versionNumber { + return + } +#if !hasFeature(Embedded) + // Allow for alternate version numbers if they correspond to the expected + // record version (e.g. "1.2.3" might map to `v1_2_0` without a problem.) + if ABI.version(forVersionNumber: versionNumber) == V.self { + return + } +#endif throw DecodingError.dataCorrupted( DecodingError.Context( codingPath: decoder.codingPath + CollectionOfOne(CodingKeys.version as any CodingKey), @@ -79,6 +88,8 @@ extension ABI.Record: Codable { ) ) } + let versionNumber = try container.decode(VersionNumber.self, forKey: .version) + try validateVersionNumber(versionNumber) switch try container.decode(String.self, forKey: .kind) { case "test": From 41fdd4a33a1b98ef0a77f3daae99bde2387ff84d Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 9 Dec 2025 08:28:25 -0500 Subject: [PATCH 2/4] git didn't pick up CurrentVersion --- Sources/Testing/ABI/ABI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Testing/ABI/ABI.swift b/Sources/Testing/ABI/ABI.swift index 7a33970fc..f8cb3da9d 100644 --- a/Sources/Testing/ABI/ABI.swift +++ b/Sources/Testing/ABI/ABI.swift @@ -43,7 +43,7 @@ extension ABI { } /// The current supported ABI version (ignoring any experimental versions.) - typealias CurrentVersion = v0 + typealias CurrentVersion = v6_3 /// The highest defined and supported ABI version (including any experimental /// versions.) From 3318311ca1c6d7fd1a6c8c4c08984bd6416e4a90 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 10 Dec 2025 14:11:17 -0600 Subject: [PATCH 3/4] Fix broken test newButNotExperimentalABIVersion(), and make ABI.version(forVersionNumber:) more testable --- Sources/Testing/ABI/ABI.swift | 10 +++++++++- Tests/TestingTests/SwiftPMTests.swift | 9 +++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Sources/Testing/ABI/ABI.swift b/Sources/Testing/ABI/ABI.swift index f8cb3da9d..aa0127f75 100644 --- a/Sources/Testing/ABI/ABI.swift +++ b/Sources/Testing/ABI/ABI.swift @@ -55,10 +55,18 @@ extension ABI { /// - Parameters: /// - versionNumber: The ABI version number for which a concrete type is /// needed. + /// - swiftCompilerVersion: The version number of the Swift compiler. This + /// is used when `versionNumber` is greater than the highest known version + /// to determine whether a version type can be returned. The default value + /// is the version of the Swift compiler which was used to build the + /// testing library. /// /// - Returns: A type conforming to ``ABI/Version`` that represents the given /// ABI version, or `nil` if no such type exists. - static func version(forVersionNumber versionNumber: VersionNumber = ABI.CurrentVersion.versionNumber) -> (any Version.Type)? { + static func version( + forVersionNumber versionNumber: VersionNumber, + givenSwiftCompilerVersion swiftCompilerVersion: VersionNumber = swiftCompilerVersion + ) -> (any Version.Type)? { if versionNumber > ABI.HighestVersion.versionNumber { // If the caller requested an ABI version higher than the current Swift // compiler version and it's not an ABI version we've explicitly defined, diff --git a/Tests/TestingTests/SwiftPMTests.swift b/Tests/TestingTests/SwiftPMTests.swift index 2d7001e8f..44877a1df 100644 --- a/Tests/TestingTests/SwiftPMTests.swift +++ b/Tests/TestingTests/SwiftPMTests.swift @@ -302,10 +302,11 @@ struct SwiftPMTests { @Test("New-but-not-experimental ABI version") func newButNotExperimentalABIVersion() async throws { - var versionNumber = ABI.CurrentVersion.versionNumber - versionNumber.patchComponent += 1 - let version = try #require(ABI.version(forVersionNumber: versionNumber)) - #expect(version.versionNumber == ABI.v0.versionNumber) + let currentVersionNumber = ABI.CurrentVersion.versionNumber + var newerVersionNumber = currentVersionNumber + newerVersionNumber.patchComponent += 1 + let version = try #require(ABI.version(forVersionNumber: newerVersionNumber, givenSwiftCompilerVersion: newerVersionNumber)) + #expect(version.versionNumber == currentVersionNumber) } @Test("Unsupported ABI version") From cfd2d48e918e8ac88c4235c879db7c2c6afd41f5 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 10 Dec 2025 14:52:39 -0600 Subject: [PATCH 4/4] Make `swiftCompilerVersion` an @autoclosure --- Sources/Testing/ABI/ABI.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Testing/ABI/ABI.swift b/Sources/Testing/ABI/ABI.swift index aa0127f75..9590949a6 100644 --- a/Sources/Testing/ABI/ABI.swift +++ b/Sources/Testing/ABI/ABI.swift @@ -65,7 +65,7 @@ extension ABI { /// ABI version, or `nil` if no such type exists. static func version( forVersionNumber versionNumber: VersionNumber, - givenSwiftCompilerVersion swiftCompilerVersion: VersionNumber = swiftCompilerVersion + givenSwiftCompilerVersion swiftCompilerVersion: @autoclosure () -> VersionNumber = swiftCompilerVersion ) -> (any Version.Type)? { if versionNumber > ABI.HighestVersion.versionNumber { // If the caller requested an ABI version higher than the current Swift @@ -79,7 +79,7 @@ extension ABI { // Note also that building an old version of Swift Testing with a newer // compiler may produce incorrect results here. We don't generally support // that configuration though. - if versionNumber > swiftCompilerVersion { + if versionNumber > swiftCompilerVersion() { return nil } }