Rename coroutines sourceset to coroutinesExperimental
Restore experimental coroutine tests as they were before e22ca022
and compile and run them twice:
- first time with LV=1.2
- second time with LV=1.3
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package test.coroutines
|
||||
|
||||
import kotlin.test.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
class CoroutineContextTest {
|
||||
data class CtxA(val i: Int) : AbstractCoroutineContextElement(CtxA) {
|
||||
companion object Key : CoroutineContext.Key<CtxA>
|
||||
}
|
||||
|
||||
data class CtxB(val i: Int) : AbstractCoroutineContextElement(CtxB) {
|
||||
companion object Key : CoroutineContext.Key<CtxB>
|
||||
}
|
||||
|
||||
data class CtxC(val i: Int) : AbstractCoroutineContextElement(CtxC) {
|
||||
companion object Key : CoroutineContext.Key<CtxC>
|
||||
}
|
||||
|
||||
object Disp1 : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
|
||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = continuation
|
||||
override fun toString(): String = "Disp1"
|
||||
}
|
||||
|
||||
object Disp2 : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
|
||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = continuation
|
||||
override fun toString(): String = "Disp2"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetPlusFold() {
|
||||
var ctx: CoroutineContext = EmptyCoroutineContext
|
||||
assertContents(ctx)
|
||||
assertEquals("EmptyCoroutineContext", ctx.toString())
|
||||
|
||||
ctx += CtxA(1)
|
||||
assertContents(ctx, CtxA(1))
|
||||
assertEquals("CtxA(i=1)", ctx.toString())
|
||||
assertEquals(CtxA(1), ctx[CtxA])
|
||||
assertEquals(null, ctx[CtxB])
|
||||
assertEquals(null, ctx[CtxC])
|
||||
|
||||
ctx += CtxB(2)
|
||||
assertContents(ctx, CtxA(1), CtxB(2))
|
||||
assertEquals("[CtxA(i=1), CtxB(i=2)]", ctx.toString())
|
||||
assertEquals(CtxA(1), ctx[CtxA])
|
||||
assertEquals(CtxB(2), ctx[CtxB])
|
||||
assertEquals(null, ctx[CtxC])
|
||||
|
||||
ctx += CtxC(3)
|
||||
assertContents(ctx, CtxA(1), CtxB(2), CtxC(3))
|
||||
assertEquals("[CtxA(i=1), CtxB(i=2), CtxC(i=3)]", ctx.toString())
|
||||
assertEquals(CtxA(1), ctx[CtxA])
|
||||
assertEquals(CtxB(2), ctx[CtxB])
|
||||
assertEquals(CtxC(3), ctx[CtxC])
|
||||
|
||||
ctx += CtxB(4)
|
||||
assertContents(ctx, CtxA(1), CtxC(3), CtxB(4))
|
||||
assertEquals("[CtxA(i=1), CtxC(i=3), CtxB(i=4)]", ctx.toString())
|
||||
assertEquals(CtxA(1), ctx[CtxA])
|
||||
assertEquals(CtxB(4), ctx[CtxB])
|
||||
assertEquals(CtxC(3), ctx[CtxC])
|
||||
|
||||
ctx += CtxA(5)
|
||||
assertContents(ctx, CtxC(3), CtxB(4), CtxA(5))
|
||||
assertEquals("[CtxC(i=3), CtxB(i=4), CtxA(i=5)]", ctx.toString())
|
||||
assertEquals(CtxA(5), ctx[CtxA])
|
||||
assertEquals(CtxB(4), ctx[CtxB])
|
||||
assertEquals(CtxC(3), ctx[CtxC])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinusKey() {
|
||||
var ctx: CoroutineContext = CtxA(1) + CtxB(2) + CtxC(3)
|
||||
assertContents(ctx, CtxA(1), CtxB(2), CtxC(3))
|
||||
assertEquals("[CtxA(i=1), CtxB(i=2), CtxC(i=3)]", ctx.toString())
|
||||
|
||||
ctx = ctx.minusKey(CtxA)
|
||||
assertContents(ctx, CtxB(2), CtxC(3))
|
||||
assertEquals("[CtxB(i=2), CtxC(i=3)]", ctx.toString())
|
||||
assertEquals(null, ctx[CtxA])
|
||||
assertEquals(CtxB(2), ctx[CtxB])
|
||||
assertEquals(CtxC(3), ctx[CtxC])
|
||||
|
||||
ctx = ctx.minusKey(CtxC)
|
||||
assertContents(ctx, CtxB(2))
|
||||
assertEquals("CtxB(i=2)", ctx.toString())
|
||||
assertEquals(null, ctx[CtxA])
|
||||
assertEquals(CtxB(2), ctx[CtxB])
|
||||
assertEquals(null, ctx[CtxC])
|
||||
|
||||
ctx = ctx.minusKey(CtxC)
|
||||
assertContents(ctx, CtxB(2))
|
||||
assertEquals("CtxB(i=2)", ctx.toString())
|
||||
assertEquals(null, ctx[CtxA])
|
||||
assertEquals(CtxB(2), ctx[CtxB])
|
||||
assertEquals(null, ctx[CtxC])
|
||||
|
||||
ctx = ctx.minusKey(CtxB)
|
||||
assertContents(ctx)
|
||||
assertEquals("EmptyCoroutineContext", ctx.toString())
|
||||
assertEquals(null, ctx[CtxA])
|
||||
assertEquals(null, ctx[CtxB])
|
||||
assertEquals(null, ctx[CtxC])
|
||||
|
||||
assertEquals(EmptyCoroutineContext, ctx)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPlusCombined() {
|
||||
val ctx1 = CtxA(1) + CtxB(2)
|
||||
val ctx2 = CtxB(3) + CtxC(4)
|
||||
val ctx = ctx1 + ctx2
|
||||
assertContents(ctx, CtxA(1), CtxB(3), CtxC(4))
|
||||
assertEquals("[CtxA(i=1), CtxB(i=3), CtxC(i=4)]", ctx.toString())
|
||||
assertEquals(CtxA(1), ctx[CtxA])
|
||||
assertEquals(CtxB(3), ctx[CtxB])
|
||||
assertEquals(CtxC(4), ctx[CtxC])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLastDispatcher() {
|
||||
var ctx: CoroutineContext = EmptyCoroutineContext
|
||||
assertContents(ctx)
|
||||
ctx += CtxA(1)
|
||||
assertContents(ctx, CtxA(1))
|
||||
ctx += Disp1
|
||||
assertContents(ctx, CtxA(1), Disp1)
|
||||
ctx += CtxA(2)
|
||||
assertContents(ctx, CtxA(2), Disp1)
|
||||
ctx += CtxB(3)
|
||||
assertContents(ctx, CtxA(2), CtxB(3), Disp1)
|
||||
ctx += Disp2
|
||||
assertContents(ctx, CtxA(2), CtxB(3), Disp2)
|
||||
ctx += (CtxB(4) + CtxC(5))
|
||||
assertContents(ctx, CtxA(2), CtxB(4), CtxC(5), Disp2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEquals() {
|
||||
val ctx1 = CtxA(1) + CtxB(2) + CtxC(3)
|
||||
val ctx2 = CtxB(2) + CtxC(3) + CtxA(1) // same
|
||||
val ctx3 = CtxC(3) + CtxA(1) + CtxB(2) // same
|
||||
val ctx4 = CtxA(1) + CtxB(2) + CtxC(4) // different
|
||||
assertEquals(ctx1, ctx2)
|
||||
assertEquals(ctx1, ctx3)
|
||||
assertEquals(ctx2, ctx3)
|
||||
assertNotEquals(ctx1, ctx4)
|
||||
assertNotEquals(ctx2, ctx4)
|
||||
assertNotEquals(ctx3, ctx4)
|
||||
}
|
||||
|
||||
private fun assertContents(ctx: CoroutineContext, vararg elements: CoroutineContext.Element) {
|
||||
val set = ctx.fold(setOf<CoroutineContext>()) { a, b -> a + b }
|
||||
assertEquals(listOf(*elements), set.toList())
|
||||
for (elem in elements)
|
||||
assertTrue(ctx[elem.key] == elem)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package test.coroutines
|
||||
|
||||
import test.assertStaticAndRuntimeTypeIs
|
||||
import kotlin.test.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
/**
|
||||
* Test to ensure that coroutine machinery does not call equals/hashCode/toString anywhere.
|
||||
*/
|
||||
class CoroutinesReferenceValuesTest {
|
||||
class BadClass {
|
||||
override fun equals(other: Any?): Boolean = error("equals")
|
||||
override fun hashCode(): Int = error("hashCode")
|
||||
override fun toString(): String = error("toString")
|
||||
}
|
||||
|
||||
var counter = 0
|
||||
|
||||
// tail-suspend function via suspendCoroutine (test SafeContinuation)
|
||||
suspend fun getBadClassViaSuspend(): BadClass = suspendCoroutine { cont ->
|
||||
counter++
|
||||
cont.resume(BadClass())
|
||||
}
|
||||
|
||||
// state machine
|
||||
suspend fun checkBadClassTwice() {
|
||||
assertStaticAndRuntimeTypeIs<BadClass>(getBadClassViaSuspend())
|
||||
assertStaticAndRuntimeTypeIs<BadClass>(getBadClassViaSuspend())
|
||||
}
|
||||
|
||||
fun <T> suspend(block: suspend () -> T) = block
|
||||
|
||||
@Test
|
||||
fun testBadClass() {
|
||||
val bad = suspend {
|
||||
checkBadClassTwice()
|
||||
getBadClassViaSuspend()
|
||||
}
|
||||
var result: BadClass? = null
|
||||
bad.startCoroutine(object : Continuation<BadClass> {
|
||||
override val context: CoroutineContext = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: BadClass) {
|
||||
assertTrue(result == null)
|
||||
result = value
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
assertTrue(result is BadClass)
|
||||
assertEquals(3, counter)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("ObsoleteExperimentalCoroutines", "DEPRECATION")
|
||||
|
||||
package test.coroutines
|
||||
|
||||
import kotlin.test.*
|
||||
import kotlin.coroutines.experimental.buildSequence
|
||||
import kotlin.coroutines.experimental.buildIterator
|
||||
|
||||
class SequenceBuilderTest {
|
||||
@Test
|
||||
fun testSimple() {
|
||||
val result = buildSequence {
|
||||
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 = buildSequence {
|
||||
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())
|
||||
|
||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testManualIteration() {
|
||||
val result = buildSequence {
|
||||
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())
|
||||
|
||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
||||
|
||||
assertEquals(1, result.iterator().next())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEmptySequence() {
|
||||
val result = buildSequence<Int> {}
|
||||
val iterator = result.iterator()
|
||||
|
||||
assertFalse(iterator.hasNext())
|
||||
assertFalse(iterator.hasNext())
|
||||
|
||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLaziness() {
|
||||
var sharedVar = -2
|
||||
val result = buildSequence {
|
||||
while (true) {
|
||||
when (sharedVar) {
|
||||
-1 -> return@buildSequence
|
||||
-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())
|
||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExceptionInCoroutine() {
|
||||
var sharedVar = -2
|
||||
val result = buildSequence {
|
||||
while (true) {
|
||||
when (sharedVar) {
|
||||
-1 -> return@buildSequence
|
||||
-2 -> throw UnsupportedOperationException("-2 is unsupported")
|
||||
else -> yield(sharedVar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val iterator = result.iterator()
|
||||
|
||||
sharedVar = 1
|
||||
assertEquals(1, iterator.next())
|
||||
|
||||
sharedVar = -2
|
||||
assertFailsWith<UnsupportedOperationException> { iterator.hasNext() }
|
||||
assertFailsWith<IllegalStateException> { iterator.hasNext() }
|
||||
assertFailsWith<IllegalStateException> { iterator.next() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParallelIteration() {
|
||||
var inc = 0
|
||||
val result = buildSequence {
|
||||
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 = buildSequence {
|
||||
yieldAll(listOf(1, 2, 3).iterator())
|
||||
}
|
||||
assertEquals(listOf(1, 2, 3), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllSequence() {
|
||||
val result = buildSequence {
|
||||
yieldAll(sequenceOf(1, 2, 3))
|
||||
}
|
||||
assertEquals(listOf(1, 2, 3), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllCollection() {
|
||||
val result = buildSequence {
|
||||
yieldAll(listOf(1, 2, 3))
|
||||
}
|
||||
assertEquals(listOf(1, 2, 3), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllCollectionMixedFirst() {
|
||||
val result = buildSequence {
|
||||
yield(0)
|
||||
yieldAll(listOf(1, 2, 3))
|
||||
}
|
||||
assertEquals(listOf(0, 1, 2, 3), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllCollectionMixedLast() {
|
||||
val result = buildSequence {
|
||||
yieldAll(listOf(1, 2, 3))
|
||||
yield(4)
|
||||
}
|
||||
assertEquals(listOf(1, 2, 3, 4), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllCollectionMixedBoth() {
|
||||
val result = buildSequence {
|
||||
yield(0)
|
||||
yieldAll(listOf(1, 2, 3))
|
||||
yield(4)
|
||||
}
|
||||
assertEquals(listOf(0, 1, 2, 3, 4), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllCollectionMixedLong() {
|
||||
val result = buildSequence {
|
||||
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 = buildSequence<Int> {
|
||||
yieldAll(listOf())
|
||||
}
|
||||
assertEquals(listOf(), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllCollectionManyEmpty() {
|
||||
val result = buildSequence<Int> {
|
||||
yieldAll(listOf())
|
||||
yieldAll(listOf())
|
||||
yieldAll(listOf())
|
||||
}
|
||||
assertEquals(listOf(), result.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testYieldAllSideEffects() {
|
||||
val effects = arrayListOf<Any>()
|
||||
val result = buildSequence {
|
||||
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()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInfiniteYieldAll() {
|
||||
val values = buildIterator {
|
||||
while (true) {
|
||||
yieldAll((1..5).map { it })
|
||||
}
|
||||
}
|
||||
|
||||
var sum = 0
|
||||
repeat(10) {
|
||||
sum += values.next() //.also(::println)
|
||||
}
|
||||
assertEquals(30, sum)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user