resolve flaky jvm multi threaded coroutine tests
By switching to using the jvm only (hopefully by 1.6 in common) coroutine test lib we can swap to using a fake dispatcher instead of defining threads which should resolve any odd timing issues.
This commit is contained in:
parent
08cf52bfd4
commit
07b4d61d3f
@ -3,6 +3,7 @@ object Versions {
|
||||
const val kotlin = "1.5.10"
|
||||
const val kotlinBenchmark = "0.2.0-dev-20"
|
||||
const val kotlinCoroutines = "1.5.0"
|
||||
const val kotlinCoroutinesTest = "1.5.0"
|
||||
const val ktor = "1.5.4"
|
||||
const val logback = "1.2.3"
|
||||
const val versionsPlugin = "0.38.0"
|
||||
|
@ -31,6 +31,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation(kotlin("test-junit"))
|
||||
implementation(kotlin("test"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.kotlinCoroutinesTest}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,19 +3,19 @@ package com.github.michaelbull.result.coroutines.binding
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class AsyncSuspendableBindingTest {
|
||||
|
||||
private sealed class BindingError {
|
||||
@ -35,7 +35,7 @@ class AsyncSuspendableBindingTest {
|
||||
return Ok(2)
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
runBlockingTest {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = async { provideX().bind() }
|
||||
val y = async { provideY().bind() }
|
||||
@ -67,7 +67,7 @@ class AsyncSuspendableBindingTest {
|
||||
return Err(BindingError.BindingErrorB)
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
runBlockingTest {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = async { provideX().bind() }
|
||||
val y = async { provideY().bind() }
|
||||
@ -95,18 +95,19 @@ class AsyncSuspendableBindingTest {
|
||||
}
|
||||
|
||||
suspend fun provideY(): Result<Int, BindingError.BindingErrorB> {
|
||||
// as this test uses a new thread for each coroutine, we want to set this delay to a high enough number that
|
||||
// there isn't any chance of a jvm run actually completing this suspending function in this thread first
|
||||
// otherwise the assertions might fail.
|
||||
delay(100)
|
||||
delay(3)
|
||||
yStateChange = true
|
||||
return Err(BindingError.BindingErrorB)
|
||||
}
|
||||
|
||||
val dispatcherA = TestCoroutineDispatcher()
|
||||
val dispatcherB = TestCoroutineDispatcher()
|
||||
|
||||
runBlocking {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = async(newThread("ThreadA")) { provideX().bind() }
|
||||
val y = async(newThread("ThreadB")) { provideY().bind() }
|
||||
val x = async(dispatcherA) { provideX().bind() }
|
||||
val y = async(dispatcherB) { provideY().bind() }
|
||||
dispatcherA.advanceTimeBy(2)
|
||||
x.await() + y.await()
|
||||
}
|
||||
|
||||
@ -144,11 +145,17 @@ class AsyncSuspendableBindingTest {
|
||||
return Err(BindingError.BindingErrorB)
|
||||
}
|
||||
|
||||
val dispatcherA = TestCoroutineDispatcher()
|
||||
val dispatcherB = TestCoroutineDispatcher()
|
||||
val dispatcherC = TestCoroutineDispatcher()
|
||||
|
||||
runBlocking {
|
||||
val result = binding<Unit, BindingError> {
|
||||
launch(newThread("Thread A")) { provideX().bind() }
|
||||
launch(newThread("Thread B")) { provideY().bind() }
|
||||
launch(newThread("Thread C")) { provideZ().bind() }
|
||||
launch(dispatcherA) { provideX().bind() }
|
||||
dispatcherA.advanceTimeBy(20)
|
||||
launch(dispatcherB) { provideY().bind() }
|
||||
dispatcherB.advanceTimeBy(20)
|
||||
launch(dispatcherC) { provideZ().bind() }
|
||||
}
|
||||
|
||||
assertTrue(result is Err)
|
||||
@ -161,8 +168,4 @@ class AsyncSuspendableBindingTest {
|
||||
assertFalse(zStateChange)
|
||||
}
|
||||
}
|
||||
|
||||
private fun newThread(name: String): CoroutineContext {
|
||||
return Executors.newSingleThreadExecutor().asCoroutineDispatcher() + CoroutineName(name)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user