1 2 /* 3 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 4 */ 5 6 @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "UNREACHABLE_CODE") // KT-21913 7 8 package kotlinx.coroutines 9 10 import kotlin.test.* 11 12 class WithTimeoutTest : TestBase() { 13 /** 14 * Tests a case of no timeout and no suspension inside. 15 */ 16 @Test <lambda>null17 fun testBasicNoSuspend() = runTest { 18 expect(1) 19 val result = withTimeout(10_000) { 20 expect(2) 21 "OK" 22 } 23 assertEquals("OK", result) 24 finish(3) 25 } 26 27 /** 28 * Tests a case of no timeout and one suspension inside. 29 */ 30 @Test <lambda>null31 fun testBasicSuspend() = runTest { 32 expect(1) 33 val result = withTimeout(10_000) { 34 expect(2) 35 yield() 36 expect(3) 37 "OK" 38 } 39 assertEquals("OK", result) 40 finish(4) 41 } 42 43 /** 44 * Tests proper dispatching of `withTimeout` blocks 45 */ 46 @Test <lambda>null47 fun testDispatch() = runTest { 48 expect(1) 49 launch { 50 expect(4) 51 yield() // back to main 52 expect(7) 53 } 54 expect(2) 55 // test that it does not yield to the above job when started 56 val result = withTimeout(1000) { 57 expect(3) 58 yield() // yield only now 59 expect(5) 60 "OK" 61 } 62 assertEquals("OK", result) 63 expect(6) 64 yield() // back to launch 65 finish(8) 66 } 67 68 69 /** 70 * Tests that a 100% CPU-consuming loop will react on timeout if it has yields. 71 */ 72 @Test testYieldBlockingWithTimeoutnull73 fun testYieldBlockingWithTimeout() = runTest( 74 expected = { it is CancellationException } <lambda>null75 ) { 76 withTimeout(100) { 77 while (true) { 78 yield() 79 } 80 } 81 } 82 83 /** 84 * Tests that [withTimeout] waits for children coroutines to complete. 85 */ 86 @Test <lambda>null87 fun testWithTimeoutChildWait() = runTest { 88 expect(1) 89 withTimeout(100) { 90 expect(2) 91 // launch child with timeout 92 launch { 93 expect(4) 94 } 95 expect(3) 96 // now will wait for child before returning 97 } 98 finish(5) 99 } 100 101 @Test <lambda>null102 fun testBadClass() = runTest { 103 val bad = BadClass() 104 val result = withTimeout(100) { 105 bad 106 } 107 assertSame(bad, result) 108 } 109 110 @Test <lambda>null111 fun testExceptionOnTimeout() = runTest { 112 expect(1) 113 try { 114 withTimeout(100) { 115 expect(2) 116 delay(1000) 117 expectUnreached() 118 "OK" 119 } 120 } catch (e: CancellationException) { 121 assertEquals("Timed out waiting for 100 ms", e.message) 122 finish(3) 123 } 124 } 125 126 @Test testSuppressExceptionWithResultnull127 fun testSuppressExceptionWithResult() = runTest( 128 expected = { it is CancellationException } <lambda>null129 ) { 130 expect(1) 131 withTimeout(100) { 132 expect(2) 133 try { 134 delay(1000) 135 } catch (e: CancellationException) { 136 finish(3) 137 } 138 "OK" 139 } 140 expectUnreached() 141 } 142 143 @Test <lambda>null144 fun testSuppressExceptionWithAnotherException() = runTest{ 145 expect(1) 146 try { 147 withTimeout(100) { 148 expect(2) 149 try { 150 delay(1000) 151 } catch (e: CancellationException) { 152 expect(3) 153 throw TestException() 154 } 155 expectUnreached() 156 "OK" 157 } 158 expectUnreached() 159 } catch (e: TestException) { 160 finish(4) 161 } 162 } 163 164 @Test <lambda>null165 fun testNegativeTimeout() = runTest { 166 expect(1) 167 try { 168 withTimeout(-1) { 169 expectUnreached() 170 "OK" 171 } 172 } catch (e: TimeoutCancellationException) { 173 assertEquals("Timed out immediately", e.message) 174 finish(2) 175 } 176 } 177 178 @Test <lambda>null179 fun testExceptionFromWithinTimeout() = runTest { 180 expect(1) 181 try { 182 expect(2) 183 withTimeout(1000) { 184 expect(3) 185 throw TestException() 186 } 187 expectUnreached() 188 } catch (e: TestException) { 189 finish(4) 190 } 191 } 192 193 @Test <lambda>null194 fun testIncompleteWithTimeoutState() = runTest { 195 lateinit var timeoutJob: Job 196 val handle = withTimeout(Long.MAX_VALUE) { 197 timeoutJob = coroutineContext[Job]!! 198 timeoutJob.invokeOnCompletion { } 199 } 200 201 handle.dispose() 202 timeoutJob.join() 203 assertTrue(timeoutJob.isCompleted) 204 assertFalse(timeoutJob.isActive) 205 assertFalse(timeoutJob.isCancelled) 206 } 207 } 208