• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines
6 
7 import org.junit.Test
8 import java.util.concurrent.CountDownLatch
9 import java.util.concurrent.atomic.AtomicReference
10 import kotlin.coroutines.*
11 
12 // Stresses scenario from #3613
13 class ReusableCancellableContinuationInvariantStressTest : TestBase() {
14 
15     // Tests have a timeout 10 sec because the bug they catch leads to an infinite spin-loop
16 
17     @Test(timeout = 10_000)
<lambda>null18     fun testExceptionFromSuspendReusable() = doTest { /* nothing */ }
19 
20 
21     @Test(timeout = 10_000)
<lambda>null22     fun testExceptionFromCancelledSuspendReusable() = doTest { it.cancel() }
23 
24 
25     @Suppress("SuspendFunctionOnCoroutineScope")
doTestnull26     private inline fun doTest(crossinline block: (Job) -> Unit) {
27         runTest {
28             repeat(10_000) {
29                 val latch = CountDownLatch(1)
30                 val continuationToResume = AtomicReference<Continuation<Unit>?>(null)
31                 val j1 = launch(Dispatchers.Default) {
32                     latch.await()
33                     suspendCancellableCoroutineReusable {
34                         continuationToResume.set(it)
35                         block(coroutineContext.job)
36                         throw CancellationException() // Don't let getResult() chance to execute
37                     }
38                 }
39 
40                 val j2 = launch(Dispatchers.Default) {
41                     latch.await()
42                     while (continuationToResume.get() == null) {
43                         // spin
44                     }
45                     continuationToResume.get()!!.resume(Unit)
46                 }
47 
48                 latch.countDown()
49                 joinAll(j1, j2)
50             }
51         }
52     }
53 }
54