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 }