blob: c21d4f7298eb32922e61e074855d9010f58e718f [file] [log] [blame]
/*
* Copyright 2016-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlinx.coroutines.experimental
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.core.IsEqual
import org.junit.Test
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import kotlin.coroutines.experimental.*
class DelayJvmTest : TestBase() {
/**
* Test that delay works properly in contexts with custom [ContinuationInterceptor]
*/
@Test
fun testDelayInArbitraryContext() = runBlocking {
var thread: Thread? = null
val pool = Executors.newFixedThreadPool(1) { runnable ->
Thread(runnable).also { thread = it }
}
val context = CustomInterceptor(pool)
val c = async(context) {
assertThat(Thread.currentThread(), IsEqual(thread))
delay(100)
assertThat(Thread.currentThread(), IsEqual(thread))
42
}
assertThat(c.await(), IsEqual(42))
pool.shutdown()
}
@Test
fun testDelayWithoutDispatcher() = runBlocking(CoroutineName("testNoDispatcher.main")) {
// launch w/o a specified dispatcher
val c = async(CoroutineName("testNoDispatcher.inner")) {
delay(100)
42
}
assertThat(c.await(), IsEqual(42))
}
@Test
fun testNegativeDelay() = runBlocking {
expect(1)
val job = async(coroutineContext) {
expect(3)
delay(0)
expect(4)
}
delay(-1)
expect(2)
job.await()
finish(5)
}
class CustomInterceptor(val pool: Executor) : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
Wrapper(pool, continuation)
}
class Wrapper<T>(val pool: Executor, val cont: Continuation<T>) : Continuation<T> {
override val context: CoroutineContext
get() = cont.context
override fun resume(value: T) {
pool.execute { cont.resume(value) }
}
override fun resumeWithException(exception: Throwable) {
pool.execute { cont.resumeWithException(exception) }
}
}
}