• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 package kotlinx.coroutines.debug
5 
6 import kotlinx.coroutines.*
7 import org.junit.Test
8 import java.util.concurrent.*
9 import java.util.concurrent.atomic.AtomicBoolean
10 import kotlin.test.*
11 
12 class DebugProbesTest : DebugTestBase() {
13 
createDeferrednull14     private fun CoroutineScope.createDeferred(): Deferred<*> = async(NonCancellable) {
15         throw ExecutionException(null)
16     }
17 
18     @Test
<lambda>null19     fun testAsync() = runTest {
20         val deferred = createDeferred()
21         val traces = listOf(
22             "java.util.concurrent.ExecutionException\n" +
23                     "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
24                     "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
25                     "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:49)\n" +
26                     "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:44)\n" +
27                     "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsync\$1.invokeSuspend(DebugProbesTest.kt:17)\n",
28             "Caused by: java.util.concurrent.ExecutionException\n" +
29                     "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
30                     "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)"
31         )
32         nestedMethod(deferred, traces)
33         deferred.join()
34     }
35 
36     @Test
<lambda>null37     fun testAsyncWithProbes() = DebugProbes.withDebugProbes {
38         DebugProbes.sanitizeStackTraces = false
39         runTest {
40             val deferred = createDeferred()
41             val traces = listOf(
42                 "java.util.concurrent.ExecutionException\n" +
43                         "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
44                         "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
45                         "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt)\n" +
46                         "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt)\n" +
47                         "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:62)\n" +
48                         "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
49                         "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)\n" +
50                         "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt)\n" +
51                         "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable\$default(Cancellable.kt)\n" +
52                         "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt)\n" +
53                         "\tat kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt)\n" +
54                         "\tat kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt)\n" +
55                         "\tat kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)\n" +
56                         "\tat kotlinx.coroutines.TestBase.runTest(TestBase.kt)\n" +
57                         "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt)\n" +
58                         "\tat kotlinx.coroutines.debug.DebugProbesTest.testAsyncWithProbes(DebugProbesTest.kt)",
59                 "Caused by: java.util.concurrent.ExecutionException\n" +
60                         "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
61                         "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)\n")
62             nestedMethod(deferred, traces)
63             deferred.join()
64         }
65     }
66 
67     @Test
<lambda>null68     fun testAsyncWithSanitizedProbes() = DebugProbes.withDebugProbes {
69         DebugProbes.sanitizeStackTraces = true
70         runTest {
71             val deferred = createDeferred()
72             val traces = listOf(
73                 "java.util.concurrent.ExecutionException\n" +
74                         "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
75                         "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
76                         "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:71)\n" +
77                         "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:66)\n" +
78                         "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithSanitizedProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:87)\n" +
79                         "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
80                         "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
81                         "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" +
82                         "\tat kotlinx.coroutines.debug.DebugProbesTest.testAsyncWithSanitizedProbes(DebugProbesTest.kt:38)",
83                 "Caused by: java.util.concurrent.ExecutionException\n" +
84                         "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
85                         "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n")
86             nestedMethod(deferred, traces)
87             deferred.join()
88         }
89     }
90 
nestedMethodnull91     private suspend fun nestedMethod(deferred: Deferred<*>, traces: List<String>) {
92         oneMoreNestedMethod(deferred, traces)
93         assertTrue(true) // Prevent tail-call optimization
94     }
95 
oneMoreNestedMethodnull96     private suspend fun oneMoreNestedMethod(deferred: Deferred<*>, traces: List<String>) {
97         try {
98             deferred.await()
99             expectUnreached()
100         } catch (e: ExecutionException) {
101             verifyStackTrace(e, traces)
102         }
103     }
104 
105     @Test
testMultipleConsecutiveProbeResumednull106     fun testMultipleConsecutiveProbeResumed() = runTest {
107         val job = launch {
108             expect(1)
109             foo()
110             expect(4)
111             delay(Long.MAX_VALUE)
112             expectUnreached()
113         }
114         yield()
115         yield()
116         expect(5)
117         val infos = DebugProbes.dumpCoroutinesInfo()
118         assertEquals(2, infos.size)
119         assertEquals(setOf(State.RUNNING, State.SUSPENDED), infos.map { it.state }.toSet())
120         job.cancel()
121         finish(6)
122     }
123 
124     @Test
<lambda>null125     fun testMultipleConsecutiveProbeResumedAndLaterRunning() = runTest {
126         val reachedActiveStage = AtomicBoolean(false)
127         val job = launch(Dispatchers.Default) {
128             expect(1)
129             foo()
130             expect(4)
131             yield()
132             reachedActiveStage.set(true)
133             while (isActive) {
134                 // Spin until test is done
135             }
136         }
137         while (!reachedActiveStage.get()) {
138             delay(10)
139         }
140         expect(5)
141         val infos = DebugProbes.dumpCoroutinesInfo()
142         assertEquals(2, infos.size)
143         assertEquals(setOf(State.RUNNING, State.RUNNING), infos.map { it.state }.toSet())
144         job.cancel()
145         finish(6)
146     }
147 
foonull148     private suspend fun foo() {
149         bar()
150         // Kill TCO
151         expect(3)
152     }
153 
154 
barnull155     private suspend fun bar() {
156         yield()
157         expect(2)
158     }
159 }
160