Zach Klippenstein (he/him) [MOD]
10/18/2022, 6:41 PMContinuationInterceptor
and CoroutineDispatcher
actually have separate “polymorphic” keys. This seems to mean it’s possible to create a coroutine context with a dispatcher A and an interceptor B that wraps A, where if you ask it for the interceptor you will get B but if you ask specifically for the dispatcher you’ll get A.
Has anyone written a blog or anything about gotchas with combinations of this, or done it before and hit snags? I’m seeing some weird behavior in this situation when B tries to wrap a continuation and then ask the wrapped dispatcher to intercept.Zach Klippenstein (he/him) [MOD]
10/19/2022, 4:53 PMadvanceUntilIdle()
isn’t working with runTest(UnconfinedTestDispatcher())
when the ContinuationInterceptor
returns a DispatchedContinuation
. This test fails:
@Test
fun minimalRepro() {
runTest(UnconfinedTestDispatcher()) {
val parentInterceptor = coroutineContext[ContinuationInterceptor]!!
val wrappedInterceptor =
object : AbstractCoroutineContextElement(ContinuationInterceptor),
ContinuationInterceptor {
override fun <T> interceptContinuation(continuation: Continuation<T>) =
// Return continuation directly and the test passes
// (DispatchedContinuation vs Continuation).
parentInterceptor.interceptContinuation(continuation)
}
var entered = false
withContext(wrappedInterceptor) {
launch {
entered = true
}
// OR replace this with yield() and the test passes.
advanceUntilIdle()
assertTrue(entered)
}
}
}
Zach Klippenstein (he/him) [MOD]
10/19/2022, 4:58 PMZach Klippenstein (he/him) [MOD]
10/19/2022, 11:22 PM