From eeeecf4422de7a5dfed1057a890ae26425f39922 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 10 Jul 2024 16:59:25 -0700 Subject: [PATCH 01/11] Add support for Swift Testing --- Package.swift | 4 ++-- Package@swift-6.0.swift | 4 ++-- Sources/Clocks/TestClock.swift | 16 ++++++++++------ Sources/Clocks/UnimplementedClock.swift | 8 ++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Package.swift b/Package.swift index a3b2df04..2320e17a 100644 --- a/Package.swift +++ b/Package.swift @@ -22,14 +22,14 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.0.0"), + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", branch: "swift-testing"), ], targets: [ .target( name: "Clocks", dependencies: [ .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"), + .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), ] ), .testTarget( diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 2efa4dc8..dcccde0b 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -22,14 +22,14 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.0.0"), + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", branch: "swift-testing"), ], targets: [ .target( name: "Clocks", dependencies: [ .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"), + .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), ] ), .testTarget( diff --git a/Sources/Clocks/TestClock.swift b/Sources/Clocks/TestClock.swift index 0cda3855..748db190 100644 --- a/Sources/Clocks/TestClock.swift +++ b/Sources/Clocks/TestClock.swift @@ -1,7 +1,7 @@ #if (canImport(RegexBuilder) || !os(macOS) && !targetEnvironment(macCatalyst)) import ConcurrencyExtras import Foundation - import XCTestDynamicOverlay + import IssueReporting /// A clock whose time can be controlled in a deterministic manner. /// @@ -225,8 +225,10 @@ /// - duration: The amount of time to allow for all work on the clock to finish. public func run( timeout duration: Swift.Duration = .milliseconds(500), - file: StaticString = #file, - line: UInt = #line + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column ) async { do { try await withThrowingTaskGroup(of: Void.self) { group in @@ -248,7 +250,7 @@ group.cancelAll() } } catch { - XCTFail( + reportIssue( """ Expected all sleeps to finish, but some are still suspending after \(duration). @@ -258,8 +260,10 @@ You can also increase the timeout of 'run' to be greater than \(duration). """, - file: file, - line: line + fileID: fileID, + filePath: filePath, + line: line, + column: column ) } } diff --git a/Sources/Clocks/UnimplementedClock.swift b/Sources/Clocks/UnimplementedClock.swift index 2dd06da9..82347b69 100644 --- a/Sources/Clocks/UnimplementedClock.swift +++ b/Sources/Clocks/UnimplementedClock.swift @@ -1,7 +1,7 @@ #if (canImport(RegexBuilder) || !os(macOS) && !targetEnvironment(macCatalyst)) import ConcurrencyExtras import Foundation - import XCTestDynamicOverlay + import IssueReporting /// A clock that causes an XCTest failure when any of its endpoints are invoked. /// @@ -101,17 +101,17 @@ } public var now: Instant { - XCTFail("Unimplemented: \(self.name).now") + reportIssue("Unimplemented: \(self.name).now") return Instant(rawValue: self.base.now) } public var minimumResolution: Duration { - XCTFail("Unimplemented: \(self.name).minimumResolution") + reportIssue("Unimplemented: \(self.name).minimumResolution") return self.base.minimumResolution } public func sleep(until deadline: Instant, tolerance: Duration?) async throws { - XCTFail("Unimplemented: \(self.name).sleep") + reportIssue("Unimplemented: \(self.name).sleep") try await self.base.sleep(until: deadline.rawValue, tolerance: tolerance) } } From bf4bb58052b4712b3e381be1dfec5493eae5dc1d Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 10 Jul 2024 23:05:52 -0700 Subject: [PATCH 02/11] wip --- Tests/ClocksTests/TestClocksTests.swift | 2 +- Tests/ClocksTests/UnimplementedClockTests.swift | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Tests/ClocksTests/TestClocksTests.swift b/Tests/ClocksTests/TestClocksTests.swift index ec3b8ded..3c131289 100644 --- a/Tests/ClocksTests/TestClocksTests.swift +++ b/Tests/ClocksTests/TestClocksTests.swift @@ -66,7 +66,7 @@ final class TestClockTests: XCTestCase, @unchecked Sendable { func testRunWithTimeout() async throws { XCTExpectFailure { $0.compactDescription == """ - Expected all sleeps to finish, but some are still suspending after 1.0 seconds. + failed - Expected all sleeps to finish, but some are still suspending after 1.0 seconds. There are sleeps suspending. This could mean you are not advancing the test clock far \ enough for your feature to execute its logic, or there could be a bug in your feature's \ diff --git a/Tests/ClocksTests/UnimplementedClockTests.swift b/Tests/ClocksTests/UnimplementedClockTests.swift index 8b29a620..a4e357b9 100644 --- a/Tests/ClocksTests/UnimplementedClockTests.swift +++ b/Tests/ClocksTests/UnimplementedClockTests.swift @@ -7,8 +7,8 @@ func testUnimplementedClock() async throws { XCTExpectFailure { [ - "Unimplemented: Clock.sleep", - "Unimplemented: Clock.now", + "failed - Unimplemented: Clock.sleep", + "failed - Unimplemented: Clock.now", ] .contains($0.compactDescription) } @@ -20,8 +20,8 @@ func testUnimplementedClock_WithName() async throws { XCTExpectFailure { [ - "Unimplemented: ContinuousClock.sleep", - "Unimplemented: ContinuousClock.now", + "failed - Unimplemented: ContinuousClock.sleep", + "failed - Unimplemented: ContinuousClock.now", ] .contains($0.compactDescription) } @@ -33,8 +33,8 @@ func testNow() async throws { XCTExpectFailure { [ - "Unimplemented: Clock.sleep", - "Unimplemented: Clock.now", + "failed - Unimplemented: Clock.sleep", + "failed - Unimplemented: Clock.now", ] .contains($0.compactDescription) } @@ -48,8 +48,8 @@ let task = Task { XCTExpectFailure { [ - "Unimplemented: Clock.sleep", - "Unimplemented: Clock.now", + "failed - Unimplemented: Clock.sleep", + "failed - Unimplemented: Clock.now", ] .contains($0.compactDescription) } From 6644041285a7192f3af490b4b1a4cae4d5cdc6a3 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Thu, 11 Jul 2024 13:48:14 -0700 Subject: [PATCH 03/11] wip --- Package.resolved | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Package.resolved b/Package.resolved index d9770c86..77c5ec86 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-concurrency-extras", "state" : { - "revision" : "ea631ce892687f5432a833312292b80db238186a", - "version" : "1.0.0" + "revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71", + "version" : "1.1.0" } }, { @@ -14,7 +14,16 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-docc-plugin", "state" : { - "revision" : "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "revision" : "26ac5758409154cc448d7ab82389c520fa8a8247", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", "version" : "1.0.0" } }, @@ -23,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { - "revision" : "302891700c7fa3b92ebde9fe7b42933f8349f3c7", - "version" : "1.0.0" + "branch" : "swift-testing", + "revision" : "b77c8b7198508cf747344c93a592643df2ffff4e" } } ], From d232a15e0a96dfe4d0c93f85b5176afe1808e28d Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Thu, 11 Jul 2024 13:50:13 -0700 Subject: [PATCH 04/11] wip --- Package.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.resolved b/Package.resolved index 77c5ec86..3d40f699 100644 --- a/Package.resolved +++ b/Package.resolved @@ -33,7 +33,7 @@ "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { "branch" : "swift-testing", - "revision" : "b77c8b7198508cf747344c93a592643df2ffff4e" + "revision" : "790cd0036de1946e97f66105c3e366ec06dd932a" } } ], From 74e4934df3d903a07f1fc4d80fb8459ba48e0b33 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Fri, 12 Jul 2024 11:35:45 -0700 Subject: [PATCH 05/11] wip --- Package.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.resolved b/Package.resolved index 3d40f699..507cac1a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -33,7 +33,7 @@ "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { "branch" : "swift-testing", - "revision" : "790cd0036de1946e97f66105c3e366ec06dd932a" + "revision" : "0bf5ef4746bb193865b946ced53b61aec223af42" } } ], From 2d16a24bb30b530eb5e86b519bd7afe25fb3034d Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Fri, 19 Jul 2024 09:34:37 -0700 Subject: [PATCH 06/11] wip --- Package.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.resolved b/Package.resolved index 507cac1a..b55cc502 100644 --- a/Package.resolved +++ b/Package.resolved @@ -33,7 +33,7 @@ "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { "branch" : "swift-testing", - "revision" : "0bf5ef4746bb193865b946ced53b61aec223af42" + "revision" : "eb270c44fff42d8f0657749048e8519875ebdd6d" } } ], From e0efee21ecbabcc5e15eb0d004701c3a2024adae Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Mon, 22 Jul 2024 13:29:37 -0700 Subject: [PATCH 07/11] wip --- Package.resolved | 8 ++++---- Package.swift | 4 ++-- Package@swift-6.0.swift | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Package.resolved b/Package.resolved index b55cc502..8aba5aef 100644 --- a/Package.resolved +++ b/Package.resolved @@ -28,12 +28,12 @@ } }, { - "identity" : "xctest-dynamic-overlay", + "identity" : "swift-issue-reporting", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "location" : "https://github.com/pointfreeco/swift-issue-reporting", "state" : { - "branch" : "swift-testing", - "revision" : "eb270c44fff42d8f0657749048e8519875ebdd6d" + "revision" : "926f43898706eaa127db79ac42138e1ad7e85a3f", + "version" : "1.2.0" } } ], diff --git a/Package.swift b/Package.swift index 2320e17a..6c3d1816 100644 --- a/Package.swift +++ b/Package.swift @@ -22,14 +22,14 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", branch: "swift-testing"), + .package(url: "https://github.com/pointfreeco/swift-issue-reporting", from: "1.2.0"), ], targets: [ .target( name: "Clocks", dependencies: [ .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), + .product(name: "IssueReporting", package: "swift-issue-reporting"), ] ), .testTarget( diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index dcccde0b..fb03ab7a 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -22,14 +22,14 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", branch: "swift-testing"), + .package(url: "https://github.com/pointfreeco/swift-issue-reporting", from: "1.2.0"), ], targets: [ .target( name: "Clocks", dependencies: [ .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), + .product(name: "IssueReporting", package: "swift-issue-reporting"), ] ), .testTarget( From ccedd19815c4f4d67de06ebeb541cd3bb7b4835f Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 22 Jul 2024 16:03:00 -0500 Subject: [PATCH 08/11] disable library evolution CI for now --- .github/workflows/ci.yml | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 19 ++++++++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 097b4565..7ab59d1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,8 +25,8 @@ jobs: run: sudo xcode-select -s /Applications/Xcode_15.4.app - name: Run ${{ matrix.config }} tests run: CONFIG=${{ matrix.config }} make test-all - - name: Build for library evolution - run: CONFIG=${{ matrix.config }} make build-for-library-evolution + # - name: Build for library evolution + # run: CONFIG=${{ matrix.config }} make build-for-library-evolution linux: strategy: diff --git a/Clocks.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Clocks.xcworkspace/xcshareddata/swiftpm/Package.resolved index 91e9d7de..8aba5aef 100644 --- a/Clocks.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Clocks.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,17 +14,26 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-docc-plugin", "state" : { - "revision" : "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "revision" : "26ac5758409154cc448d7ab82389c520fa8a8247", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", "version" : "1.0.0" } }, { - "identity" : "xctest-dynamic-overlay", + "identity" : "swift-issue-reporting", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "location" : "https://github.com/pointfreeco/swift-issue-reporting", "state" : { - "revision" : "23cbf2294e350076ea4dbd7d5d047c1e76b03631", - "version" : "1.0.2" + "revision" : "926f43898706eaa127db79ac42138e1ad7e85a3f", + "version" : "1.2.0" } } ], From 94feb554c34d764112e58b35bf5bbef76390c901 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Mon, 22 Jul 2024 15:08:34 -0700 Subject: [PATCH 09/11] wip --- Sources/Clocks/UnimplementedClock.swift | 68 +++++++++++++++++++++---- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/Sources/Clocks/UnimplementedClock.swift b/Sources/Clocks/UnimplementedClock.swift index 82347b69..d8928897 100644 --- a/Sources/Clocks/UnimplementedClock.swift +++ b/Sources/Clocks/UnimplementedClock.swift @@ -84,34 +84,75 @@ private let base: AnyClock private let name: String + private let fileID: StaticString + private let filePath: StaticString + private let line: UInt + private let column: UInt public init( _ base: C, - name: String = "\(C.self)" + name: String = "\(C.self)", + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column ) where C.Duration == Duration { self.base = AnyClock(base) self.name = name + self.fileID = fileID + self.filePath = filePath + self.line = line + self.column = column } public init( name: String = "Clock", - now: ImmediateClock.Instant = .init() + now: ImmediateClock.Instant = .init(), + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column ) { - self.init(ImmediateClock(now: now), name: name) + self.init( + ImmediateClock(now: now), + name: name, + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) } public var now: Instant { - reportIssue("Unimplemented: \(self.name).now") + reportIssue( + "Unimplemented: \(self.name).now", + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) return Instant(rawValue: self.base.now) } public var minimumResolution: Duration { - reportIssue("Unimplemented: \(self.name).minimumResolution") + reportIssue( + "Unimplemented: \(self.name).minimumResolution" + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) return self.base.minimumResolution } public func sleep(until deadline: Instant, tolerance: Duration?) async throws { - reportIssue("Unimplemented: \(self.name).sleep") + reportIssue( + "Unimplemented: \(self.name).sleep" + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) try await self.base.sleep(until: deadline.rawValue, tolerance: tolerance) } } @@ -129,11 +170,11 @@ /// /// Constructs and returns an ``UnimplementedClock`` /// - /// > Important: Due to [a bug in Swift](https://github.com/apple/swift/issues/61645), this static - /// > value cannot be used in an existential context: + /// > Important: Due to [a bug in Swift <6](https://github.com/apple/swift/issues/61645), this + /// > static value cannot be used in an existential context: /// > /// > ```swift - /// > let clock: any Clock = .unimplemented // 🛑 + /// > let clock: any Clock = .unimplemented() // 🛑 /// > ``` /// > /// > To work around this bug, construct an unimplemented clock directly: @@ -141,8 +182,13 @@ /// > ```swift /// > let clock: any Clock = UnimplementedClock() // ✅ /// > ``` - public static var unimplemented: Self { - UnimplementedClock() + public static func unimplemented( + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column + ) -> Self { + UnimplementedClock(fileID: fileID, filePath: filePath, line: line, column: column) } } #endif From 496db2989d0ee27004b1f000c4984fbe08a416cc Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Mon, 22 Jul 2024 15:13:44 -0700 Subject: [PATCH 10/11] wip --- Sources/Clocks/UnimplementedClock.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Clocks/UnimplementedClock.swift b/Sources/Clocks/UnimplementedClock.swift index d8928897..d678bf51 100644 --- a/Sources/Clocks/UnimplementedClock.swift +++ b/Sources/Clocks/UnimplementedClock.swift @@ -136,7 +136,7 @@ public var minimumResolution: Duration { reportIssue( - "Unimplemented: \(self.name).minimumResolution" + "Unimplemented: \(self.name).minimumResolution", fileID: fileID, filePath: filePath, line: line, @@ -147,7 +147,7 @@ public func sleep(until deadline: Instant, tolerance: Duration?) async throws { reportIssue( - "Unimplemented: \(self.name).sleep" + "Unimplemented: \(self.name).sleep", fileID: fileID, filePath: filePath, line: line, From 62390265e43d85147ee12ee5965daaa3aca437fd Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Mon, 22 Jul 2024 15:20:21 -0700 Subject: [PATCH 11/11] wip --- Tests/ClocksTests/UnimplementedClockTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ClocksTests/UnimplementedClockTests.swift b/Tests/ClocksTests/UnimplementedClockTests.swift index a4e357b9..e9285a2e 100644 --- a/Tests/ClocksTests/UnimplementedClockTests.swift +++ b/Tests/ClocksTests/UnimplementedClockTests.swift @@ -13,7 +13,7 @@ .contains($0.compactDescription) } - let clock: some Clock = .unimplemented + let clock: some Clock = .unimplemented() try await clock.sleep(for: .seconds(1)) }