Repository: Kotlin/kotlinx.coroutines
File: kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt (Kotlin)

Code before:
        val list = mutableListOf<String>()
        flow.timeout(300.milliseconds).catch { if (it is TimeoutCancellationException) emit("-1") }.collect { list.add(it) }
        assertEquals(listOf("A", "B", "C", "-1"), list)
        finish(5)
    }

    @Test
    fun testDelayedFirst() = withVirtualTime {
        expect(1)
        val flow = flow {
            expect(3)
            delay(100)
            emit(1)
            expect(4)
        }.timeout(250.milliseconds)
        expect(2)
        assertEquals(1, flow.singleOrNull())
        finish(5)
    }

    // Test may rarely fail due to timeout being reached before test has completed
    @Test
    fun testEmpty() = runTest {
        val flow = emptyFlow<Any?>().timeout(1.milliseconds)
        assertNull(flow.singleOrNull())
    }

    // Test may rarely fail due to timeout being reached before test has completed
    @Test
    fun testScalar() = runTest {
        val flow = flowOf(1, 2, 3).timeout(1.milliseconds)
        assertEquals(listOf(1, 2, 3), flow.toList())
    }

    @Test
    fun testUpstreamError() = testUpstreamError(TestException())

    @Test
    fun testUpstreamErrorTimeoutException() = testUpstreamError(TimeoutCancellationException(0, Job()))

    private inline fun <reified T: Throwable> testUpstreamError(cause: T) = runTest {
        val flow = flow {
            emit(1)
            throw cause
        }.timeout(1.milliseconds)

        assertFailsWith<T>(flow)
    }

    @Test
    fun testDownstreamError() = runTest {

Review comment (suggestion):
```suggestion
    @Test
    fun testEmpty() = withVirtualTime {
        val flow = emptyFlow<Any?>().timeout(1.milliseconds)
        assertNull(flow.singleOrNull())
        finish(1)
    }
```

Code after:
        val list = mutableListOf<String>()
        flow.timeout(300.milliseconds).catch { if (it is TimeoutCancellationException) emit("-1") }.collect { list.add(it) }
        assertEquals(listOf("A", "B", "C", "-1"), list)
        finish(5)
    }

    @Test
    fun testDelayedFirst() = withVirtualTime {
        expect(1)
        val flow = flow {
            expect(3)
            delay(100)
            emit(1)
            expect(4)
        }.timeout(250.milliseconds)
        expect(2)
        assertEquals(1, flow.singleOrNull())
        finish(5)
    }

    @Test
    fun testEmpty() = withVirtualTime {
        val flow = emptyFlow<Any?>().timeout(1.milliseconds)
        assertNull(flow.singleOrNull())
        finish(1)
    }

    @Test
    fun testScalar() = withVirtualTime {
        val flow = flowOf(1, 2, 3).timeout(1.milliseconds)
        assertEquals(listOf(1, 2, 3), flow.toList())
        finish(1)
    }

    @Test
    fun testUpstreamError() = testUpstreamError(TestException())

    @Test
    fun testUpstreamErrorTimeoutException() = testUpstreamError(TimeoutCancellationException(0, Job()))

    private inline fun <reified T: Throwable> testUpstreamError(cause: T) = runTest {
        try {
            // Workaround for JS legacy bug
            flow {
                emit(1)
                throw cause
            }.timeout(1.milliseconds).collect()
            expectUnreached()
        } catch (e: Throwable) {
            assertTrue { e is T }
            finish(1)