1 /*
2  * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 import kotlinx.coroutines.*
6 import kotlinx.coroutines.debug.*
7 import kotlinx.coroutines.debug.internal.*
8 import org.junit.*
9 
10 /**
11  * This is fast but fragile version of [DebugLeaksStressTest] that check reachability of a captured object
12  * in [DebugProbesImpl] via [FieldWalker].
13  */
14 @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
15 class DebugLeaksTest : DebugTestBase() {
16     private class Captured
17 
18     @Test
testIteratorLeaknull19     fun testIteratorLeak() {
20         val captured = Captured()
21         iterator { yield(captured) }
22         assertNoCapturedReference()
23     }
24 
25     @Test
testLazyGlobalCoroutineLeaknull26     fun testLazyGlobalCoroutineLeak() {
27         val captured = Captured()
28         GlobalScope.launch(start = CoroutineStart.LAZY) { println(captured) }
29         assertNoCapturedReference()
30     }
31 
32     @Test
<lambda>null33     fun testLazyCancelledChildCoroutineLeak() = runTest {
34         val captured = Captured()
35         coroutineScope {
36             val child = launch(start = CoroutineStart.LAZY) { println(captured) }
37             child.cancel()
38         }
39         assertNoCapturedReference()
40     }
41 
42     @Test
testAbandonedGlobalCoroutineLeaknull43     fun testAbandonedGlobalCoroutineLeak() {
44         val captured = Captured()
45         GlobalScope.launch {
46             suspendForever()
47             println(captured)
48         }
49         assertNoCapturedReference()
50     }
51 
<lambda>null52     private suspend fun suspendForever() = suspendCancellableCoroutine<Unit> {  }
53 
assertNoCapturedReferencenull54     private fun assertNoCapturedReference() {
55         FieldWalker.assertReachableCount(0, DebugProbesImpl, rootStatics = true) { it is Captured }
56     }
57 }