From bb82c0fb69b3c96574cd4b508586b359a13e630e Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Wed, 15 Jul 2026 16:53:56 -0400 Subject: [PATCH] Remove underscore from `iteration` in JSON record for encoded events (#1792) I missed this in the implementation of ST-0024, `iteration` on the encoded event needs to be non-underscored. Fixes rdar://182236523 Implements the ST-0024 spec. Just removes the underscore and adds a regression test. - [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. --- Documentation/ABI/JSON.md | 3 ++ .../ABI/Encoded/ABI.EncodedEvent.swift | 21 ++++---- .../TestingTests/ABI.EncodedEventTests.swift | 48 +++++++++++++++++++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/Documentation/ABI/JSON.md b/Documentation/ABI/JSON.md index 196123a85..656d516e3 100644 --- a/Documentation/ABI/JSON.md +++ b/Documentation/ABI/JSON.md @@ -205,6 +205,8 @@ sufficient information to display the event in a human-readable format. ["attachment": ,] ; the attachment (if kind is "valueAttached") "messages": , ["testID": ,] + ["iteration": ,] ; the iteration number (if the event is recorded + ; during test execution) } ::= "runStarted" | "testStarted" | "testCaseStarted" | @@ -249,3 +251,4 @@ sufficient information to display the event in a human-readable format. | [ST-0016](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0016-test-cancellation.md#integration-with-supporting-tools) | Added test cancellation. | 6.3 | `"6.3"` | | [ST-0019](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0019-include-tags-bugs-and-timeline-in-event-stream.md#json-schema-changes) | Added `tags`, `bugs`, and `timeLimit`. | 6.4 | `"6.4"` | | [ST-0020](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0020-sourcelocation-filepath.md#detailed-design) | Added `filePath`. | 6.3 | `"6.3"` | +| [ST-0024](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0024-per-test-case-repetitions.md)| Added `iteration`. | 6.4 | `"6.4"` | diff --git a/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift b/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift index d2794d25a..612e6c6e8 100644 --- a/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift +++ b/Sources/Testing/ABI/Encoded/ABI.EncodedEvent.swift @@ -66,6 +66,11 @@ extension ABI { /// The ID of the test associated with this event, if any. var testID: EncodedTest.ID? + /// The iteration of the `testID` being executed. + /// + /// This value is one-indexed; the first iteration is `1`. + public var iteration: Int? + /// The ID of the test case associated with this event, if any. /// /// - Warning: Test cases are not yet part of the JSON schema. @@ -104,13 +109,6 @@ extension ABI { @_spi(Experimental) public var _sourceLocation: EncodedSourceLocation? - /// The iteration of the `testID` being executed. - /// - /// This value is one-indexed; the first iteration is `1`. - /// - /// - Warning: Iteration indices are not yet part of the JSON schema. - var _iteration: Int? - init?(encoding event: borrowing Event, in eventContext: borrowing Event.Context, messages: borrowing [Event.HumanReadableOutputRecorder.Message]) { switch event.kind { case .runStarted: @@ -163,6 +161,12 @@ extension ABI { self.messages = messages.map(EncodedMessage.init) testID = event.testID.map(EncodedTest.ID.init) + // Fields introduced in 6.4 + + if V.versionNumber >= ABI.v6_4.versionNumber { + iteration = eventContext.iteration + } + // Experimental fields if V.includesExperimentalFields { switch event.kind { @@ -171,14 +175,11 @@ extension ABI { _sourceLocation = recordedIssue.sourceLocation.map { EncodedSourceLocation(encoding: $0) } case let .valueAttached(attachment): _sourceLocation = EncodedSourceLocation(encoding: attachment.sourceLocation) - case .testCaseStarted, .testCaseEnded, .testStarted, .testEnded: - _iteration = eventContext.iteration case let .testCaseCancelled(skipInfo), let .testSkipped(skipInfo), let .testCancelled(skipInfo): _comments = Array(skipInfo.comment).map(\.rawValue) _sourceLocation = skipInfo.sourceLocation.map { EncodedSourceLocation(encoding: $0) } - _iteration = eventContext.iteration default: break } diff --git a/Tests/TestingTests/ABI.EncodedEventTests.swift b/Tests/TestingTests/ABI.EncodedEventTests.swift index 2ea561a78..7773190ce 100644 --- a/Tests/TestingTests/ABI.EncodedEventTests.swift +++ b/Tests/TestingTests/ABI.EncodedEventTests.swift @@ -118,5 +118,53 @@ return } } + + // MARK: Iteration + + @Test func `Encode iteration`() throws { + let test = Test {} + let event = Event(.testCaseStarted, testID: .init(["SomeValidTestID", "testFunc()"]), testCaseID: nil) + let context = Event.Context(test: test, testCase: nil, iteration: 2, configuration: nil) + let encoded = try #require(ABI.EncodedEvent(encoding: event, in: context, messages: [])) + + #expect(encoded.iteration == 2) + + try JSON.withEncoding(of: encoded) { buf in + let str = String(decoding: buf, as: UTF8.self) + #expect(str.contains(#""iteration":2"#)) + } + + let encoded6_3 = try #require(ABI.EncodedEvent(encoding: event, in: context, messages: [])) + #expect(encoded6_3.iteration == nil) + try JSON.withEncoding(of: encoded6_3) { buf in + let str = String(decoding: buf, as: UTF8.self) + #expect(!str.contains(#"iteration"#)) + } + } + + @Test func `Decode iteration`() throws { + var event = try encodedEvent( + """ + { + "kind": "testStarted", + "instant": {"absolute": 123, "since1970": 456}, + "messages": [], + "testID": "SomeValidTestID/testFunc()", + "iteration": 2 + } + """) + #expect(event.iteration == 2) + + event = try encodedEvent( + """ + { + "kind": "testStarted", + "instant": {"absolute": 123, "since1970": 456}, + "messages": [], + "testID": "SomeValidTestID/testFunc()" + } + """) + #expect(event.iteration == nil) + } } #endif