Skip to content

Commit bbb8188

Browse files
committed
test: add task queue tests
1 parent 84e4d29 commit bbb8188

File tree

1 file changed

+341
-0
lines changed

1 file changed

+341
-0
lines changed
Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
import XCTest
2+
@testable import AsyncObjects
3+
4+
class TaskQueueTests: XCTestCase {
5+
6+
func testSignalingQueueDoesNothing() async {
7+
let queue = TaskQueue()
8+
await queue.signal()
9+
let barriered = await queue.barriered
10+
XCTAssertFalse(barriered)
11+
}
12+
13+
func testSignalingLockedQueueDoesNothing() async throws {
14+
let queue = TaskQueue()
15+
Task.detached {
16+
try await queue.exec(barrier: true) {
17+
try await Task.sleep(nanoseconds: UInt64(5E9))
18+
}
19+
}
20+
try await Task.sleep(nanoseconds: UInt64(1E9))
21+
await queue.signal()
22+
let barriered = await queue.barriered
23+
XCTAssertTrue(barriered)
24+
}
25+
26+
func testWaitOnQueue() async throws {
27+
let queue = TaskQueue()
28+
try await checkExecInterval(durationInSeconds: 5) {
29+
try await withThrowingTaskGroup(of: Void.self) { group in
30+
group.addTask {
31+
try await queue.exec(barrier: true) {
32+
try await Task.sleep(nanoseconds: UInt64(5E9))
33+
}
34+
}
35+
// To make sure barrier task started before wait
36+
try await Task.sleep(nanoseconds: UInt64(1E7))
37+
group.addTask { await queue.wait() }
38+
try await group.waitForAll()
39+
}
40+
}
41+
}
42+
43+
func testWaitTimeoutOnQueue() async throws {
44+
let queue = TaskQueue()
45+
try await checkExecInterval(durationInSeconds: 3) {
46+
try await withThrowingTaskGroup(of: Void.self) { group in
47+
group.addTask {
48+
try await queue.exec(barrier: true) {
49+
try await Task.sleep(nanoseconds: UInt64(5E9))
50+
}
51+
}
52+
// To make sure barrier task started before wait
53+
try await Task.sleep(nanoseconds: UInt64(1E7))
54+
group.addTask { await queue.wait(forNanoseconds: UInt64(3E9)) }
55+
for try await _ in group.prefix(1) {
56+
group.cancelAll()
57+
}
58+
}
59+
}
60+
}
61+
62+
func testExecutionOfTwoBarriers() async throws {
63+
let queue = TaskQueue()
64+
try await checkExecInterval(durationInSeconds: 10) {
65+
try await withThrowingTaskGroup(of: Void.self) { group in
66+
group.addTask {
67+
try await queue.exec(barrier: true) {
68+
try await Task.sleep(nanoseconds: UInt64(5E9))
69+
}
70+
}
71+
group.addTask {
72+
try await queue.exec(barrier: true) {
73+
try await Task.sleep(nanoseconds: UInt64(5E9))
74+
}
75+
}
76+
try await group.waitForAll()
77+
}
78+
}
79+
}
80+
81+
func testExecutionOfTaskBeforeBarrier() async throws {
82+
let queue = TaskQueue()
83+
try await checkExecInterval(durationInSeconds: 5) {
84+
try await withThrowingTaskGroup(of: Void.self) { group in
85+
group.addTask {
86+
try await queue.exec {
87+
try await Task.sleep(nanoseconds: UInt64(5E9))
88+
}
89+
}
90+
// To make sure barrier task added after concurrent task
91+
try await Task.sleep(nanoseconds: UInt64(1E7))
92+
group.addTask {
93+
try await queue.exec(barrier: true) {
94+
try await Task.sleep(nanoseconds: UInt64(5E9))
95+
}
96+
}
97+
try await group.waitForAll()
98+
}
99+
}
100+
}
101+
102+
func testExecutionOfTaskAfterBarrier() async throws {
103+
let queue = TaskQueue()
104+
try await checkExecInterval(durationInSeconds: 10) {
105+
try await withThrowingTaskGroup(of: Void.self) { group in
106+
group.addTask {
107+
try await queue.exec(barrier: true) {
108+
try await Task.sleep(nanoseconds: UInt64(5E9))
109+
}
110+
}
111+
// To make sure barrier task started before adding new task
112+
try await Task.sleep(nanoseconds: UInt64(1E7))
113+
group.addTask {
114+
try await queue.exec {
115+
try await Task.sleep(nanoseconds: UInt64(5E9))
116+
}
117+
}
118+
try await group.waitForAll()
119+
}
120+
}
121+
}
122+
123+
func testCancellationOfBarrierTaskWithoutBlockingQueue() async throws {
124+
let queue = TaskQueue()
125+
try await checkExecInterval(durationInSeconds: 7) {
126+
try await withThrowingTaskGroup(of: Void.self) { group in
127+
group.addTask {
128+
try await Task.sleep(nanoseconds: UInt64(2E9))
129+
// Throws error for waiting method
130+
throw CancellationError()
131+
}
132+
// To make sure cancellation task started before adding barrier task
133+
try await Task.sleep(nanoseconds: UInt64(1E7))
134+
group.addTask {
135+
try await queue.exec(barrier: true) {
136+
try await Task.sleep(nanoseconds: UInt64(5E9))
137+
}
138+
}
139+
do {
140+
try await group.waitForAll()
141+
} catch {
142+
// Cancels barrier task
143+
group.cancelAll()
144+
}
145+
try await queue.exec {
146+
try await Task.sleep(nanoseconds: UInt64(5E9))
147+
}
148+
}
149+
}
150+
}
151+
152+
func testCancellationOfMultipleBarrierTasksWithoutBlockingQueue()
153+
async throws
154+
{
155+
let queue = TaskQueue()
156+
try await checkExecInterval(durationInSeconds: 8) {
157+
try await withThrowingTaskGroup(of: Void.self) { group in
158+
group.addTask {
159+
try await Task.sleep(nanoseconds: UInt64(3E9))
160+
// Throws error for waiting method
161+
throw CancellationError()
162+
}
163+
// To make sure cancellation task started before adding barrier task
164+
try await Task.sleep(nanoseconds: UInt64(1E7))
165+
group.addTask {
166+
try await queue.exec(barrier: true) {
167+
try await Task.sleep(nanoseconds: UInt64(5E9))
168+
}
169+
}
170+
group.addTask {
171+
try await queue.exec(barrier: true) {
172+
try await Task.sleep(nanoseconds: UInt64(5E9))
173+
}
174+
}
175+
do {
176+
try await group.waitForAll()
177+
} catch {
178+
// Cancels barrier tasks
179+
group.cancelAll()
180+
}
181+
try await queue.exec {
182+
try await Task.sleep(nanoseconds: UInt64(5E9))
183+
}
184+
}
185+
}
186+
}
187+
188+
func
189+
testCancellationOfMultipleBarrierTasksAndOneConcurrentTaskWithoutBlockingQueue()
190+
async throws
191+
{
192+
let queue = TaskQueue()
193+
try await checkExecInterval(durationInSeconds: 8) {
194+
try await withThrowingTaskGroup(of: Void.self) { group in
195+
group.addTask {
196+
try await Task.sleep(nanoseconds: UInt64(3E9))
197+
// Throws error for waiting method
198+
throw CancellationError()
199+
}
200+
// To make sure cancellation task started before adding barrier task
201+
try await Task.sleep(nanoseconds: UInt64(1E7))
202+
group.addTask {
203+
try await queue.exec(barrier: true) {
204+
try await Task.sleep(nanoseconds: UInt64(5E9))
205+
}
206+
}
207+
group.addTask {
208+
try await queue.exec(barrier: true) {
209+
try await Task.sleep(nanoseconds: UInt64(5E9))
210+
}
211+
}
212+
group.addTask {
213+
try await queue.exec {
214+
try await Task.sleep(nanoseconds: UInt64(5E9))
215+
}
216+
}
217+
do {
218+
try await group.waitForAll()
219+
} catch {
220+
// Cancels barrier tasks
221+
group.cancelAll()
222+
}
223+
try await queue.exec {
224+
try await Task.sleep(nanoseconds: UInt64(5E9))
225+
}
226+
}
227+
}
228+
}
229+
}
230+
231+
class SafeContinuationTests: XCTestCase {
232+
233+
func testSafeContinuationMultipleResumeReturningValues() async {
234+
let value = await withUnsafeContinuation {
235+
(continuation: UnsafeContinuation<Int, Never>) in
236+
let safeContinuation = SafeContinuation(continuation: continuation)
237+
safeContinuation.resume(returning: 5)
238+
safeContinuation.resume(returning: 10)
239+
}
240+
XCTAssertEqual(value, 5)
241+
}
242+
243+
func testSafeContinuationMultipleResumeReturningValueThrowingError()
244+
async throws
245+
{
246+
let value = try await withUnsafeThrowingContinuation {
247+
(continuation: UnsafeContinuation<Int, Error>) in
248+
let safeContinuation = SafeContinuation(continuation: continuation)
249+
safeContinuation.resume(returning: 5)
250+
safeContinuation.resume(throwing: CancellationError())
251+
}
252+
XCTAssertEqual(value, 5)
253+
}
254+
255+
func testSafeContinuationMultipleResumeThrowingErrorReturningValue()
256+
async throws
257+
{
258+
do {
259+
let _ = try await withUnsafeThrowingContinuation {
260+
(continuation: UnsafeContinuation<Int, Error>) in
261+
let safeContinuation = SafeContinuation(
262+
continuation: continuation)
263+
safeContinuation.resume(throwing: CancellationError())
264+
safeContinuation.resume(returning: 5)
265+
}
266+
XCTFail()
267+
} catch {
268+
XCTAssertTrue(type(of: error) == CancellationError.self)
269+
}
270+
}
271+
272+
func testSafeContinuationMultipleResumeThrowingErrors() async throws {
273+
do {
274+
let _ = try await withUnsafeThrowingContinuation {
275+
(continuation: UnsafeContinuation<Int, Error>) in
276+
let safeContinuation = SafeContinuation(
277+
continuation: continuation)
278+
safeContinuation.resume(throwing: CancellationError())
279+
safeContinuation.resume(throwing: URLError(.cancelled))
280+
}
281+
XCTFail()
282+
} catch {
283+
XCTAssertTrue(type(of: error) == CancellationError.self)
284+
}
285+
}
286+
287+
func testSafeContinuationMultipleResultsResumeReturningValues() async {
288+
let value = await withUnsafeContinuation {
289+
(continuation: UnsafeContinuation<Int, Never>) in
290+
let safeContinuation = SafeContinuation(continuation: continuation)
291+
safeContinuation.resume(with: .success(5))
292+
safeContinuation.resume(with: .success(10))
293+
}
294+
XCTAssertEqual(value, 5)
295+
}
296+
297+
func testSafeContinuationMultipleResultsResumeReturningValueThrowingError()
298+
async throws
299+
{
300+
let value = try await withUnsafeThrowingContinuation {
301+
(continuation: UnsafeContinuation<Int, Error>) in
302+
let safeContinuation = SafeContinuation(continuation: continuation)
303+
safeContinuation.resume(with: .success(5))
304+
safeContinuation.resume(with: .failure(CancellationError()))
305+
}
306+
XCTAssertEqual(value, 5)
307+
}
308+
309+
func testSafeContinuationMultipleResultsResumeThrowingErrorReturningValue()
310+
async throws
311+
{
312+
do {
313+
let _ = try await withUnsafeThrowingContinuation {
314+
(continuation: UnsafeContinuation<Int, Error>) in
315+
let safeContinuation = SafeContinuation(
316+
continuation: continuation)
317+
safeContinuation.resume(with: .failure(CancellationError()))
318+
safeContinuation.resume(with: .success(5))
319+
}
320+
XCTFail()
321+
} catch {
322+
XCTAssertTrue(type(of: error) == CancellationError.self)
323+
}
324+
}
325+
326+
func testSafeContinuationMultipleResultsResumeThrowingErrors() async throws
327+
{
328+
do {
329+
let _ = try await withUnsafeThrowingContinuation {
330+
(continuation: UnsafeContinuation<Int, Error>) in
331+
let safeContinuation = SafeContinuation(
332+
continuation: continuation)
333+
safeContinuation.resume(with: .failure(CancellationError()))
334+
safeContinuation.resume(with: .failure(URLError(.cancelled)))
335+
}
336+
XCTFail()
337+
} catch {
338+
XCTAssertTrue(type(of: error) == CancellationError.self)
339+
}
340+
}
341+
}

0 commit comments

Comments
 (0)