1 2 @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913 3 4 package kotlinx.coroutines 5 6 import kotlinx.coroutines.testing.* 7 import kotlinx.coroutines.channels.* 8 import kotlin.test.* 9 10 class WithTimeoutOrNullTest : TestBase() { 11 /** 12 * Tests a case of no timeout and no suspension inside. 13 */ 14 @Test <lambda>null15 fun testBasicNoSuspend() = runTest { 16 expect(1) 17 val result = withTimeoutOrNull(10_000) { 18 expect(2) 19 "OK" 20 } 21 assertEquals("OK", result) 22 finish(3) 23 } 24 25 /** 26 * Tests a case of no timeout and one suspension inside. 27 */ 28 @Test <lambda>null29 fun testBasicSuspend() = runTest { 30 expect(1) 31 val result = withTimeoutOrNull(10_000) { 32 expect(2) 33 yield() 34 expect(3) 35 "OK" 36 } 37 assertEquals("OK", result) 38 finish(4) 39 } 40 41 /** 42 * Tests property dispatching of `withTimeoutOrNull` blocks 43 */ 44 @Test <lambda>null45 fun testDispatch() = runTest { 46 expect(1) 47 launch { 48 expect(4) 49 yield() // back to main 50 expect(7) 51 } 52 expect(2) 53 // test that it does not yield to the above job when started 54 val result = withTimeoutOrNull(1000) { 55 expect(3) 56 yield() // yield only now 57 expect(5) 58 "OK" 59 } 60 assertEquals("OK", result) 61 expect(6) 62 yield() // back to launch 63 finish(8) 64 } 65 66 /** 67 * Tests that a 100% CPU-consuming loop will react on timeout if it has yields. 68 */ 69 @Test <lambda>null70 fun testYieldBlockingWithTimeout() = runTest { 71 expect(1) 72 val result = withTimeoutOrNull(100) { 73 while (true) { 74 yield() 75 } 76 } 77 assertNull(result) 78 finish(2) 79 } 80 81 @Test testSmallTimeoutnull82 fun testSmallTimeout() = runTest { 83 val channel = Channel<Int>(1) 84 val value = withTimeoutOrNull(1) { 85 channel.receive() 86 } 87 assertNull(value) 88 } 89 90 @Test <lambda>null91 fun testThrowException() = runTest(expected = {it is AssertionError}) { <lambda>null92 withTimeoutOrNull<Unit>(Long.MAX_VALUE) { 93 throw AssertionError() 94 } 95 } 96 97 @Test testInnerTimeoutnull98 fun testInnerTimeout() = runTest( 99 expected = { it is CancellationException } <lambda>null100 ) { 101 withTimeoutOrNull(1000) { 102 withTimeout(10) { 103 while (true) { 104 yield() 105 } 106 } 107 @Suppress("UNREACHABLE_CODE") 108 expectUnreached() // will timeout 109 } 110 expectUnreached() // will timeout 111 } 112 113 @Test testNestedTimeoutnull114 fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { <lambda>null115 withTimeoutOrNull(Long.MAX_VALUE) { 116 // Exception from this withTimeout is not suppressed by withTimeoutOrNull 117 withTimeout(10) { 118 delay(Long.MAX_VALUE) 119 1 120 } 121 } 122 123 expectUnreached() 124 } 125 126 @Test <lambda>null127 fun testOuterTimeout() = runTest { 128 if (isJavaAndWindows) return@runTest 129 var counter = 0 130 val result = withTimeoutOrNull(320) { 131 while (true) { 132 val inner = withTimeoutOrNull(150) { 133 while (true) { 134 yield() 135 } 136 } 137 assertNull(inner) 138 counter++ 139 } 140 } 141 assertNull(result) 142 check(counter in 1..2) {"Executed: $counter times"} 143 } 144 145 @Test <lambda>null146 fun testBadClass() = runTest { 147 val bad = BadClass() 148 val result = withTimeoutOrNull(100) { 149 bad 150 } 151 assertSame(bad, result) 152 } 153 154 @Test <lambda>null155 fun testNullOnTimeout() = runTest { 156 expect(1) 157 val result = withTimeoutOrNull(100) { 158 expect(2) 159 delay(1000) 160 expectUnreached() 161 "OK" 162 } 163 assertNull(result) 164 finish(3) 165 } 166 167 @Test <lambda>null168 fun testSuppressExceptionWithResult() = runTest { 169 expect(1) 170 val result = withTimeoutOrNull(100) { 171 expect(2) 172 try { 173 delay(1000) 174 } catch (e: CancellationException) { 175 expect(3) 176 } 177 "OK" 178 } 179 assertNull(result) 180 finish(4) 181 } 182 183 @Test <lambda>null184 fun testSuppressExceptionWithAnotherException() = runTest { 185 expect(1) 186 try { 187 withTimeoutOrNull(100) { 188 expect(2) 189 try { 190 delay(1000) 191 } catch (e: CancellationException) { 192 expect(3) 193 throw TestException() 194 } 195 expectUnreached() 196 "OK" 197 } 198 expectUnreached() 199 } catch (e: TestException) { 200 // catches TestException 201 finish(4) 202 203 } 204 } 205 206 @Test <lambda>null207 fun testNegativeTimeout() = runTest { 208 expect(1) 209 var result = withTimeoutOrNull(-1) { 210 expectUnreached() 211 } 212 assertNull(result) 213 result = withTimeoutOrNull(0) { 214 expectUnreached() 215 } 216 assertNull(result) 217 finish(2) 218 } 219 220 @Test <lambda>null221 fun testExceptionFromWithinTimeout() = runTest { 222 expect(1) 223 try { 224 expect(2) 225 withTimeoutOrNull(1000) { 226 expect(3) 227 throw TestException() 228 } 229 expectUnreached() 230 } catch (e: TestException) { 231 finish(4) 232 } 233 } 234 } 235