Skip to content

Commit 8a0cadb

Browse files
committed
CancellingContinuationTests
1 parent 672142a commit 8a0cadb

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

FlyingSocks/Sources/CancellingContinuation.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,12 @@ private extension CancellingContinuation {
8181
func getValue() async throws -> Success {
8282
precondition(hasStarted == false, "Can only wait a single time.")
8383
hasStarted = true
84-
if let result = result {
85-
return try result.get()
86-
} else {
84+
guard let result = result else {
8785
return try await withCheckedThrowingContinuation(function: function) {
8886
continuation = $0
8987
}
9088
}
89+
return try result.get()
9190
}
9291

9392
func resume(with result: Result<Success, Error>) {
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//
2+
// CancellingContinuationTests.swift
3+
// FlyingFox
4+
//
5+
// Created by Simon Whitty on 28/08/2022.
6+
// Copyright © 2022 Simon Whitty. All rights reserved.
7+
//
8+
// Distributed under the permissive MIT license
9+
// Get the latest version from here:
10+
//
11+
// https://github.com/swhitty/FlyingFox
12+
//
13+
// Permission is hereby granted, free of charge, to any person obtaining a copy
14+
// of this software and associated documentation files (the "Software"), to deal
15+
// in the Software without restriction, including without limitation the rights
16+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17+
// copies of the Software, and to permit persons to whom the Software is
18+
// furnished to do so, subject to the following conditions:
19+
//
20+
// The above copyright notice and this permission notice shall be included in all
21+
// copies or substantial portions of the Software.
22+
//
23+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29+
// SOFTWARE.
30+
//
31+
32+
import FlyingSocks
33+
import XCTest
34+
35+
final class CancellingContinuationTests: XCTestCase {
36+
37+
func testContinuationHashable() {
38+
let continuation = CancellingContinuation<String, Never>()
39+
let other = CancellingContinuation<String, Never>()
40+
41+
var continuations = Set([continuation])
42+
43+
XCTAssertTrue(continuations.contains(continuation))
44+
XCTAssertFalse(continuations.contains(other))
45+
46+
continuations.insert(other)
47+
XCTAssertTrue(continuations.contains(continuation))
48+
XCTAssertTrue(continuations.contains(other))
49+
50+
continuations.remove(continuation)
51+
XCTAssertFalse(continuations.contains(continuation))
52+
XCTAssertTrue(continuations.contains(other))
53+
}
54+
55+
func testEarlyResultIsReturned() async {
56+
let continuation = CancellingContinuation<String, Never>()
57+
58+
continuation.resume(returning: "Fish")
59+
let task = Task { try await continuation.value }
60+
task.cancel()
61+
62+
await XCTAssertEqualAsync(
63+
try await task.value,
64+
"Fish"
65+
)
66+
}
67+
68+
func testCancellationIsReturned() async {
69+
let continuation = CancellingContinuation<String, Never>()
70+
71+
let task = Task { try await continuation.value }
72+
task.cancel()
73+
74+
await XCTAssertThrowsError(
75+
try await task.value,
76+
of: CancellationError.self
77+
)
78+
}
79+
80+
func testResumeIsReturned() async {
81+
let continuation = CancellingContinuation<Void, Error>()
82+
83+
let task = Task { try await continuation.value }
84+
continuation.resume()
85+
86+
let result = await task.result
87+
XCTAssertNoThrow(try result.get())
88+
}
89+
90+
func testErrorIsReturned() async {
91+
let continuation = CancellingContinuation<String, Error>()
92+
93+
let task = Task { try await continuation.value }
94+
continuation.resume(throwing: SocketError.disconnected)
95+
96+
await XCTAssertThrowsError(
97+
try await task.value,
98+
of: SocketError.self
99+
)
100+
}
101+
}

0 commit comments

Comments
 (0)