diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5ace4600a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index b9ac3ab08..d3f5e7ddd 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -18,7 +18,7 @@ on: jobs: create_merge_pr: name: Create PR to merge main into release branch - uses: swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml@main + uses: swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml@0.0.3 with: head_branch: main base_branch: release/6.3 diff --git a/.github/workflows/main_using_main.yml b/.github/workflows/main_using_main.yml index dbf27c0f4..2b7c9ac16 100644 --- a/.github/workflows/main_using_main.yml +++ b/.github/workflows/main_using_main.yml @@ -15,7 +15,7 @@ concurrency: jobs: tests: name: Test - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: linux_swift_versions: '["nightly-main"]' linux_os_versions: '["amazonlinux2", "jammy"]' diff --git a/.github/workflows/main_using_release.yml b/.github/workflows/main_using_release.yml index b861be1f8..ef6742d82 100644 --- a/.github/workflows/main_using_release.yml +++ b/.github/workflows/main_using_release.yml @@ -15,7 +15,7 @@ concurrency: jobs: tests: name: Test - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: linux_swift_versions: '["nightly-6.2"]' linux_os_versions: '["amazonlinux2", "jammy"]' diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 086b2226e..ca6aa7446 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -14,11 +14,11 @@ concurrency: jobs: tests: name: Test - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: - linux_swift_versions: '["nightly-main", "nightly-6.2"]' + linux_swift_versions: '["nightly-main", "nightly-6.3", "nightly-6.2"]' linux_os_versions: '["amazonlinux2", "jammy"]' - windows_swift_versions: '["nightly-main", "nightly-6.2"]' + windows_swift_versions: '["nightly-main", "nightly-6.3", "nightly-6.2"]' enable_macos_checks: true macos_exclude_xcode_versions: '[{"xcode_version": "16.2"}, {"xcode_version": "16.3"}, {"xcode_version": "16.4"}]' enable_ios_checks: true @@ -27,7 +27,7 @@ jobs: enable_android_sdk_build: true soundness: name: Soundness - uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@0.0.3 with: license_header_check_project_name: "Swift" docs_check_enabled: false 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": diff --git a/Sources/Testing/ABI/ABI.swift b/Sources/Testing/ABI/ABI.swift index 7a33970fc..9590949a6 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.) @@ -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: @autoclosure () -> 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, @@ -71,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 } } diff --git a/Sources/Testing/Issues/KnownIssue.swift b/Sources/Testing/Issues/KnownIssue.swift index f59185388..17214c12c 100644 --- a/Sources/Testing/Issues/KnownIssue.swift +++ b/Sources/Testing/Issues/KnownIssue.swift @@ -77,6 +77,13 @@ struct KnownIssueScope: Sendable { /// - sourceLocation: The source location to which the issue should be /// attributed. private func _matchError(_ error: any Error, in scope: KnownIssueScope, comment: Comment?, sourceLocation: SourceLocation) throws { + // ExpectationFailedError is thrown by expectation checking functions to + // indicate a condition evaluated to `false`. Those functions record their + // own issue, so we don't need to create a new issue and attempt to match it. + if error is ExpectationFailedError { + return + } + let sourceContext = SourceContext(backtrace: Backtrace(forFirstThrowOf: error), sourceLocation: sourceLocation) var issue = Issue(kind: .errorCaught(error), comments: [], sourceContext: sourceContext) if let context = scope.matcher(issue) { diff --git a/Sources/Testing/Running/Runner.swift b/Sources/Testing/Running/Runner.swift index a6a76189e..9a04f6d7e 100644 --- a/Sources/Testing/Running/Runner.swift +++ b/Sources/Testing/Running/Runner.swift @@ -77,7 +77,7 @@ extension Runner { /// type at runtime, it may be better-suited for ``Configuration`` instead. private struct _Context: Sendable { /// A serializer used to reduce parallelism among test cases. - var testCaseSerializer: Serializer? + var testCaseSerializer: Serializer? } /// Apply the custom scope for any test scope providers of the traits diff --git a/Sources/Testing/Support/Serializer.swift b/Sources/Testing/Support/Serializer.swift index 94f7d4f5b..fee310bc7 100644 --- a/Sources/Testing/Support/Serializer.swift +++ b/Sources/Testing/Support/Serializer.swift @@ -42,8 +42,13 @@ var defaultParallelizationWidth: Int { /// items do not start running; they must wait until the suspended work item /// either returns or throws an error. /// +/// The generic type parameter `T` is unused. It avoids warnings when multiple +/// copies of the testing library are loaded into a runner process on platforms +/// which use the Objective-C runtime, due to non-generic actor types being +/// implemented as classes there. +/// /// This type is not part of the public interface of the testing library. -final actor Serializer { +final actor Serializer { /// The maximum number of work items that may run concurrently. nonisolated let maximumWidth: Int diff --git a/Tests/TestingTests/KnownIssueTests.swift b/Tests/TestingTests/KnownIssueTests.swift index 9174bfdd8..88deef5ec 100644 --- a/Tests/TestingTests/KnownIssueTests.swift +++ b/Tests/TestingTests/KnownIssueTests.swift @@ -574,6 +574,26 @@ final class KnownIssueTests: XCTestCase { await fulfillment(of: [issueRecorded, knownIssueNotRecorded], timeout: 0.0) } + func testKnownIssueWithRequiredExpectationFailure() async { + let issueRecorded = expectation(description: "Issue recorded") + + var configuration = Configuration() + configuration.eventHandler = { event, _ in + guard case .issueRecorded = event.kind else { + return + } + issueRecorded.fulfill() + } + + await Test { + withKnownIssue { + try #require(Bool(false)) + } + }.run(configuration: configuration) + + await fulfillment(of: [issueRecorded], timeout: 0.0) + } + func testAsyncKnownIssueThatDoesNotAlwaysOccur() async { struct MyError: Error {} 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")