Skip to content

Commit d5a66e0

Browse files
hfhbddkhalanskyjb
authored andcommitted
Add TimeSource implementation to TestCoroutineScheduler
1 parent 7a249c3 commit d5a66e0

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

kotlinx-coroutines-test/api/kotlinx-coroutines-test.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public final class kotlinx/coroutines/test/TestCoroutineScheduler : kotlin/corou
6565
public final fun advanceTimeBy (J)V
6666
public final fun advanceUntilIdle ()V
6767
public final fun getCurrentTime ()J
68+
public final fun getTimeSource ()Lkotlin/time/TimeSource;
6869
public final fun runCurrent ()V
6970
}
7071

@@ -113,6 +114,7 @@ public final class kotlinx/coroutines/test/TestScopeKt {
113114
public static final fun advanceTimeBy (Lkotlinx/coroutines/test/TestScope;J)V
114115
public static final fun advanceUntilIdle (Lkotlinx/coroutines/test/TestScope;)V
115116
public static final fun getCurrentTime (Lkotlinx/coroutines/test/TestScope;)J
117+
public static final fun getTestTimeSource (Lkotlinx/coroutines/test/TestScope;)Lkotlin/time/TimeSource;
116118
public static final fun runCurrent (Lkotlinx/coroutines/test/TestScope;)V
117119
}
118120

kotlinx-coroutines-test/common/src/TestCoroutineScheduler.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import kotlinx.coroutines.internal.*
1212
import kotlinx.coroutines.selects.*
1313
import kotlin.coroutines.*
1414
import kotlin.jvm.*
15+
import kotlin.time.*
1516

1617
/**
1718
* This is a scheduler for coroutines used in tests, providing the delay-skipping behavior.
@@ -26,7 +27,6 @@ import kotlin.jvm.*
2627
* haven't yet been dispatched (via [runCurrent]).
2728
*/
2829
@ExperimentalCoroutinesApi
29-
// TODO: maybe make this a `TimeSource`?
3030
public class TestCoroutineScheduler : AbstractCoroutineContextElement(TestCoroutineScheduler),
3131
CoroutineContext.Element {
3232

@@ -43,7 +43,7 @@ public class TestCoroutineScheduler : AbstractCoroutineContextElement(TestCorout
4343
/** This counter establishes some order on the events that happen at the same virtual time. */
4444
private val count = atomic(0L)
4545

46-
/** The current virtual time. */
46+
/** The current virtual time in milliseconds. */
4747
@ExperimentalCoroutinesApi
4848
public var currentTime: Long = 0
4949
get() = synchronized(lock) { field }
@@ -193,6 +193,15 @@ public class TestCoroutineScheduler : AbstractCoroutineContextElement(TestCorout
193193
* Consumes the knowledge that a dispatch event happened recently.
194194
*/
195195
internal val onDispatchEvent: SelectClause1<Unit> get() = dispatchEvents.onReceive
196+
197+
/**
198+
* Returns the [TimeSource] representation of the virtual time of this scheduler.
199+
*/
200+
@ExperimentalCoroutinesApi
201+
@ExperimentalTime
202+
public val timeSource: TimeSource = object : AbstractLongTimeSource(DurationUnit.MILLISECONDS) {
203+
override fun read(): Long = currentTime
204+
}
196205
}
197206

198207
// Some error-throwing functions for pretty stack traces

kotlinx-coroutines-test/common/src/TestScope.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package kotlinx.coroutines.test
77
import kotlinx.coroutines.*
88
import kotlinx.coroutines.internal.*
99
import kotlin.coroutines.*
10+
import kotlin.time.*
1011

1112
/**
1213
* A coroutine scope that for launching test coroutines.
@@ -84,6 +85,14 @@ public fun TestScope.runCurrent(): Unit = testScheduler.runCurrent()
8485
@ExperimentalCoroutinesApi
8586
public fun TestScope.advanceTimeBy(delayTimeMillis: Long): Unit = testScheduler.advanceTimeBy(delayTimeMillis)
8687

88+
/**
89+
* The [test scheduler][TestScope.testScheduler] as a [TimeSource].
90+
* @see TestCoroutineScheduler.timeSource
91+
*/
92+
@ExperimentalCoroutinesApi
93+
@ExperimentalTime
94+
public val TestScope.testTimeSource: TimeSource get() = testScheduler.timeSource
95+
8796
/**
8897
* Creates a [TestScope].
8998
*
@@ -237,4 +246,4 @@ internal class UncaughtExceptionsBeforeTest : IllegalStateException(
237246
* Thrown when a test has completed and there are tasks that are not completed or cancelled.
238247
*/
239248
@ExperimentalCoroutinesApi
240-
internal class UncompletedCoroutinesError(message: String) : AssertionError(message)
249+
internal class UncompletedCoroutinesError(message: String) : AssertionError(message)

kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package kotlinx.coroutines.test
66

77
import kotlinx.coroutines.*
88
import kotlin.test.*
9+
import kotlin.time.*
10+
import kotlin.time.Duration.Companion.seconds
911

1012
class TestCoroutineSchedulerTest {
1113
/** Tests that `TestCoroutineScheduler` attempts to detect if there are several instances of it. */
@@ -308,6 +310,16 @@ class TestCoroutineSchedulerTest {
308310
}
309311
}
310312

313+
@Test
314+
@ExperimentalTime
315+
fun testAdvanceTimeSource() = runTest {
316+
val expected = 1.seconds
317+
val actual = testTimeSource.measureTime {
318+
delay(expected)
319+
}
320+
assertEquals(expected, actual)
321+
}
322+
311323
private fun forTestDispatchers(block: (TestDispatcher) -> Unit): Unit =
312324
@Suppress("DEPRECATION")
313325
listOf(

0 commit comments

Comments
 (0)