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<Unit>(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 @Suppress("UNREACHABLE_CODE") 111 expectUnreached() // will timeout 112 } 113 expectUnreached() // will timeout 114 } 115 116 @Test testNestedTimeoutnull117 fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { <lambda>null118 withTimeoutOrNull(Long.MAX_VALUE) { 119 // Exception from this withTimeout is not suppressed by withTimeoutOrNull 120 withTimeout(10) { 121 delay(Long.MAX_VALUE) 122 1 123 } 124 } 125 126 expectUnreached() 127 } 128 129 @Test <lambda>null130 fun testOuterTimeout() = runTest { 131 var counter = 0 132 val result = withTimeoutOrNull(320) { 133 while (true) { 134 val inner = withTimeoutOrNull(150) { 135 while (true) { 136 yield() 137 } 138 } 139 assertNull(inner) 140 counter++ 141 } 142 } 143 assertNull(result) 144 check(counter in 1..2) {"Executed: $counter times"} 145 } 146 147 @Test <lambda>null148 fun testBadClass() = runTest { 149 val bad = BadClass() 150 val result = withTimeoutOrNull(100) { 151 bad 152 } 153 assertSame(bad, result) 154 } 155 156 @Test <lambda>null157 fun testNullOnTimeout() = runTest { 158 expect(1) 159 val result = withTimeoutOrNull(100) { 160 expect(2) 161 delay(1000) 162 expectUnreached() 163 "OK" 164 } 165 assertNull(result) 166 finish(3) 167 } 168 169 @Test <lambda>null170 fun testSuppressExceptionWithResult() = runTest { 171 expect(1) 172 val result = withTimeoutOrNull(100) { 173 expect(2) 174 try { 175 delay(1000) 176 } catch (e: CancellationException) { 177 expect(3) 178 } 179 "OK" 180 } 181 assertNull(result) 182 finish(4) 183 } 184 185 @Test <lambda>null186 fun testSuppressExceptionWithAnotherException() = runTest { 187 expect(1) 188 try { 189 withTimeoutOrNull(100) { 190 expect(2) 191 try { 192 delay(1000) 193 } catch (e: CancellationException) { 194 expect(3) 195 throw TestException() 196 } 197 expectUnreached() 198 "OK" 199 } 200 expectUnreached() 201 } catch (e: TestException) { 202 // catches TestException 203 finish(4) 204 205 } 206 } 207 208 @Test <lambda>null209 fun testNegativeTimeout() = runTest { 210 expect(1) 211 var result = withTimeoutOrNull(-1) { 212 expectUnreached() 213 } 214 assertNull(result) 215 result = withTimeoutOrNull(0) { 216 expectUnreached() 217 } 218 assertNull(result) 219 finish(2) 220 } 221 222 @Test <lambda>null223 fun testExceptionFromWithinTimeout() = runTest { 224 expect(1) 225 try { 226 expect(2) 227 withTimeoutOrNull(1000) { 228 expect(3) 229 throw TestException() 230 } 231 expectUnreached() 232 } catch (e: TestException) { 233 finish(4) 234 } 235 } 236 } 237