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") // KT-21913 7 8 package kotlinx.coroutines 9 10 import kotlinx.coroutines.channels.* 11 import kotlin.test.* 12 13 class WithTimeoutOrNullTest : TestBase() { 14 /** 15 * Tests a case of no timeout and no suspension inside. 16 */ 17 @Test <lambda>null18 fun testBasicNoSuspend() = runTest { 19 expect(1) 20 val result = withTimeoutOrNull(10_000) { 21 expect(2) 22 "OK" 23 } 24 assertEquals("OK", result) 25 finish(3) 26 } 27 28 /** 29 * Tests a case of no timeout and one suspension inside. 30 */ 31 @Test <lambda>null32 fun testBasicSuspend() = runTest { 33 expect(1) 34 val result = withTimeoutOrNull(10_000) { 35 expect(2) 36 yield() 37 expect(3) 38 "OK" 39 } 40 assertEquals("OK", result) 41 finish(4) 42 } 43 44 /** 45 * Tests property dispatching of `withTimeoutOrNull` blocks 46 */ 47 @Test <lambda>null48 fun testDispatch() = runTest { 49 expect(1) 50 launch { 51 expect(4) 52 yield() // back to main 53 expect(7) 54 } 55 expect(2) 56 // test that it does not yield to the above job when started 57 val result = withTimeoutOrNull(1000) { 58 expect(3) 59 yield() // yield only now 60 expect(5) 61 "OK" 62 } 63 assertEquals("OK", result) 64 expect(6) 65 yield() // back to launch 66 finish(8) 67 } 68 69 /** 70 * Tests that a 100% CPU-consuming loop will react on timeout if it has yields. 71 */ 72 @Test <lambda>null73 fun testYieldBlockingWithTimeout() = runTest { 74 expect(1) 75 val result = withTimeoutOrNull(100) { 76 while (true) { 77 yield() 78 } 79 } 80 assertNull(result) 81 finish(2) 82 } 83 84 @Test testSmallTimeoutnull85 fun testSmallTimeout() = runTest { 86 val channel = Channel<Int>(1) 87 val value = withTimeoutOrNull(1) { 88 channel.receive() 89 } 90 assertNull(value) 91 } 92 93 @Test <lambda>null94 fun testThrowException() = runTest(expected = {it is AssertionError}) { <lambda>null95 withTimeoutOrNull(Long.MAX_VALUE) { 96 throw AssertionError() 97 } 98 } 99 100 @Test testInnerTimeoutnull101 fun testInnerTimeout() = runTest( 102 expected = { it is CancellationException } <lambda>null103 ) { 104 withTimeoutOrNull(1000) { 105 withTimeout(10) { 106 while (true) { 107 yield() 108 } 109 } 110 expectUnreached() // will timeout 111 } 112 expectUnreached() // will timeout 113 } 114 115 @Test testNestedTimeoutnull116 fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { <lambda>null117 withTimeoutOrNull(Long.MAX_VALUE) { 118 // Exception from this withTimeout is not suppressed by withTimeoutOrNull 119 withTimeout(10) { 120 delay(Long.MAX_VALUE) 121 1 122 } 123 } 124 125 expectUnreached() 126 } 127 128 @Test <lambda>null129 fun testOuterTimeout() = runTest { 130 var counter = 0 131 val result = withTimeoutOrNull(250) { 132 while (true) { 133 val inner = withTimeoutOrNull(100) { 134 while (true) { 135 yield() 136 } 137 } 138 assertNull(inner) 139 counter++ 140 } 141 } 142 assertNull(result) 143 check(counter in 1..2) {"Executed: $counter times"} 144 } 145 146 @Test <lambda>null147 fun testBadClass() = runTest { 148 val bad = BadClass() 149 val result = withTimeoutOrNull(100) { 150 bad 151 } 152 assertSame(bad, result) 153 } 154 155 @Test <lambda>null156 fun testNullOnTimeout() = runTest { 157 expect(1) 158 val result = withTimeoutOrNull(100) { 159 expect(2) 160 delay(1000) 161 expectUnreached() 162 "OK" 163 } 164 assertNull(result) 165 finish(3) 166 } 167 168 @Test <lambda>null169 fun testSuppressExceptionWithResult() = runTest { 170 expect(1) 171 val result = withTimeoutOrNull(100) { 172 expect(2) 173 try { 174 delay(1000) 175 } catch (e: CancellationException) { 176 expect(3) 177 } 178 "OK" 179 } 180 assertNull(result) 181 finish(4) 182 } 183 184 @Test <lambda>null185 fun testSuppressExceptionWithAnotherException() = runTest { 186 expect(1) 187 try { 188 withTimeoutOrNull(100) { 189 expect(2) 190 try { 191 delay(1000) 192 } catch (e: CancellationException) { 193 expect(3) 194 throw TestException() 195 } 196 expectUnreached() 197 "OK" 198 } 199 expectUnreached() 200 } catch (e: TestException) { 201 // catches TestException 202 finish(4) 203 204 } 205 } 206 207 @Test <lambda>null208 fun testNegativeTimeout() = runTest { 209 expect(1) 210 var result = withTimeoutOrNull(-1) { 211 expectUnreached() 212 } 213 assertNull(result) 214 result = withTimeoutOrNull(0) { 215 expectUnreached() 216 } 217 assertNull(result) 218 finish(2) 219 } 220 221 @Test <lambda>null222 fun testExceptionFromWithinTimeout() = runTest { 223 expect(1) 224 try { 225 expect(2) 226 withTimeoutOrNull(1000) { 227 expect(3) 228 throw TestException() 229 } 230 expectUnreached() 231 } catch (e: TestException) { 232 finish(4) 233 } 234 } 235 } 236