1 @file:Suppress("PackageDirectoryMismatch") 2 package definitely.not.kotlinx.coroutines 3 4 import kotlinx.coroutines.testing.* 5 import kotlinx.coroutines.* 6 import kotlinx.coroutines.debug.* 7 import kotlinx.coroutines.selects.* 8 import org.junit.* 9 import org.junit.Test 10 import java.util.concurrent.* 11 import kotlin.test.* 12 13 class SanitizedProbesTest : DebugTestBase() { 14 @Before setUpnull15 override fun setUp() { 16 super.setUp() 17 DebugProbes.sanitizeStackTraces = true 18 DebugProbes.enableCreationStackTraces = true 19 } 20 21 @Test <lambda>null22 fun testRecoveredStackTrace() = runTest { 23 val deferred = createDeferred() 24 val traces = listOf( 25 "java.util.concurrent.ExecutionException\n" + 26 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$createDeferredNested\$1.invokeSuspend(SanitizedProbesTest.kt:97)\n" + 27 "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" + 28 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.oneMoreNestedMethod(SanitizedProbesTest.kt:67)\n" + 29 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.nestedMethod(SanitizedProbesTest.kt:61)\n" + 30 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testRecoveredStackTrace\$1.invokeSuspend(SanitizedProbesTest.kt:50)\n" + 31 "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" + 32 "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + 33 "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + 34 "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:141)\n" + 35 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testRecoveredStackTrace(SanitizedProbesTest.kt:33)", 36 "Caused by: java.util.concurrent.ExecutionException\n" + 37 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$createDeferredNested\$1.invokeSuspend(SanitizedProbesTest.kt:57)\n" + 38 "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" 39 ) 40 nestedMethod(deferred, traces) 41 deferred.join() 42 } 43 44 @Test <lambda>null45 fun testCoroutinesDump() = runTest { 46 val deferred = createActiveDeferred() 47 yield() 48 verifyDump( 49 "Coroutine \"coroutine#3\":BlockingCoroutine{Active}@7d68ef40, state: RUNNING\n" + 50 "\tat java.lang.Thread.getStackTrace(Thread.java)\n" + 51 "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" + 52 "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + 53 "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + 54 "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:141)\n" + 55 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testCoroutinesDump(SanitizedProbesTest.kt:56)", 56 57 "Coroutine \"coroutine#4\":DeferredCoroutine{Active}@75c072cb, state: SUSPENDED\n" + 58 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$createActiveDeferred\$1.invokeSuspend(SanitizedProbesTest.kt:63)\n" + 59 "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" + 60 "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + 61 "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + 62 "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt)\n" + 63 "\tat kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + 64 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.createActiveDeferred(SanitizedProbesTest.kt:62)\n" + 65 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$createActiveDeferred(SanitizedProbesTest.kt:16)\n" + 66 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testCoroutinesDump\$1.invokeSuspend(SanitizedProbesTest.kt:57)\n" + 67 "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" + 68 "\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:237)\n" + 69 "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:141)\n" + 70 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testCoroutinesDump(SanitizedProbesTest.kt:56)" 71 ) 72 deferred.cancelAndJoin() 73 } 74 75 @Test <lambda>null76 fun testSelectBuilder() = runTest { 77 val selector = launchSelector() 78 expect(1) 79 yield() 80 expect(3) 81 verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@35fc6dc4, state: RUNNING\n" + 82 "\tat java.lang.Thread.getStackTrace(Thread.java:1552)\n" + // Skip the rest 83 "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" + 84 "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", 85 86 "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@1b68b9a4, state: SUSPENDED\n" + 87 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1\$1\$1.invokeSuspend(SanitizedProbesTest.kt)\n" + 88 "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" + 89 "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + 90 "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)\n" + 91 "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.launch\$default(Builders.common.kt)\n" + 92 "\tat kotlinx.coroutines.BuildersKt.launch\$default(Unknown Source)\n" + 93 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.launchSelector(SanitizedProbesTest.kt:100)\n" + 94 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$launchSelector(SanitizedProbesTest.kt:16)\n" + 95 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testSelectBuilder\$1.invokeSuspend(SanitizedProbesTest.kt:89)\n" + 96 "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" + 97 "\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:233)\n" + 98 "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:154)\n" + 99 "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testSelectBuilder(SanitizedProbesTest.kt:88)") 100 finish(4) 101 selector.cancelAndJoin() 102 } 103 launchSelectornull104 private fun CoroutineScope.launchSelector(): Job { 105 val job = CompletableDeferred(Unit) 106 return launch { 107 select<Int> { 108 job.onJoin { 109 expect(2) 110 delay(Long.MAX_VALUE) 111 1 112 } 113 } 114 } 115 } 116 <lambda>null117 private fun CoroutineScope.createActiveDeferred(): Deferred<*> = async { 118 suspendingMethod() 119 assertTrue(true) 120 } 121 suspendingMethodnull122 private suspend fun suspendingMethod() { 123 delay(Long.MAX_VALUE) 124 } 125 createDeferrednull126 private fun CoroutineScope.createDeferred(): Deferred<*> = createDeferredNested() 127 128 private fun CoroutineScope.createDeferredNested(): Deferred<*> = async(NonCancellable) { 129 throw ExecutionException(null) 130 } 131 nestedMethodnull132 private suspend fun nestedMethod(deferred: Deferred<*>, traces: List<String>) { 133 oneMoreNestedMethod(deferred, traces) 134 assertTrue(true) // Prevent tail-call optimization 135 } 136 oneMoreNestedMethodnull137 private suspend fun oneMoreNestedMethod(deferred: Deferred<*>, traces: List<String>) { 138 try { 139 deferred.await() 140 expectUnreached() 141 } catch (e: ExecutionException) { 142 verifyStackTrace(e, traces) 143 } 144 } 145 } 146