Repository: Kotlin/kotlinx.coroutines
File: ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt (Kotlin)

Code before:
import org.robolectric.shadows.*
import org.robolectric.util.*
import kotlin.test.*

@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, sdk = [28])
class HandlerDispatcherTest : TestBase() {

    /**
     * Because [Dispatchers.Main] is a singleton, we cannot vary its initialization behavior. As a
     * result we only test its behavior on the newest API level and assert that it uses async
     * messages. We rely on the other tests to exercise the variance of the mechanism that the main
     * dispatcher uses to ensure it has correct behavior on all API levels.
     */
    @Test
    fun mainIsAsync() = runTest {
        ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", 28)

        val mainLooper = shadowOf(Looper.getMainLooper())
        mainLooper.pause()
        val mainMessageQueue = shadowOf(Looper.getMainLooper().queue)

        val job = launch(Dispatchers.Main) {
            expect(2)
        }

        val message = mainMessageQueue.head
        assertTrue(message.isAsynchronous)
        job.join(mainLooper)
    }

    @Test
    fun asyncMessagesApi14() = runTest {
        ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", 14)

        val main = Looper.getMainLooper().asHandler(async = true).asCoroutineDispatcher()

        val mainLooper = shadowOf(Looper.getMainLooper())
        mainLooper.pause()
        val mainMessageQueue = shadowOf(Looper.getMainLooper().queue)

        val job = launch(main) {
            expect(2)
        }

        val message = mainMessageQueue.head
        assertFalse(message.isAsynchronous)
        job.join(mainLooper)
    }

    @Test

Review comment (bug):
Life hack: `git diff --patience` provides a sensible diff instead of this broken mess with methods broken in half. Alas, doesn't seem like there's a way to make Github use another diffing algorithm.

Code after:
import java.util.concurrent.*
import kotlin.test.*

@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, sdk = [28])
class HandlerDispatcherTest : TestBase() {
    @Test
    fun testImmediateDispatcherYield() = runBlocking(Dispatchers.Main) {
        expect(1)
        // launch in the immediate dispatcher
        launch(Dispatchers.Main.immediate) {
            expect(2)
            yield()
            expect(4)
        }
        expect(3) // after yield
        yield() // yield back
        finish(5)
    }

    @Test
    fun testMainDispatcherToString() {
        assertEquals("Dispatchers.Main", Dispatchers.Main.toString())
        assertEquals("Dispatchers.Main.immediate", Dispatchers.Main.immediate.toString())
    }

    @Test
    fun testDefaultDelayIsNotDelegatedToMain() = runTest {
        val mainLooper = Shadows.shadowOf(Looper.getMainLooper())
        mainLooper.pause()
        assertFalse { mainLooper.scheduler.areAnyRunnable() }

        val job = launch(Dispatchers.Default, start = CoroutineStart.UNDISPATCHED) {
            expect(1)
            delay(Long.MAX_VALUE)
            expectUnreached()
        }
        expect(2)
        assertEquals(0, mainLooper.scheduler.size())
        job.cancelAndJoin()
        finish(3)
    }

    @Test
    fun testWithTimeoutIsDelegatedToMain() = runTest {
        val mainLooper = Shadows.shadowOf(Looper.getMainLooper())
        mainLooper.pause()
        assertFalse { mainLooper.scheduler.areAnyRunnable() }
        val job = launch(Dispatchers.Main, start = CoroutineStart.UNDISPATCHED) {
            withTimeout(1) {
                expect(1)