1 /* <lambda>null2 * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines.test 6 7 import kotlinx.coroutines.* 8 import kotlin.test.* 9 10 @Suppress("DEPRECATION") 11 class TestRunBlockingTest { 12 13 @Test 14 fun delay_advancesTimeAutomatically() = runBlockingTest { 15 assertRunsFast { 16 delay(SLOW) 17 } 18 } 19 20 @Test 21 fun callingSuspendWithDelay_advancesAutomatically() = runBlockingTest { 22 suspend fun withDelay(): Int { 23 delay(SLOW) 24 return 3 25 } 26 27 assertRunsFast { 28 assertEquals(3, withDelay()) 29 } 30 } 31 32 @Test 33 fun launch_advancesAutomatically() = runBlockingTest { 34 val job = launch { 35 delay(SLOW) 36 } 37 assertRunsFast { 38 job.join() 39 assertTrue(job.isCompleted) 40 } 41 } 42 43 @Test 44 fun async_advancesAutomatically() = runBlockingTest { 45 val deferred = async { 46 delay(SLOW) 47 3 48 } 49 50 assertRunsFast { 51 assertEquals(3, deferred.await()) 52 } 53 } 54 55 @Test 56 fun whenUsingTimeout_triggersWhenDelayed() { 57 assertFailsWith<TimeoutCancellationException> { 58 runBlockingTest { 59 assertRunsFast { 60 withTimeout(SLOW) { 61 delay(SLOW) 62 } 63 } 64 } 65 } 66 } 67 68 @Test 69 fun whenUsingTimeout_doesNotTriggerWhenFast() = runBlockingTest { 70 assertRunsFast { 71 withTimeout(SLOW) { 72 delay(0) 73 } 74 } 75 } 76 77 @Test 78 fun whenUsingTimeout_triggersWhenWaiting() { 79 assertFailsWith<TimeoutCancellationException> { 80 runBlockingTest { 81 val uncompleted = CompletableDeferred<Unit>() 82 assertRunsFast { 83 withTimeout(SLOW) { 84 uncompleted.await() 85 } 86 } 87 } 88 } 89 } 90 91 @Test 92 fun whenUsingTimeout_doesNotTriggerWhenComplete() = runBlockingTest { 93 val completed = CompletableDeferred<Unit>() 94 assertRunsFast { 95 completed.complete(Unit) 96 withTimeout(SLOW) { 97 completed.await() 98 } 99 } 100 } 101 102 @Test 103 fun testDelayInAsync_withAwait() = runBlockingTest { 104 assertRunsFast { 105 val deferred = async { 106 delay(SLOW) 107 3 108 } 109 assertEquals(3, deferred.await()) 110 } 111 } 112 113 @Test 114 fun whenUsingTimeout_inAsync_triggersWhenDelayed() { 115 assertFailsWith<TimeoutCancellationException> { 116 runBlockingTest { 117 val deferred = async { 118 withTimeout(SLOW) { 119 delay(SLOW) 120 } 121 } 122 123 assertRunsFast { 124 deferred.await() 125 } 126 } 127 } 128 } 129 130 @Test 131 fun whenUsingTimeout_inAsync_doesNotTriggerWhenNotDelayed() = runBlockingTest { 132 val deferred = async { 133 withTimeout(SLOW) { 134 delay(0) 135 } 136 } 137 138 assertRunsFast { 139 deferred.await() 140 } 141 } 142 143 @Test 144 fun whenUsingTimeout_inLaunch_triggersWhenDelayed() { 145 assertFailsWith<TimeoutCancellationException> { 146 runBlockingTest { 147 val job = launch { 148 withTimeout(1) { 149 delay(SLOW + 1) 150 } 151 } 152 153 assertRunsFast { 154 job.join() 155 throw job.getCancellationException() 156 } 157 } 158 } 159 } 160 161 @Test 162 fun whenUsingTimeout_inLaunch_doesNotTriggerWhenNotDelayed() = runBlockingTest { 163 val job = launch { 164 withTimeout(SLOW) { 165 delay(0) 166 } 167 } 168 169 assertRunsFast { 170 job.join() 171 assertTrue(job.isCompleted) 172 } 173 } 174 175 @Test 176 fun throwingException_throws() { 177 assertFailsWith<IllegalArgumentException> { 178 runBlockingTest { 179 assertRunsFast { 180 delay(SLOW) 181 throw IllegalArgumentException("Test") 182 } 183 } 184 } 185 } 186 187 @Test 188 fun throwingException_inLaunch_throws() { 189 assertFailsWith<IllegalArgumentException> { 190 runBlockingTest { 191 val job = launch { 192 delay(SLOW) 193 throw IllegalArgumentException("Test") 194 } 195 196 assertRunsFast { 197 job.join() 198 throw job.getCancellationException().cause ?: AssertionError("expected exception") 199 } 200 } 201 } 202 } 203 204 @Test 205 fun throwingException__inAsync_throws() { 206 assertFailsWith<IllegalArgumentException> { 207 runBlockingTest { 208 val deferred: Deferred<Unit> = async { 209 delay(SLOW) 210 throw IllegalArgumentException("Test") 211 } 212 213 assertRunsFast { 214 deferred.await() 215 } 216 } 217 } 218 } 219 220 @Test 221 fun callingLaunchFunction_executesLaunchBlockImmediately() = runBlockingTest { 222 assertRunsFast { 223 var executed = false 224 launch { 225 delay(SLOW) 226 executed = true 227 } 228 229 delay(SLOW) 230 assertTrue(executed) 231 } 232 } 233 234 @Test 235 fun callingAsyncFunction_executesAsyncBlockImmediately() = runBlockingTest { 236 assertRunsFast { 237 var executed = false 238 val deferred = async { 239 delay(SLOW) 240 executed = true 241 } 242 advanceTimeBy(SLOW) 243 244 assertTrue(deferred.isCompleted) 245 assertTrue(executed) 246 } 247 } 248 249 @Test 250 fun nestingBuilders_executesSecondLevelImmediately() = runBlockingTest { 251 assertRunsFast { 252 var levels = 0 253 launch { 254 delay(SLOW) 255 levels++ 256 launch { 257 delay(SLOW) 258 levels++ 259 } 260 } 261 advanceUntilIdle() 262 263 assertEquals(2, levels) 264 } 265 } 266 267 @Test 268 fun testCancellationException() = runBlockingTest { 269 var actual: CancellationException? = null 270 val uncompleted = CompletableDeferred<Unit>() 271 val job = launch { 272 actual = kotlin.runCatching { uncompleted.await() }.exceptionOrNull() as? CancellationException 273 } 274 275 assertNull(actual) 276 job.cancel() 277 assertNotNull(actual) 278 } 279 280 @Test 281 fun testCancellationException_notThrown() = runBlockingTest { 282 val uncompleted = CompletableDeferred<Unit>() 283 val job = launch { 284 uncompleted.await() 285 } 286 287 job.cancel() 288 job.join() 289 } 290 291 @Test 292 fun whenACoroutineLeaks_errorIsThrown() { 293 assertFailsWith<UncompletedCoroutinesError> { 294 runBlockingTest { 295 val uncompleted = CompletableDeferred<Unit>() 296 launch { 297 uncompleted.await() 298 } 299 } 300 } 301 } 302 303 @Test 304 fun runBlockingTestBuilder_throwsOnBadDispatcher() { 305 assertFailsWith<IllegalArgumentException> { 306 runBlockingTest(Dispatchers.Default) { 307 308 } 309 } 310 } 311 312 @Test 313 fun runBlockingTestBuilder_throwsOnBadHandler() { 314 assertFailsWith<IllegalArgumentException> { 315 runBlockingTest(CoroutineExceptionHandler { _, _ -> }) { 316 317 } 318 } 319 } 320 321 @Test 322 fun pauseDispatcher_disablesAutoAdvance_forCurrent() = runBlockingTest { 323 var mutable = 0 324 pauseDispatcher { 325 launch { 326 mutable++ 327 } 328 assertEquals(0, mutable) 329 runCurrent() 330 assertEquals(1, mutable) 331 } 332 } 333 334 @Test 335 fun pauseDispatcher_disablesAutoAdvance_forDelay() = runBlockingTest { 336 var mutable = 0 337 pauseDispatcher { 338 launch { 339 mutable++ 340 delay(SLOW) 341 mutable++ 342 } 343 assertEquals(0, mutable) 344 runCurrent() 345 assertEquals(1, mutable) 346 advanceTimeBy(SLOW) 347 assertEquals(2, mutable) 348 } 349 } 350 351 @Test 352 fun pauseDispatcher_withDelay_resumesAfterPause() = runBlockingTest { 353 var mutable = 0 354 assertRunsFast { 355 pauseDispatcher { 356 delay(1_000) 357 mutable++ 358 } 359 } 360 assertEquals(1, mutable) 361 } 362 363 364 @Test 365 fun testWithTestContextThrowingAnAssertionError() { 366 assertFailsWith<TestException> { 367 runBlockingTest { 368 val expectedError = TestException("hello") 369 370 launch { 371 throw expectedError 372 } 373 374 // don't rethrow or handle the exception 375 } 376 } 377 } 378 379 @Test 380 fun testExceptionHandlingWithLaunch() { 381 assertFailsWith<TestException> { 382 runBlockingTest { 383 val expectedError = TestException("hello") 384 385 launch { 386 throw expectedError 387 } 388 } 389 } 390 } 391 392 @Test 393 fun testExceptions_notThrownImmediately() { 394 assertFailsWith<TestException> { 395 runBlockingTest { 396 val expectedException = TestException("hello") 397 val result = runCatching { 398 launch { 399 throw expectedException 400 } 401 } 402 runCurrent() 403 assertEquals(true, result.isSuccess) 404 } 405 } 406 } 407 408 409 private val exceptionHandler = TestCoroutineExceptionHandler() 410 411 @Test 412 fun testPartialContextOverride() = runBlockingTest(CoroutineName("named")) { 413 assertEquals(CoroutineName("named"), coroutineContext[CoroutineName]) 414 assertNotNull(coroutineContext[CoroutineExceptionHandler]) 415 assertNotSame(coroutineContext[CoroutineExceptionHandler], exceptionHandler) 416 } 417 418 @Test 419 fun testPartialDispatcherOverride() { 420 assertFailsWith<IllegalArgumentException> { 421 runBlockingTest(Dispatchers.Unconfined) { 422 fail("Unreached") 423 } 424 } 425 } 426 427 @Test 428 fun testOverrideExceptionHandler() = runBlockingTest(exceptionHandler) { 429 assertSame(coroutineContext[CoroutineExceptionHandler], exceptionHandler) 430 } 431 432 @Test 433 fun testOverrideExceptionHandlerError() { 434 assertFailsWith<IllegalArgumentException> { 435 runBlockingTest(CoroutineExceptionHandler { _, _ -> }) { 436 fail("Unreached") 437 } 438 } 439 } 440 }