mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
The playback/queue wall-clock awaits have flaked on the 4-vCPU GitHub runner at exactly the 30s limit, a different test each time. That is a stall, not slowness: the suite finishes ~80s for 795 tests, so no test is anywhere near 30s normally. The JUnit XML holds the stacks but is not uploaded, leaving the failures undiagnosable from the CI log. Put every thread's stack in the failure message, which Gradle prints.
32 lines
1.2 KiB
Kotlin
32 lines
1.2 KiB
Kotlin
package com.subtracks
|
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Job
|
|
import kotlinx.coroutines.cancelAndJoin
|
|
import kotlinx.coroutines.runBlocking
|
|
import org.junit.Assert.fail
|
|
|
|
const val TEST_TIMEOUT_MS = 30_000L
|
|
|
|
fun cancelAndJoinBlocking(vararg scopes: CoroutineScope) {
|
|
runBlocking { scopes.forEach { it.coroutineContext[Job]?.cancelAndJoin() } }
|
|
}
|
|
|
|
fun awaitUntil(
|
|
message: String,
|
|
predicate: () -> Boolean,
|
|
) {
|
|
val deadline = System.nanoTime() + TEST_TIMEOUT_MS * 1_000_000
|
|
while (!predicate() && System.nanoTime() < deadline) Thread.sleep(10)
|
|
if (predicate()) return
|
|
// A wall-clock wait that expires means something stalled rather than ran slow: the suite
|
|
// finishes in milliseconds per test. Print every thread's stack in the failure message so the
|
|
// stall is diagnosable from the CI log, which shows exception messages but not the test XML.
|
|
fail("Timed out after ${TEST_TIMEOUT_MS}ms $message\n\n${threadDump()}")
|
|
}
|
|
|
|
private fun threadDump(): String =
|
|
Thread.getAllStackTraces().entries.joinToString("\n\n") { (thread, frames) ->
|
|
"${thread.name} [${thread.state}]\n" + frames.joinToString("\n") { " at $it" }
|
|
}
|