@@ -14,6 +14,7 @@ import kotlin.jvm.*
14
14
import kotlin.time.*
15
15
import kotlin.time.Duration.Companion.milliseconds
16
16
import kotlin.time.Duration.Companion.seconds
17
+ import kotlinx.coroutines.internal.*
17
18
18
19
/* *
19
20
* A test result.
@@ -309,19 +310,13 @@ public fun TestScope.runTest(
309
310
it.start(CoroutineStart .UNDISPATCHED , it) {
310
311
testBody()
311
312
}
312
- /* *
313
- * The thread in which the task was last seen executing.
314
- */
315
- val lastKnownPosition = MutableStateFlow <Any ?>(null )
316
-
317
313
/* *
318
314
* We run the tasks in the test coroutine using [Dispatchers.Default]. On JS, this does nothing particularly,
319
315
* but on the JVM and Native, this means that the timeout can be processed even while the test runner is busy
320
316
* doing some synchronous work.
321
317
*/
322
318
val workRunner = launch(Dispatchers .Default + CoroutineName (" kotlinx.coroutines.test runner" )) {
323
319
while (true ) {
324
- lastKnownPosition.value = getLastKnownPosition()
325
320
val executedSomething = testScheduler.tryRunNextTaskUnless { ! isActive }
326
321
if (executedSomething) {
327
322
/* * yield to check for cancellation. On JS, we can't use [ensureActive] here, as the cancellation
@@ -355,19 +350,13 @@ public fun TestScope.runTest(
355
350
}
356
351
timeoutError = UncompletedCoroutinesError (message)
357
352
dumpCoroutines()
358
- /* *
359
- * There's a race that may lead to the misleading results here, but it's better than nothing.
360
- * The race: `lastKnownPosition` is read, then the task executed in `workRunner` completes,
361
- * then `updateStacktrace` does its thing, but the thread is already busy doing something else.
362
- */
363
- updateStacktrace(timeoutError, lastKnownPosition.value)
364
- val cancellationException = CancellationException (" The test timed out" , timeoutError)
353
+ val cancellationException = CancellationException (" The test timed out" )
365
354
(it as Job ).cancel(cancellationException)
366
355
// we can't abandon the work we're doing, so if it hanged, we'll still hang, despite the timeout.
367
356
it.join()
368
- it.getCompletionExceptionOrNull()?. let { exception ->
369
- if (exception != = cancellationException)
370
- timeoutError.addSuppressed(exception )
357
+ val completion = it.getCompletionExceptionOrNull()
358
+ if (completion != null && completion != = cancellationException) {
359
+ timeoutError.addSuppressed(completion )
371
360
}
372
361
workRunner.cancelAndJoin()
373
362
} finally {
@@ -578,8 +567,4 @@ internal fun throwAll(head: Throwable?, other: List<Throwable>) {
578
567
}
579
568
}
580
569
581
- internal expect fun getLastKnownPosition (): Any?
582
-
583
570
internal expect fun dumpCoroutines ()
584
-
585
- internal expect fun updateStacktrace (exception : Throwable , lastKnownPosition : Any? ): Throwable
0 commit comments