From ff6cf12cd4c30d89650b7f7fffc089c17e9d4842 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Mon, 27 Jan 2025 17:04:40 -0600 Subject: [PATCH 01/32] Introduce a severity level for issues, and a 'warning' severity --- .../Testing/ABI/EntryPoints/EntryPoint.swift | 2 +- .../Event.ConsoleOutputRecorder.swift | 2 +- .../Event.HumanReadableOutputRecorder.swift | 81 ++++++++++++++----- .../Events/Recorder/Event.Symbol.swift | 10 ++- Sources/Testing/Issues/Issue.swift | 59 +++++++++++++- Tests/TestingTests/IssueTests.swift | 6 +- 6 files changed, 126 insertions(+), 34 deletions(-) diff --git a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift index a0a5df2a0..254311968 100644 --- a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift @@ -40,7 +40,7 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha // Set up the event handler. configuration.eventHandler = { [oldEventHandler = configuration.eventHandler] event, context in - if case let .issueRecorded(issue) = event.kind, !issue.isKnown { + if case let .issueRecorded(issue) = event.kind, !issue.isKnown, issue.severity >= .error { exitCode.withLock { exitCode in exitCode = EXIT_FAILURE } diff --git a/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift index cce3a732c..d89f855e4 100644 --- a/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift @@ -354,7 +354,7 @@ extension Event.ConsoleOutputRecorder { /// /// The caller is responsible for presenting this message to the user. static func warning(_ message: String, options: Event.ConsoleOutputRecorder.Options) -> String { - let symbol = Event.Symbol.warning.stringValue(options: options) + let symbol = Event.Symbol.warning().stringValue(options: options) return "\(symbol) \(message)\n" } } diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index 98303f11c..824ec53b5 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -56,8 +56,11 @@ extension Event { /// The instant at which the test started. var startInstant: Test.Clock.Instant - /// The number of issues recorded for the test. - var issueCount = 0 + /// The number of issues with error severity recorded for the test. + var errorIssueCount = 0 + + /// The number of issues with warning severity recorded for the test. + var warningIssueCount = 0 /// The number of known issues recorded for the test. var knownIssueCount = 0 @@ -114,27 +117,36 @@ extension Event.HumanReadableOutputRecorder { /// - graph: The graph to walk while counting issues. /// /// - Returns: A tuple containing the number of issues recorded in `graph`. - private func _issueCounts(in graph: Graph?) -> (issueCount: Int, knownIssueCount: Int, totalIssueCount: Int, description: String) { + private func _issueCounts(in graph: Graph?) -> (errorIssueCount: Int, warningIssueCount: Int, knownIssueCount: Int, totalIssueCount: Int, description: String) { guard let graph else { - return (0, 0, 0, "") + return (0, 0, 0, 0, "") } - let issueCount = graph.compactMap(\.value?.issueCount).reduce(into: 0, +=) + let errorIssueCount = graph.compactMap(\.value?.errorIssueCount).reduce(into: 0, +=) + let warningIssueCount = graph.compactMap(\.value?.warningIssueCount).reduce(into: 0, +=) let knownIssueCount = graph.compactMap(\.value?.knownIssueCount).reduce(into: 0, +=) - let totalIssueCount = issueCount + knownIssueCount + let totalIssueCount = errorIssueCount + warningIssueCount + knownIssueCount // Construct a string describing the issue counts. - let description = switch (issueCount > 0, knownIssueCount > 0) { - case (true, true): + let description = switch (errorIssueCount > 0, warningIssueCount > 0, knownIssueCount > 0) { + case (true, true, true): + " with \(totalIssueCount.counting("issue")) (including \(warningIssueCount.counting("warning")) and \(knownIssueCount.counting("known issue")))" + case (true, false, true): " with \(totalIssueCount.counting("issue")) (including \(knownIssueCount.counting("known issue")))" - case (false, true): + case (false, true, true): + " with \(warningIssueCount.counting("warning")) and \(knownIssueCount.counting("known issue"))" + case (false, false, true): " with \(knownIssueCount.counting("known issue"))" - case (true, false): + case (true, true, false): + " with \(totalIssueCount.counting("issue")) (including \(warningIssueCount.counting("warning")))" + case (true, false, false): " with \(totalIssueCount.counting("issue"))" - case(false, false): + case(false, true, false): + " with \(warningIssueCount.counting("warning"))" + case(false, false, false): "" } - return (issueCount, knownIssueCount, totalIssueCount, description) + return (errorIssueCount, warningIssueCount, knownIssueCount, totalIssueCount, description) } } @@ -267,7 +279,12 @@ extension Event.HumanReadableOutputRecorder { if issue.isKnown { testData.knownIssueCount += 1 } else { - testData.issueCount += 1 + switch issue.severity { + case .warning: + testData.warningIssueCount += 1 + case .error: + testData.errorIssueCount += 1 + } } context.testData[id] = testData @@ -355,15 +372,22 @@ extension Event.HumanReadableOutputRecorder { let testData = testDataGraph?.value ?? .init(startInstant: instant) let issues = _issueCounts(in: testDataGraph) let duration = testData.startInstant.descriptionOfDuration(to: instant) - return if issues.issueCount > 0 { + return if issues.errorIssueCount > 0 { CollectionOfOne( Message( symbol: .fail, stringValue: "\(_capitalizedTitle(for: test)) \(testName) failed after \(duration)\(issues.description)." ) ) + _formattedComments(for: test) + } else if issues.warningIssueCount > 0 { + [ + Message( + symbol: .warning(warningIssueCount: issues.warningIssueCount), + stringValue: "\(_capitalizedTitle(for: test)) \(testName) passed after \(duration)\(issues.description)." + ) + ] } else { - [ + [ Message( symbol: .pass(knownIssueCount: issues.knownIssueCount), stringValue: "\(_capitalizedTitle(for: test)) \(testName) passed after \(duration)\(issues.description)." @@ -400,13 +424,19 @@ extension Event.HumanReadableOutputRecorder { "" } let symbol: Event.Symbol - let known: String + let introducer: String if issue.isKnown { symbol = .pass(knownIssueCount: 1) - known = " known" + introducer = "a known" } else { - symbol = .fail - known = "n" + switch issue.severity { + case .warning: + symbol = .warning(warningIssueCount: 1) + introducer = "a warning" + case .error: + symbol = .fail + introducer = "an" + } } var additionalMessages = [Message]() @@ -435,13 +465,13 @@ extension Event.HumanReadableOutputRecorder { let primaryMessage: Message = if parameterCount == 0 { Message( symbol: symbol, - stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded a\(known) issue\(atSourceLocation): \(issue.kind)", + stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded \(introducer) issue\(atSourceLocation): \(issue.kind)", conciseStringValue: String(describing: issue.kind) ) } else { Message( symbol: symbol, - stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded a\(known) issue with \(parameterCount.counting("argument")) \(labeledArguments)\(atSourceLocation): \(issue.kind)", + stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded \(introducer) issue with \(parameterCount.counting("argument")) \(labeledArguments)\(atSourceLocation): \(issue.kind)", conciseStringValue: String(describing: issue.kind) ) } @@ -498,13 +528,20 @@ extension Event.HumanReadableOutputRecorder { let runStartInstant = context.runStartInstant ?? instant let duration = runStartInstant.descriptionOfDuration(to: instant) - return if issues.issueCount > 0 { + return if issues.errorIssueCount > 0 { [ Message( symbol: .fail, stringValue: "Test run with \(testCount.counting("test")) failed after \(duration)\(issues.description)." ) ] + } else if issues.warningIssueCount > 0 { + [ + Message( + symbol: .warning(warningIssueCount: issues.warningIssueCount), + stringValue: "Test run with \(testCount.counting("test")) passed after \(duration)\(issues.description)." + ) + ] } else { [ Message( diff --git a/Sources/Testing/Events/Recorder/Event.Symbol.swift b/Sources/Testing/Events/Recorder/Event.Symbol.swift index 0f50ed95c..d956c3faa 100644 --- a/Sources/Testing/Events/Recorder/Event.Symbol.swift +++ b/Sources/Testing/Events/Recorder/Event.Symbol.swift @@ -22,8 +22,8 @@ extension Event { /// The symbol to use when a test passes. /// /// - Parameters: - /// - knownIssueCount: The number of known issues encountered by the end - /// of the test. + /// - knownIssueCount: The number of known issues recorded for the test. + /// The default value is `0`. case pass(knownIssueCount: Int = 0) /// The symbol to use when a test fails. @@ -34,7 +34,11 @@ extension Event { /// A warning or caution symbol to use when the developer should be aware of /// some condition. - case warning + /// + /// - Parameters: + /// - warningIssueCount: The number of issues with warning severity + /// recorded for the test. The default value is `0`. + case warning(warningIssueCount: Int = 0) /// The symbol to use when presenting details about an event to the user. case details diff --git a/Sources/Testing/Issues/Issue.swift b/Sources/Testing/Issues/Issue.swift index dae58400a..18d1322a0 100644 --- a/Sources/Testing/Issues/Issue.swift +++ b/Sources/Testing/Issues/Issue.swift @@ -79,6 +79,35 @@ public struct Issue: Sendable { /// The kind of issue this value represents. public var kind: Kind + /// An enumeration representing the level of severity of a recorded issue. + /// + /// The supported levels, in decreasing order of severity, are: + /// + /// - ``error`` + /// - ``warning`` + @_spi(Experimental) + public enum Severity: Sendable { + /// The severity level representing an issue which may be a concern but is + /// not an error. + /// + /// An issue with warning severity does not cause the test it's associated + /// with to be marked as a failure, but is noted in the results. + case warning + + /// The severity level representing an issue which represents an error in a + /// test. + /// + /// An issue with error severity causes the test it's associated with to be + /// marked as a failure. + case error + } + + /// The severity of this issue. + /// + /// The default value of this property is ``Severity-swift.enum/error``. + @_spi(Experimental) + public var severity: Severity = .error + /// Any comments provided by the developer and associated with this issue. /// /// If no comment was supplied when the issue occurred, the value of this @@ -97,12 +126,15 @@ public struct Issue: Sendable { /// /// - Parameters: /// - kind: The kind of issue this value represents. + /// - severity: The severity of this issue. The default value is + /// ``Severity-swift.enum/error``. /// - comments: An array of comments describing the issue. This array may be /// empty. /// - sourceContext: A ``SourceContext`` indicating where and how this issue /// occurred. init( kind: Kind, + severity: Severity = .error, comments: [Comment], sourceContext: SourceContext ) { @@ -154,6 +186,8 @@ public struct Issue: Sendable { } } +extension Issue.Severity: Comparable {} + // MARK: - CustomStringConvertible, CustomDebugStringConvertible extension Issue: CustomStringConvertible, CustomDebugStringConvertible { @@ -164,7 +198,7 @@ extension Issue: CustomStringConvertible, CustomDebugStringConvertible { let joinedComments = comments.lazy .map(\.rawValue) .joined(separator: "\n") - return "\(kind): \(joinedComments)" + return "\(severity): \(kind): \(joinedComments)" } public var debugDescription: String { @@ -174,7 +208,7 @@ extension Issue: CustomStringConvertible, CustomDebugStringConvertible { let joinedComments: String = comments.lazy .map(\.rawValue) .joined(separator: "\n") - return "\(kind)\(sourceLocation.map { " at \($0)" } ?? ""): \(joinedComments)" + return "\(severity): \(kind)\(sourceLocation.map { " at \($0)" } ?? ""): \(joinedComments)" } } @@ -234,6 +268,17 @@ extension Issue.Kind: CustomStringConvertible { } } +extension Issue.Severity: CustomStringConvertible { + public var description: String { + switch self { + case .warning: + "warning" + case .error: + "error" + } + } +} + #if !SWT_NO_SNAPSHOT_TYPES // MARK: - Snapshotting @@ -244,6 +289,9 @@ extension Issue { /// The kind of issue this value represents. public var kind: Kind.Snapshot + @_spi(Experimental) + public var severity: Severity + /// Any comments provided by the developer and associated with this issue. /// /// If no comment was supplied when the issue occurred, the value of this @@ -268,6 +316,7 @@ extension Issue { self.kind = Issue.Kind.Snapshot(snapshotting: issue.kind) self.comments = issue.comments } + self.severity = issue.severity self.sourceContext = issue.sourceContext self.isKnown = issue.isKnown } @@ -295,6 +344,8 @@ extension Issue { } } +extension Issue.Severity: Codable {} + extension Issue.Kind { /// Serializable kinds of issues which may be recorded. @_spi(ForToolsIntegrationOnly) @@ -484,7 +535,7 @@ extension Issue.Snapshot: CustomStringConvertible, CustomDebugStringConvertible let joinedComments = comments.lazy .map(\.rawValue) .joined(separator: "\n") - return "\(kind): \(joinedComments)" + return "\(severity): \(kind): \(joinedComments)" } public var debugDescription: String { @@ -494,7 +545,7 @@ extension Issue.Snapshot: CustomStringConvertible, CustomDebugStringConvertible let joinedComments: String = comments.lazy .map(\.rawValue) .joined(separator: "\n") - return "\(kind)\(sourceLocation.map { " at \($0)" } ?? ""): \(joinedComments)" + return "\(severity): \(kind)\(sourceLocation.map { " at \($0)" } ?? ""): \(joinedComments)" } } diff --git a/Tests/TestingTests/IssueTests.swift b/Tests/TestingTests/IssueTests.swift index 4a4fda631..cdcf9f3b1 100644 --- a/Tests/TestingTests/IssueTests.swift +++ b/Tests/TestingTests/IssueTests.swift @@ -1124,12 +1124,12 @@ final class IssueTests: XCTestCase { do { let sourceLocation = SourceLocation.init(fileID: "FakeModule/FakeFile.swift", filePath: "", line: 9999, column: 1) let issue = Issue(kind: .system, comments: ["Some issue"], sourceContext: SourceContext(sourceLocation: sourceLocation)) - XCTAssertEqual(issue.description, "A system failure occurred: Some issue") - XCTAssertEqual(issue.debugDescription, "A system failure occurred at FakeFile.swift:9999:1: Some issue") + XCTAssertEqual(issue.description, "error: A system failure occurred: Some issue") + XCTAssertEqual(issue.debugDescription, "error: A system failure occurred at FakeFile.swift:9999:1: Some issue") } do { let issue = Issue(kind: .system, comments: ["Some issue"], sourceContext: SourceContext(sourceLocation: nil)) - XCTAssertEqual(issue.debugDescription, "A system failure occurred: Some issue") + XCTAssertEqual(issue.debugDescription, "error: A system failure occurred: Some issue") } } From e81ce3d7983ffa32dee13346a3cfc9c8abfe144f Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Mon, 27 Jan 2025 17:33:41 -0600 Subject: [PATCH 02/32] Improve wording --- Sources/Testing/Issues/Issue.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/Testing/Issues/Issue.swift b/Sources/Testing/Issues/Issue.swift index 18d1322a0..c3dafd0f1 100644 --- a/Sources/Testing/Issues/Issue.swift +++ b/Sources/Testing/Issues/Issue.swift @@ -87,15 +87,14 @@ public struct Issue: Sendable { /// - ``warning`` @_spi(Experimental) public enum Severity: Sendable { - /// The severity level representing an issue which may be a concern but is - /// not an error. + /// The severity level for an issue which should be noted but is not + /// necessarily an error. /// /// An issue with warning severity does not cause the test it's associated /// with to be marked as a failure, but is noted in the results. case warning - /// The severity level representing an issue which represents an error in a - /// test. + /// The severity level for an issue which represents an error in a test. /// /// An issue with error severity causes the test it's associated with to be /// marked as a failure. From 8415b9047b52f8f9793168b55edd9d23cac5ffa0 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 10:43:15 -0600 Subject: [PATCH 03/32] Add missing documentation to Snapshot property --- Sources/Testing/Issues/Issue.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Testing/Issues/Issue.swift b/Sources/Testing/Issues/Issue.swift index c3dafd0f1..23d131d93 100644 --- a/Sources/Testing/Issues/Issue.swift +++ b/Sources/Testing/Issues/Issue.swift @@ -288,6 +288,7 @@ extension Issue { /// The kind of issue this value represents. public var kind: Kind.Snapshot + /// The severity of this issue. @_spi(Experimental) public var severity: Severity From 11dec4b44b23ab370da3c41b61365cf12d6dec28 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 10:43:27 -0600 Subject: [PATCH 04/32] Describe the cases in increasing order instead of decreasing --- Sources/Testing/Issues/Issue.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Testing/Issues/Issue.swift b/Sources/Testing/Issues/Issue.swift index 23d131d93..e161adfcc 100644 --- a/Sources/Testing/Issues/Issue.swift +++ b/Sources/Testing/Issues/Issue.swift @@ -81,10 +81,10 @@ public struct Issue: Sendable { /// An enumeration representing the level of severity of a recorded issue. /// - /// The supported levels, in decreasing order of severity, are: + /// The supported levels, in increasing order of severity, are: /// - /// - ``error`` /// - ``warning`` + /// - ``error`` @_spi(Experimental) public enum Severity: Sendable { /// The severity level for an issue which should be noted but is not From 671536269f44e3a475656d91ca521b27161958c7 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 10:43:54 -0600 Subject: [PATCH 05/32] Add severity to the ABIv0 JSON, as private initially --- Documentation/ABI/JSON.md | 10 ++++++++++ .../ABI/v0/Encoded/ABIv0.EncodedIssue.swift | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Documentation/ABI/JSON.md b/Documentation/ABI/JSON.md index 23dd5b1dc..0a97c9e68 100644 --- a/Documentation/ABI/JSON.md +++ b/Documentation/ABI/JSON.md @@ -197,10 +197,20 @@ sufficient information to display the event in a human-readable format. "runEnded" ; additional event kinds may be added in the future ::= { + "isKnown": , ; is this a known issue or not? ["sourceLocation": ,] ; where the issue occurred, if known } + + ::= { "symbol": , "text": , ; the human-readable text of this message diff --git a/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift b/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift index 2bf1c8462..7c5b5185a 100644 --- a/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift +++ b/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift @@ -16,6 +16,19 @@ extension ABIv0 { /// assists in converting values to JSON; clients that consume this JSON are /// expected to write their own decoders. struct EncodedIssue: Sendable { + /// An enumeration representing the level of severity of a recorded issue. + /// + /// For descriptions of individual cases, see ``Issue/Severity-swift.enum``. + enum Severity: String { + case warning + case error + } + + /// The severity of this issue. + /// + /// - Warning: Severity is not yet part of the JSON schema. + var _severity: Severity + /// Whether or not this issue is known to occur. var isKnown: Bool @@ -33,6 +46,11 @@ extension ABIv0 { var _error: EncodedError? init(encoding issue: borrowing Issue, in eventContext: borrowing Event.Context) { + _severity = switch issue.severity { + case .warning: .warning + case .error: .error + } + isKnown = issue.isKnown sourceLocation = issue.sourceLocation if let backtrace = issue.sourceContext.backtrace { @@ -48,3 +66,4 @@ extension ABIv0 { // MARK: - Codable extension ABIv0.EncodedIssue: Codable {} +extension ABIv0.EncodedIssue.Severity: Codable {} From 7cdfeb2031255593167007f461ed84d126f484ff Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 10:47:27 -0600 Subject: [PATCH 06/32] We don't need to pass the count of warning issues in the symbol --- .../Events/Recorder/Event.ConsoleOutputRecorder.swift | 2 +- .../Events/Recorder/Event.HumanReadableOutputRecorder.swift | 6 +++--- Sources/Testing/Events/Recorder/Event.Symbol.swift | 6 +----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift index d89f855e4..cce3a732c 100644 --- a/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.ConsoleOutputRecorder.swift @@ -354,7 +354,7 @@ extension Event.ConsoleOutputRecorder { /// /// The caller is responsible for presenting this message to the user. static func warning(_ message: String, options: Event.ConsoleOutputRecorder.Options) -> String { - let symbol = Event.Symbol.warning().stringValue(options: options) + let symbol = Event.Symbol.warning.stringValue(options: options) return "\(symbol) \(message)\n" } } diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index 824ec53b5..e2fcaeafb 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -382,7 +382,7 @@ extension Event.HumanReadableOutputRecorder { } else if issues.warningIssueCount > 0 { [ Message( - symbol: .warning(warningIssueCount: issues.warningIssueCount), + symbol: .warning, stringValue: "\(_capitalizedTitle(for: test)) \(testName) passed after \(duration)\(issues.description)." ) ] @@ -431,7 +431,7 @@ extension Event.HumanReadableOutputRecorder { } else { switch issue.severity { case .warning: - symbol = .warning(warningIssueCount: 1) + symbol = .warning introducer = "a warning" case .error: symbol = .fail @@ -538,7 +538,7 @@ extension Event.HumanReadableOutputRecorder { } else if issues.warningIssueCount > 0 { [ Message( - symbol: .warning(warningIssueCount: issues.warningIssueCount), + symbol: .warning, stringValue: "Test run with \(testCount.counting("test")) passed after \(duration)\(issues.description)." ) ] diff --git a/Sources/Testing/Events/Recorder/Event.Symbol.swift b/Sources/Testing/Events/Recorder/Event.Symbol.swift index d956c3faa..40bb05d40 100644 --- a/Sources/Testing/Events/Recorder/Event.Symbol.swift +++ b/Sources/Testing/Events/Recorder/Event.Symbol.swift @@ -34,11 +34,7 @@ extension Event { /// A warning or caution symbol to use when the developer should be aware of /// some condition. - /// - /// - Parameters: - /// - warningIssueCount: The number of issues with warning severity - /// recorded for the test. The default value is `0`. - case warning(warningIssueCount: Int = 0) + case warning /// The symbol to use when presenting details about an event to the user. case details From ca838a351424d6eb7c9ee0159da0d1ac7f851259 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 11:10:23 -0600 Subject: [PATCH 07/32] Simplify issue count tracking with a dictionary --- .../Event.HumanReadableOutputRecorder.swift | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index e2fcaeafb..aac629da8 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -56,11 +56,9 @@ extension Event { /// The instant at which the test started. var startInstant: Test.Clock.Instant - /// The number of issues with error severity recorded for the test. - var errorIssueCount = 0 - - /// The number of issues with warning severity recorded for the test. - var warningIssueCount = 0 + /// The number of issues recorded for the test, grouped by their + /// level of severity. + var issueCount: [Issue.Severity: Int] = [:] /// The number of known issues recorded for the test. var knownIssueCount = 0 @@ -121,8 +119,8 @@ extension Event.HumanReadableOutputRecorder { guard let graph else { return (0, 0, 0, 0, "") } - let errorIssueCount = graph.compactMap(\.value?.errorIssueCount).reduce(into: 0, +=) - let warningIssueCount = graph.compactMap(\.value?.warningIssueCount).reduce(into: 0, +=) + let errorIssueCount = graph.compactMap { $0.value?.issueCount[.error] }.reduce(into: 0, +=) + let warningIssueCount = graph.compactMap { $0.value?.issueCount[.warning] }.reduce(into: 0, +=) let knownIssueCount = graph.compactMap(\.value?.knownIssueCount).reduce(into: 0, +=) let totalIssueCount = errorIssueCount + warningIssueCount + knownIssueCount @@ -279,12 +277,7 @@ extension Event.HumanReadableOutputRecorder { if issue.isKnown { testData.knownIssueCount += 1 } else { - switch issue.severity { - case .warning: - testData.warningIssueCount += 1 - case .error: - testData.errorIssueCount += 1 - } + testData.issueCount[issue.severity, default: 0] += 1 } context.testData[id] = testData From 04f115f74f371cde9646035bf6529002001f202a Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 12:21:18 -0600 Subject: [PATCH 08/32] Simplify compactMap with key path --- .../Events/Recorder/Event.HumanReadableOutputRecorder.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index aac629da8..49335519f 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -119,8 +119,8 @@ extension Event.HumanReadableOutputRecorder { guard let graph else { return (0, 0, 0, 0, "") } - let errorIssueCount = graph.compactMap { $0.value?.issueCount[.error] }.reduce(into: 0, +=) - let warningIssueCount = graph.compactMap { $0.value?.issueCount[.warning] }.reduce(into: 0, +=) + let errorIssueCount = graph.compactMap(\.value?.issueCount[.error]).reduce(into: 0, +=) + let warningIssueCount = graph.compactMap(\.value?.issueCount[.warning]).reduce(into: 0, +=) let knownIssueCount = graph.compactMap(\.value?.knownIssueCount).reduce(into: 0, +=) let totalIssueCount = errorIssueCount + warningIssueCount + knownIssueCount From a51b3856fdc8aafb9c2d546b416009e133529990 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 28 Jan 2025 12:21:41 -0600 Subject: [PATCH 09/32] Replace "a warning issue" with "a warning" --- .../Recorder/Event.HumanReadableOutputRecorder.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index 49335519f..d2fa235f0 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -417,18 +417,18 @@ extension Event.HumanReadableOutputRecorder { "" } let symbol: Event.Symbol - let introducer: String + let subject: String if issue.isKnown { symbol = .pass(knownIssueCount: 1) - introducer = "a known" + subject = "a known issue" } else { switch issue.severity { case .warning: symbol = .warning - introducer = "a warning" + subject = "a warning" case .error: symbol = .fail - introducer = "an" + subject = "an issue" } } @@ -458,13 +458,13 @@ extension Event.HumanReadableOutputRecorder { let primaryMessage: Message = if parameterCount == 0 { Message( symbol: symbol, - stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded \(introducer) issue\(atSourceLocation): \(issue.kind)", + stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded \(subject) \(atSourceLocation): \(issue.kind)", conciseStringValue: String(describing: issue.kind) ) } else { Message( symbol: symbol, - stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded \(introducer) issue with \(parameterCount.counting("argument")) \(labeledArguments)\(atSourceLocation): \(issue.kind)", + stringValue: "\(_capitalizedTitle(for: test)) \(testName) recorded \(subject) with \(parameterCount.counting("argument")) \(labeledArguments)\(atSourceLocation): \(issue.kind)", conciseStringValue: String(describing: issue.kind) ) } From fba703fa48d0f1d61db8130dff3aa2dd4d198544 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 29 Jan 2025 17:23:22 -0600 Subject: [PATCH 10/32] Introduce new Configuration SPI controlling whether warning issues should be delivered, consolidating some similar functionality with an existing SPI. Address the ABI compatibility problem by defaulting all existing entry point versions to disable this feature, but default it to enabled so that the eventual v1 will have it enabled by default --- .../ABI/EntryPoints/ABIEntryPoint.swift | 6 +-- .../Testing/ABI/EntryPoints/EntryPoint.swift | 9 ++++ Sources/Testing/Events/Event.swift | 25 +++++++++-- Sources/Testing/Running/Configuration.swift | 45 ++++++++++++++++--- 4 files changed, 71 insertions(+), 14 deletions(-) diff --git a/Sources/Testing/ABI/EntryPoints/ABIEntryPoint.swift b/Sources/Testing/ABI/EntryPoints/ABIEntryPoint.swift index cc150740e..143f7b549 100644 --- a/Sources/Testing/ABI/EntryPoints/ABIEntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/ABIEntryPoint.swift @@ -47,7 +47,7 @@ extension ABIv0 { /// callback. public static var entryPoint: EntryPoint { return { configurationJSON, recordHandler in - try await Testing.entryPoint( + try await _entryPoint( configurationJSON: configurationJSON, recordHandler: recordHandler ) == EXIT_SUCCESS @@ -87,7 +87,7 @@ typealias ABIEntryPoint_v0 = @Sendable ( @usableFromInline func copyABIEntryPoint_v0() -> UnsafeMutableRawPointer { let result = UnsafeMutablePointer.allocate(capacity: 1) result.initialize { configurationJSON, recordHandler in - try await entryPoint( + try await _entryPoint( configurationJSON: configurationJSON, eventStreamVersionIfNil: -1, recordHandler: recordHandler @@ -104,7 +104,7 @@ typealias ABIEntryPoint_v0 = @Sendable ( /// /// This function will be removed (with its logic incorporated into /// ``ABIv0/entryPoint-swift.type.property``) in a future update. -private func entryPoint( +private func _entryPoint( configurationJSON: UnsafeRawBufferPointer?, eventStreamVersionIfNil: Int? = nil, recordHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void diff --git a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift index 254311968..700e50ffa 100644 --- a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift @@ -547,6 +547,15 @@ public func configurationForEntryPoint(from args: __CommandLineArguments_v0) thr configuration.exitTestHandler = ExitTest.handlerForEntryPoint() #endif + switch args.eventStreamVersion { + case .some(...0): + // If the event stream version was specified explicitly to a value < 1, + // disable delivery of warning issue events to maintain legacy behavior. + configuration.eventHandlingOptions.isWarningIssueEventDeliveryEnabled = false + default: + break + } + return configuration } diff --git a/Sources/Testing/Events/Event.swift b/Sources/Testing/Events/Event.swift index 60e564d5a..dc5468465 100644 --- a/Sources/Testing/Events/Event.swift +++ b/Sources/Testing/Events/Event.swift @@ -290,10 +290,7 @@ extension Event { if let configuration = configuration ?? Configuration.current { // The caller specified a configuration, or the current task has an // associated configuration. Post to either configuration's event handler. - switch kind { - case .expectationChecked where !configuration.deliverExpectationCheckedEvents: - break - default: + if configuration.eventHandlingOptions.shouldHandleEvent(self) { configuration.handleEvent(self, in: context) } } else { @@ -306,6 +303,26 @@ extension Event { } } +extension Configuration.EventHandlingOptions { + /// Determine whether the specified event should be handled according to the + /// options in this instance. + /// + /// - Parameters: + /// - event: The event to consider handling. + /// + /// - Returns: Whether or not the event should be handled or suppressed. + fileprivate func shouldHandleEvent(_ event: borrowing Event) -> Bool { + switch event.kind { + case let .issueRecorded(issue): + issue.severity > .warning || isWarningIssueEventDeliveryEnabled + case .expectationChecked: + isExpectationCheckedEventDeliveryEnabled + default: + true + } + } +} + #if !SWT_NO_SNAPSHOT_TYPES // MARK: - Snapshotting diff --git a/Sources/Testing/Running/Configuration.swift b/Sources/Testing/Running/Configuration.swift index f4ae59813..fa2d868fc 100644 --- a/Sources/Testing/Running/Configuration.swift +++ b/Sources/Testing/Running/Configuration.swift @@ -178,14 +178,35 @@ public struct Configuration: Sendable { // MARK: - Event handling - /// Whether or not events of the kind - /// ``Event/Kind-swift.enum/expectationChecked(_:)`` should be delivered to - /// this configuration's ``eventHandler`` closure. + /// A type describing options to use when delivering events to this + /// configuration's event handler + public struct EventHandlingOptions: Sendable { + /// Whether or not events of the kind ``Event/Kind-swift.enum/issueRecorded(_:)`` + /// containing issues with warning (or lower) severity should be delivered + /// to the event handler of the configuration these options are applied to. + /// + /// By default, events matching this criteria are delivered to event + /// handlers unless the entry point specifies an event stream version which + /// predates the introduction of warning issues, in which case this is + /// disabled to maintain legacy behavior. + public var isWarningIssueEventDeliveryEnabled: Bool = true + + /// Whether or not events of the kind + /// ``Event/Kind-swift.enum/expectationChecked(_:)`` should be delivered to + /// the event handler of the configuration these options are applied to. + /// + /// By default, events of this kind are not delivered to event handlers + /// because they occur frequently in a typical test run and can generate + /// significant back-pressure on the event handler. + public var isExpectationCheckedEventDeliveryEnabled: Bool = false + } + + /// The options to use when delivering events to this configuration's event + /// handler. /// - /// By default, events of this kind are not delivered to event handlers - /// because they occur frequently in a typical test run and can generate - /// significant backpressure on the event handler. - public var deliverExpectationCheckedEvents: Bool = false + /// The default value of this property is an instance of ``EventHandlingOptions-swift.struct`` + /// with its properties initialized to their default values. + public var eventHandlingOptions: EventHandlingOptions = .init() /// The event handler to which events should be passed when they occur. public var eventHandler: Event.Handler = { _, _ in } @@ -325,4 +346,14 @@ extension Configuration { } } #endif + + @available(*, deprecated, message: "Set eventHandlingOptions.isExpectationCheckedEventDeliveryEnabled instead.") + public var deliverExpectationCheckedEvents: Bool { + get { + eventHandlingOptions.isExpectationCheckedEventDeliveryEnabled + } + set { + eventHandlingOptions.isExpectationCheckedEventDeliveryEnabled = newValue + } + } } From cefc62de98a2fdab4074507f1539c1b1212e1cab Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 29 Jan 2025 21:29:02 -0600 Subject: [PATCH 11/32] Attempt to work around compiler crash --- .../Events/Recorder/Event.HumanReadableOutputRecorder.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index d2fa235f0..ef784a195 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -277,7 +277,8 @@ extension Event.HumanReadableOutputRecorder { if issue.isKnown { testData.knownIssueCount += 1 } else { - testData.issueCount[issue.severity, default: 0] += 1 + let issueCount = testData.issueCount[issue.severity] ?? 0 + testData.issueCount[issue.severity] = issueCount + 1 } context.testData[id] = testData From f224697ddfa9fdb0f0c60e6dc17e6b3521bf304c Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Thu, 30 Jan 2025 11:15:08 -0600 Subject: [PATCH 12/32] PR feedback --- Documentation/ABI/JSON.md | 16 ++++++---------- .../Testing/ABI/EntryPoints/EntryPoint.swift | 2 +- Sources/Testing/Events/Event.swift | 4 ++-- Sources/Testing/Running/Configuration.swift | 18 +++++++++--------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Documentation/ABI/JSON.md b/Documentation/ABI/JSON.md index 0a97c9e68..2fcf4b268 100644 --- a/Documentation/ABI/JSON.md +++ b/Documentation/ABI/JSON.md @@ -197,20 +197,10 @@ sufficient information to display the event in a human-readable format. "runEnded" ; additional event kinds may be added in the future ::= { - "isKnown": , ; is this a known issue or not? ["sourceLocation": ,] ; where the issue occurred, if known } - - ::= { "symbol": , "text": , ; the human-readable text of this message @@ -220,6 +210,12 @@ sufficient information to display the event in a human-readable format. "fail" | "difference" | "warning" | "details" ``` + + + +## Version history + +- Version 1 (unreleased) + - Introduced issue severity, with a new "warning" severity level which is + lower than the default "error" level. Clients upgrading from v0 should + begin consulting the severity of recorded issues to determine whether the + associated test should be marked as failing. +- Version 0 (Initial ABI version) diff --git a/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift b/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift index 7c5b5185a..97c051d28 100644 --- a/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift +++ b/Sources/Testing/ABI/v0/Encoded/ABIv0.EncodedIssue.swift @@ -19,7 +19,7 @@ extension ABIv0 { /// An enumeration representing the level of severity of a recorded issue. /// /// For descriptions of individual cases, see ``Issue/Severity-swift.enum``. - enum Severity: String { + enum Severity: String, Sendable { case warning case error } diff --git a/Sources/Testing/Events/Event.swift b/Sources/Testing/Events/Event.swift index 507549604..b81f1c2c7 100644 --- a/Sources/Testing/Events/Event.swift +++ b/Sources/Testing/Events/Event.swift @@ -303,26 +303,6 @@ extension Event { } } -extension Configuration.EventHandlingOptions { - /// Determine whether the specified event should be handled according to the - /// options in this instance. - /// - /// - Parameters: - /// - event: The event to consider handling. - /// - /// - Returns: Whether or not the event should be handled or suppressed. - fileprivate func shouldHandleEvent(_ event: borrowing Event) -> Bool { - switch event.kind { - case let .issueRecorded(issue): - issue.severity > .warning || isWarningIssueRecordedEventEnabled - case .expectationChecked: - isExpectationCheckedEventEnabled - default: - true - } - } -} - #if !SWT_NO_SNAPSHOT_TYPES // MARK: - Snapshotting diff --git a/Sources/Testing/Running/Configuration+EventHandling.swift b/Sources/Testing/Running/Configuration+EventHandling.swift index 025f07d2c..e3c189f8b 100644 --- a/Sources/Testing/Running/Configuration+EventHandling.swift +++ b/Sources/Testing/Running/Configuration+EventHandling.swift @@ -38,3 +38,23 @@ extension Configuration { return eventHandler(event, contextCopy) } } + +extension Configuration.EventHandlingOptions { + /// Determine whether the specified event should be handled according to the + /// options in this instance. + /// + /// - Parameters: + /// - event: The event to consider handling. + /// + /// - Returns: Whether or not the event should be handled or suppressed. + func shouldHandleEvent(_ event: borrowing Event) -> Bool { + switch event.kind { + case let .issueRecorded(issue): + issue.severity > .warning || isWarningIssueRecordedEventEnabled + case .expectationChecked: + isExpectationCheckedEventEnabled + default: + true + } + } +} diff --git a/Sources/Testing/Running/Configuration.swift b/Sources/Testing/Running/Configuration.swift index 868cb16a2..635749b6c 100644 --- a/Sources/Testing/Running/Configuration.swift +++ b/Sources/Testing/Running/Configuration.swift @@ -203,9 +203,6 @@ public struct Configuration: Sendable { /// The options to use when delivering events to this configuration's event /// handler. - /// - /// The default value of this property is an instance of ``EventHandlingOptions-swift.struct`` - /// with its properties initialized to their default values. public var eventHandlingOptions: EventHandlingOptions = .init() /// The event handler to which events should be passed when they occur. diff --git a/Tests/TestingTests/ConfigurationTests.swift b/Tests/TestingTests/ConfigurationTests.swift new file mode 100644 index 000000000..a735d8ac5 --- /dev/null +++ b/Tests/TestingTests/ConfigurationTests.swift @@ -0,0 +1,25 @@ +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for Swift project authors +// + +@_spi(ForToolsIntegrationOnly) import Testing + +@Suite("Configuration Tests") +struct ConfigurationTests { + @Test + @available(*, deprecated, message: "Testing a deprecated SPI.") + func deliverExpectationCheckedEventsProperty() throws { + var configuration = Configuration() + #expect(!configuration.deliverExpectationCheckedEvents) + #expect(!configuration.eventHandlingOptions.isExpectationCheckedEventEnabled) + + configuration.deliverExpectationCheckedEvents = true + #expect(configuration.eventHandlingOptions.isExpectationCheckedEventEnabled) + } +} diff --git a/Tests/TestingTests/EntryPointTests.swift b/Tests/TestingTests/EntryPointTests.swift index fb77643f7..eae7d4b7e 100644 --- a/Tests/TestingTests/EntryPointTests.swift +++ b/Tests/TestingTests/EntryPointTests.swift @@ -69,7 +69,6 @@ struct EntryPointTests { } #expect(exitCode == EXIT_SUCCESS) } - } // MARK: - Fixtures From 1e6e866dba2ea591dc7c0089c6302ec42e80971e Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 7 Feb 2025 15:01:38 -0600 Subject: [PATCH 27/32] Don't use warning symbol for test and run ended events, only for issue recorded events (for warning issues) --- .../Event.HumanReadableOutputRecorder.swift | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift index cdb877398..704ee78bb 100644 --- a/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift +++ b/Sources/Testing/Events/Recorder/Event.HumanReadableOutputRecorder.swift @@ -373,13 +373,6 @@ extension Event.HumanReadableOutputRecorder { stringValue: "\(_capitalizedTitle(for: test)) \(testName) failed after \(duration)\(issues.description)." ) ) + _formattedComments(for: test) - } else if issues.warningIssueCount > 0 { - [ - Message( - symbol: .warning, - stringValue: "\(_capitalizedTitle(for: test)) \(testName) passed after \(duration)\(issues.description)." - ) - ] } else { [ Message( @@ -529,13 +522,6 @@ extension Event.HumanReadableOutputRecorder { stringValue: "Test run with \(testCount.counting("test")) failed after \(duration)\(issues.description)." ) ] - } else if issues.warningIssueCount > 0 { - [ - Message( - symbol: .warning, - stringValue: "Test run with \(testCount.counting("test")) passed after \(duration)\(issues.description)." - ) - ] } else { [ Message( From 95d83ffe9a34d40efd20d5fa006f8bd403bf5861 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 7 Feb 2025 15:43:48 -0600 Subject: [PATCH 28/32] Move pending ABI changes writeup to a separate file --- Documentation/ABI/JSON.md | 9 --------- Documentation/ABI/Pending-ABIv1.md | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 Documentation/ABI/Pending-ABIv1.md diff --git a/Documentation/ABI/JSON.md b/Documentation/ABI/JSON.md index 44053ff2c..2fcf4b268 100644 --- a/Documentation/ABI/JSON.md +++ b/Documentation/ABI/JSON.md @@ -220,12 +220,3 @@ sufficient information to display the event in a human-readable format. ["testID": , ["testCase": ]] --> - -## Version history - -- Version 1 (unreleased) - - Introduced issue severity, with a new "warning" severity level which is - lower than the default "error" level. Clients upgrading from v0 should - begin consulting the severity of recorded issues to determine whether the - associated test should be marked as failing. -- Version 0 (Initial ABI version) diff --git a/Documentation/ABI/Pending-ABIv1.md b/Documentation/ABI/Pending-ABIv1.md new file mode 100644 index 000000000..e1013f313 --- /dev/null +++ b/Documentation/ABI/Pending-ABIv1.md @@ -0,0 +1,20 @@ +# Pending ABIv1 Changes + +This document collects changes which have been made and are anticipated to be +released in a future ABI/event stream version, but are still pending. + +> [!IMPORTANT] +> This file describes changes which are unreleased, and are subject to change. +> Do not depend on this version or make assumptions that these changes will +> remain part of this ABI version. + +## Issue severity and warning issues. + +Introduced a notion of "severity" for issues, and a new "warning" severity level +which is lower than the default "error" level. Clients upgrading from v0 should +begin consulting the severity of recorded issues to determine whether the +associated test should be marked as failing. + +### See Also + +- https://github.com/swiftlang/swift-testing/pull/931 From c23a4d68f81faa649a00df28def9ecc3c52da141 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 7 Feb 2025 16:15:01 -0600 Subject: [PATCH 29/32] Adjust symbols and ABI documentation --- Documentation/ABI/JSON.md | 6 ----- Documentation/ABI/Pending-ABIv1.md | 2 +- .../ABI/v0/Encoded/ABIv0.EncodedMessage.swift | 9 ++++--- .../Event.ConsoleOutputRecorder.swift | 6 +++-- .../Event.HumanReadableOutputRecorder.swift | 2 +- .../Events/Recorder/Event.Symbol.swift | 24 +++++++++++++------ 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Documentation/ABI/JSON.md b/Documentation/ABI/JSON.md index 2fcf4b268..23dd5b1dc 100644 --- a/Documentation/ABI/JSON.md +++ b/Documentation/ABI/JSON.md @@ -210,12 +210,6 @@ sufficient information to display the event in a human-readable format. "fail" | "difference" | "warning" | "details" ``` - -