-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathAsyncEventTests.swift
152 lines (136 loc) · 4.44 KB
/
AsyncEventTests.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import XCTest
@testable import AsyncObjects
@MainActor
class AsyncEventTests: XCTestCase {
func testSignal() async throws {
let event = AsyncEvent(signaledInitially: false)
event.signal()
try await event.wait(forSeconds: 3)
}
func testSignalAfterSomeWait() async throws {
let event = AsyncEvent(signaledInitially: false)
Task {
try await Task.sleep(seconds: 1)
event.signal()
}
try await event.wait(forSeconds: 10)
}
func testResetSignal() async throws {
let event = AsyncEvent()
event.reset()
event.signal()
try await event.wait(forSeconds: 3)
}
func testSignalled() async throws {
let event = AsyncEvent()
try await event.wait(forSeconds: 3)
}
func testDeinit() async throws {
let event = AsyncEvent(signaledInitially: false)
let task = Task.detached { event.signal() }
try await event.wait(forSeconds: 3)
await task.value
self.addTeardownBlock { [weak event] in
try await waitUntil(event, timeout: 10) { $0.assertReleased() }
}
}
func testConcurrentAccess() async throws {
try await withThrowingTaskGroup(of: Void.self) { group in
for _ in 0..<10 {
group.addTask {
let event = AsyncEvent(signaledInitially: false)
try await withThrowingTaskGroup(of: Void.self) { g in
g.addTask { try await event.wait(forSeconds: 3) }
g.addTask { event.signal() }
try await g.waitForAll()
}
}
try await group.waitForAll()
}
}
}
}
@MainActor
class AsyncEventTimeoutTests: XCTestCase {
func testSignal() async throws {
let event = AsyncEvent(signaledInitially: false)
do {
try await event.wait(forSeconds: 3)
XCTFail("Unexpected task progression")
} catch is DurationTimeoutError {}
}
func testResetSignal() async throws {
let event = AsyncEvent()
event.reset()
do {
let start = DispatchTime.now()
while DispatchTime.now() < start + .seconds(5) {
try await event.wait(forSeconds: 3)
}
XCTFail("Unexpected task progression")
} catch is DurationTimeoutError {}
}
}
#if swift(>=5.7)
@MainActor
class AsyncEventClockTimeoutTests: XCTestCase {
func testSignal() async throws {
guard
#available(macOS 13, iOS 16, macCatalyst 16, tvOS 16, watchOS 9, *)
else {
throw XCTSkip("Clock API not available")
}
let clock: ContinuousClock = .continuous
let event = AsyncEvent(signaledInitially: false)
do {
try await event.wait(forSeconds: 3, clock: clock)
XCTFail("Unexpected task progression")
} catch is TimeoutError<ContinuousClock> {}
}
func testResetSignal() async throws {
guard
#available(macOS 13, iOS 16, macCatalyst 16, tvOS 16, watchOS 9, *)
else {
throw XCTSkip("Clock API not available")
}
let clock: ContinuousClock = .continuous
let event = AsyncEvent()
event.reset()
do {
let start = clock.now
while clock.now < start + .seconds(5) {
try await event.wait(forSeconds: 3, clock: clock)
}
XCTFail("Unexpected task progression")
} catch is TimeoutError<ContinuousClock> {}
}
}
#endif
@MainActor
class AsyncEventCancellationTests: XCTestCase {
func testCancellation() async throws {
let event = AsyncEvent(signaledInitially: false)
let task = Task.detached { try await event.wait() }
task.cancel()
do {
try await task.value
XCTFail("Unexpected task progression")
} catch {}
}
func testAlreadyCancelledTask() async throws {
let event = AsyncEvent(signaledInitially: false)
let task = Task.detached {
do {
try await event.wait()
XCTFail("Unexpected task progression")
} catch {}
XCTAssertTrue(Task.isCancelled)
try await event.wait()
}
task.cancel()
do {
try await task.value
XCTFail("Unexpected task progression")
} catch {}
}
}