diff options
author | Aurimas Liutikas <aurimas@google.com> | 2021-08-17 16:49:58 -0700 |
---|---|---|
committer | Aurimas Liutikas <aurimas@google.com> | 2021-08-18 08:57:44 -0700 |
commit | 531d55eaeac09ad6cde55687ef802d4235040985 (patch) | |
tree | 747e5be83c6e6a2e2d9a164ebd03c5e45e6ec952 /reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt | |
parent | b5da2582b1f1d46a92cc6ceeb1525788addd5944 (diff) | |
parent | b231887c3214187cf7f09a74073f84383a487b71 (diff) | |
download | platform_external_kotlinx.coroutines-531d55eaeac09ad6cde55687ef802d4235040985.tar.gz platform_external_kotlinx.coroutines-531d55eaeac09ad6cde55687ef802d4235040985.tar.bz2 platform_external_kotlinx.coroutines-531d55eaeac09ad6cde55687ef802d4235040985.zip |
Merge Kotlin coroutines 1.5.1HEADandroid-s-beta-5masterandroid-s-beta-5
https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.5.1
Test: mmma external/kotlinx.coroutines
Change-Id: I7de89ccc26113be895f28935addb27ee07e50ee7
Diffstat (limited to 'reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt')
-rw-r--r-- | reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt | 158 |
1 files changed, 130 insertions, 28 deletions
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt index 1a36a389..3682d5e3 100644 --- a/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt +++ b/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.jdk9 import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* import org.junit.Test import java.util.concurrent.Flow as JFlow import kotlin.test.* @@ -121,44 +122,110 @@ class PublishTest : TestBase() { finish(7) } + /** Tests that, as soon as `ProducerScope.close` is called, `isClosedForSend` starts returning `true`. */ @Test - fun testOnNextError() = runTest { + fun testChannelClosing() = runTest { expect(1) - val publisher = flowPublish(currentDispatcher()) { + val publisher = flowPublish<Int>(Dispatchers.Unconfined) { + expect(3) + close() + assert(isClosedForSend) expect(4) - try { - send("OK") - } catch(e: Throwable) { - expect(6) - assert(e is TestException) - } } - expect(2) + try { + expect(2) + publisher.awaitFirstOrNull() + } catch (e: CancellationException) { + expect(5) + } + finish(6) + } + + @Test + fun testOnNextError() = runTest { val latch = CompletableDeferred<Unit>() - publisher.subscribe(object : JFlow.Subscriber<String> { - override fun onComplete() { - expectUnreached() + expect(1) + assertCallsExceptionHandlerWith<TestException> { exceptionHandler -> + val publisher = flowPublish(currentDispatcher() + exceptionHandler) { + expect(4) + try { + send("OK") + } catch (e: Throwable) { + expect(6) + assert(e is TestException) + assert(isClosedForSend) + latch.complete(Unit) + } } + expect(2) + publisher.subscribe(object : JFlow.Subscriber<String> { + override fun onComplete() { + expectUnreached() + } - override fun onSubscribe(s: JFlow.Subscription) { - expect(3) - s.request(1) - } + override fun onSubscribe(s: JFlow.Subscription) { + expect(3) + s.request(1) + } - override fun onNext(t: String) { - expect(5) - assertEquals("OK", t) - throw TestException() - } + override fun onNext(t: String) { + expect(5) + assertEquals("OK", t) + throw TestException() + } - override fun onError(t: Throwable) { - expect(7) - assert(t is TestException) - latch.complete(Unit) + override fun onError(t: Throwable) { + expectUnreached() + } + }) + latch.await() + } + finish(7) + } + + /** Tests the behavior when a call to `onNext` fails after the channel is already closed. */ + @Test + fun testOnNextErrorAfterCancellation() = runTest { + assertCallsExceptionHandlerWith<TestException> { handler -> + var producerScope: ProducerScope<Int>? = null + CompletableDeferred<Unit>() + expect(1) + var job: Job? = null + val publisher = flowPublish<Int>(handler + Dispatchers.Unconfined) { + producerScope = this + expect(4) + job = launch { + delay(Long.MAX_VALUE) + } } - }) - latch.await() - finish(8) + expect(2) + publisher.subscribe(object: JFlow.Subscriber<Int> { + override fun onSubscribe(s: JFlow.Subscription) { + expect(3) + s.request(Long.MAX_VALUE) + } + override fun onNext(t: Int) { + expect(6) + assertEquals(1, t) + job!!.cancel() + throw TestException() + } + override fun onError(t: Throwable?) { + /* Correct changes to the implementation could lead to us entering or not entering this method, but + it only matters that if we do, it is the "correct" exception that was validly used to cancel the + coroutine that gets passed here and not `TestException`. */ + assertTrue(t is CancellationException) + } + override fun onComplete() { expectUnreached() } + }) + expect(5) + val result: ChannelResult<Unit> = producerScope!!.trySend(1) + val e = result.exceptionOrNull()!! + assertTrue(e is CancellationException, "The actual error: $e") + assertTrue(producerScope!!.isClosedForSend) + assertTrue(result.isFailure) + } + finish(7) } @Test @@ -182,4 +249,39 @@ class PublishTest : TestBase() { fun testIllegalArgumentException() { assertFailsWith<IllegalArgumentException> { flowPublish<Int>(Job()) { } } } + + /** Tests that `trySend` doesn't throw in `flowPublish`. */ + @Test + fun testTrySendNotThrowing() = runTest { + var producerScope: ProducerScope<Int>? = null + expect(1) + val publisher = flowPublish<Int>(Dispatchers.Unconfined) { + producerScope = this + expect(3) + delay(Long.MAX_VALUE) + } + val job = launch(start = CoroutineStart.UNDISPATCHED) { + expect(2) + publisher.awaitFirstOrNull() + expectUnreached() + } + job.cancel() + expect(4) + val result = producerScope!!.trySend(1) + assertTrue(result.isFailure) + finish(5) + } + + /** Tests that all methods on `flowPublish` fail without closing the channel when attempting to emit `null`. */ + @Test + fun testEmittingNull() = runTest { + val publisher = flowPublish { + assertFailsWith<NullPointerException> { send(null) } + assertFailsWith<NullPointerException> { trySend(null) } + @Suppress("DEPRECATION") + assertFailsWith<NullPointerException> { offer(null) } + send("OK") + } + assertEquals("OK", publisher.awaitFirstOrNull()) + } }
\ No newline at end of file |