1 /* 2 * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 package kotlinx.coroutines 5 6 import kotlinx.coroutines.exceptions.* 7 import kotlin.coroutines.* 8 import kotlin.test.* 9 10 class RunBlockingTest : TestBase() { 11 12 @Test <lambda>null13 fun testWithTimeoutBusyWait() = runTest { 14 val value = withTimeoutOrNull(10) { 15 while (isActive) { 16 // Busy wait 17 } 18 "value" 19 } 20 21 assertEquals("value", value) 22 } 23 24 @Test testPrivateEventLoopnull25 fun testPrivateEventLoop() { 26 expect(1) 27 runBlocking { 28 expect(2) 29 assertTrue(coroutineContext[ContinuationInterceptor] is EventLoop) 30 yield() // is supported! 31 expect(3) 32 } 33 finish(4) 34 } 35 36 @Test testOuterEventLoopnull37 fun testOuterEventLoop() { 38 expect(1) 39 runBlocking { 40 expect(2) 41 val outerEventLoop = coroutineContext[ContinuationInterceptor] as EventLoop 42 runBlocking(coroutineContext) { 43 expect(3) 44 // still same event loop 45 assertSame(coroutineContext[ContinuationInterceptor], outerEventLoop) 46 yield() // still works 47 expect(4) 48 } 49 expect(5) 50 } 51 finish(6) 52 } 53 54 @Test <lambda>null55 fun testOtherDispatcher() = runTest { 56 expect(1) 57 val name = "RunBlockingTest.testOtherDispatcher" 58 val thread = newSingleThreadContext(name) 59 runBlocking(thread) { 60 expect(2) 61 assertSame(coroutineContext[ContinuationInterceptor], thread) 62 assertTrue(currentThreadName().contains(name)) 63 yield() // should work 64 expect(3) 65 } 66 finish(4) 67 thread.close() 68 } 69 70 @Test testCancellationnull71 fun testCancellation() = runTest { 72 newFixedThreadPoolContext(2, "testCancellation").use { 73 val job = GlobalScope.launch(it) { 74 runBlocking(coroutineContext) { 75 while (true) { 76 yield() 77 } 78 } 79 } 80 81 runBlocking { 82 job.cancelAndJoin() 83 } 84 } 85 } 86 87 @Test testCancelWithDelaynull88 fun testCancelWithDelay() { 89 // see https://github.com/Kotlin/kotlinx.coroutines/issues/586 90 try { 91 runBlocking { 92 expect(1) 93 coroutineContext.cancel() 94 expect(2) 95 try { 96 delay(1) 97 expectUnreached() 98 } finally { 99 expect(3) 100 } 101 } 102 expectUnreached() 103 } catch (e: CancellationException) { 104 finish(4) 105 } 106 } 107 108 @Test <lambda>null109 fun testDispatchOnShutdown(): Unit = assertFailsWith<CancellationException> { 110 runBlocking { 111 expect(1) 112 val job = launch(NonCancellable) { 113 try { 114 expect(2) 115 delay(Long.MAX_VALUE) 116 } finally { 117 finish(4) 118 } 119 } 120 121 yield() 122 expect(3) 123 coroutineContext.cancel() 124 job.cancel() 125 } 126 }.let { } 127 128 @Test <lambda>null129 fun testDispatchOnShutdown2(): Unit = assertFailsWith<CancellationException> { 130 runBlocking { 131 coroutineContext.cancel() 132 expect(1) 133 val job = launch(NonCancellable, start = CoroutineStart.UNDISPATCHED) { 134 try { 135 expect(2) 136 delay(Long.MAX_VALUE) 137 } finally { 138 finish(4) 139 } 140 } 141 142 expect(3) 143 job.cancel() 144 } 145 }.let { } 146 147 @Test <lambda>null148 fun testNestedRunBlocking() = runBlocking { 149 delay(100) 150 val value = runBlocking { 151 delay(100) 152 runBlocking { 153 delay(100) 154 1 155 } 156 } 157 158 assertEquals(1, value) 159 } 160 161 @Test testIncompleteStatenull162 fun testIncompleteState() { 163 val handle = runBlocking { 164 // See #835 165 coroutineContext[Job]!!.invokeOnCompletion { } 166 } 167 168 handle.dispose() 169 } 170 171 @Test testCancelledParentnull172 fun testCancelledParent() { 173 val job = Job() 174 job.cancel() 175 assertFailsWith<CancellationException> { 176 runBlocking(job) { 177 expectUnreached() 178 } 179 } 180 } 181 } 182