Skip to content

Commit 7cf84a1

Browse files
committed
Simplify tests by returning Task.isCancelled directly
Remove Expectation usage in favor of checking task.value directly. This eliminates timeouts and makes tests cleaner.
1 parent 4c5fc52 commit 7cf84a1

File tree

1 file changed

+54
-79
lines changed

1 file changed

+54
-79
lines changed

Tests/AsyncQueueTests/CancellableQueueTests.swift

Lines changed: 54 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23-
import Foundation
2423
import Testing
2524

2625
@testable import AsyncQueue
@@ -31,36 +30,33 @@ struct CancellableQueueTests {
3130
@Test
3231
func cancelTasks_fifoQueue_doesNotCancelCompletedTask() async throws {
3332
let systemUnderTest = CancellableQueue(underlyingQueue: FIFOQueue())
34-
let expectation = Expectation()
3533

36-
// Create a task that completes immediately
34+
// Create a task that completes immediately and returns its cancellation status
3735
let task = Task(on: systemUnderTest) {
38-
expectation.fulfill()
3936
try doWork()
37+
return Task.isCancelled
4038
}
4139

4240
// Wait for the task to complete
43-
try await task.value
41+
let wasCancelled = try await task.value
4442

4543
// Now cancel tasks - should have no effect since task already completed
4644
systemUnderTest.cancelTasks()
4745

48-
await expectation.fulfillment(withinSeconds: 30)
46+
#expect(!wasCancelled)
4947
}
5048

5149
@Test
5250
func cancelTasks_fifoQueue_cancelsCurrentlyExecutingTask() async {
5351
let systemUnderTest = CancellableQueue(underlyingQueue: FIFOQueue())
5452
let taskStarted = Semaphore()
5553
let proceedAfterCancel = Semaphore()
56-
let expectation = Expectation()
5754

5855
// Create a task that signals when it starts, then waits
59-
Task(on: systemUnderTest) {
56+
let task = Task(on: systemUnderTest) {
6057
await taskStarted.signal()
6158
await proceedAfterCancel.wait()
62-
#expect(Task.isCancelled)
63-
expectation.fulfill()
59+
return Task.isCancelled
6460
}
6561

6662
// Wait for the task to start executing
@@ -72,7 +68,7 @@ struct CancellableQueueTests {
7268
// Signal the semaphore to let the task continue
7369
await proceedAfterCancel.signal()
7470

75-
await expectation.fulfillment(withinSeconds: 30)
71+
#expect(await task.value)
7672
}
7773

7874
@Test
@@ -81,25 +77,21 @@ struct CancellableQueueTests {
8177
let taskStarted = Semaphore()
8278
let proceedAfterCancel = Semaphore()
8379
let counter = Counter()
84-
let expectation = Expectation(expectedCount: 3)
8580

8681
// Create a task that signals when it starts, then waits
87-
Task(on: systemUnderTest, isolatedTo: counter) { _ in
82+
let task1 = Task(on: systemUnderTest, isolatedTo: counter) { _ in
8883
await taskStarted.signal()
8984
await proceedAfterCancel.wait()
90-
#expect(Task.isCancelled)
91-
expectation.fulfill()
85+
return Task.isCancelled
9286
}
9387

9488
// Create pending tasks that won't start until the first task completes
95-
Task(on: systemUnderTest, isolatedTo: counter) { _ in
96-
#expect(Task.isCancelled)
97-
expectation.fulfill()
89+
let task2 = Task(on: systemUnderTest, isolatedTo: counter) { _ in
90+
Task.isCancelled
9891
}
9992

100-
Task(on: systemUnderTest, isolatedTo: counter) { _ in
101-
#expect(Task.isCancelled)
102-
expectation.fulfill()
93+
let task3 = Task(on: systemUnderTest, isolatedTo: counter) { _ in
94+
Task.isCancelled
10395
}
10496

10597
// Wait for the first task to start executing
@@ -111,27 +103,26 @@ struct CancellableQueueTests {
111103
// Signal the semaphore to let tasks continue
112104
await proceedAfterCancel.signal()
113105

114-
await expectation.fulfillment(withinSeconds: 30)
106+
#expect(await task1.value)
107+
#expect(await task2.value)
108+
#expect(await task3.value)
115109
}
116110

117111
@Test
118112
func cancelTasks_fifoQueue_doesNotCancelFutureTasks() async throws {
119113
let systemUnderTest = CancellableQueue(underlyingQueue: FIFOQueue())
120114
let counter = Counter()
121-
let expectation = Expectation()
122115

123116
// Cancel tasks before creating any
124117
systemUnderTest.cancelTasks()
125118

126119
// Create a task after cancellation - it should NOT be cancelled
127120
let task = Task(on: systemUnderTest, isolatedTo: counter) { _ in
128-
#expect(!Task.isCancelled)
129-
expectation.fulfill()
130121
try doWork()
122+
return Task.isCancelled
131123
}
132124

133-
try await task.value
134-
await expectation.fulfillment(withinSeconds: 30)
125+
#expect(try await !task.value)
135126
}
136127

137128
// MARK: ActorQueue Tests
@@ -142,21 +133,20 @@ struct CancellableQueueTests {
142133
let counter = Counter()
143134
actorQueue.adoptExecutionContext(of: counter)
144135
let systemUnderTest = CancellableQueue(underlyingQueue: actorQueue)
145-
let expectation = Expectation()
146136

147-
// Create a task that completes immediately
137+
// Create a task that completes immediately and returns its cancellation status
148138
let task = Task(on: systemUnderTest) { _ in
149-
expectation.fulfill()
150139
try doWork()
140+
return Task.isCancelled
151141
}
152142

153143
// Wait for the task to complete
154-
try await task.value
144+
let wasCancelled = try await task.value
155145

156146
// Now cancel tasks - should have no effect since task already completed
157147
systemUnderTest.cancelTasks()
158148

159-
await expectation.fulfillment(withinSeconds: 30)
149+
#expect(!wasCancelled)
160150
}
161151

162152
@Test
@@ -167,14 +157,12 @@ struct CancellableQueueTests {
167157
let systemUnderTest = CancellableQueue(underlyingQueue: actorQueue)
168158
let taskStarted = Semaphore()
169159
let proceedAfterCancel = Semaphore()
170-
let expectation = Expectation()
171160

172161
// Create a task that signals when it starts, then waits
173-
Task(on: systemUnderTest) { _ in
162+
let task = Task(on: systemUnderTest) { _ in
174163
await taskStarted.signal()
175164
await proceedAfterCancel.wait()
176-
#expect(Task.isCancelled)
177-
expectation.fulfill()
165+
return Task.isCancelled
178166
}
179167

180168
// Wait for the task to start executing
@@ -186,7 +174,7 @@ struct CancellableQueueTests {
186174
// Signal the semaphore to let the task continue
187175
await proceedAfterCancel.signal()
188176

189-
await expectation.fulfillment(withinSeconds: 30)
177+
#expect(await task.value)
190178
}
191179

192180
@Test
@@ -197,25 +185,21 @@ struct CancellableQueueTests {
197185
let systemUnderTest = CancellableQueue(underlyingQueue: actorQueue)
198186
let taskStarted = Semaphore()
199187
let proceedAfterCancel = Semaphore()
200-
let expectation = Expectation(expectedCount: 3)
201188

202189
// Create a task that signals when it starts, then waits
203-
Task(on: systemUnderTest) { _ in
190+
let task1 = Task(on: systemUnderTest) { _ in
204191
await taskStarted.signal()
205192
await proceedAfterCancel.wait()
206-
#expect(Task.isCancelled)
207-
expectation.fulfill()
193+
return Task.isCancelled
208194
}
209195

210196
// Create pending tasks that won't start until the first task suspends
211-
Task(on: systemUnderTest) { _ in
212-
#expect(Task.isCancelled)
213-
expectation.fulfill()
197+
let task2 = Task(on: systemUnderTest) { _ in
198+
Task.isCancelled
214199
}
215200

216-
Task(on: systemUnderTest) { _ in
217-
#expect(Task.isCancelled)
218-
expectation.fulfill()
201+
let task3 = Task(on: systemUnderTest) { _ in
202+
Task.isCancelled
219203
}
220204

221205
// Wait for the first task to start executing
@@ -227,7 +211,9 @@ struct CancellableQueueTests {
227211
// Signal the semaphore to let tasks continue
228212
await proceedAfterCancel.signal()
229213

230-
await expectation.fulfillment(withinSeconds: 30)
214+
#expect(await task1.value)
215+
#expect(await task2.value)
216+
#expect(await task3.value)
231217
}
232218

233219
@Test
@@ -236,57 +222,51 @@ struct CancellableQueueTests {
236222
let counter = Counter()
237223
actorQueue.adoptExecutionContext(of: counter)
238224
let systemUnderTest = CancellableQueue(underlyingQueue: actorQueue)
239-
let expectation = Expectation()
240225

241226
// Cancel tasks before creating any
242227
systemUnderTest.cancelTasks()
243228

244229
// Create a task after cancellation - it should NOT be cancelled
245230
let task = Task(on: systemUnderTest) { _ in
246-
#expect(!Task.isCancelled)
247-
expectation.fulfill()
248231
try doWork()
232+
return Task.isCancelled
249233
}
250234

251-
try await task.value
252-
await expectation.fulfillment(withinSeconds: 30)
235+
#expect(try await !task.value)
253236
}
254237

255238
// MARK: MainActor Queue Tests
256239

257240
@Test
258241
func cancelTasks_mainActorQueue_doesNotCancelCompletedTask() async throws {
259242
let systemUnderTest = CancellableQueue(underlyingQueue: MainActor.queue)
260-
let expectation = Expectation()
261243

262-
// Create a task that completes immediately
244+
// Create a task that completes immediately and returns its cancellation status
263245
let task = Task(on: systemUnderTest) {
264-
expectation.fulfill()
265246
try doWork()
247+
return Task.isCancelled
266248
}
267249

268250
// Wait for the task to complete
269-
try await task.value
251+
let wasCancelled = try await task.value
270252

271253
// Now cancel tasks - should have no effect since task already completed
272254
systemUnderTest.cancelTasks()
273255

274-
await expectation.fulfillment(withinSeconds: 30)
256+
#expect(!wasCancelled)
275257
}
276258

277259
@Test
278260
func cancelTasks_mainActorQueue_cancelsCurrentlyExecutingTask() async {
279261
let systemUnderTest = CancellableQueue(underlyingQueue: MainActor.queue)
280262
let taskStarted = Semaphore()
281263
let proceedAfterCancel = Semaphore()
282-
let expectation = Expectation()
283264

284265
// Create a task that signals when it starts, then waits
285-
Task(on: systemUnderTest) {
266+
let task = Task(on: systemUnderTest) {
286267
await taskStarted.signal()
287268
await proceedAfterCancel.wait()
288-
#expect(Task.isCancelled)
289-
expectation.fulfill()
269+
return Task.isCancelled
290270
}
291271

292272
// Wait for the task to start executing
@@ -298,33 +278,29 @@ struct CancellableQueueTests {
298278
// Signal the semaphore to let the task continue
299279
await proceedAfterCancel.signal()
300280

301-
await expectation.fulfillment(withinSeconds: 30)
281+
#expect(await task.value)
302282
}
303283

304284
@Test
305285
func cancelTasks_mainActorQueue_cancelsCurrentlyExecutingAndPendingTasks() async {
306286
let systemUnderTest = CancellableQueue(underlyingQueue: MainActor.queue)
307287
let taskStarted = Semaphore()
308288
let proceedAfterCancel = Semaphore()
309-
let expectation = Expectation(expectedCount: 3)
310289

311290
// Create a task that signals when it starts, then waits
312-
Task(on: systemUnderTest) {
291+
let task1 = Task(on: systemUnderTest) {
313292
await taskStarted.signal()
314293
await proceedAfterCancel.wait()
315-
#expect(Task.isCancelled)
316-
expectation.fulfill()
294+
return Task.isCancelled
317295
}
318296

319297
// Create pending tasks that won't start until the first task suspends
320-
Task(on: systemUnderTest) {
321-
#expect(Task.isCancelled)
322-
expectation.fulfill()
298+
let task2 = Task(on: systemUnderTest) {
299+
Task.isCancelled
323300
}
324301

325-
Task(on: systemUnderTest) {
326-
#expect(Task.isCancelled)
327-
expectation.fulfill()
302+
let task3 = Task(on: systemUnderTest) {
303+
Task.isCancelled
328304
}
329305

330306
// Wait for the first task to start executing
@@ -336,26 +312,25 @@ struct CancellableQueueTests {
336312
// Signal the semaphore to let tasks continue
337313
await proceedAfterCancel.signal()
338314

339-
await expectation.fulfillment(withinSeconds: 30)
315+
#expect(await task1.value)
316+
#expect(await task2.value)
317+
#expect(await task3.value)
340318
}
341319

342320
@Test
343321
func cancelTasks_mainActorQueue_doesNotCancelFutureTasks() async throws {
344322
let systemUnderTest = CancellableQueue(underlyingQueue: MainActor.queue)
345-
let expectation = Expectation()
346323

347324
// Cancel tasks before creating any
348325
systemUnderTest.cancelTasks()
349326

350327
// Create a task after cancellation - it should NOT be cancelled
351328
let task = Task(on: systemUnderTest) {
352-
#expect(!Task.isCancelled)
353-
expectation.fulfill()
354329
try doWork()
330+
return Task.isCancelled
355331
}
356332

357-
try await task.value
358-
await expectation.fulfillment(withinSeconds: 30)
333+
#expect(try await !task.value)
359334
}
360335

361336
// MARK: Private

0 commit comments

Comments
 (0)