| |
| import kotlinx.coroutines.generate |
| import org.junit.Test |
| import java.util.* |
| import kotlin.test.assertEquals |
| import kotlin.test.assertFails |
| import kotlin.test.assertFalse |
| import kotlin.test.assertTrue |
| |
| class GenerateTest { |
| @Test |
| fun testSimple() { |
| val result = generate { |
| for (i in 1..3) { |
| yield(2 * i) |
| } |
| } |
| |
| assertEquals(listOf(2, 4, 6), result.toList()) |
| // Repeated calls also work |
| assertEquals(listOf(2, 4, 6), result.toList()) |
| } |
| |
| @Test |
| fun testCallHasNextSeveralTimes() { |
| val result = generate { |
| yield(1) |
| } |
| |
| val iterator = result.iterator() |
| |
| assertTrue(iterator.hasNext()) |
| assertTrue(iterator.hasNext()) |
| assertTrue(iterator.hasNext()) |
| |
| assertEquals(1, iterator.next()) |
| |
| assertFalse(iterator.hasNext()) |
| assertFalse(iterator.hasNext()) |
| assertFalse(iterator.hasNext()) |
| |
| assertTrue(assertFails { iterator.next() } is NoSuchElementException) |
| } |
| |
| @Test |
| fun testManualIteration() { |
| val result = generate { |
| yield(1) |
| yield(2) |
| yield(3) |
| } |
| |
| val iterator = result.iterator() |
| |
| assertTrue(iterator.hasNext()) |
| assertTrue(iterator.hasNext()) |
| assertEquals(1, iterator.next()) |
| |
| assertTrue(iterator.hasNext()) |
| assertTrue(iterator.hasNext()) |
| assertEquals(2, iterator.next()) |
| |
| assertEquals(3, iterator.next()) |
| |
| assertFalse(iterator.hasNext()) |
| assertFalse(iterator.hasNext()) |
| |
| assertTrue(assertFails { iterator.next() } is NoSuchElementException) |
| |
| assertEquals(1, result.iterator().next()) |
| } |
| |
| @Test |
| fun testEmptySequence() { |
| val result = generate<Int> {} |
| val iterator = result.iterator() |
| |
| assertFalse(iterator.hasNext()) |
| assertFalse(iterator.hasNext()) |
| |
| assertTrue(assertFails { iterator.next() } is NoSuchElementException) |
| } |
| |
| @Test |
| fun testLaziness() { |
| var sharedVar = -2 |
| val result = generate { |
| while (true) { |
| when (sharedVar) { |
| -1 -> return@generate |
| -2 -> error("Invalid state: -2") |
| else -> yield(sharedVar) |
| } |
| } |
| } |
| |
| val iterator = result.iterator() |
| |
| sharedVar = 1 |
| assertTrue(iterator.hasNext()) |
| assertEquals(1, iterator.next()) |
| |
| sharedVar = 2 |
| assertTrue(iterator.hasNext()) |
| assertEquals(2, iterator.next()) |
| |
| sharedVar = 3 |
| assertTrue(iterator.hasNext()) |
| assertEquals(3, iterator.next()) |
| |
| sharedVar = -1 |
| assertFalse(iterator.hasNext()) |
| assertTrue(assertFails { iterator.next() } is NoSuchElementException) |
| } |
| |
| @Test |
| fun testExceptionInCoroutine() { |
| var sharedVar = -2 |
| val result = generate { |
| while (true) { |
| when (sharedVar) { |
| -1 -> return@generate |
| -2 -> error("Invalid state: -2") |
| else -> yield(sharedVar) |
| } |
| } |
| } |
| |
| val iterator = result.iterator() |
| |
| sharedVar = 1 |
| assertEquals(1, iterator.next()) |
| |
| sharedVar = -2 |
| assertTrue(assertFails { iterator.hasNext() } is IllegalStateException) |
| } |
| |
| @Test |
| fun testParallelIteration() { |
| var inc = 0 |
| val result = generate { |
| for (i in 1..3) { |
| inc++ |
| yield(inc * i) |
| } |
| } |
| |
| assertEquals(listOf(Pair(1, 2), Pair(6, 8), Pair(15, 18)), result.zip(result).toList()) |
| } |
| |
| @Test |
| fun testYieldAllIterator() { |
| val result = generate { |
| yieldAll(listOf(1, 2, 3).iterator()) |
| } |
| assertEquals(listOf(1, 2, 3), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllSequence() { |
| val result = generate { |
| yieldAll(sequenceOf(1, 2, 3)) |
| } |
| assertEquals(listOf(1, 2, 3), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollection() { |
| val result = generate { |
| yieldAll(listOf(1, 2, 3)) |
| } |
| assertEquals(listOf(1, 2, 3), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollectionMixedFirst() { |
| val result = generate { |
| yield(0) |
| yieldAll(listOf(1, 2, 3)) |
| } |
| assertEquals(listOf(0, 1, 2, 3), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollectionMixedLast() { |
| val result = generate { |
| yieldAll(listOf(1, 2, 3)) |
| yield(4) |
| } |
| assertEquals(listOf(1, 2, 3, 4), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollectionMixedBoth() { |
| val result = generate { |
| yield(0) |
| yieldAll(listOf(1, 2, 3)) |
| yield(4) |
| } |
| assertEquals(listOf(0, 1, 2, 3, 4), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollectionMixedLong() { |
| val result = generate { |
| yield(0) |
| yieldAll(listOf(1, 2, 3)) |
| yield(4) |
| yield(5) |
| yieldAll(listOf(6)) |
| yield(7) |
| yieldAll(listOf()) |
| yield(8) |
| } |
| assertEquals(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollectionOneEmpty() { |
| val result = generate<Int> { |
| yieldAll(listOf()) |
| } |
| assertEquals(listOf(), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllCollectionManyEmpty() { |
| val result = generate<Int> { |
| yieldAll(listOf()) |
| yieldAll(listOf()) |
| yieldAll(listOf()) |
| } |
| assertEquals(listOf(), result.toList()) |
| } |
| |
| @Test |
| fun testYieldAllSideEffects() { |
| val effects = arrayListOf<Any>() |
| val result = generate { |
| effects.add("a") |
| yieldAll(listOf(1, 2)) |
| effects.add("b") |
| yieldAll(listOf()) |
| effects.add("c") |
| yieldAll(listOf(3)) |
| effects.add("d") |
| yield(4) |
| effects.add("e") |
| yieldAll(listOf()) |
| effects.add("f") |
| yield(5) |
| } |
| |
| for (res in result) { |
| effects.add("(") // marks step start |
| effects.add(res) |
| effects.add(")") // marks step end |
| } |
| assertEquals( |
| listOf( |
| "a", |
| "(", 1, ")", |
| "(", 2, ")", |
| "b", "c", |
| "(", 3, ")", |
| "d", |
| "(", 4, ")", |
| "e", "f", |
| "(", 5, ")" |
| ), |
| effects.toList() |
| ) |
| } |
| } |