Skip to content

Commit fd075bd

Browse files
committed
test: add async semaphore tests
1 parent fbd6b65 commit fd075bd

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import XCTest
2+
@testable import AsyncObject
3+
4+
actor TaskTimeoutStore {
5+
var successes: UInt = 0
6+
var failures: UInt = 0
7+
8+
func addSuccess() {
9+
successes += 1
10+
}
11+
12+
func addFailure() {
13+
failures += 1
14+
}
15+
}
16+
17+
class AsyncSemaphoreTests: XCTestCase {
18+
19+
func checkSemaphoreWait(
20+
for semaphore: AsyncSemaphore,
21+
taskCount count: Int = 1,
22+
withDelay delay: UInt64 = UInt64(5E9),
23+
durationInSeconds seconds: Int = 0
24+
) async throws {
25+
try await checkExecInterval(for: {
26+
try await withThrowingTaskGroup(of: Void.self) { group in
27+
for _ in 0..<count {
28+
group.addTask {
29+
await semaphore.wait()
30+
try await Task.sleep(nanoseconds: delay)
31+
await semaphore.signal()
32+
}
33+
}
34+
try await group.waitForAll()
35+
}
36+
}, durationInSeconds: seconds)
37+
}
38+
39+
func checkSemaphoreWaitWithTimeOut(
40+
value: UInt = 3,
41+
taskCount count: Int = 1,
42+
withDelay delay: UInt64 = UInt64(5E9),
43+
timeout: UInt64 = UInt64(3E9),
44+
durationInSeconds seconds: Int = 0
45+
) async throws {
46+
let semaphore = AsyncSemaphore(value: value)
47+
let store = TaskTimeoutStore()
48+
try await checkExecInterval(for: {
49+
try await withThrowingTaskGroup(of: Void.self) { group in
50+
for _ in 0..<count {
51+
group.addTask {
52+
let result = await semaphore.wait(forNanoseconds: timeout)
53+
result == .success ? await store.addSuccess() : await store.addFailure()
54+
try await Task.sleep(nanoseconds: delay)
55+
await semaphore.signal()
56+
}
57+
}
58+
try await group.waitForAll()
59+
}
60+
}, durationInSeconds: seconds)
61+
let (successes, failures) = (await store.successes, await store.failures)
62+
XCTAssertEqual(successes, value)
63+
XCTAssertEqual(failures, UInt(count) - value)
64+
}
65+
66+
func testSemaphoreWaitWithTasksLessThanCount() async throws {
67+
let semaphore = AsyncSemaphore(value: 3)
68+
try await checkSemaphoreWait(
69+
for: semaphore,
70+
taskCount: 2,
71+
durationInSeconds: 5
72+
)
73+
}
74+
75+
func testSemaphoreWaitWithTasksEqualToCount() async throws {
76+
let semaphore = AsyncSemaphore(value: 3)
77+
try await checkSemaphoreWait(
78+
for: semaphore,
79+
taskCount: 3,
80+
durationInSeconds: 5
81+
)
82+
}
83+
84+
func testSemaphoreWaitWithTasksGreaterThanCount() async throws {
85+
let semaphore = AsyncSemaphore(value: 3)
86+
try await checkSemaphoreWait(
87+
for: semaphore,
88+
taskCount: 5,
89+
durationInSeconds: 10
90+
)
91+
}
92+
93+
func testSignaledSemaphoreWaitWithTasksGreaterThanCount() async throws {
94+
let semaphore = AsyncSemaphore(value: 3)
95+
await semaphore.signal()
96+
try await checkSemaphoreWait(
97+
for: semaphore,
98+
taskCount: 4,
99+
durationInSeconds: 10
100+
)
101+
}
102+
103+
func testSemaphoreWaitTimeoutWithTasksLessThanCount() async throws {
104+
try await checkSemaphoreWaitWithTimeOut(
105+
taskCount: 3,
106+
timeout: UInt64(3E9),
107+
durationInSeconds: 5
108+
)
109+
}
110+
111+
func testSemaphoreWaitTimeoutWithTasksGreaterThanCount() async throws {
112+
try await checkSemaphoreWaitWithTimeOut(
113+
taskCount: 5,
114+
timeout: UInt64(3E9),
115+
durationInSeconds: 8
116+
)
117+
}
118+
119+
}

0 commit comments

Comments
 (0)