@@ -6,9 +6,11 @@ package kotlinx.coroutines.exceptions
6
6
7
7
import kotlinx.coroutines.*
8
8
import kotlinx.coroutines.channels.*
9
+ import kotlinx.coroutines.intrinsics.*
9
10
import kotlinx.coroutines.selects.*
10
11
import org.junit.Test
11
12
import java.util.concurrent.*
13
+ import kotlin.coroutines.*
12
14
import kotlin.test.*
13
15
14
16
/*
@@ -271,4 +273,40 @@ class StackTraceRecoveryTest : TestBase() {
271
273
checkCycles(e)
272
274
}
273
275
}
276
+
277
+
278
+ private suspend fun throws () {
279
+ yield () // TCE
280
+ throw RecoverableTestException ()
281
+ }
282
+
283
+ private suspend fun awaiter () {
284
+ val task = GlobalScope .async(Dispatchers .Default , start = CoroutineStart .LAZY ) { throws() }
285
+ task.await()
286
+ yield () // TCE
287
+ }
288
+
289
+ @Test
290
+ fun testNonDispatchedRecovery () {
291
+ val await = suspend { awaiter() }
292
+
293
+ val barrier = CyclicBarrier (2 )
294
+ var exception: Throwable ? = null
295
+ await.startCoroutineUnintercepted(Continuation (EmptyCoroutineContext ) {
296
+ exception = it.exceptionOrNull()
297
+ barrier.await()
298
+ })
299
+
300
+ barrier.await()
301
+ val e = exception
302
+ assertNotNull(e)
303
+ verifyStackTrace(e, " kotlinx.coroutines.RecoverableTestException\n " +
304
+ " \t at kotlinx.coroutines.exceptions.StackTraceRecoveryTest.throws(StackTraceRecoveryTest.kt:280)\n " +
305
+ " \t at kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$ throws\$ 1.invokeSuspend(StackTraceRecoveryTest.kt)\n " +
306
+ " \t (Coroutine boundary)\n " +
307
+ " \t at kotlinx.coroutines.DeferredCoroutine.await\$ suspendImpl(Builders.common.kt:99)\n " +
308
+ " \t at kotlinx.coroutines.exceptions.StackTraceRecoveryTest.awaiter(StackTraceRecoveryTest.kt:285)\n " +
309
+ " \t at kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$ testNonDispatchedRecovery\$ await\$ 1.invokeSuspend(StackTraceRecoveryTest.kt:291)\n " +
310
+ " Caused by: kotlinx.coroutines.RecoverableTestException" )
311
+ }
274
312
}
0 commit comments