xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)
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