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 assertEquals(null, 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 assertEquals(null, inner) 139 counter++ 140 } 141 } 142 assertEquals(null, 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 class BadClass { equalsnull156 override fun equals(other: Any?): Boolean = error("Should not be called") 157 override fun hashCode(): Int = error("Should not be called") 158 override fun toString(): String = error("Should not be called") 159 } 160 161 @Test 162 fun testNullOnTimeout() = runTest { 163 expect(1) 164 val result = withTimeoutOrNull(100) { 165 expect(2) 166 delay(1000) 167 expectUnreached() 168 "OK" 169 } 170 assertEquals(null, result) 171 finish(3) 172 } 173 174 @Test <lambda>null175 fun testSuppressExceptionWithResult() = runTest { 176 expect(1) 177 val result = withTimeoutOrNull(100) { 178 expect(2) 179 try { 180 delay(1000) 181 } catch (e: CancellationException) { 182 expect(3) 183 } 184 "OK" 185 } 186 assertEquals(null, result) 187 finish(4) 188 } 189 190 @Test <lambda>null191 fun testSuppressExceptionWithAnotherException() = runTest { 192 expect(1) 193 try { 194 withTimeoutOrNull(100) { 195 expect(2) 196 try { 197 delay(1000) 198 } catch (e: CancellationException) { 199 expect(3) 200 throw TestException() 201 } 202 expectUnreached() 203 "OK" 204 } 205 expectUnreached() 206 } catch (e: TestException) { 207 // catches TestException 208 finish(4) 209 210 } 211 } 212 213 @Test <lambda>null214 fun testNegativeTimeout() = runTest { 215 expect(1) 216 var result = withTimeoutOrNull(-1) { 217 expectUnreached() 218 } 219 assertNull(result) 220 result = withTimeoutOrNull(0) { 221 expectUnreached() 222 } 223 assertNull(result) 224 finish(2) 225 } 226 227 @Test <lambda>null228 fun testExceptionFromWithinTimeout() = runTest { 229 expect(1) 230 try { 231 expect(2) 232 withTimeoutOrNull(1000) { 233 expect(3) 234 throw TestException() 235 } 236 expectUnreached() 237 } catch (e: TestException) { 238 finish(4) 239 } 240 } 241 } 242