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