Skip to content

Commit

Permalink
~ More tests on double invokeOnCancellation calls
Browse files Browse the repository at this point in the history
Removed old TODO
  • Loading branch information
elizarov committed Oct 6, 2020
1 parent 12bba52 commit 3df38e9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,6 @@ internal open class CancellableContinuationImpl<in T>(
// BeforeResumeCancelHandler does not need to be called on a completed continuation
if (cancelHandler is BeforeResumeCancelHandler) return
if (state.cancelled) {
// todo: extra layer of protection against the second invokeOnCancellation
// if (!state.makeHandled()) multipleHandlersError(handler, state)
// Was already cancelled while being dispatched -- invoke the handler directly
callCancelHandler(handler, state.cancelCause)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,59 @@ class CancellableContinuationHandlersTest : TestBase() {
}
}

@Test
fun testSecondSubscriptionAfterCancellation() = runTest {
try {
suspendCancellableCoroutine<Unit> { c ->
// Set IOC first
c.invokeOnCancellation {
assertNull(it)
expect(2)
}
expect(1)
// then cancel (it gets called)
c.cancel()
// then try to install another one
assertFailsWith<IllegalStateException> { c.invokeOnCancellation { expectUnreached() } }
}
} catch (e: CancellationException) {
finish(3)
}
}

@Test
fun testSecondSubscriptionAfterResumeCancelAndDispatch() = runTest {
var cont: CancellableContinuation<Unit>? = null
val job = launch(start = CoroutineStart.UNDISPATCHED) {
// will be cancelled during dispatch
assertFailsWith<CancellationException> {
suspendCancellableCoroutine<Unit> { c ->
cont = c
// Set IOC first -- not called (completed)
c.invokeOnCancellation {
assertTrue(it is CancellationException)
expect(4)
}
expect(1)
}
}
expect(5)
}
expect(2)
// then resume it
cont!!.resume(Unit) // schedule cancelled continuation for dispatch
// then cancel the job during dispatch
job.cancel()
expect(3)
yield() // finish dispatching (will call IOC handler here!)
expect(6)
// then try to install another one after we've done dispatching it
assertFailsWith<IllegalStateException> {
cont!!.invokeOnCancellation { expectUnreached() }
}
finish(7)
}

@Test
fun testDoubleSubscriptionAfterCancellationWithCause() = runTest {
try {
Expand Down

0 comments on commit 3df38e9

Please sign in to comment.