parent
b3f1edc369
commit
72df4c0ff6
@ -2,8 +2,7 @@ object Versions {
|
|||||||
const val dokka = "1.6.10"
|
const val dokka = "1.6.10"
|
||||||
const val kotlin = "1.6.10"
|
const val kotlin = "1.6.10"
|
||||||
const val kotlinBenchmark = "0.4.1"
|
const val kotlinBenchmark = "0.4.1"
|
||||||
const val kotlinCoroutines = "1.5.2"
|
const val kotlinCoroutines = "1.6.0"
|
||||||
const val kotlinCoroutinesTest = "1.5.2"
|
|
||||||
const val ktor = "2.0.0-beta-1"
|
const val ktor = "2.0.0-beta-1"
|
||||||
const val logback = "1.2.3"
|
const val logback = "1.2.3"
|
||||||
const val versionsPlugin = "0.41.0"
|
const val versionsPlugin = "0.41.0"
|
||||||
|
@ -24,6 +24,7 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("test-common"))
|
implementation(kotlin("test-common"))
|
||||||
implementation(kotlin("test-annotations-common"))
|
implementation(kotlin("test-annotations-common"))
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.kotlinCoroutines}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +32,6 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("test-junit"))
|
implementation(kotlin("test-junit"))
|
||||||
implementation(kotlin("test"))
|
implementation(kotlin("test"))
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.kotlinCoroutinesTest}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,30 +40,6 @@ kotlin {
|
|||||||
implementation(kotlin("test-js"))
|
implementation(kotlin("test-js"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val nativeTest by creating {
|
|
||||||
dependsOn(commonTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
val linuxX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
val mingwX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
val macosX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
val iosX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
val iosArm64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package com.github.michaelbull.result.coroutines
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Workaround to use suspending functions in unit tests for multiplatform/native projects.
|
|
||||||
* Solution was found here: https://github.com/Kotlin/kotlinx.coroutines/issues/885#issuecomment-446586161
|
|
||||||
*/
|
|
||||||
expect fun runBlockingTest(
|
|
||||||
context: CoroutineContext = EmptyCoroutineContext,
|
|
||||||
testBody: suspend CoroutineScope.() -> Unit
|
|
||||||
)
|
|
@ -3,19 +3,21 @@ package com.github.michaelbull.result.coroutines.binding
|
|||||||
import com.github.michaelbull.result.Err
|
import com.github.michaelbull.result.Err
|
||||||
import com.github.michaelbull.result.Ok
|
import com.github.michaelbull.result.Ok
|
||||||
import com.github.michaelbull.result.Result
|
import com.github.michaelbull.result.Result
|
||||||
import com.github.michaelbull.result.coroutines.runBlockingTest
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
class SuspendableBindingTest {
|
class SuspendableBindingTest {
|
||||||
|
|
||||||
private object BindingError
|
private object BindingError
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsOkIfAllBindsSuccessful() {
|
fun returnsOkIfAllBindsSuccessful() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(1)
|
delay(1)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -26,23 +28,20 @@ class SuspendableBindingTest {
|
|||||||
return Ok(2)
|
return Ok(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = provideX().bind()
|
val x = provideX().bind()
|
||||||
val y = provideY().bind()
|
val y = provideY().bind()
|
||||||
x + y
|
x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Ok)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = 3,
|
expected = Ok(3),
|
||||||
actual = result.value
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsOkIfAllBindsOfDifferentTypeAreSuccessful() {
|
fun returnsOkIfAllBindsOfDifferentTypeAreSuccessful() = runTest {
|
||||||
suspend fun provideX(): Result<String, BindingError> {
|
suspend fun provideX(): Result<String, BindingError> {
|
||||||
delay(1)
|
delay(1)
|
||||||
return Ok("1")
|
return Ok("1")
|
||||||
@ -53,23 +52,20 @@ class SuspendableBindingTest {
|
|||||||
return Ok(x + 2)
|
return Ok(x + 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = provideX().bind()
|
val x = provideX().bind()
|
||||||
val y = provideY(x.toInt()).bind()
|
val y = provideY(x.toInt()).bind()
|
||||||
y
|
y
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Ok)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = 3,
|
expected = Ok(3),
|
||||||
actual = result.value
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsFirstErrIfBindingFailed() {
|
fun returnsFirstErrIfBindingFailed() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(1)
|
delay(1)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -85,7 +81,6 @@ class SuspendableBindingTest {
|
|||||||
return Ok(2)
|
return Ok(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = provideX().bind()
|
val x = provideX().bind()
|
||||||
val y = provideY().bind()
|
val y = provideY().bind()
|
||||||
@ -93,19 +88,18 @@ class SuspendableBindingTest {
|
|||||||
x + y + z
|
x + y + z
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError,
|
expected = Err(BindingError),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsStateChangedUntilFirstBindFailed() {
|
fun returnsStateChangedUntilFirstBindFailed() = runTest {
|
||||||
var xStateChange = false
|
var xStateChange = false
|
||||||
var yStateChange = false
|
var yStateChange = false
|
||||||
var zStateChange = false
|
var zStateChange = false
|
||||||
|
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(1)
|
delay(1)
|
||||||
xStateChange = true
|
xStateChange = true
|
||||||
@ -124,7 +118,6 @@ class SuspendableBindingTest {
|
|||||||
return Err(BindingError)
|
return Err(BindingError)
|
||||||
}
|
}
|
||||||
|
|
||||||
runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = provideX().bind()
|
val x = provideX().bind()
|
||||||
val y = provideY().bind()
|
val y = provideY().bind()
|
||||||
@ -132,19 +125,18 @@ class SuspendableBindingTest {
|
|||||||
x + y + z
|
x + y + z
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError,
|
expected = Err(BindingError),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
|
|
||||||
assertTrue(xStateChange)
|
assertTrue(xStateChange)
|
||||||
assertTrue(yStateChange)
|
assertTrue(yStateChange)
|
||||||
assertFalse(zStateChange)
|
assertFalse(zStateChange)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsFirstErrIfBindingsOfDifferentTypesFailed() {
|
fun returnsFirstErrIfBindingsOfDifferentTypesFailed() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(1)
|
delay(1)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -160,7 +152,6 @@ class SuspendableBindingTest {
|
|||||||
return Ok(2)
|
return Ok(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = provideX().bind()
|
val x = provideX().bind()
|
||||||
val y = provideY().bind()
|
val y = provideY().bind()
|
||||||
@ -168,11 +159,9 @@ class SuspendableBindingTest {
|
|||||||
x + y.toInt() + z
|
x + y.toInt() + z
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError,
|
expected = Err(BindingError),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package com.github.michaelbull.result.coroutines
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.promise
|
|
||||||
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
actual fun runBlockingTest(context: CoroutineContext, testBody: suspend CoroutineScope.() -> Unit): dynamic {
|
|
||||||
return GlobalScope.promise(context) {
|
|
||||||
testBody(this)
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,14 +3,16 @@ package com.github.michaelbull.result.coroutines.binding
|
|||||||
import com.github.michaelbull.result.Err
|
import com.github.michaelbull.result.Err
|
||||||
import com.github.michaelbull.result.Ok
|
import com.github.michaelbull.result.Ok
|
||||||
import com.github.michaelbull.result.Result
|
import com.github.michaelbull.result.Result
|
||||||
import com.github.michaelbull.result.coroutines.runBlockingTest
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
class AsyncSuspendableBindingTest {
|
class AsyncSuspendableBindingTest {
|
||||||
|
|
||||||
private sealed class BindingError {
|
private sealed class BindingError {
|
||||||
@ -19,7 +21,7 @@ class AsyncSuspendableBindingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsOkIfAllBindsSuccessful(): dynamic {
|
fun returnsOkIfAllBindsSuccessful() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(100)
|
delay(100)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -30,22 +32,20 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Ok(2)
|
return Ok(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = async { provideX().bind() }
|
val x = async { provideX().bind() }
|
||||||
val y = async { provideY().bind() }
|
val y = async { provideY().bind() }
|
||||||
x.await() + y.await()
|
x.await() + y.await()
|
||||||
}
|
}
|
||||||
assertTrue(result is Ok)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = 3,
|
expected = Ok(3),
|
||||||
actual = result.value
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsFirstErrIfBindingFailed(): dynamic {
|
fun returnsFirstErrIfBindingFailed() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(10)
|
delay(10)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -61,7 +61,6 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Err(BindingError.BindingErrorB)
|
return Err(BindingError.BindingErrorB)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = async { provideX().bind() }
|
val x = async { provideX().bind() }
|
||||||
val y = async { provideY().bind() }
|
val y = async { provideY().bind() }
|
||||||
@ -69,19 +68,18 @@ class AsyncSuspendableBindingTest {
|
|||||||
x.await() + y.await() + z.await()
|
x.await() + y.await() + z.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError.BindingErrorB,
|
expected = Err(BindingError.BindingErrorB),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsStateChangedForOnlyTheFirstAsyncBindFailWhenEagerlyCancellingBinding(): dynamic {
|
fun returnsStateChangedForOnlyTheFirstAsyncBindFailWhenEagerlyCancellingBinding() = runTest {
|
||||||
var xStateChange = false
|
var xStateChange = false
|
||||||
var yStateChange = false
|
var yStateChange = false
|
||||||
var zStateChange = false
|
var zStateChange = false
|
||||||
|
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(20)
|
delay(20)
|
||||||
xStateChange = true
|
xStateChange = true
|
||||||
@ -100,7 +98,6 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Err(BindingError.BindingErrorB)
|
return Err(BindingError.BindingErrorB)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = async { provideX().bind() }
|
val x = async { provideX().bind() }
|
||||||
val y = async { provideY().bind() }
|
val y = async { provideY().bind() }
|
||||||
@ -109,14 +106,13 @@ class AsyncSuspendableBindingTest {
|
|||||||
x.await() + y.await() + z.await()
|
x.await() + y.await() + z.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError.BindingErrorB,
|
expected = Err(BindingError.BindingErrorB),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
|
|
||||||
assertFalse(xStateChange)
|
assertFalse(xStateChange)
|
||||||
assertFalse(yStateChange)
|
assertFalse(yStateChange)
|
||||||
assertTrue(zStateChange)
|
assertTrue(zStateChange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package com.github.michaelbull.result.coroutines
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
actual fun runBlockingTest(context: CoroutineContext, testBody: suspend CoroutineScope.() -> Unit) {
|
|
||||||
return runBlocking {
|
|
||||||
testBody(this)
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.test.runBlockingTest
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
@ -17,7 +18,7 @@ import kotlin.test.assertNull
|
|||||||
class RunSuspendCatchingTest {
|
class RunSuspendCatchingTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun propagatesCoroutineCancellation() = runBlockingTest {
|
fun propagatesCoroutineCancellation() = runTest(UnconfinedTestDispatcher()) {
|
||||||
var value: String? = null
|
var value: String? = null
|
||||||
|
|
||||||
launch(CoroutineName("outer scope")) {
|
launch(CoroutineName("outer scope")) {
|
||||||
@ -31,7 +32,8 @@ class RunSuspendCatchingTest {
|
|||||||
result.onSuccess { value = it }
|
result.onSuccess { value = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
advanceTimeBy(2_000)
|
testScheduler.advanceTimeBy(2_000)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
// Cancel outer scope, which should cancel inner scope
|
// Cancel outer scope, which should cancel inner scope
|
||||||
cancel()
|
cancel()
|
||||||
@ -41,7 +43,7 @@ class RunSuspendCatchingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsOkIfInvocationSuccessful() = runBlockingTest {
|
fun returnsOkIfInvocationSuccessful() = runTest {
|
||||||
val block = { "example" }
|
val block = { "example" }
|
||||||
val result = runSuspendCatching(block)
|
val result = runSuspendCatching(block)
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ class RunSuspendCatchingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsErrIfInvocationFailsWithAnythingOtherThanCancellationException() = runBlockingTest {
|
fun returnsErrIfInvocationFailsWithAnythingOtherThanCancellationException() = runTest {
|
||||||
val exception = IllegalArgumentException("throw me")
|
val exception = IllegalArgumentException("throw me")
|
||||||
val block = { throw exception }
|
val block = { throw exception }
|
||||||
val result = runSuspendCatching(block)
|
val result = runSuspendCatching(block)
|
||||||
|
@ -5,11 +5,10 @@ import com.github.michaelbull.result.Ok
|
|||||||
import com.github.michaelbull.result.Result
|
import com.github.michaelbull.result.Result
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.runBlockingTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
@ -24,7 +23,7 @@ class AsyncSuspendableBindingTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsOkIfAllBindsSuccessful() {
|
fun returnsOkIfAllBindsSuccessful() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(100)
|
delay(100)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -35,23 +34,20 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Ok(2)
|
return Ok(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = async { provideX().bind() }
|
val x = async { provideX().bind() }
|
||||||
val y = async { provideY().bind() }
|
val y = async { provideY().bind() }
|
||||||
x.await() + y.await()
|
x.await() + y.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Ok)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = 3,
|
expected = Ok(3),
|
||||||
actual = result.value
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsFirstErrIfBindingFailed() {
|
fun returnsFirstErrIfBindingFailed() = runTest {
|
||||||
suspend fun provideX(): Result<Int, BindingError> {
|
suspend fun provideX(): Result<Int, BindingError> {
|
||||||
delay(3)
|
delay(3)
|
||||||
return Ok(1)
|
return Ok(1)
|
||||||
@ -67,7 +63,6 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Err(BindingError.BindingErrorB)
|
return Err(BindingError.BindingErrorB)
|
||||||
}
|
}
|
||||||
|
|
||||||
runBlockingTest {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = async { provideX().bind() }
|
val x = async { provideX().bind() }
|
||||||
val y = async { provideY().bind() }
|
val y = async { provideY().bind() }
|
||||||
@ -75,16 +70,14 @@ class AsyncSuspendableBindingTest {
|
|||||||
x.await() + y.await() + z.await()
|
x.await() + y.await() + z.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError.BindingErrorB,
|
expected = Err(BindingError.BindingErrorB),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsStateChangedForOnlyTheFirstAsyncBindFailWhenEagerlyCancellingBinding() {
|
fun returnsStateChangedForOnlyTheFirstAsyncBindFailWhenEagerlyCancellingBinding() = runTest {
|
||||||
var xStateChange = false
|
var xStateChange = false
|
||||||
var yStateChange = false
|
var yStateChange = false
|
||||||
|
|
||||||
@ -100,29 +93,30 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Err(BindingError.BindingErrorB)
|
return Err(BindingError.BindingErrorB)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dispatcherA = TestCoroutineDispatcher()
|
val dispatcherA = StandardTestDispatcher(testScheduler)
|
||||||
val dispatcherB = TestCoroutineDispatcher()
|
val dispatcherB = StandardTestDispatcher(testScheduler)
|
||||||
|
|
||||||
runBlocking {
|
|
||||||
val result = binding<Int, BindingError> {
|
val result = binding<Int, BindingError> {
|
||||||
val x = async(dispatcherA) { provideX().bind() }
|
val x = async(dispatcherA) { provideX().bind() }
|
||||||
val y = async(dispatcherB) { provideY().bind() }
|
val y = async(dispatcherB) { provideY().bind() }
|
||||||
dispatcherA.advanceTimeBy(2)
|
|
||||||
|
testScheduler.advanceTimeBy(2)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
x.await() + y.await()
|
x.await() + y.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError.BindingErrorA,
|
expected = Err(BindingError.BindingErrorA),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
|
|
||||||
assertTrue(xStateChange)
|
assertTrue(xStateChange)
|
||||||
assertFalse(yStateChange)
|
assertFalse(yStateChange)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsStateChangedForOnlyTheFirstLaunchBindFailWhenEagerlyCancellingBinding() {
|
fun returnsStateChangedForOnlyTheFirstLaunchBindFailWhenEagerlyCancellingBinding() = runTest {
|
||||||
var xStateChange = false
|
var xStateChange = false
|
||||||
var yStateChange = false
|
var yStateChange = false
|
||||||
var zStateChange = false
|
var zStateChange = false
|
||||||
@ -145,27 +139,31 @@ class AsyncSuspendableBindingTest {
|
|||||||
return Err(BindingError.BindingErrorB)
|
return Err(BindingError.BindingErrorB)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dispatcherA = TestCoroutineDispatcher()
|
val dispatcherA = StandardTestDispatcher(testScheduler)
|
||||||
val dispatcherB = TestCoroutineDispatcher()
|
val dispatcherB = StandardTestDispatcher(testScheduler)
|
||||||
val dispatcherC = TestCoroutineDispatcher()
|
val dispatcherC = StandardTestDispatcher(testScheduler)
|
||||||
|
|
||||||
runBlocking {
|
|
||||||
val result = binding<Unit, BindingError> {
|
val result = binding<Unit, BindingError> {
|
||||||
launch(dispatcherA) { provideX().bind() }
|
launch(dispatcherA) { provideX().bind() }
|
||||||
dispatcherA.advanceTimeBy(20)
|
|
||||||
|
testScheduler.advanceTimeBy(20)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
launch(dispatcherB) { provideY().bind() }
|
launch(dispatcherB) { provideY().bind() }
|
||||||
dispatcherB.advanceTimeBy(20)
|
|
||||||
|
testScheduler.advanceTimeBy(20)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
launch(dispatcherC) { provideZ().bind() }
|
launch(dispatcherC) { provideZ().bind() }
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(result is Err)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = BindingError.BindingErrorA,
|
expected = Err(BindingError.BindingErrorA),
|
||||||
actual = result.error
|
actual = result
|
||||||
)
|
)
|
||||||
|
|
||||||
assertTrue(xStateChange)
|
assertTrue(xStateChange)
|
||||||
assertTrue(yStateChange)
|
assertTrue(yStateChange)
|
||||||
assertFalse(zStateChange)
|
assertFalse(zStateChange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package com.github.michaelbull.result.coroutines
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
actual fun runBlockingTest(context: CoroutineContext, testBody: suspend CoroutineScope.() -> Unit) {
|
|
||||||
runBlocking {
|
|
||||||
testBody(this)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user