diff --git a/Tests/AsyncAlgorithmsTests/TestLazy.swift b/Tests/AsyncAlgorithmsTests/TestLazy.swift index 3d7f58ca..a173d80f 100644 --- a/Tests/AsyncAlgorithmsTests/TestLazy.swift +++ b/Tests/AsyncAlgorithmsTests/TestLazy.swift @@ -13,97 +13,102 @@ import AsyncAlgorithms final class TestLazy: XCTestCase { - func test_array() async { - let source = [1, 2, 3, 4] - let expected = source - let sequence = source.async - - var actual = [Int]() + func test_lazy_outputs_elements_and_finishes_when_source_is_array() async { + let expected = [1, 2, 3, 4] + let sequence = expected.async + + var collected = [Int]() for await item in sequence { - actual.append(item) + collected.append(item) } - XCTAssertEqual(expected, actual) + XCTAssertEqual(expected, collected) } - func test_set() async { - let source: Set = [1, 2, 3, 4] - let expected = source - let sequence = source.async + func test_lazy_outputs_elements_and_finishes_when_source_is_set() async { + let expected: Set = [1, 2, 3, 4] + let sequence = expected.async - var actual = Set() + var collected = Set() for await item in sequence { - actual.insert(item) + collected.insert(item) } - XCTAssertEqual(expected, actual) + XCTAssertEqual(expected, collected) } - func test_empty() async { - let source = EmptyCollection() + func test_lazy_finishes_without_elements_when_source_is_empty() async { let expected = [Int]() - let sequence = source.async + let sequence = expected.async - var actual = [Int]() + var collected = [Int]() for await item in sequence { - actual.append(item) + collected.append(item) } - XCTAssertEqual(expected, actual) + XCTAssertEqual(expected, collected) } - func test_iteration() async { - let source = ReportingSequence([1, 2, 3]) + func test_lazy_triggers_expected_iterator_events_when_source_is_iterated() async { + let expected = [1, 2, 3] + let expectedEvents = [ + ReportingSequence.Event.makeIterator, + .next, + .next, + .next, + .next + ] + let source = ReportingSequence(expected) let sequence = source.async + XCTAssertEqual(source.events, []) + var collected = [Int]() for await item in sequence { collected.append(item) } - XCTAssertEqual(collected, [1, 2, 3]) - XCTAssertEqual(source.events, [ - .makeIterator, + + XCTAssertEqual(expected, collected) + XCTAssertEqual(expectedEvents, source.events) + } + + func test_lazy_stops_triggering_iterator_events_when_source_is_pastEnd() async { + let expected = [1, 2, 3] + let expectedEvents = [ + ReportingSequence.Event.makeIterator, .next, .next, .next, .next - ]) - } - - func test_manual_iteration() async { - let source = ReportingSequence([1, 2, 3]) + ] + let source = ReportingSequence(expected) let sequence = source.async + XCTAssertEqual(source.events, []) + var collected = [Int]() var iterator = sequence.makeAsyncIterator() while let item = await iterator.next() { collected.append(item) } - XCTAssertEqual(collected, [1, 2, 3]) - XCTAssertEqual(source.events, [ - .makeIterator, - .next, - .next, - .next, - .next - ]) + + XCTAssertEqual(expected, collected) + XCTAssertEqual(expectedEvents, source.events) + let pastEnd = await iterator.next() + XCTAssertEqual(pastEnd, nil) // ensure that iterating past the end does not invoke next again - XCTAssertEqual(source.events, [ - .makeIterator, - .next, - .next, - .next, - .next - ]) + XCTAssertEqual(expectedEvents, source.events) } - func test_cancellation() async { - let source = Indefinite(value: "test") - let sequence = source.async + func test_lazy_finishes_when_task_is_cancelled() async { let finished = expectation(description: "finished") let iterated = expectation(description: "iterated") + + let source = Indefinite(value: "test") + let sequence = source.async + let task = Task { var firstIteration = false for await _ in sequence { @@ -114,11 +119,14 @@ final class TestLazy: XCTestCase { } finished.fulfill() } + // ensure the other task actually starts wait(for: [iterated], timeout: 1.0) + // cancellation should ensure the loop finishes // without regards to the remaining underlying sequence task.cancel() + wait(for: [finished], timeout: 1.0) } }