Skip to content

Commit 2db3d36

Browse files
committed
Make TestDispatcher experimental, prohibit setMain(Dispatchers.Main), cleanup
1 parent 84485dd commit 2db3d36

File tree

6 files changed

+26
-21
lines changed

6 files changed

+26
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
public final class kotlinx/coroutines/test/TestDispatchers {
22
public static final fun resetMain (Lkotlinx/coroutines/Dispatchers;)V
33
public static final fun setMain (Lkotlinx/coroutines/Dispatchers;Lkotlinx/coroutines/CoroutineDispatcher;)V
4-
public static synthetic fun setMain$default (Lkotlinx/coroutines/Dispatchers;Lkotlinx/coroutines/CoroutineDispatcher;ILjava/lang/Object;)V
54
}
65

core/kotlinx-coroutines-core/src/internal/MainDispatchers.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,15 @@ public fun MainDispatcherFactory.tryCreateDispatcher(factories: List<MainDispatc
3737
MissingMainCoroutineDispatcher(cause, hintOnError())
3838
}
3939

40-
private class MissingMainCoroutineDispatcher(private val cause: Throwable?, private val errorHint: String? = null) :
41-
MainCoroutineDispatcher(), Delay {
40+
/** @suppress */
41+
@InternalCoroutinesApi
42+
public fun MainCoroutineDispatcher.isMissing(): Boolean = this is MissingMainCoroutineDispatcher
43+
44+
private class MissingMainCoroutineDispatcher(
45+
private val cause: Throwable?,
46+
private val errorHint: String? = null
47+
) : MainCoroutineDispatcher(), Delay {
48+
4249
override val immediate: MainCoroutineDispatcher get() = this
4350

4451
override fun isDispatchNeeded(context: CoroutineContext): Boolean {

core/kotlinx-coroutines-test/src/TestDispatchers.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ import kotlinx.coroutines.test.internal.*
1515
*
1616
* It is unsafe to call this method if alive coroutines launched in [Dispatchers.Main] exist.
1717
*/
18-
public fun Dispatchers.setMain(dispatcher: CoroutineDispatcher = Dispatchers.Unconfined) {
18+
@ExperimentalCoroutinesApi
19+
public fun Dispatchers.setMain(dispatcher: CoroutineDispatcher) {
20+
require(dispatcher !is TestMainDispatcher) { "Dispatchers.setMain(Dispatchers.Main) is prohibited, probably Dispatchers.resetMain() should be used instead" }
1921
val mainDispatcher = Dispatchers.Main
2022
require(mainDispatcher is TestMainDispatcher) { "TestMainDispatcher is not set as main dispatcher, have $mainDispatcher instead." }
2123
mainDispatcher.setDispatcher(dispatcher)
22-
2324
}
2425

2526
/**
@@ -29,6 +30,7 @@ public fun Dispatchers.setMain(dispatcher: CoroutineDispatcher = Dispatchers.Unc
2930
*
3031
* It is unsafe to call this method if alive coroutines launched in [Dispatchers.Main] exist.
3132
*/
33+
@ExperimentalCoroutinesApi
3234
public fun Dispatchers.resetMain() {
3335
val mainDispatcher = Dispatchers.Main
3436
require(mainDispatcher is TestMainDispatcher) { "TestMainDispatcher is not set as main dispatcher, have $mainDispatcher instead." }

core/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt

+6-15
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ internal class TestMainDispatcher(private val mainFactory: MainDispatcherFactory
1717
private val delegate: CoroutineDispatcher get() {
1818
if (_delegate != null) return _delegate!!
1919

20-
val newInstance = createDispatcher()
21-
if (newInstance != null) {
22-
_delegate = newInstance
23-
return newInstance
20+
mainFactory.tryCreateDispatcher(emptyList()).let {
21+
// If we've failed to create a dispatcher, do no set _delegate
22+
if (!isMissing()) {
23+
_delegate = it
24+
}
25+
return it
2426
}
25-
26-
// Return missing dispatcher, but do not set _delegate
27-
return mainFactory.tryCreateDispatcher(emptyList())
2827
}
2928

3029
@Suppress("INVISIBLE_MEMBER")
@@ -60,14 +59,6 @@ internal class TestMainDispatcher(private val mainFactory: MainDispatcherFactory
6059
public fun resetDispatcher() {
6160
_delegate = null
6261
}
63-
64-
private fun createDispatcher(): CoroutineDispatcher? {
65-
return try {
66-
mainFactory.createDispatcher(emptyList())
67-
} catch (cause: Throwable) {
68-
null
69-
}
70-
}
7162
}
7263

7364
internal class TestMainDispatcherFactory : MainDispatcherFactory {

core/kotlinx-coroutines-test/test/TestDispatchersTest.kt

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package kotlinx.coroutines.test
66
import kotlinx.coroutines.*
77
import org.junit.*
88
import org.junit.Test
9+
import java.lang.IllegalArgumentException
910
import kotlin.coroutines.*
1011
import kotlin.test.*
1112

@@ -16,6 +17,11 @@ class TestDispatchersTest : TestBase() {
1617
Dispatchers.resetMain()
1718
}
1819

20+
@Test(expected = IllegalArgumentException::class)
21+
fun testSelfSet() = runTest {
22+
Dispatchers.setMain(Dispatchers.Main)
23+
}
24+
1925
@Test
2026
fun testSingleThreadExecutor() = runTest {
2127
val mainThread = Thread.currentThread()

ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstMockedMainTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ open class FirstMockedMainTest : TestBase() {
1515

1616
@Before
1717
fun setUp() {
18-
Dispatchers.setMain()
18+
Dispatchers.setMain(Dispatchers.Unconfined)
1919
}
2020

2121
@After

0 commit comments

Comments
 (0)