xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-debug/test/DebugLeaksTest.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)
1 import kotlinx.coroutines.testing.*
2 import kotlinx.coroutines.*
3 import kotlinx.coroutines.debug.*
4 import kotlinx.coroutines.debug.internal.*
5 import org.junit.*
6 
7 /**
8  * This is fast but fragile version of [DebugLeaksStressTest] that check reachability of a captured object
9  * in [DebugProbesImpl] via [FieldWalker].
10  */
11 @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
12 class DebugLeaksTest : DebugTestBase() {
13     private class Captured
14 
15     @Test
testIteratorLeaknull16     fun testIteratorLeak() {
17         val captured = Captured()
18         iterator { yield(captured) }
19         assertNoCapturedReference()
20     }
21 
22     @Test
testLazyGlobalCoroutineLeaknull23     fun testLazyGlobalCoroutineLeak() {
24         val captured = Captured()
25         GlobalScope.launch(start = CoroutineStart.LAZY) { println(captured) }
26         assertNoCapturedReference()
27     }
28 
29     @Test
<lambda>null30     fun testLazyCancelledChildCoroutineLeak() = runTest {
31         val captured = Captured()
32         coroutineScope {
33             val child = launch(start = CoroutineStart.LAZY) { println(captured) }
34             child.cancel()
35         }
36         assertNoCapturedReference()
37     }
38 
39     @Test
testAbandonedGlobalCoroutineLeaknull40     fun testAbandonedGlobalCoroutineLeak() {
41         val captured = Captured()
42         GlobalScope.launch {
43             suspendForever()
44             println(captured)
45         }
46         assertNoCapturedReference()
47     }
48 
<lambda>null49     private suspend fun suspendForever() = suspendCancellableCoroutine<Unit> {  }
50 
assertNoCapturedReferencenull51     private fun assertNoCapturedReference() {
52         FieldWalker.assertReachableCount(0, DebugProbesImpl, rootStatics = true) { it is Captured }
53     }
54 }
55