All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonTest.CancellableContinuationHandlersTest.kt Maven / Gradle / Ivy

There is a newer version: 1.9.0
Show newest version
/*
 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913

package kotlinx.coroutines

import kotlin.coroutines.*
import kotlin.test.*

class CancellableContinuationHandlersTest : TestBase() {

    @Test
    fun testDoubleSubscription() = runTest({ it is IllegalStateException }) {
        suspendCancellableCoroutine { c ->
            c.invokeOnCancellation { finish(1) }
            c.invokeOnCancellation { expectUnreached() }
        }
    }

    @Test
    fun testDoubleSubscriptionAfterCompletion() = runTest {
        suspendCancellableCoroutine { c ->
            c.resume(Unit)
            // First invokeOnCancellation is Ok
            c.invokeOnCancellation { expectUnreached() }
            // Second invokeOnCancellation is not allowed
            assertFailsWith { c.invokeOnCancellation { expectUnreached() } }
        }
    }

    @Test
    fun testDoubleSubscriptionAfterCompletionWithException() = runTest {
        assertFailsWith {
            suspendCancellableCoroutine { c ->
                c.resumeWithException(TestException())
                // First invokeOnCancellation is Ok
                c.invokeOnCancellation { expectUnreached() }
                // Second invokeOnCancellation is not allowed
                assertFailsWith { c.invokeOnCancellation { expectUnreached() } }
            }
        }
    }

    @Test
    fun testDoubleSubscriptionAfterCancellation() = runTest {
        try {
            suspendCancellableCoroutine { c ->
                c.cancel()
                c.invokeOnCancellation {
                    assertTrue(it is CancellationException)
                    expect(1)
                }
                assertFailsWith { c.invokeOnCancellation { expectUnreached() } }
            }
        } catch (e: CancellationException) {
            finish(2)
        }
    }

    @Test
    fun testSecondSubscriptionAfterCancellation() = runTest {
        try {
            suspendCancellableCoroutine { 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 { c.invokeOnCancellation { expectUnreached() } }
            }
        } catch (e: CancellationException) {
            finish(3)
        }
    }

    @Test
    fun testSecondSubscriptionAfterResumeCancelAndDispatch() = runTest {
        var cont: CancellableContinuation? = null
        val job = launch(start = CoroutineStart.UNDISPATCHED) {
            // will be cancelled during dispatch
            assertFailsWith {
                suspendCancellableCoroutine { 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 {
            cont!!.invokeOnCancellation { expectUnreached() }
        }
        finish(7)
    }

    @Test
    fun testDoubleSubscriptionAfterCancellationWithCause() = runTest {
        try {
            suspendCancellableCoroutine { c ->
                c.cancel(AssertionError())
                c.invokeOnCancellation {
                    require(it is AssertionError)
                    expect(1)
                }
                assertFailsWith { c.invokeOnCancellation { expectUnreached() } }
            }
        } catch (e: AssertionError) {
            finish(2)
        }
    }

    @Test
    fun testDoubleSubscriptionMixed() = runTest {
        try {
            suspendCancellableCoroutine { c ->
                c.invokeOnCancellation {
                    require(it is IndexOutOfBoundsException)
                    expect(1)
                }
                c.cancel(IndexOutOfBoundsException())
                assertFailsWith { c.invokeOnCancellation { expectUnreached() } }
            }
        } catch (e: IndexOutOfBoundsException) {
            finish(2)
        }
    }

    @Test
    fun testExceptionInHandler() = runTest(
        unhandled = listOf({ it -> it is CompletionHandlerException })
    ) {
        expect(1)
        try {
            suspendCancellableCoroutine { c ->
                c.invokeOnCancellation { throw AssertionError() }
                c.cancel()
            }
        } catch (e: CancellationException) {
            expect(2)
        }
        finish(3)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy