diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt index 674f8322f2..a21ec47fc3 100644 --- a/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt +++ b/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt @@ -71,7 +71,7 @@ public suspend fun Flow.single(): T { * The terminal operator, that awaits for one and only one value to be published. * Throws [IllegalStateException] for flow that contains more than one element. */ -public suspend fun Flow.singleOrNull(): T? { +public suspend fun Flow.singleOrNull(): T? { var result: T? = null collect { value -> if (result != null) error("Expected only one element") @@ -124,7 +124,7 @@ public suspend fun Flow.first(predicate: suspend (T) -> Boolean): T { * The terminal operator that returns the first element emitted by the flow and then cancels flow's collection. * Returns `null` if the flow was empty. */ -public suspend fun Flow.firstOrNull(): T? { +public suspend fun Flow.firstOrNull(): T? { var result: T? = null try { collect { value -> @@ -138,10 +138,10 @@ public suspend fun Flow.firstOrNull(): T? { } /** - * The terminal operator that returns the first element emitted by the flow matching the given [predicate] and then cancels flow's collection. + * The terminal operator that returns the first element emitted by the flow matching the given [predicate] and then cancels flow's collection. * Returns `null` if the flow did not contain an element matching the [predicate]. */ -public suspend fun Flow.firstOrNull(predicate: suspend (T) -> Boolean): T? { +public suspend fun Flow.firstOrNull(predicate: suspend (T) -> Boolean): T? { var result: T? = null try { collect { value -> diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt index f737a1d0de..e78cd1d321 100644 --- a/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt @@ -127,6 +127,12 @@ class FirstTest : TestBase() { assertNull(emptyFlow().firstOrNull { true }) } + @Test + fun testFirstOrNullWithNullElement() = runTest { + assertNull(flowOf(null).firstOrNull()) + assertNull(flowOf(null).firstOrNull { true }) + } + @Test fun testFirstOrNullWhenErrorCancelsUpstream() = runTest { val latch = Channel() diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt index 4e89b93bd7..dd9857c7aa 100644 --- a/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt @@ -7,7 +7,7 @@ package kotlinx.coroutines.flow import kotlinx.coroutines.* import kotlin.test.* -class SingleTest : TestBase() { +class SingleTest : TestBase() { @Test fun testSingle() = runTest { @@ -61,6 +61,10 @@ class SingleTest : TestBase() { assertEquals(1, flowOf(1).single()) assertNull(flowOf(null).single()) assertFailsWith { flowOf().single() } + + assertEquals(1, flowOf(1).singleOrNull()) + assertNull(flowOf(null).singleOrNull()) + assertNull(flowOf().singleOrNull()) } @Test