Skip to content

Commit

Permalink
Filter out "java.util.concurrent" frames from debugging test machinery (
Browse files Browse the repository at this point in the history
#3723)

We do rely on java.util.concurrent primitives for rendezvous in tests,
but we cannot rely on their internal stacktraces in tests, thus filtering them out from test data.

Otherwise, tests outcome depends on the underlying JDK version

Fixes #3700
  • Loading branch information
qwwdfsad authored Apr 26, 2023
1 parent ea78820 commit f537089
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
4 changes: 2 additions & 2 deletions kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/*
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package kotlinx.coroutines.debug

import kotlinx.coroutines.*
Expand Down Expand Up @@ -170,7 +169,8 @@ class RunningThreadStackMergeTest : DebugTestBase() {
assertTrue(true)
}

@Test
@Test // IDEA-specific debugger API test
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun testActiveThread() = runBlocking<Unit> {
launchCoroutine()
awaitCoroutineStarted()
Expand Down
23 changes: 19 additions & 4 deletions kotlinx-coroutines-debug/test/StacktraceUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ private fun cleanBlockHoundTraces(frames: List<String>): List<String> {
return result
}

/**
* Removes all frames that contain "java.util.concurrent" in it.
*
* We do leverage Java's locks for proper rendezvous and to fix the coroutine stack's state,
* but this API doesn't have (nor expected to) stable stacktrace, so we are filtering all such
* frames out.
*
* See https://github.com/Kotlin/kotlinx.coroutines/issues/3700 for the example of failure
*/
private fun removeJavaUtilConcurrentTraces(frames: List<String>): List<String> =
frames.filter { !it.contains("java.util.concurrent") }

private data class CoroutineDump(
val header: CoroutineDumpHeader,
val coroutineStackTrace: List<String>,
Expand Down Expand Up @@ -185,7 +197,9 @@ public fun verifyDump(vararg expectedTraces: String, ignoredCoroutine: String? =
.drop(1)
// Parse dumps and filter out ignored coroutines
.mapNotNull { trace ->
val dump = CoroutineDump.parse(trace, traceCleaner = ::cleanBlockHoundTraces)
val dump = CoroutineDump.parse(trace, {
removeJavaUtilConcurrentTraces(cleanBlockHoundTraces(it))
})
if (dump.header.className == ignoredCoroutine) {
null
} else {
Expand All @@ -194,9 +208,10 @@ public fun verifyDump(vararg expectedTraces: String, ignoredCoroutine: String? =
}

assertEquals(expectedTraces.size, dumps.size)
dumps.zip(expectedTraces.map(CoroutineDump::parse)).forEach { (dump, expectedDump) ->
dump.verify(expectedDump)
}
dumps.zip(expectedTraces.map { CoroutineDump.parse(it, ::removeJavaUtilConcurrentTraces) })
.forEach { (dump, expectedDump) ->
dump.verify(expectedDump)
}
}

public fun String.trimPackage() = replace("kotlinx.coroutines.debug.", "")
Expand Down

0 comments on commit f537089

Please sign in to comment.