Skip to content

Commit b550afa

Browse files
committed
Specify exception types, add tests on it
1 parent 64be795 commit b550afa

File tree

7 files changed

+65
-4
lines changed

7 files changed

+65
-4
lines changed

kotlinx-coroutines-core/common/src/flow/Builders.kt

-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ public fun <T> flowViaChannel(
219219
bufferSize: Int = 16,
220220
@BuilderInference block: suspend (SendChannel<T>) -> Unit
221221
): Flow<T> {
222-
require(bufferSize >= 0) { "Buffer size should be positive, but was $bufferSize" }
223222
return flow {
224223
coroutineScope {
225224
val channel = Channel<T>(bufferSize)

kotlinx-coroutines-core/common/src/flow/operators/Context.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import kotlinx.coroutines.flow.unsafeFlow as flow
3434
* This operator uses a channel of the specific [bufferSize] in order to switch between contexts,
3535
* but it is not guaranteed that the channel will be created, implementation is free to optimize it away in case of fusing.
3636
*
37-
* @throws [IllegalStateException] if provided context contains [Job] instance.
37+
* @throws [IllegalArgumentException] if provided context contains [Job] instance.
3838
*/
3939
@FlowPreview
4040
public fun <T> Flow<T>.flowOn(flowContext: CoroutineContext, bufferSize: Int = 16): Flow<T> {
@@ -88,7 +88,7 @@ public fun <T> Flow<T>.flowOn(flowContext: CoroutineContext, bufferSize: Int = 1
8888
* This operator uses channel of the specific [bufferSize] in order to switch between contexts,
8989
* but it is not guaranteed that channel will be created, implementation is free to optimize it away in case of fusing.
9090
*
91-
* @throws [IllegalStateException] if provided context contains [Job] instance.
91+
* @throws [IllegalArgumentException] if provided context contains [Job] instance.
9292
*/
9393
@FlowPreview
9494
public fun <T, R> Flow<T>.flowWith(

kotlinx-coroutines-core/common/src/flow/operators/Limit.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import kotlin.jvm.*
1414

1515
/**
1616
* Returns a flow that ignores first [count] elements.
17+
* Throws [IllegalArgumentException] if [count] is negative.
1718
*/
1819
@FlowPreview
1920
public fun <T> Flow<T>.drop(count: Int): Flow<T> {
@@ -45,10 +46,12 @@ public fun <T> Flow<T>.dropWhile(predicate: suspend (T) -> Boolean): Flow<T> = f
4546
/**
4647
* Returns a flow that contains first [count] elements.
4748
* When [count] elements are consumed, the original flow is cancelled.
49+
* Throws [IllegalArgumentException] if [count] is negative.
4850
*/
4951
@FlowPreview
5052
public fun <T> Flow<T>.take(count: Int): Flow<T> {
51-
require(count > 0) { "Take count should be positive, but had $count" }
53+
require(count >= 0) { "Requested element count $count is less than zero." }
54+
if (count == 0) return emptyFlow()
5255
return flow {
5356
var consumed = 0
5457
try {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines.flow
6+
7+
import kotlinx.coroutines.*
8+
import kotlinx.coroutines.channels.*
9+
import kotlin.test.*
10+
11+
class FlowViaChannelTest : TestBase() {
12+
@Test
13+
fun testRegular() = runTest {
14+
val flow = flowViaChannel<Int> {
15+
it.send(1)
16+
it.send(2)
17+
it.close()
18+
}
19+
assertEquals(listOf(1, 2), flow.toList())
20+
}
21+
22+
@Test
23+
fun testConflated() = runTest {
24+
val flow = flowViaChannel<Int>(bufferSize = Channel.CONFLATED) {
25+
it.send(1)
26+
it.send(2)
27+
it.close()
28+
}
29+
assertEquals(listOf(1), flow.toList())
30+
}
31+
}

kotlinx-coroutines-core/common/test/flow/operators/DropTest.kt

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ class DropTest : TestBase() {
2727
assertEquals(0, flowOf<Int>().drop(1).sum())
2828
}
2929

30+
@Test
31+
fun testNegativeCount() {
32+
assertFailsWith<IllegalArgumentException> {
33+
emptyFlow<Int>().drop(-1)
34+
}
35+
}
36+
3037
@Test
3138
fun testErrorCancelsUpstream() = runTest {
3239
val flow = flow {

kotlinx-coroutines-core/common/test/flow/operators/FlowContextTest.kt

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package kotlinx.coroutines.flow
66

77
import kotlinx.coroutines.*
88
import kotlinx.coroutines.channels.*
9+
import kotlin.coroutines.*
910
import kotlin.test.*
1011

1112
class FlowContextTest : TestBase() {
@@ -142,4 +143,14 @@ class FlowContextTest : TestBase() {
142143
finish(7)
143144
ensureActive()
144145
}
146+
147+
@Test
148+
fun testIllegalArgumentException() {
149+
val flow = emptyFlow<Int>()
150+
assertFailsWith<IllegalArgumentException> { flow.flowOn(Job()) }
151+
assertFailsWith<IllegalArgumentException> { flow.flowWith(Job()) { this } }
152+
assertFailsWith<IllegalArgumentException> { flow.flowOn(EmptyCoroutineContext, bufferSize = -1) }
153+
assertFailsWith<IllegalArgumentException> { flow.flowWith(EmptyCoroutineContext, bufferSize = -1) { this } }
154+
155+
}
145156
}

kotlinx-coroutines-core/common/test/flow/operators/TakeTest.kt

+10
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ class TakeTest : TestBase() {
2727
assertEquals(0, sum)
2828
}
2929

30+
@Test
31+
fun testNonPositiveValues() = runTest {
32+
val flow = flowOf(1)
33+
assertFailsWith<IllegalArgumentException> {
34+
flow.take(-1)
35+
}
36+
37+
assertNull(flow.take(0).singleOrNull())
38+
}
39+
3040
@Test
3141
fun testCancelUpstream() = runTest {
3242
var cancelled = false

0 commit comments

Comments
 (0)