rastrillo / native Public

Clone
git clone https://amadan.net/rastrillo/native

Plain git — no account needed to clone.

Download

Download this file

1import XCTest
2@testable import RastrilloNative
3
4@MainActor
5final class CoalescedRunnerTests: XCTestCase {
6 func testSequentialCallsEachRefresh() async {
7 let runner = CoalescedRunner()
8 var passes = 0
9 for _ in 0..<3 { await runner.run { passes += 1 } }
10 XCTAssertEqual(passes, 3)
11 }
12
13 func testBurstWaitsForTrailingPassAndReusesOriginalOperation() async {
14 let runner = CoalescedRunner()
15 var passes = 0
16 var release: CheckedContinuation<Void, Never>?
17 var trailingRelease: CheckedContinuation<Void, Never>?
18 let first = Task { @MainActor in
19 await runner.run {
20 passes += 1
21 if passes == 1 {
22 await withCheckedContinuation { release = $0 }
23 } else {
24 await withCheckedContinuation { trailingRelease = $0 }
25 }
26 }
27 }
28 while release == nil { await Task.yield() }
29 var entered = 0
30 var resumed = 0
31 let waiters = (0..<5).map { _ in
32 Task { @MainActor in
33 entered += 1
34 await runner.run { XCTFail("A burst must reuse the active operation") }
35 resumed += 1
36 }
37 }
38 // Each task runs on this actor until run suspends, so observing all
39 // entries proves they have queued without timing-based sleeps.
40 while entered != 5 { await Task.yield() }
41 XCTAssertEqual(passes, 1)
42 XCTAssertEqual(resumed, 0)
43 release?.resume()
44 while trailingRelease == nil { await Task.yield() }
45 XCTAssertEqual(resumed, 0, "Callers must also wait for the trailing pass")
46 trailingRelease?.resume()
47 await first.value
48 for waiter in waiters { await waiter.value }
49 XCTAssertEqual(passes, 2)
50 XCTAssertEqual(resumed, 5)
51 await runner.run { passes += 1 }
52 XCTAssertEqual(passes, 3, "Completed work must not swallow the next refresh")
53 }
54
55 func testCancelledWaiterDoesNotCancelSharedRefresh() async {
56 let runner = CoalescedRunner()
57 var release: CheckedContinuation<Void, Never>?
58 var passes = 0
59 let first = Task { @MainActor in
60 await runner.run {
61 XCTAssertFalse(Task.isCancelled)
62 passes += 1
63 if passes == 1 { await withCheckedContinuation { release = $0 } }
64 }
65 }
66 while release == nil { await Task.yield() }
67 var entered = false
68 let waiter = Task { @MainActor in
69 entered = true
70 await runner.run { XCTFail("Must not replace the active operation") }
71 }
72 while !entered { await Task.yield() }
73 waiter.cancel()
74 release?.resume()
75 await first.value
76 await waiter.value
77 XCTAssertEqual(passes, 2)
78 }
79}
80