1313import AsyncAlgorithms
1414
1515final class TestChain2: XCTestCase {
16- func test_chain( ) async {
17- let chained = chain ( [ 1 , 2 , 3 ] . async , [ 4 , 5 , 6 ] . async )
16+ func test_chain2_concatenates_elements_from_sequences_and_returns_nil_when_source_is_pastEnd( ) async {
17+ let expected1 = [ 1 , 2 , 3 ]
18+ let expected2 = [ 4 , 5 , 6 ]
19+ let expected = expected1 + expected2
20+ let chained = chain ( expected1. async , expected2. async )
21+
1822 var iterator = chained. makeAsyncIterator ( )
19- var actual = [ Int] ( )
23+ var collected = [ Int] ( )
2024 while let item = await iterator. next ( ) {
21- actual . append ( item)
25+ collected . append ( item)
2226 }
23- XCTAssertEqual ( [ 1 , 2 , 3 , 4 , 5 , 6 ] , actual)
27+ XCTAssertEqual ( expected, collected)
28+
2429 let pastEnd = await iterator. next ( )
2530 XCTAssertNil ( pastEnd)
2631 }
2732
28- func test_throwing_first ( ) async throws {
33+ func test_chain2_outputs_elements_from_first_sequence_and_throws_when_first_throws ( ) async throws {
2934 let chained = chain ( [ 1 , 2 , 3 ] . async . map { try throwOn ( 3 , $0) } , [ 4 , 5 , 6 ] . async )
3035 var iterator = chained. makeAsyncIterator ( )
31- var actual = [ Int] ( )
36+
37+ var collected = [ Int] ( )
3238 do {
3339 while let item = try await iterator. next ( ) {
34- actual . append ( item)
40+ collected . append ( item)
3541 }
36- XCTFail( )
42+ XCTFail( " Chained sequence should throw when first sequence throws " )
3743 } catch {
3844 XCTAssertEqual ( Failure ( ) , error as? Failure )
3945 }
40- XCTAssertEqual ( [ 1 , 2 ] , actual)
46+ XCTAssertEqual ( [ 1 , 2 ] , collected)
47+
4148 let pastEnd = try await iterator. next ( )
4249 XCTAssertNil ( pastEnd)
4350 }
4451
45- func test_throwing_second ( ) async throws {
52+ func test_chain2_outputs_elements_from_sequences_and_throws_when_second_throws ( ) async throws {
4653 let chained = chain ( [ 1 , 2 , 3 ] . async , [ 4 , 5 , 6 ] . async . map { try throwOn ( 5 , $0) } )
4754 var iterator = chained. makeAsyncIterator ( )
48- var actual = [ Int] ( )
55+
56+ var collected = [ Int] ( )
4957 do {
5058 while let item = try await iterator. next ( ) {
51- actual . append ( item)
59+ collected . append ( item)
5260 }
53- XCTFail( )
61+ XCTFail( " Chained sequence should throw when second sequence throws " )
5462 } catch {
5563 XCTAssertEqual ( Failure ( ) , error as? Failure )
5664 }
57- XCTAssertEqual ( [ 1 , 2 , 3 , 4 ] , actual)
65+ XCTAssertEqual ( collected, [ 1 , 2 , 3 , 4 ] )
66+
5867 let pastEnd = try await iterator. next ( )
5968 XCTAssertNil ( pastEnd)
6069 }
6170
62- func test_cancellation( ) async {
63- let source = Indefinite ( value: " test " )
64- let sequence = chain ( source. async , [ " past indefinite " ] . async )
71+ func test_chain2_finishes_when_task_is_cancelled( ) async {
6572 let finished = expectation ( description: " finished " )
6673 let iterated = expectation ( description: " iterated " )
74+
75+ let source = Indefinite ( value: " test " )
76+ let sequence = chain ( source. async , [ " past indefinite " ] . async )
77+
6778 let task = Task {
6879 var firstIteration = false
6980 for await _ in sequence {
@@ -74,84 +85,101 @@ final class TestChain2: XCTestCase {
7485 }
7586 finished. fulfill ( )
7687 }
88+
7789 // ensure the other task actually starts
7890 wait ( for: [ iterated] , timeout: 1.0 )
91+
7992 // cancellation should ensure the loop finishes
8093 // without regards to the remaining underlying sequence
8194 task. cancel ( )
95+
8296 wait ( for: [ finished] , timeout: 1.0 )
8397 }
8498}
8599
86100final class TestChain3: XCTestCase {
87- func test_chain( ) async {
88- let chained = chain ( [ 1 , 2 , 3 ] . async , [ 4 , 5 , 6 ] . async , [ 7 , 8 , 9 ] . async )
101+ func test_chain3_concatenates_elements_from_sequences_and_returns_nil_when_source_is_pastEnd( ) async {
102+ let expected1 = [ 1 , 2 , 3 ]
103+ let expected2 = [ 4 , 5 , 6 ]
104+ let expected3 = [ 7 , 8 , 9 ]
105+ let expected = expected1 + expected2 + expected3
106+ let chained = chain ( expected1. async , expected2. async , expected3. async )
89107 var iterator = chained. makeAsyncIterator ( )
90- var actual = [ Int] ( )
108+
109+ var collected = [ Int] ( )
91110 while let item = await iterator. next ( ) {
92- actual . append ( item)
111+ collected . append ( item)
93112 }
94- XCTAssertEqual ( [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] , actual)
113+ XCTAssertEqual ( expected, collected)
114+
95115 let pastEnd = await iterator. next ( )
96116 XCTAssertNil ( pastEnd)
97117 }
98118
99- func test_throwing_first ( ) async throws {
119+ func test_chain3_outputs_elements_from_first_sequence_and_throws_when_first_throws ( ) async throws {
100120 let chained = chain ( [ 1 , 2 , 3 ] . async . map { try throwOn ( 3 , $0) } , [ 4 , 5 , 6 ] . async , [ 7 , 8 , 9 ] . async )
101121 var iterator = chained. makeAsyncIterator ( )
102- var actual = [ Int] ( )
122+
123+ var collected = [ Int] ( )
103124 do {
104125 while let item = try await iterator. next ( ) {
105- actual . append ( item)
126+ collected . append ( item)
106127 }
107- XCTFail( )
128+ XCTFail( " Chained sequence should throw when first sequence throws " )
108129 } catch {
109130 XCTAssertEqual ( Failure ( ) , error as? Failure )
110131 }
111- XCTAssertEqual ( [ 1 , 2 ] , actual)
132+ XCTAssertEqual ( collected, [ 1 , 2 ] )
133+
112134 let pastEnd = try await iterator. next ( )
113135 XCTAssertNil ( pastEnd)
114136 }
115137
116- func test_throwing_second ( ) async throws {
138+ func test_chain3_outputs_elements_from_sequences_and_throws_when_second_throws ( ) async throws {
117139 let chained = chain ( [ 1 , 2 , 3 ] . async , [ 4 , 5 , 6 ] . async . map { try throwOn ( 5 , $0) } , [ 7 , 8 , 9 ] . async )
118140 var iterator = chained. makeAsyncIterator ( )
119- var actual = [ Int] ( )
141+
142+ var collected = [ Int] ( )
120143 do {
121144 while let item = try await iterator. next ( ) {
122- actual . append ( item)
145+ collected . append ( item)
123146 }
124- XCTFail( )
147+ XCTFail( " Chained sequence should throw when second sequence throws " )
125148 } catch {
126149 XCTAssertEqual ( Failure ( ) , error as? Failure )
127150 }
128- XCTAssertEqual ( [ 1 , 2 , 3 , 4 ] , actual)
151+ XCTAssertEqual ( collected, [ 1 , 2 , 3 , 4 ] )
152+
129153 let pastEnd = try await iterator. next ( )
130154 XCTAssertNil ( pastEnd)
131155 }
132156
133- func test_throwing_third ( ) async throws {
157+ func test_chain3_outputs_elements_from_sequences_and_throws_when_third_throws ( ) async throws {
134158 let chained = chain ( [ 1 , 2 , 3 ] . async , [ 4 , 5 , 6 ] . async , [ 7 , 8 , 9 ] . async . map { try throwOn ( 8 , $0) } )
135159 var iterator = chained. makeAsyncIterator ( )
136- var actual = [ Int] ( )
160+
161+ var collected = [ Int] ( )
137162 do {
138163 while let item = try await iterator. next ( ) {
139- actual . append ( item)
164+ collected . append ( item)
140165 }
141- XCTFail( )
166+ XCTFail( " Chained sequence should throw when third sequence throws " )
142167 } catch {
143168 XCTAssertEqual ( Failure ( ) , error as? Failure )
144169 }
145- XCTAssertEqual ( [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] , actual)
170+ XCTAssertEqual ( collected, [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] )
171+
146172 let pastEnd = try await iterator. next ( )
147173 XCTAssertNil ( pastEnd)
148174 }
149175
150- func test_cancellation( ) async {
151- let source = Indefinite ( value: " test " )
152- let sequence = chain ( source. async , [ " past indefinite " ] . async , [ " and even further " ] . async )
176+ func test_chain3_finishes_when_task_is_cancelled( ) async {
153177 let finished = expectation ( description: " finished " )
154178 let iterated = expectation ( description: " iterated " )
179+
180+ let source = Indefinite ( value: " test " )
181+ let sequence = chain ( source. async , [ " past indefinite " ] . async , [ " and even further " ] . async )
182+
155183 let task = Task {
156184 var firstIteration = false
157185 for await _ in sequence {
@@ -162,11 +190,14 @@ final class TestChain3: XCTestCase {
162190 }
163191 finished. fulfill ( )
164192 }
193+
165194 // ensure the other task actually starts
166195 wait ( for: [ iterated] , timeout: 1.0 )
196+
167197 // cancellation should ensure the loop finishes
168198 // without regards to the remaining underlying sequence
169199 task. cancel ( )
200+
170201 wait ( for: [ finished] , timeout: 1.0 )
171202 }
172203}
0 commit comments