diff --git a/Package.swift b/Package.swift index afc2378f..c43747c0 100644 --- a/Package.swift +++ b/Package.swift @@ -25,20 +25,10 @@ let package = Package( .systemLibrary(name: "_CAsyncSequenceValidationSupport"), .target( name: "AsyncAlgorithms_XCTest", - dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"], - swiftSettings: [ - .unsafeFlags([ - "-Xfrontend", "-disable-availability-checking" - ]) - ]), + dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"]), .testTarget( name: "AsyncAlgorithmsTests", - dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"], - swiftSettings: [ - .unsafeFlags([ - "-Xfrontend", "-disable-availability-checking" - ]) - ]), + dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"]), ] ) diff --git a/README.md b/README.md index e3c957a9..cde1208f 100644 --- a/README.md +++ b/README.md @@ -87,28 +87,17 @@ Finally, add `import AsyncAlgorithms` to your source code. ## Getting Started -⚠️ Please note that this package currently requires a recent [Swift Trunk Development toolchain](https://www.swift.org/download/#trunk-development-main). More information on how to use custom toolchains with Xcode can be viewed [here](https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/AlternativeToolchains.html). +⚠️ Please note that this package requires Xcode 14 on macOS hosts. Previous versions of Xcode do not contain the required Swift version. ### Building/Testing Using Xcode on macOS - 1. Download the most recent development Xcode toolchain. - 2. Install the package - 4. Select the development toolchain in Xcode - 4. Open the `swift-async-algorithms` package directory in Xcode - 5. Build or Test in Xcode as normal - -⚠️ Note: `swift test` does not currently work properly with custom toolchains for this package. + 1. In the `swift-async-algorithms` directory run `swift build` or `swift test` accordingly ### Building/Testing on Linux 1. Download the most recent development toolchain for your Linux distribution 2. Decompress the archive to a path in which the `swift` executable is in the binary search path environment variable (`$PATH`) 3. In the `swift-async-algorithms` directory run `swift build` or `swift test` accordingly - -### Building with Swift 5.6 - - 1. `git checkout swift-5.6` - 2. run `swift build` or `swift test` accordingly ## Source Stability diff --git a/Sources/AsyncSequenceValidation/AsyncSequenceValidationDiagram.swift b/Sources/AsyncSequenceValidation/AsyncSequenceValidationDiagram.swift index 63c59ad0..b7ee6547 100644 --- a/Sources/AsyncSequenceValidation/AsyncSequenceValidationDiagram.swift +++ b/Sources/AsyncSequenceValidation/AsyncSequenceValidationDiagram.swift @@ -11,7 +11,6 @@ import _CAsyncSequenceValidationSupport -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) @resultBuilder public struct AsyncSequenceValidationDiagram : Sendable { public struct Component { @@ -97,15 +96,20 @@ public struct AsyncSequenceValidationDiagram : Sendable { } let queue: WorkQueue + let _clock: Clock public var inputs: InputList - public let clock: Clock + + @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) + public var clock: Clock { + _clock + } internal init() { let queue = WorkQueue() self.queue = queue self.inputs = InputList(queue: queue) - self.clock = Clock(queue: queue) + self._clock = Clock(queue: queue) } } diff --git a/Sources/AsyncSequenceValidation/Clock.swift b/Sources/AsyncSequenceValidation/Clock.swift index 66f8a532..5eeb7360 100644 --- a/Sources/AsyncSequenceValidation/Clock.swift +++ b/Sources/AsyncSequenceValidation/Clock.swift @@ -11,7 +11,6 @@ import AsyncAlgorithms -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationDiagram { public struct Clock { let queue: WorkQueue @@ -22,8 +21,20 @@ extension AsyncSequenceValidationDiagram { } } -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) -extension AsyncSequenceValidationDiagram.Clock: Clock { + +public protocol TestClock: Sendable { + associatedtype Instant: TestInstant + + var now: Instant { get } + + func sleep(until deadline: Self.Instant, tolerance: Self.Instant.Duration?) async throws +} + +public protocol TestInstant: Equatable { + associatedtype Duration +} + +extension AsyncSequenceValidationDiagram.Clock { public struct Step: DurationProtocol, Hashable, CustomStringConvertible { internal var rawValue: Int @@ -66,7 +77,7 @@ extension AsyncSequenceValidationDiagram.Clock: Clock { } } - public struct Instant: InstantProtocol, CustomStringConvertible { + public struct Instant: CustomStringConvertible { public typealias Duration = Step let when: Step @@ -111,3 +122,13 @@ extension AsyncSequenceValidationDiagram.Clock: Clock { } } } + +extension AsyncSequenceValidationDiagram.Clock.Instant: TestInstant { } + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension AsyncSequenceValidationDiagram.Clock.Instant: InstantProtocol { } + +extension AsyncSequenceValidationDiagram.Clock: TestClock { } + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension AsyncSequenceValidationDiagram.Clock: Clock { } diff --git a/Sources/AsyncSequenceValidation/Event.swift b/Sources/AsyncSequenceValidation/Event.swift index 0ee11fe5..70101475 100644 --- a/Sources/AsyncSequenceValidation/Event.swift +++ b/Sources/AsyncSequenceValidation/Event.swift @@ -9,7 +9,6 @@ // //===----------------------------------------------------------------------===// -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationDiagram { struct Failure: Error, Equatable { } diff --git a/Sources/AsyncSequenceValidation/Expectation.swift b/Sources/AsyncSequenceValidation/Expectation.swift index 1cc1a439..63121d66 100644 --- a/Sources/AsyncSequenceValidation/Expectation.swift +++ b/Sources/AsyncSequenceValidation/Expectation.swift @@ -9,7 +9,6 @@ // //===----------------------------------------------------------------------===// -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationDiagram { public struct ExpectationResult: Sendable { public struct Event: Sendable { diff --git a/Sources/AsyncSequenceValidation/Input.swift b/Sources/AsyncSequenceValidation/Input.swift index 7cd31e0c..35ede268 100644 --- a/Sources/AsyncSequenceValidation/Input.swift +++ b/Sources/AsyncSequenceValidation/Input.swift @@ -9,7 +9,6 @@ // //===----------------------------------------------------------------------===// -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationDiagram { public struct Specification: Sendable { public let specification: String diff --git a/Sources/AsyncSequenceValidation/Job.swift b/Sources/AsyncSequenceValidation/Job.swift index 87ccd44e..44dedbc8 100644 --- a/Sources/AsyncSequenceValidation/Job.swift +++ b/Sources/AsyncSequenceValidation/Job.swift @@ -11,7 +11,6 @@ import _CAsyncSequenceValidationSupport -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) struct Job: Hashable, @unchecked Sendable { let job: JobRef diff --git a/Sources/AsyncSequenceValidation/TaskDriver.swift b/Sources/AsyncSequenceValidation/TaskDriver.swift index 28140ebb..9f45c1f6 100644 --- a/Sources/AsyncSequenceValidation/TaskDriver.swift +++ b/Sources/AsyncSequenceValidation/TaskDriver.swift @@ -20,7 +20,6 @@ import _CAsyncSequenceValidationSupport #endif #if canImport(Darwin) -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) func start_thread(_ raw: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? { Unmanaged.fromOpaque(raw).takeRetainedValue().run() return nil @@ -34,7 +33,6 @@ func start_thread(_ raw: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? { #error("TODO: Port TaskDriver threading to windows") #endif -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) final class TaskDriver { let work: (TaskDriver) -> Void let queue: WorkQueue diff --git a/Sources/AsyncSequenceValidation/Test.swift b/Sources/AsyncSequenceValidation/Test.swift index 981dd4d7..35177cf2 100644 --- a/Sources/AsyncSequenceValidation/Test.swift +++ b/Sources/AsyncSequenceValidation/Test.swift @@ -19,22 +19,20 @@ internal func _swiftJobRun( _ executor: UnownedSerialExecutor ) -> () -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) public protocol AsyncSequenceValidationTest: Sendable { var inputs: [AsyncSequenceValidationDiagram.Specification] { get } var output: AsyncSequenceValidationDiagram.Specification { get } - func test(with clock: C, activeTicks: [C.Instant], output: AsyncSequenceValidationDiagram.Specification, _ event: (String) -> Void) async throws + func test(with clock: C, activeTicks: [C.Instant], output: AsyncSequenceValidationDiagram.Specification, _ event: (String) -> Void) async throws } -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationDiagram { struct Test: AsyncSequenceValidationTest, @unchecked Sendable where Operation.Element == String { let inputs: [Specification] let sequence: Operation let output: Specification - func test(with clock: C, activeTicks: [C.Instant], output: Specification, _ event: (String) -> Void) async throws { + func test(with clock: C, activeTicks: [C.Instant], output: Specification, _ event: (String) -> Void) async throws { var iterator = sequence.makeAsyncIterator() do { for tick in activeTicks { @@ -265,7 +263,7 @@ extension AsyncSequenceValidationDiagram { @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test ) throws -> (ExpectationResult, [ExpectationFailure]) { let diagram = AsyncSequenceValidationDiagram() - let clock = diagram.clock + let clock = diagram._clock let test = build(diagram) for index in 0.. AsyncSequenceValidationDiagram.Token func description(for token: AsyncSequenceValidationDiagram.Token) -> String } -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationTheme where Self == AsyncSequenceValidationDiagram.ASCIITheme { public static var ascii: AsyncSequenceValidationDiagram.ASCIITheme { return AsyncSequenceValidationDiagram.ASCIITheme() } } -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) extension AsyncSequenceValidationDiagram { public enum Token: Sendable { case step diff --git a/Sources/AsyncSequenceValidation/WorkQueue.swift b/Sources/AsyncSequenceValidation/WorkQueue.swift index 769ea6f8..784e5e82 100644 --- a/Sources/AsyncSequenceValidation/WorkQueue.swift +++ b/Sources/AsyncSequenceValidation/WorkQueue.swift @@ -9,7 +9,6 @@ // //===----------------------------------------------------------------------===// -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) struct WorkQueue: Sendable { enum Item: CustomStringConvertible, Comparable { case blocked(Token, AsyncSequenceValidationDiagram.Clock.Instant, UnsafeContinuation) diff --git a/Tests/AsyncAlgorithmsTests/TestChunk.swift b/Tests/AsyncAlgorithmsTests/TestChunk.swift index ba340a80..4970cdc0 100644 --- a/Tests/AsyncAlgorithmsTests/TestChunk.swift +++ b/Tests/AsyncAlgorithmsTests/TestChunk.swift @@ -22,7 +22,6 @@ func concatCharacters(_ array: [String]) -> String { } final class TestChunk: XCTestCase { - func test_signal_equalChunks() { validate { "ABC- DEF- GHI- |" @@ -113,7 +112,8 @@ final class TestChunk: XCTestCase { } } - func test_time_equalChunks() { + func test_time_equalChunks() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "ABC- DEF- GHI- |" $0.inputs[0].chunked(by: .repeating(every: .steps(4), clock: $0.clock)).map(concatCharacters) @@ -121,7 +121,8 @@ final class TestChunk: XCTestCase { } } - func test_time_unequalChunks() { + func test_time_unequalChunks() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "AB------ A------- ABCDEFG- |" $0.inputs[0].chunked(by: .repeating(every: .steps(8), clock: $0.clock)).map(concatCharacters) @@ -129,7 +130,8 @@ final class TestChunk: XCTestCase { } } - func test_time_emptyChunks() { + func test_time_emptyChunks() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "-- 1- --|" $0.inputs[0].chunked(by: .repeating(every: .steps(2), clock: $0.clock)).map(concatCharacters) @@ -137,7 +139,8 @@ final class TestChunk: XCTestCase { } } - func test_time_error() { + func test_time_error() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "AB^" $0.inputs[0].chunked(by: .repeating(every: .steps(5), clock: $0.clock)).map(concatCharacters) @@ -145,7 +148,8 @@ final class TestChunk: XCTestCase { } } - func test_time_unsignaledTrailingChunk() { + func test_time_unsignaledTrailingChunk() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "111-111|" $0.inputs[0].chunked(by: .repeating(every: .steps(4), clock: $0.clock)).map(sumCharacters) @@ -153,7 +157,8 @@ final class TestChunk: XCTestCase { } } - func test_timeAndCount_timeAlwaysPrevails() { + func test_timeAndCount_timeAlwaysPrevails() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "AB------ A------- ABCDEFG- |" $0.inputs[0].chunks(ofCount: 42, or: .repeating(every: .steps(8), clock: $0.clock)).map(concatCharacters) @@ -161,7 +166,8 @@ final class TestChunk: XCTestCase { } } - func test_timeAndCount_countAlwaysPrevails() { + func test_timeAndCount_countAlwaysPrevails() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "AB --A-B -|" $0.inputs[0].chunks(ofCount: 2, or: .repeating(every: .steps(8), clock: $0.clock)).map(concatCharacters) @@ -169,7 +175,8 @@ final class TestChunk: XCTestCase { } } - func test_timeAndCount_countResetsAfterCount() { + func test_timeAndCount_countResetsAfterCount() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "ABCDE --- ABCDE |" $0.inputs[0].chunks(ofCount: 5, or: .repeating(every: .steps(8), clock: $0.clock)).map(concatCharacters) @@ -177,7 +184,8 @@ final class TestChunk: XCTestCase { } } - func test_timeAndCount_countResetsAfterSignal() { + func test_timeAndCount_countResetsAfterSignal() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "AB------ ABCDE |" $0.inputs[0].chunks(ofCount: 5, or: .repeating(every: .steps(8), clock: $0.clock)).map(concatCharacters) @@ -185,7 +193,8 @@ final class TestChunk: XCTestCase { } } - func test_timeAndCount_error() { + func test_timeAndCount_error() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "ABC^" $0.inputs[0].chunks(ofCount: 5, or: .repeating(every: .steps(8), clock: $0.clock)).map(concatCharacters) diff --git a/Tests/AsyncAlgorithmsTests/TestDebounce.swift b/Tests/AsyncAlgorithmsTests/TestDebounce.swift index 27643dfb..2005c134 100644 --- a/Tests/AsyncAlgorithmsTests/TestDebounce.swift +++ b/Tests/AsyncAlgorithmsTests/TestDebounce.swift @@ -13,7 +13,8 @@ import XCTest import AsyncAlgorithms final class TestDebounce: XCTestCase { - func test_delayingValues() { + func test_delayingValues() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcd----e---f-g----|" $0.inputs[0].debounce(for: .steps(3), clock: $0.clock) @@ -21,7 +22,8 @@ final class TestDebounce: XCTestCase { } } - func test_delayingValues_dangling_last() { + func test_delayingValues_dangling_last() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcd----e---f-g-|" $0.inputs[0].debounce(for: .steps(3), clock: $0.clock) @@ -30,7 +32,8 @@ final class TestDebounce: XCTestCase { } - func test_finishDoesntDebounce() { + func test_finishDoesntDebounce() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "a|" $0.inputs[0].debounce(for: .steps(3), clock: $0.clock) @@ -38,7 +41,8 @@ final class TestDebounce: XCTestCase { } } - func test_throwDoesntDebounce() { + func test_throwDoesntDebounce() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "a^" $0.inputs[0].debounce(for: .steps(3), clock: $0.clock) @@ -46,7 +50,8 @@ final class TestDebounce: XCTestCase { } } - func test_noValues() { + func test_noValues() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "----|" $0.inputs[0].debounce(for: .steps(3), clock: $0.clock) diff --git a/Tests/AsyncAlgorithmsTests/TestTaskSelect.swift b/Tests/AsyncAlgorithmsTests/TestTaskSelect.swift index d054257b..e70b3adf 100644 --- a/Tests/AsyncAlgorithmsTests/TestTaskSelect.swift +++ b/Tests/AsyncAlgorithmsTests/TestTaskSelect.swift @@ -18,7 +18,11 @@ final class TestTaskSelect: XCTestCase { let firstValue = await Task.select(Task { return 1 }, Task { - try! await Task.sleep(until: .now + .seconds(2), clock: .continuous) + if #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { + try! await Task.sleep(until: .now + .seconds(2), clock: .continuous) + } else { + try! await Task.sleep(nanoseconds: 2_000_000_000) + } return 2 }).value XCTAssertEqual(firstValue, 1) @@ -26,7 +30,11 @@ final class TestTaskSelect: XCTestCase { func test_second() async { let firstValue = await Task.select(Task { - try! await Task.sleep(until: .now + .seconds(2), clock: .continuous) + if #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { + try! await Task.sleep(until: .now + .seconds(2), clock: .continuous) + } else { + try! await Task.sleep(nanoseconds: 2_000_000_000) + } return 1 }, Task { return 2 @@ -37,7 +45,11 @@ final class TestTaskSelect: XCTestCase { func test_throwing() async { do { _ = try await Task.select(Task { () async throws -> Int in - try await Task.sleep(until: .now + .seconds(2), clock: .continuous) + if #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { + try await Task.sleep(until: .now + .seconds(2), clock: .continuous) + } else { + try await Task.sleep(nanoseconds: 2_000_000_000) + } return 1 }, Task { () async throws -> Int in throw NSError(domain: NSCocoaErrorDomain, code: -1, userInfo: nil) @@ -59,7 +71,11 @@ final class TestTaskSelect: XCTestCase { firstCancelled.fulfill() } operation: { () -> Int in firstReady.fulfill() - try? await Task.sleep(until: .now + .seconds(2), clock: .continuous) + if #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { + try? await Task.sleep(until: .now + .seconds(2), clock: .continuous) + } else { + try? await Task.sleep(nanoseconds: 2_000_000_000) + } return 1 } }, Task { @@ -67,7 +83,11 @@ final class TestTaskSelect: XCTestCase { secondCancelled.fulfill() } operation: { () -> Int in secondReady.fulfill() - try? await Task.sleep(until: .now + .seconds(2), clock: .continuous) + if #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { + try? await Task.sleep(until: .now + .seconds(2), clock: .continuous) + } else { + try? await Task.sleep(nanoseconds: 2_000_000_000) + } return 1 } }) diff --git a/Tests/AsyncAlgorithmsTests/TestThrottle.swift b/Tests/AsyncAlgorithmsTests/TestThrottle.swift index 972f04c1..72c90f65 100644 --- a/Tests/AsyncAlgorithmsTests/TestThrottle.swift +++ b/Tests/AsyncAlgorithmsTests/TestThrottle.swift @@ -13,7 +13,8 @@ import XCTest import AsyncAlgorithms final class TestThrottle: XCTestCase { - func test_rate_0() { + func test_rate_0() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(0), clock: $0.clock) @@ -21,7 +22,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_0_leading_edge() { + func test_rate_0_leading_edge() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(0), clock: $0.clock, latest: false) @@ -29,7 +31,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_1() { + func test_rate_1() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(1), clock: $0.clock) @@ -37,7 +40,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_1_leading_edge() { + func test_rate_1_leading_edge() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(1), clock: $0.clock, latest: false) @@ -45,7 +49,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_2() { + func test_rate_2() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(2), clock: $0.clock) @@ -53,7 +58,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_2_leading_edge() { + func test_rate_2_leading_edge() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(2), clock: $0.clock, latest: false) @@ -61,7 +67,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_3() { + func test_rate_3() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(3), clock: $0.clock) @@ -69,7 +76,8 @@ final class TestThrottle: XCTestCase { } } - func test_rate_3_leading_edge() { + func test_rate_3_leading_edge() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdefghijk|" $0.inputs[0].throttle(for: .steps(3), clock: $0.clock, latest: false) @@ -77,7 +85,8 @@ final class TestThrottle: XCTestCase { } } - func test_throwing() { + func test_throwing() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdef^hijk|" $0.inputs[0].throttle(for: .steps(2), clock: $0.clock) @@ -85,7 +94,8 @@ final class TestThrottle: XCTestCase { } } - func test_throwing_leading_edge() { + func test_throwing_leading_edge() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "abcdef^hijk|" $0.inputs[0].throttle(for: .steps(2), clock: $0.clock, latest: false) @@ -93,7 +103,8 @@ final class TestThrottle: XCTestCase { } } - func test_emission_2_rate_1() { + func test_emission_2_rate_1() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "-a-b-c-d-e-f-g-h-i-j-k-|" $0.inputs[0].throttle(for: .steps(1), clock: $0.clock) @@ -101,7 +112,8 @@ final class TestThrottle: XCTestCase { } } - func test_emission_2_rate_2() { + func test_emission_2_rate_2() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "-a-b-c-d-e-f-g-h-i-j-k-|" $0.inputs[0].throttle(for: .steps(2), clock: $0.clock) @@ -109,7 +121,8 @@ final class TestThrottle: XCTestCase { } } - func test_emission_3_rate_2() { + func test_emission_3_rate_2() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "--a--b--c--d--e--f--g|" $0.inputs[0].throttle(for: .steps(2), clock: $0.clock) @@ -117,7 +130,8 @@ final class TestThrottle: XCTestCase { } } - func test_emission_2_rate_3() { + func test_emission_2_rate_3() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "-a-b-c-d-e-f-g-h-i-j-k-|" $0.inputs[0].throttle(for: .steps(3), clock: $0.clock) diff --git a/Tests/AsyncAlgorithmsTests/TestTimer.swift b/Tests/AsyncAlgorithmsTests/TestTimer.swift index 823e7701..65db910e 100644 --- a/Tests/AsyncAlgorithmsTests/TestTimer.swift +++ b/Tests/AsyncAlgorithmsTests/TestTimer.swift @@ -14,28 +14,32 @@ import AsyncAlgorithms import AsyncSequenceValidation final class TestTimer: XCTestCase { - func test_tick1() { + func test_tick1() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { AsyncTimerSequence(interval: .steps(1), clock: $0.clock).map { _ in "x" } "xxxxxxx[;|]" } } - func test_tick2() { + func test_tick2() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { AsyncTimerSequence(interval: .steps(2), clock: $0.clock).map { _ in "x" } "-x-x-x-[;|]" } } - func test_tick3() { + func test_tick3() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { AsyncTimerSequence(interval: .steps(3), clock: $0.clock).map { _ in "x" } "--x--x-[;|]" } } - func test_tick2_event_skew3() { + func test_tick2_event_skew3() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { diagram in AsyncTimerSequence(interval: .steps(2), clock: diagram.clock).map { [diagram] (_) -> String in try? await diagram.clock.sleep(until: diagram.clock.now.advanced(by: .steps(3))) diff --git a/Tests/AsyncAlgorithmsTests/TestValidationTests.swift b/Tests/AsyncAlgorithmsTests/TestValidationTests.swift index f60259c1..c002d64a 100644 --- a/Tests/AsyncAlgorithmsTests/TestValidationTests.swift +++ b/Tests/AsyncAlgorithmsTests/TestValidationTests.swift @@ -292,7 +292,8 @@ final class TestValidationDiagram: XCTestCase { } } - func test_delayNext_into_emptyTick() { + func test_delayNext_into_emptyTick() throws { + guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") } validate { "xx|" LaggingAsyncSequence($0.inputs[0], delayBy: .steps(3), using: $0.clock) @@ -309,6 +310,7 @@ final class TestValidationDiagram: XCTestCase { } } +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) struct LaggingAsyncSequence : AsyncSequence { typealias Element = Base.Element