Roman Elizarov | 8552f0e | 2017-09-28 13:03:44 +0300 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016-2017 JetBrains s.r.o. |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package kotlinx.coroutines.experimental |
| 18 | |
| 19 | import org.hamcrest.MatcherAssert.assertThat |
| 20 | import org.hamcrest.core.IsEqual |
| 21 | import org.junit.Test |
| 22 | import java.util.concurrent.Executor |
| 23 | import java.util.concurrent.Executors |
Vsevolod Tolstopyatov | 4cb5d19 | 2018-04-11 17:42:16 +0300 | [diff] [blame] | 24 | import kotlin.coroutines.experimental.* |
Roman Elizarov | 8552f0e | 2017-09-28 13:03:44 +0300 | [diff] [blame] | 25 | |
Vsevolod Tolstopyatov | cd00643 | 2018-04-26 16:03:40 +0300 | [diff] [blame] | 26 | class DelayJvmTest : TestBase() { |
Roman Elizarov | 8552f0e | 2017-09-28 13:03:44 +0300 | [diff] [blame] | 27 | /** |
| 28 | * Test that delay works properly in contexts with custom [ContinuationInterceptor] |
| 29 | */ |
| 30 | @Test |
| 31 | fun testDelayInArbitraryContext() = runBlocking { |
| 32 | var thread: Thread? = null |
| 33 | val pool = Executors.newFixedThreadPool(1) { runnable -> |
| 34 | Thread(runnable).also { thread = it } |
| 35 | } |
| 36 | val context = CustomInterceptor(pool) |
| 37 | val c = async(context) { |
| 38 | assertThat(Thread.currentThread(), IsEqual(thread)) |
| 39 | delay(100) |
| 40 | assertThat(Thread.currentThread(), IsEqual(thread)) |
| 41 | 42 |
| 42 | } |
| 43 | assertThat(c.await(), IsEqual(42)) |
| 44 | pool.shutdown() |
| 45 | } |
| 46 | |
Roman Elizarov | 8552f0e | 2017-09-28 13:03:44 +0300 | [diff] [blame] | 47 | @Test |
| 48 | fun testDelayWithoutDispatcher() = runBlocking(CoroutineName("testNoDispatcher.main")) { |
| 49 | // launch w/o a specified dispatcher |
| 50 | val c = async(CoroutineName("testNoDispatcher.inner")) { |
| 51 | delay(100) |
| 52 | 42 |
| 53 | } |
| 54 | assertThat(c.await(), IsEqual(42)) |
| 55 | } |
| 56 | |
Vsevolod Tolstopyatov | 4cb5d19 | 2018-04-11 17:42:16 +0300 | [diff] [blame] | 57 | @Test |
| 58 | fun testNegativeDelay() = runBlocking { |
| 59 | expect(1) |
| 60 | val job = async(coroutineContext) { |
| 61 | expect(3) |
| 62 | delay(0) |
| 63 | expect(4) |
| 64 | } |
| 65 | |
| 66 | delay(-1) |
| 67 | expect(2) |
| 68 | job.await() |
| 69 | finish(5) |
| 70 | } |
| 71 | |
Roman Elizarov | 8552f0e | 2017-09-28 13:03:44 +0300 | [diff] [blame] | 72 | class CustomInterceptor(val pool: Executor) : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor { |
| 73 | override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = |
| 74 | Wrapper(pool, continuation) |
| 75 | } |
| 76 | |
| 77 | class Wrapper<T>(val pool: Executor, val cont: Continuation<T>) : Continuation<T> { |
| 78 | override val context: CoroutineContext |
| 79 | get() = cont.context |
| 80 | |
| 81 | override fun resume(value: T) { |
| 82 | pool.execute { cont.resume(value) } |
| 83 | } |
| 84 | |
| 85 | override fun resumeWithException(exception: Throwable) { |
| 86 | pool.execute { cont.resumeWithException(exception) } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | } |