Created
January 3, 2021 16:15
-
-
Save libliboom/3efb24f4766e51563e198f649fe96015 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import junit.framework.TestCase.assertEquals | |
import kotlinx.coroutines.* | |
import kotlinx.coroutines.test.TestCoroutineDispatcher | |
import org.junit.Rule | |
import org.junit.Test | |
/** | |
* Check the official example for ScopeBuilder with the following url. | |
* https://kotlinlang.org/docs/reference/coroutines/basics.html#scope-builder | |
* **/ | |
@ExperimentalStdlibApi | |
@ExperimentalCoroutinesApi | |
class CoroutinesExecutionOrderTest { | |
/** | |
* By default, [TestCoroutineDispatcher] is immediate. | |
* That means any tasks scheduled to be run without delay are immediately executed. | |
*/ | |
@get: Rule | |
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule() | |
@get: Rule | |
var retry: RetryRule = RetryRule(100) | |
@Test | |
fun `official example for ScopeBuilder`() { | |
val result = mutableListOf<String>() | |
// Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion. | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("1-${coroutineContext[CoroutineDispatcher]}") | |
result.add("1") | |
} | |
// This function returns as soon as the given block and all its children coroutines are completed. | |
coroutineScope { /** just suspends **/ | |
launch { | |
println("2-${coroutineContext[CoroutineDispatcher]}") | |
result.add("2") | |
} | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
assertEquals(listOf("3", "1", "2", "4"), result) | |
} | |
@Test | |
fun `change coroutineScope to runBlocking`() { | |
val result = mutableListOf<String>() | |
// Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion. | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("1-${coroutineContext[CoroutineDispatcher]}") | |
result.add("1") | |
} | |
runBlocking { | |
launch { | |
println("2-${coroutineContext[CoroutineDispatcher]}") | |
result.add("2") | |
} | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
assertEquals(listOf("1", "3", "2", "4"), result) | |
} | |
@Test | |
fun `change coroutineScope to async or launch`() { | |
val result = mutableListOf<String>() | |
// Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion. | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("1-${coroutineContext[CoroutineDispatcher]}") | |
result.add("1") | |
} | |
async { | |
launch { | |
println("2-${coroutineContext[CoroutineDispatcher]}") | |
result.add("2") | |
} | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
assertEquals(listOf("4", "1", "3", "2"), result) | |
} | |
@Test | |
fun `change coroutineScope to GlobalScope's launch`() { | |
val result = mutableListOf<String>() | |
// Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion. | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("1-${coroutineContext[CoroutineDispatcher]}") | |
result.add("1") | |
} | |
GlobalScope.launch { | |
launch { | |
println("2-${coroutineContext[CoroutineDispatcher]}") | |
result.add("2") | |
} | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
// It's depends on Event loop. That means there is no guarantees on the order of execution | |
} | |
@Test | |
fun `change coroutineScope to runBlocking with other Dispatcher`() { | |
val result = mutableListOf<String>() | |
// Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion. | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("1-${coroutineContext[CoroutineDispatcher]}") | |
result.add("1") | |
} | |
runBlocking(Dispatchers.IO) { | |
launch { | |
println("2-${coroutineContext[CoroutineDispatcher]}") | |
result.add("2") | |
} | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
// It's depends on Event loop. That means there is no guarantees on the order of execution | |
} | |
@Test | |
fun `change coroutineScope to runBlocking with nested one`() { | |
val result = mutableListOf<String>() | |
// Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion. | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("1-${coroutineContext[CoroutineDispatcher]}") | |
result.add("1") | |
} | |
runBlocking { | |
runBlocking { /** blocks the current thread for waiting **/ | |
launch { | |
println("2-${coroutineContext[CoroutineDispatcher]}") | |
result.add("2") | |
} | |
runBlocking { | |
launch { | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
println("5-${coroutineContext[CoroutineDispatcher]}") | |
result.add("5") | |
} | |
} | |
println("6-${coroutineContext[CoroutineDispatcher]}") | |
result.add("6") | |
} | |
assertEquals(listOf("1", "2", "4", "3", "5", "6"), result) | |
} | |
@Test | |
fun `part of change coroutineScope to runBlocking with nested one`() { | |
val result = mutableListOf<String>() | |
runBlocking { | |
launch { | |
println("3-${coroutineContext[CoroutineDispatcher]}") | |
result.add("3") | |
} | |
println("4-${coroutineContext[CoroutineDispatcher]}") | |
result.add("4") | |
} | |
assertEquals(listOf("4", "3"), result) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlinx.coroutines.Dispatchers | |
import kotlinx.coroutines.ExperimentalCoroutinesApi | |
import kotlinx.coroutines.test.TestCoroutineDispatcher | |
import kotlinx.coroutines.test.TestCoroutineScope | |
import kotlinx.coroutines.test.resetMain | |
import kotlinx.coroutines.test.setMain | |
import org.junit.rules.TestWatcher | |
import org.junit.runner.Description | |
@ExperimentalCoroutinesApi | |
open class MainCoroutineScopeRule( | |
val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher() | |
) : TestWatcher(), | |
TestCoroutineScope by TestCoroutineScope(testDispatcher) { | |
override fun starting(description: Description?) { | |
super.starting(description) | |
Dispatchers.setMain(testDispatcher) | |
} | |
override fun finished(description: Description?) { | |
super.finished(description) | |
cleanupTestCoroutines() | |
Dispatchers.resetMain() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.junit.rules.TestRule | |
import org.junit.runner.Description | |
import org.junit.runners.model.Statement | |
// https://stackoverflow.com/questions/8295100/how-to-re-run-failed-junit-tests-immediately/8301639#8301639 | |
class RetryRule(private val retryCount: Int) : TestRule { | |
override fun apply( | |
base: Statement, | |
description: Description | |
): Statement { | |
return object : Statement() { | |
@Throws(Throwable::class) | |
override fun evaluate() { | |
var caughtThrowable: Throwable? = null | |
var failuresCount = 0 | |
for (i in 0 until retryCount) { | |
try { | |
base.evaluate() | |
} catch (t: Throwable) { | |
caughtThrowable = t | |
System.err.println( | |
description.displayName | |
.toString() + ": run " + (i + 1) + " failed:" | |
) | |
t.printStackTrace() | |
++failuresCount | |
} | |
} | |
if (caughtThrowable == null) return | |
throw AssertionError( | |
(description.displayName | |
.toString() + ": failures " + failuresCount + " out of " | |
+ retryCount + " tries. See last throwable as the cause."), caughtThrowable | |
) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment