• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
2 package kotlinx.coroutines.debug
3 
4 import kotlinx.coroutines.testing.*
5 import com.google.gson.*
6 import kotlinx.coroutines.*
7 import kotlinx.coroutines.debug.internal.*
8 import org.junit.Test
9 import kotlin.coroutines.*
10 import kotlin.test.*
11 
12 @ExperimentalStdlibApi
13 class DumpCoroutineInfoAsJsonAndReferencesTest : DebugTestBase() {
14     private data class CoroutineInfoFromJson(
15         val name: String?,
16         val id: Long?,
17         val dispatcher: String?,
18         val sequenceNumber: Long?,
19         val state: String?
20     )
21 
22     @Test
testDumpOfUnnamedCoroutinenull23     fun testDumpOfUnnamedCoroutine() =
24         runTestWithNamedDeferred(name = null)
25 
26     @Test
27     fun testDumpOfNamedCoroutine() =
28         runTestWithNamedDeferred("Name")
29 
30     @Test
31     fun testDumpOfNamedCoroutineWithSpecialCharacters() =
32         runTestWithNamedDeferred("Name with\n \"special\" characters\\/\t\b")
33 
34     @Test
35     fun testDumpWithNoCoroutines() {
36         val dumpResult = DebugProbesImpl.dumpCoroutinesInfoAsJsonAndReferences()
37         assertEquals(dumpResult.size, 4)
38         assertIsEmptyArray(dumpResult[1])
39         assertIsEmptyArray(dumpResult[2])
40         assertIsEmptyArray(dumpResult[3])
41     }
42 
assertIsEmptyArraynull43     private fun assertIsEmptyArray(obj: Any) =
44         assertTrue(obj is Array<*> && obj.isEmpty())
45 
46     private fun runTestWithNamedDeferred(name: String?) = runTest {
47         val context = if (name == null) EmptyCoroutineContext else CoroutineName(name)
48         val deferred = async(context) {
49             suspendingMethod()
50             assertTrue(true)
51         }
52         yield()
53         verifyDump()
54         deferred.cancelAndJoin()
55     }
56 
suspendingMethodnull57     private suspend fun suspendingMethod() {
58         delay(Long.MAX_VALUE)
59     }
60 
verifyDumpnull61     private fun verifyDump() {
62         val dumpResult = DebugProbesImpl.dumpCoroutinesInfoAsJsonAndReferences()
63 
64         assertEquals(dumpResult.size, 4)
65 
66         val coroutinesInfoAsJsonString = dumpResult[0]
67         val lastObservedThreads = dumpResult[1]
68         val lastObservedFrames = dumpResult[2]
69         val coroutinesInfo = dumpResult[3]
70 
71         assertIs<String>(coroutinesInfoAsJsonString)
72         assertIs<Array<*>>(lastObservedThreads)
73         assertIs<Array<*>>(lastObservedFrames)
74         assertIs<Array<*>>(coroutinesInfo)
75 
76         val coroutinesInfoFromJson =
77             Gson().fromJson(coroutinesInfoAsJsonString, Array<CoroutineInfoFromJson>::class.java)
78 
79         val size = coroutinesInfo.size
80         assertTrue(size != 0)
81         assertEquals(size, coroutinesInfoFromJson.size)
82         assertEquals(size, lastObservedFrames.size)
83         assertEquals(size, lastObservedThreads.size)
84 
85         for (i in 0 until size) {
86             val info = coroutinesInfo[i]
87             val infoFromJson = coroutinesInfoFromJson[i]
88             assertIs<DebugCoroutineInfo>(info)
89             assertEquals(info.lastObservedThread, lastObservedThreads[i])
90             assertEquals(info.lastObservedFrame, lastObservedFrames[i])
91             assertEquals(info.sequenceNumber, infoFromJson.sequenceNumber)
92             assertEquals(info.state, infoFromJson.state)
93             val context = info.context
94             assertEquals(context[CoroutineName.Key]?.name, infoFromJson.name)
95             assertEquals(context[CoroutineId.Key]?.id, infoFromJson.id)
96             assertEquals(context[CoroutineDispatcher.Key]?.toString(), infoFromJson.dispatcher)
97         }
98     }
99 }
100