From 59a3a6081b414f75c83b280eb4bb79f68e0e407e Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Mon, 31 Oct 2022 15:10:40 +0100 Subject: [PATCH 1/4] Replace the exception in withTimeout --- kotlinx-coroutines-core/common/src/Timeout.kt | 16 ++- .../common/src/intrinsics/Undispatched.kt | 14 ++ .../common/src/time/Timeout.kt | 125 ++++++++++++++++++ kotlinx-coroutines-core/jdk8/src/time/Time.kt | 6 +- 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 kotlinx-coroutines-core/common/src/time/Timeout.kt diff --git a/kotlinx-coroutines-core/common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt index aea57546a1..b3e4b9025d 100644 --- a/kotlinx-coroutines-core/common/src/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/Timeout.kt @@ -2,9 +2,11 @@ * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:OptIn(ExperimentalContracts::class) +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") package kotlinx.coroutines +import kotlin.internal.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* @@ -36,6 +38,12 @@ import kotlin.time.* * * @param timeMillis timeout time in milliseconds. */ +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@LowPriorityInOverloadResolution +@Deprecated("Use withTimeout from the 'kotlinx-coroutines-time' package instead.", + ReplaceWith("kotlinx.coroutines.time.withTimeout(timeMillis, block)", + "kotlinx.coroutines.time"), + level = DeprecationLevel.WARNING) public suspend fun withTimeout(timeMillis: Long, block: suspend CoroutineScope.() -> T): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -66,11 +74,17 @@ public suspend fun withTimeout(timeMillis: Long, block: suspend CoroutineSco * * > Implementation note: how the time is tracked exactly is an implementation detail of the context's [CoroutineDispatcher]. */ +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@LowPriorityInOverloadResolution +@Deprecated("Use withTimeout from the 'kotlinx-coroutines-time' package instead.", + ReplaceWith("kotlinx.coroutines.time.withTimeout(timeout, block)", + "kotlinx.coroutines.time"), + level = DeprecationLevel.WARNING) public suspend fun withTimeout(timeout: Duration, block: suspend CoroutineScope.() -> T): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return withTimeout(timeout.toDelayMillis(), block) + return kotlinx.coroutines.time.withTimeout(timeout.toDelayMillis(), block) } /** diff --git a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt index 38e870ef9c..157e623f36 100644 --- a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt +++ b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.intrinsics import kotlinx.coroutines.* import kotlinx.coroutines.internal.* +import kotlinx.coroutines.time.* import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* @@ -101,6 +102,19 @@ internal fun ScopeCoroutine.startUndispatchedOrReturnIgnoreTimeout( } } +/** + * Same as [startUndispatchedOrReturn], but ignores [TimeoutException] on fast-path. + */ +internal fun ScopeCoroutine.startUndispatchedOrReturnIgnoreNewTimeout( + receiver: R, block: suspend R.() -> T +): Any? { + return undispatchedResult({ e -> + !(e is TimeoutException && e.coroutine === this) + }) { + block.startCoroutineUninterceptedOrReturn(receiver, this) + } +} + private inline fun ScopeCoroutine.undispatchedResult( shouldThrow: (Throwable) -> Boolean, startBlock: () -> Any? diff --git a/kotlinx-coroutines-core/common/src/time/Timeout.kt b/kotlinx-coroutines-core/common/src/time/Timeout.kt new file mode 100644 index 0000000000..c7933bb479 --- /dev/null +++ b/kotlinx-coroutines-core/common/src/time/Timeout.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:OptIn(ExperimentalContracts::class) + +package kotlinx.coroutines.time + +import kotlinx.coroutines.* +import kotlinx.coroutines.internal.* +import kotlinx.coroutines.intrinsics.* +import kotlinx.coroutines.selects.* +import kotlin.contracts.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* +import kotlin.jvm.* +import kotlin.time.* + +/** + * Runs a given suspending [block] of code inside a coroutine with a specified [timeout][timeMillis] and throws + * a [TimeoutException] if the timeout was exceeded. + * If the given [timeMillis] is non-positive, [TimeoutException] is thrown immediately. + * + * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of + * the cancellable suspending function inside the block throws a [TimeoutException]. + * + * The sibling function that does not throw an exception on timeout is [withTimeoutOrNull]. + * Note that the timeout action can be specified for a [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause. + * + * **The timeout event is asynchronous with respect to the code running in the block** and may happen at any time, + * even right before the return from inside the timeout [block]. Keep this in mind if you open or acquire some + * resource inside the [block] that needs closing or release outside the block. + * See the + * [Asynchronous timeout and resources][https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html#asynchronous-timeout-and-resources] + * section of the coroutines guide for details. + * + * > Implementation note: how the time is tracked exactly is an implementation detail of the context's [CoroutineDispatcher]. + * + * @param timeMillis timeout time in milliseconds. + */ +public suspend fun withTimeout(timeMillis: Long, block: suspend CoroutineScope.() -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + if (timeMillis <= 0L) throw TimeoutException("Timed out immediately") + return suspendCoroutineUninterceptedOrReturn { uCont -> + setupTimeout(TimeoutCoroutine(timeMillis, uCont), block) + } +} + +/** + * Runs a given suspending [block] of code inside a coroutine with the specified [timeout] and throws + * a [TimeoutException] if the timeout was exceeded. + * If the given [timeout] is non-positive, [TimeoutException] is thrown immediately. + * + * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of + * the cancellable suspending function inside the block throws a [TimeoutException]. + * + * The sibling function that does not throw an exception on timeout is [withTimeoutOrNull]. + * Note that the timeout action can be specified for a [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause. + * + * **The timeout event is asynchronous with respect to the code running in the block** and may happen at any time, + * even right before the return from inside the timeout [block]. Keep this in mind if you open or acquire some + * resource inside the [block] that needs closing or release outside the block. + * See the + * [Asynchronous timeout and resources][https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html#asynchronous-timeout-and-resources] + * section of the coroutines guide for details. + * + * > Implementation note: how the time is tracked exactly is an implementation detail of the context's [CoroutineDispatcher]. + */ +public suspend fun withTimeout(timeout: Duration, block: suspend CoroutineScope.() -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return withTimeout(timeout.toDelayMillis(), block) +} + +private fun setupTimeout( + coroutine: TimeoutCoroutine, + block: suspend CoroutineScope.() -> T +): Any? { + // schedule cancellation of this coroutine on time + val cont = coroutine.uCont + val context = cont.context + coroutine.disposeOnCompletion(context.delay.invokeOnTimeout(coroutine.time, coroutine, coroutine.context)) + // restart the block using a new coroutine with a new job, + // however, start it undispatched, because we already are in the proper context + return coroutine.startUndispatchedOrReturnIgnoreNewTimeout(coroutine, block) +} + +private class TimeoutCoroutine( + @JvmField val time: Long, + uCont: Continuation // unintercepted continuation +) : ScopeCoroutine(uCont.context, uCont), Runnable { + override fun run() { + cancelCoroutine(TimeoutException(time, this)) + } + + override fun nameString(): String = + "${super.nameString()}(timeMillis=$time)" +} + +/** + * This exception is thrown by [withTimeout] to indicate timeout. + */ +public class TimeoutException internal constructor( + message: String, + @JvmField @Transient internal val coroutine: Job? +) : CancellationException(message), CopyableThrowable { + /** + * Creates a timeout exception with the given message. + * This constructor is needed for exception stack-traces recovery. + */ + @Suppress("UNUSED") + internal constructor(message: String) : this(message, null) + + // message is never null in fact + override fun createCopy(): TimeoutException = + TimeoutException(message ?: "", coroutine).also { it.initCause(this) } +} + +internal fun TimeoutException( + time: Long, + coroutine: Job +) : TimeoutException = TimeoutException("Timed out waiting for $time ms", coroutine) diff --git a/kotlinx-coroutines-core/jdk8/src/time/Time.kt b/kotlinx-coroutines-core/jdk8/src/time/Time.kt index 78cf6e5305..6bcd30df9f 100644 --- a/kotlinx-coroutines-core/jdk8/src/time/Time.kt +++ b/kotlinx-coroutines-core/jdk8/src/time/Time.kt @@ -33,7 +33,7 @@ public fun Flow.sample(period: Duration): Flow = sample(period.coerceT * "java.time" adapter method for [SelectBuilder.onTimeout]. */ public fun SelectBuilder.onTimeout(duration: Duration, block: suspend () -> R): Unit = - onTimeout(duration.coerceToMillis(), block) + onTimeout(duration.coerceToMillis(), block) /** * "java.time" adapter method for [kotlinx.coroutines.withTimeout]. @@ -42,14 +42,14 @@ public suspend fun withTimeout(duration: Duration, block: suspend CoroutineS contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return kotlinx.coroutines.withTimeout(duration.coerceToMillis(), block) + return withTimeout(duration.coerceToMillis(), block) } /** * "java.time" adapter method for [kotlinx.coroutines.withTimeoutOrNull]. */ public suspend fun withTimeoutOrNull(duration: Duration, block: suspend CoroutineScope.() -> T): T? = - kotlinx.coroutines.withTimeoutOrNull(duration.coerceToMillis(), block) + withTimeoutOrNull(duration.coerceToMillis(), block) /** * Coerces the given [Duration] to a millisecond delay. From 4e8e6089df4205bf944db95710f2a56bb93113d1 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Mon, 31 Oct 2022 15:13:21 +0100 Subject: [PATCH 2/4] Autorefactor the deprecated definitions --- .../test/ListenableFutureTest.kt | 2 +- .../common/test/BuilderContractsTest.kt | 2 +- .../common/test/CancelledParentAttachTest.kt | 2 +- .../common/test/ParentCancellationTest.kt | 4 +-- .../common/test/UndispatchedResultTest.kt | 2 +- .../common/test/WithTimeoutDurationTest.kt | 24 ++++++------- .../test/WithTimeoutOrNullDurationTest.kt | 4 +-- .../common/test/WithTimeoutOrNullTest.kt | 4 +-- .../common/test/WithTimeoutTest.kt | 24 ++++++------- .../test/flow/channels/ChannelFlowTest.kt | 2 +- .../common/test/flow/operators/CatchTest.kt | 2 +- .../common/test/flow/operators/FlowOnTest.kt | 4 +-- .../common/test/flow/operators/RetryTest.kt | 2 +- .../common/test/flow/sharing/ShareInTest.kt | 4 +-- .../channels/BroadcastChannelSubStressTest.kt | 2 +- ...nflatedBroadcastChannelNotifyStressTest.kt | 2 +- .../jvm/test/RejectedExecutionTest.kt | 4 +-- .../test/ThreadContextElementRestoreTest.kt | 6 ++-- .../WithTimeoutChildDipspatchStressTest.kt | 4 +-- .../jvm/test/WithTimeoutOrNullJvmTest.kt | 2 +- .../jvm/test/WithTimeoutThreadDispatchTest.kt | 4 +-- .../BroadcastChannelMultiReceiveStressTest.kt | 18 +++++----- .../channels/ChannelSendReceiveStressTest.kt | 2 +- .../StackTraceRecoveryNestedScopesTest.kt | 34 ++++++++++--------- .../StackTraceRecoveryWithTimeoutTest.kt | 16 ++++----- .../WithContextCancellationStressTest.kt | 5 ++- .../jvm/test/flow/SharingStressTest.kt | 2 +- .../jvm/test/guide/example-cancel-07.kt | 2 +- .../jvm/test/guide/example-cancel-09.kt | 6 ++-- .../jvm/test/guide/example-cancel-10.kt | 8 ++--- .../jvm/test/jdk8/future/FutureTest.kt | 2 +- .../jvm/test/scheduling/SchedulerTestBase.kt | 2 +- .../selects/SelectPhilosophersStressTest.kt | 4 +-- .../nativeDarwin/test/MainDispatcherTest.kt | 26 +++++++------- .../test/StartModeProbesTest.kt | 21 +++++++----- .../common/test/RunTestTest.kt | 2 +- .../common/test/TestCoroutineSchedulerTest.kt | 2 +- .../RunBlockingTestOnTestScopeTest.kt | 2 +- .../test/migration/RunTestLegacyScopeTest.kt | 2 +- .../jvm/test/migration/TestRunBlockingTest.kt | 18 +++++----- .../test/FlowAsPublisherTest.kt | 2 +- .../test/PublisherCompletionStressTest.kt | 4 +-- .../test/FlowAsPublisherTest.kt | 2 +- .../test/IntegrationTest.kt | 2 +- .../test/PublisherCompletionStressTest.kt | 4 +-- .../test/FluxCompletionStressTest.kt | 4 +-- .../test/MonoTest.kt | 2 +- .../test/IntegrationTest.kt | 2 +- .../test/ObservableCompletionStressTest.kt | 2 +- .../test/IntegrationTest.kt | 2 +- .../test/ObservableCompletionStressTest.kt | 2 +- .../test/HandlerDispatcherTest.kt | 2 +- 52 files changed, 159 insertions(+), 151 deletions(-) diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt index 511b1b0322..1eac741145 100644 --- a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt +++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt @@ -749,7 +749,7 @@ class ListenableFutureTest : TestBase() { } } future.set(1) - withTimeout(60_000) { + kotlinx.coroutines.time.withTimeout(60_000) { children.forEach { it.join() } assertEquals(count, completed.get()) } diff --git a/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt b/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt index 5a96c54460..853494c8cd 100644 --- a/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt +++ b/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt @@ -34,7 +34,7 @@ class BuilderContractsTest : TestBase() { consume(wctx) val wt: Int - withTimeout(Long.MAX_VALUE) { + kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { wt = 123 } consume(wt) diff --git a/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt b/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt index 9dd61b8012..be75dc221e 100644 --- a/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt +++ b/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt @@ -96,7 +96,7 @@ class CancelledParentAttachTest : TestBase() { testScope { coroutineScope { } } testScope { supervisorScope { } } testScope { flowScope { } } - testScope { withTimeout(Long.MAX_VALUE) { } } + testScope { kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { } } testScope { withContext(Job()) { } } testScope { withContext(CoroutineName("")) { } } } diff --git a/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt index 96c5cf3f4f..8f87252798 100644 --- a/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt +++ b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt @@ -90,7 +90,7 @@ class ParentCancellationTest : TestBase() { @Test fun testWithTimeoutChild() = runTest { testParentCancellation(expectParentActive = true, expectRethrows = true, runsInScopeContext = true) { fail -> - withTimeout(1000) { fail() } + kotlinx.coroutines.time.withTimeout(1000) { fail() } } } @@ -168,4 +168,4 @@ class ParentCancellationTest : TestBase() { } finish(3) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt b/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt index 34b8164472..80159d995f 100644 --- a/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt +++ b/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt @@ -21,7 +21,7 @@ class UndispatchedResultTest : TestBase() { @Test fun testWithTimeout() = runTest { - invokeTest { block -> withTimeout(Long.MAX_VALUE, block) } + invokeTest { block -> kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE, block) } } @Test diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt index 60e64f5830..afe3e74170 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt @@ -18,7 +18,7 @@ class WithTimeoutDurationTest : TestBase() { @Test fun testBasicNoSuspend() = runTest { expect(1) - val result = withTimeout(10.seconds) { + val result = kotlinx.coroutines.time.withTimeout(10.seconds) { expect(2) "OK" } @@ -32,7 +32,7 @@ class WithTimeoutDurationTest : TestBase() { @Test fun testBasicSuspend() = runTest { expect(1) - val result = withTimeout(10.seconds) { + val result = kotlinx.coroutines.time.withTimeout(10.seconds) { expect(2) yield() expect(3) @@ -55,7 +55,7 @@ class WithTimeoutDurationTest : TestBase() { } expect(2) // test that it does not yield to the above job when started - val result = withTimeout(1.seconds) { + val result = kotlinx.coroutines.time.withTimeout(1.seconds) { expect(3) yield() // yield only now expect(5) @@ -75,7 +75,7 @@ class WithTimeoutDurationTest : TestBase() { fun testYieldBlockingWithTimeout() = runTest( expected = { it is CancellationException } ) { - withTimeout(100.milliseconds) { + kotlinx.coroutines.time.withTimeout(100.milliseconds) { while (true) { yield() } @@ -88,7 +88,7 @@ class WithTimeoutDurationTest : TestBase() { @Test fun testWithTimeoutChildWait() = runTest { expect(1) - withTimeout(100.milliseconds) { + kotlinx.coroutines.time.withTimeout(100.milliseconds) { expect(2) // launch child with timeout launch { @@ -103,7 +103,7 @@ class WithTimeoutDurationTest : TestBase() { @Test fun testBadClass() = runTest { val bad = BadClass() - val result = withTimeout(100.milliseconds) { + val result = kotlinx.coroutines.time.withTimeout(100.milliseconds) { bad } assertSame(bad, result) @@ -119,7 +119,7 @@ class WithTimeoutDurationTest : TestBase() { fun testExceptionOnTimeout() = runTest { expect(1) try { - withTimeout(100.milliseconds) { + kotlinx.coroutines.time.withTimeout(100.milliseconds) { expect(2) delay(1000.milliseconds) expectUnreached() @@ -136,7 +136,7 @@ class WithTimeoutDurationTest : TestBase() { expected = { it is CancellationException } ) { expect(1) - withTimeout(100.milliseconds) { + kotlinx.coroutines.time.withTimeout(100.milliseconds) { expect(2) try { delay(1000.milliseconds) @@ -152,7 +152,7 @@ class WithTimeoutDurationTest : TestBase() { fun testSuppressExceptionWithAnotherException() = runTest { expect(1) try { - withTimeout(100.milliseconds) { + kotlinx.coroutines.time.withTimeout(100.milliseconds) { expect(2) try { delay(1000.milliseconds) @@ -173,7 +173,7 @@ class WithTimeoutDurationTest : TestBase() { fun testNegativeTimeout() = runTest { expect(1) try { - withTimeout(-1.milliseconds) { + kotlinx.coroutines.time.withTimeout(-1.milliseconds) { expectUnreached() "OK" } @@ -188,7 +188,7 @@ class WithTimeoutDurationTest : TestBase() { expect(1) try { expect(2) - withTimeout(1.seconds) { + kotlinx.coroutines.time.withTimeout(1.seconds) { expect(3) throw TestException() } @@ -201,7 +201,7 @@ class WithTimeoutDurationTest : TestBase() { @Test fun testIncompleteWithTimeoutState() = runTest { lateinit var timeoutJob: Job - val handle = withTimeout(Duration.INFINITE) { + val handle = kotlinx.coroutines.time.withTimeout(Duration.INFINITE) { timeoutJob = coroutineContext[Job]!! timeoutJob.invokeOnCompletion { } } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt index 1f9ad46f47..7a8773bb22 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt @@ -105,7 +105,7 @@ class WithTimeoutOrNullDurationTest : TestBase() { expected = { it is CancellationException } ) { withTimeoutOrNull(1000.milliseconds) { - withTimeout(10.milliseconds) { + kotlinx.coroutines.time.withTimeout(10.milliseconds) { while (true) { yield() } @@ -120,7 +120,7 @@ class WithTimeoutOrNullDurationTest : TestBase() { fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { withTimeoutOrNull(Duration.INFINITE) { // Exception from this withTimeout is not suppressed by withTimeoutOrNull - withTimeout(10.milliseconds) { + kotlinx.coroutines.time.withTimeout(10.milliseconds) { delay(Duration.INFINITE) 1 } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt index 5ab8ae7df9..593c4a647c 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt @@ -102,7 +102,7 @@ class WithTimeoutOrNullTest : TestBase() { expected = { it is CancellationException } ) { withTimeoutOrNull(1000) { - withTimeout(10) { + kotlinx.coroutines.time.withTimeout(10) { while (true) { yield() } @@ -117,7 +117,7 @@ class WithTimeoutOrNullTest : TestBase() { fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { withTimeoutOrNull(Long.MAX_VALUE) { // Exception from this withTimeout is not suppressed by withTimeoutOrNull - withTimeout(10) { + kotlinx.coroutines.time.withTimeout(10) { delay(Long.MAX_VALUE) 1 } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt index 8462c96953..a2e178fbaa 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt @@ -16,7 +16,7 @@ class WithTimeoutTest : TestBase() { @Test fun testBasicNoSuspend() = runTest { expect(1) - val result = withTimeout(10_000) { + val result = kotlinx.coroutines.time.withTimeout(10_000) { expect(2) "OK" } @@ -30,7 +30,7 @@ class WithTimeoutTest : TestBase() { @Test fun testBasicSuspend() = runTest { expect(1) - val result = withTimeout(10_000) { + val result = kotlinx.coroutines.time.withTimeout(10_000) { expect(2) yield() expect(3) @@ -53,7 +53,7 @@ class WithTimeoutTest : TestBase() { } expect(2) // test that it does not yield to the above job when started - val result = withTimeout(1000) { + val result = kotlinx.coroutines.time.withTimeout(1000) { expect(3) yield() // yield only now expect(5) @@ -73,7 +73,7 @@ class WithTimeoutTest : TestBase() { fun testYieldBlockingWithTimeout() = runTest( expected = { it is CancellationException } ) { - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { while (true) { yield() } @@ -86,7 +86,7 @@ class WithTimeoutTest : TestBase() { @Test fun testWithTimeoutChildWait() = runTest { expect(1) - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { expect(2) // launch child with timeout launch { @@ -101,7 +101,7 @@ class WithTimeoutTest : TestBase() { @Test fun testBadClass() = runTest { val bad = BadClass() - val result = withTimeout(100) { + val result = kotlinx.coroutines.time.withTimeout(100) { bad } assertSame(bad, result) @@ -111,7 +111,7 @@ class WithTimeoutTest : TestBase() { fun testExceptionOnTimeout() = runTest { expect(1) try { - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { expect(2) delay(1000) expectUnreached() @@ -128,7 +128,7 @@ class WithTimeoutTest : TestBase() { expected = { it is CancellationException } ) { expect(1) - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { expect(2) try { delay(1000) @@ -144,7 +144,7 @@ class WithTimeoutTest : TestBase() { fun testSuppressExceptionWithAnotherException() = runTest{ expect(1) try { - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { expect(2) try { delay(1000) @@ -165,7 +165,7 @@ class WithTimeoutTest : TestBase() { fun testNegativeTimeout() = runTest { expect(1) try { - withTimeout(-1) { + kotlinx.coroutines.time.withTimeout(-1) { expectUnreached() "OK" } @@ -180,7 +180,7 @@ class WithTimeoutTest : TestBase() { expect(1) try { expect(2) - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { expect(3) throw TestException() } @@ -193,7 +193,7 @@ class WithTimeoutTest : TestBase() { @Test fun testIncompleteWithTimeoutState() = runTest { lateinit var timeoutJob: Job - val handle = withTimeout(Long.MAX_VALUE) { + val handle = kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { timeoutJob = coroutineContext[Job]!! timeoutJob.invokeOnCompletion { } } diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt index f197a214f5..6b77c3e40a 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt @@ -126,7 +126,7 @@ class ChannelFlowTest : TestBase() { launch { expect(4) collect { - withTimeout(-1) { + kotlinx.coroutines.time.withTimeout(-1) { send(it) } expectUnreached() diff --git a/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt index ad91e49898..a2603898ef 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt @@ -61,7 +61,7 @@ class CatchTest : TestBase() { @Test fun testWithTimeoutCatch() = runTest { val flow = flow { - withTimeout(1) { + kotlinx.coroutines.time.withTimeout(1) { hang { expect(1) } } expectUnreached() diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt index 8fba8456e8..60179fc977 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt @@ -239,7 +239,7 @@ class FlowOnTest : TestBase() { val flow = flow { emit(1) yield() - withTimeout(-1) {} + kotlinx.coroutines.time.withTimeout(-1) {} emit(42) }.flowOn(NamedDispatchers("foo")).onEach { expect(1) @@ -255,7 +255,7 @@ class FlowOnTest : TestBase() { hang { expect(2) } }.flowOn(NamedDispatchers("foo")).onEach { expect(1) - withTimeout(-1) {} + kotlinx.coroutines.time.withTimeout(-1) {} } assertFailsWith(flow) finish(3) diff --git a/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt index e5dde1b7fc..2af20625c6 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt @@ -75,7 +75,7 @@ class RetryTest : TestBase() { val flow = flow { if (state++ == 0) { expect(1) - withTimeout(1) { + kotlinx.coroutines.time.withTimeout(1) { hang { expect(2) } } expectUnreached() diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt index cf83a50b0f..86f4305964 100644 --- a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt @@ -198,8 +198,8 @@ class ShareInTest : TestBase() { val started: Boolean get() = _started.value fun start() = check(_started.compareAndSet(expect = false, update = true)) fun stop() = check(_started.compareAndSet(expect = true, update = false)) - suspend fun awaitStart() = withTimeout(timeLimit) { _started.first { it } } - suspend fun awaitStop() = withTimeout(timeLimit) { _started.first { !it } } + suspend fun awaitStart() = kotlinx.coroutines.time.withTimeout(timeLimit) { _started.first { it } } + suspend fun awaitStop() = kotlinx.coroutines.time.withTimeout(timeLimit) { _started.first { !it } } } private suspend fun FlowState.track(block: suspend () -> Unit) { diff --git a/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt b/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt index 245a80c222..2959cb8394 100644 --- a/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt +++ b/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt @@ -51,7 +51,7 @@ class BroadcastChannelSubStressTest: TestBase() { check(curSent > prevSent) { "Send stalled at $curSent events" } prevSent = curSent } - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { sender.cancelAndJoin() receiver.cancelAndJoin() } diff --git a/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt b/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt index d9ec7ad582..fe6d98242f 100644 --- a/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt +++ b/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt @@ -60,7 +60,7 @@ class ConflatedBroadcastChannelNotifyStressTest : TestBase() { } } try { - withTimeout(timeLimit) { + kotlinx.coroutines.time.withTimeout(timeLimit) { senders.forEach { it.join() } broadcast.trySend(nEvents) // last event to signal receivers termination receivers.forEach { it.join() } diff --git a/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt b/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt index 7f6d6b661c..dbef668fa7 100644 --- a/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt +++ b/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt @@ -119,7 +119,7 @@ class RejectedExecutionTest : TestBase() { withContext(executor.asCoroutineDispatcher()) { expect(2) assertExecutorThread() - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { expect(3) // atomic entry into the block (legacy behavior, it seem to be Ok with way) assertEquals(true, coroutineContext[Job]?.isCancelled) // but the job is already cancelled } @@ -168,4 +168,4 @@ class RejectedExecutionTest : TestBase() { if (thread !is CoroutineScheduler.Worker) error("Not a thread from Dispatchers.IO: $thread") assertEquals(CoroutineScheduler.WorkerState.BLOCKING, thread.state) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt index e2ab4d7282..92de110c83 100644 --- a/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt +++ b/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt @@ -54,7 +54,7 @@ class ThreadContextElementRestoreTest : TestBase() { assertEquals(null, tl.get()) } // Scenario #6: withContext(ThreadLocal) from withTimeout - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { withContext(tl.asContextElement("OK")) { block() assertEquals("OK", tl.get()) @@ -171,14 +171,14 @@ class ThreadContextElementRestoreTest : TestBase() { @Test fun testWithTimeoutDelay() = check { - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { delay(1) } } @Test fun testWithTimeoutYield() = check { - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { yield() } } diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt index 4d440a7cae..545f98bf50 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt @@ -18,7 +18,7 @@ class WithTimeoutChildDispatchStressTest : TestBase() { @Test fun testChildDispatch() = runBlocking { repeat(N_REPEATS) { - val result = withTimeout(5000) { + val result = kotlinx.coroutines.time.withTimeout(5000) { // child in different dispatcher val job = launch(Dispatchers.Default) { // done nothing, but dispatches to join from another thread @@ -29,4 +29,4 @@ class WithTimeoutChildDispatchStressTest : TestBase() { assertEquals("DONE", result) } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt index cce77bb617..f0c144b487 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt @@ -24,7 +24,7 @@ class WithTimeoutOrNullJvmTest : TestBase() { @Test fun testIgnoredTimeout() = runTest { - val value = withTimeout(1) { + val value = kotlinx.coroutines.time.withTimeout(1) { Thread.sleep(10) 42 } diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt index 82f5e92d62..95703dfef0 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt @@ -63,7 +63,7 @@ class WithTimeoutThreadDispatchTest : TestBase() { expect(2) assertEquals(thread, Thread.currentThread()) try { - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { try { expect(3) delay(1000) @@ -82,4 +82,4 @@ class WithTimeoutThreadDispatchTest : TestBase() { } finish(7) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt index 8c9777b4af..cbc1a9669e 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt @@ -65,13 +65,13 @@ class BroadcastChannelMultiReceiveStressTest( println("Launching $name") receivers += launch(pool + CoroutineName(name)) { val channel = broadcast.openSubscription() - when (receiverIndex % 5) { - 0 -> doReceive(channel, receiverIndex) - 1 -> doReceiveCatching(channel, receiverIndex) - 2 -> doIterator(channel, receiverIndex) - 3 -> doReceiveSelect(channel, receiverIndex) - 4 -> doReceiveCatchingSelect(channel, receiverIndex) - } + when (receiverIndex % 5) { + 0 -> doReceive(channel, receiverIndex) + 1 -> doReceiveCatching(channel, receiverIndex) + 2 -> doIterator(channel, receiverIndex) + 3 -> doReceiveSelect(channel, receiverIndex) + 4 -> doReceiveCatchingSelect(channel, receiverIndex) + } channel.cancel() } printProgress() @@ -87,7 +87,7 @@ class BroadcastChannelMultiReceiveStressTest( println(" Sent $total events, waiting for receivers") stopOnReceive.set(total) try { - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { receivers.forEachIndexed { index, receiver -> if (lastReceived[index].get() >= total) receiver.cancel() receiver.join() @@ -96,7 +96,7 @@ class BroadcastChannelMultiReceiveStressTest( } catch (e: Exception) { println("Failed: $e") pool.dumpThreads("Threads in pool") - receivers.indices.forEach { index -> + receivers.indices.forEach { index -> println("lastReceived[$index] = ${lastReceived[index].get()}") } throw e diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt index 7e55f2e602..b3e37ce77e 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt @@ -89,7 +89,7 @@ class ChannelSendReceiveStressTest( } } try { - withTimeout(timeLimit) { + kotlinx.coroutines.time.withTimeout(timeLimit) { senders.forEach { it.join() } channel.close() receivers.forEach { it.join() } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt index dbb1ead568..c232baaa31 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt @@ -9,18 +9,18 @@ class StackTraceRecoveryNestedScopesTest : TestBase() { private val TEST_MACROS = "TEST_NAME" private val expectedTrace = "kotlinx.coroutines.RecoverableTestException\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.failure(StackTraceRecoveryNestedScopesTest.kt:9)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.access\$failure(StackTraceRecoveryNestedScopesTest.kt:7)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$createFailingAsync\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:12)\n" + - "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$callWithTimeout\$2.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:23)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$callCoroutineScope\$2.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:29)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$$TEST_MACROS\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:36)\n" + - "Caused by: kotlinx.coroutines.RecoverableTestException\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.failure(StackTraceRecoveryNestedScopesTest.kt:9)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.access\$failure(StackTraceRecoveryNestedScopesTest.kt:7)\n" + - "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$createFailingAsync\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:12)\n" + - "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.failure(StackTraceRecoveryNestedScopesTest.kt:9)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.access\$failure(StackTraceRecoveryNestedScopesTest.kt:7)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$createFailingAsync\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:12)\n" + + "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$callWithTimeout\$2.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:23)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$callCoroutineScope\$2.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:29)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$$TEST_MACROS\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:36)\n" + + "Caused by: kotlinx.coroutines.RecoverableTestException\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.failure(StackTraceRecoveryNestedScopesTest.kt:9)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.access\$failure(StackTraceRecoveryNestedScopesTest.kt:7)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$createFailingAsync\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:12)\n" + + "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)" private fun failure(): String = throw RecoverableTestException() @@ -34,7 +34,7 @@ class StackTraceRecoveryNestedScopesTest : TestBase() { yield() } - private suspend fun callWithTimeout(doYield: Boolean) = withTimeout(Long.MAX_VALUE) { + private suspend fun callWithTimeout(doYield: Boolean) = kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { if (doYield) yield() callWithContext(doYield) yield() @@ -77,7 +77,8 @@ class StackTraceRecoveryNestedScopesTest : TestBase() { try { deferred.await() } catch (e: Exception) { - verifyStackTrace(e, + verifyStackTrace( + e, "kotlinx.coroutines.RecoverableTestException\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.failure(StackTraceRecoveryNestedScopesTest.kt:23)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.access\$failure(StackTraceRecoveryNestedScopesTest.kt:7)\n" + @@ -88,11 +89,12 @@ class StackTraceRecoveryNestedScopesTest : TestBase() { "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$testAwaitNestedScopes\$1\$deferred\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:68)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.verifyAwait(StackTraceRecoveryNestedScopesTest.kt:76)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$testAwaitNestedScopes\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:71)\n" + - "Caused by: kotlinx.coroutines.RecoverableTestException\n" + + "Caused by: kotlinx.coroutines.RecoverableTestException\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.failure(StackTraceRecoveryNestedScopesTest.kt:23)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest.access\$failure(StackTraceRecoveryNestedScopesTest.kt:7)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedScopesTest\$createFailingAsync\$1.invokeSuspend(StackTraceRecoveryNestedScopesTest.kt:26)\n" + - "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)") + "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)" + ) } } } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt index 8e628dbe90..2e80b5cbe2 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt @@ -23,14 +23,14 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { } private suspend fun outerWithTimeout() { - withTimeout(200) { + kotlinx.coroutines.time.withTimeout(200) { suspendForever() } expectUnreached() } private suspend fun suspendForever() { - hang { } + hang { } expectUnreached() } @@ -44,7 +44,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { } private suspend fun outerChildWithTimeout() { - withTimeout(200) { + kotlinx.coroutines.time.withTimeout(200) { launch { withTimeoutInChild() } @@ -54,8 +54,8 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { } private suspend fun withTimeoutInChild() { - withTimeout(300) { - hang { } + kotlinx.coroutines.time.withTimeout(300) { + hang { } } expectUnreached() } @@ -70,7 +70,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { } private suspend fun outerChild() { - withTimeout(200) { + kotlinx.coroutines.time.withTimeout(200) { launch { smallWithTimeout() } @@ -80,9 +80,9 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { } private suspend fun smallWithTimeout() { - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { suspendForever() } expectUnreached() } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt index f148a3ae43..680a002562 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt @@ -29,7 +29,7 @@ class WithContextCancellationStressTest : TestBase() { var e1Cnt = 0 var e2Cnt = 0 - withTimeout(timeoutAfter) { + kotlinx.coroutines.time.withTimeout(timeoutAfter) { while (eCnt == 0 || e1Cnt == 0 || e2Cnt == 0) { val barrier = CyclicBarrier(4) val ctx = pool + NonCancellable @@ -64,14 +64,17 @@ class WithContextCancellationStressTest : TestBase() { eCnt++ e.checkSuppressed(e1 = e1, e2 = e2) } + is TestException1 -> { e1Cnt++ e.checkSuppressed(ex = true, e2 = e2) } + is TestException2 -> { e2Cnt++ e.checkSuppressed(ex = true, e1 = e1) } + else -> error("Unexpected exception $e") } } diff --git a/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt b/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt index 25c0c98314..1a7e263a63 100644 --- a/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt @@ -109,7 +109,7 @@ class SharingStressTest : TestBase() { // let them work a bit more & make sure emitter did not hang val fromEmitIndex = emitIndex.get() val waitEmitIndex = fromEmitIndex + 100 // wait until 100 emitted - withTimeout(10000) { // wait for at most 10s for something to be emitted + kotlinx.coroutines.time.withTimeout(10000) { // wait for at most 10s for something to be emitted do { delay(random.nextLong(50L..100L)) } while (emitIndex.get() < waitEmitIndex) // Ok, enough was emitted, wait more if not diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt index ea4a10353f..26f4b68b22 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt @@ -8,7 +8,7 @@ package kotlinx.coroutines.guide.exampleCancel07 import kotlinx.coroutines.* fun main() = runBlocking { - withTimeout(1300L) { + kotlinx.coroutines.time.withTimeout(1300L) { repeat(1000) { i -> println("I'm sleeping $i ...") delay(500L) diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt index 13910a6c8a..b554d09f2d 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt @@ -17,10 +17,10 @@ class Resource { fun main() { runBlocking { repeat(100_000) { // Launch 100K coroutines - launch { - val resource = withTimeout(60) { // Timeout of 60 ms + launch { + val resource = kotlinx.coroutines.time.withTimeout(60) { // Timeout of 60 ms delay(50) // Delay for 50 ms - Resource() // Acquire a resource and return it from withTimeout block + Resource() // Acquire a resource and return it from withTimeout block } resource.close() // Release the resource } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt index 336f5e3a3a..beee797c7a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt @@ -17,15 +17,15 @@ class Resource { fun main() { runBlocking { repeat(100_000) { // Launch 100K coroutines - launch { + launch { var resource: Resource? = null // Not acquired yet try { - withTimeout(60) { // Timeout of 60 ms + kotlinx.coroutines.time.withTimeout(60) { // Timeout of 60 ms delay(50) // Delay for 50 ms - resource = Resource() // Store a resource to the variable if acquired + resource = Resource() // Store a resource to the variable if acquired } // We can do something else with the resource here - } finally { + } finally { resource?.close() // Release the resource if it was acquired } } diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt index 372e79ef1d..a1d0f32a30 100644 --- a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt +++ b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt @@ -589,7 +589,7 @@ class FutureTest : TestBase() { } } future.complete(1) - withTimeout(60_000) { + kotlinx.coroutines.time.withTimeout(60_000) { children.forEach { it.join() } assertEquals(count, completed.get()) } diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt b/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt index fc4436f418..5f5e66b005 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt @@ -91,7 +91,7 @@ abstract class SchedulerTestBase : TestBase() { @After fun after() { runBlocking { - withTimeout(5_000) { + kotlinx.coroutines.time.withTimeout(5_000) { _dispatcher?.close() } } diff --git a/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt index 22179f34ad..13e901a716 100644 --- a/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt @@ -56,10 +56,10 @@ class SelectPhilosophersStressTest : TestBase() { println("Test is failing. Lock states are:") forks.withIndex().forEach { (id, mutex) -> println("$id: $mutex") } } - val eats = withTimeout(5 * TEST_DURATION) { philosophers.map { it.await() } } + val eats = kotlinx.coroutines.time.withTimeout(5 * TEST_DURATION) { philosophers.map { it.await() } } debugJob.cancel() eats.withIndex().forEach { (id, eats) -> assertTrue(eats > 0, "$id shall not starve") } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt b/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt index 9904f06c5f..933ee5f086 100644 --- a/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt +++ b/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt @@ -62,7 +62,7 @@ class MainDispatcherTest : TestBase() { @Test fun testWithTimeoutContextDelayNoTimeout() = runTestNotOnMainDispatcher { expect(1) - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { withContext(Dispatchers.Main) { assertTrue(isMainThread()) expect(2) @@ -79,16 +79,16 @@ class MainDispatcherTest : TestBase() { fun testWithTimeoutContextDelayTimeout() = runTestNotOnMainDispatcher { expect(1) assertFailsWith { - withTimeout(100) { - withContext(Dispatchers.Main) { - assertTrue(isMainThread()) - expect(2) - delay(1000) - expectUnreached() - } - } - expectUnreached() - } + kotlinx.coroutines.time.withTimeout(100) { + withContext(Dispatchers.Main) { + assertTrue(isMainThread()) + expect(2) + delay(1000) + expectUnreached() + } + } + expectUnreached() + } assertFalse(isMainThread()) finish(3) } @@ -97,7 +97,7 @@ class MainDispatcherTest : TestBase() { fun testWithContextTimeoutDelayNoTimeout() = runTestNotOnMainDispatcher { expect(1) withContext(Dispatchers.Main) { - withTimeout(1000) { + kotlinx.coroutines.time.withTimeout(1000) { assertTrue(isMainThread()) expect(2) delay(100) @@ -114,7 +114,7 @@ class MainDispatcherTest : TestBase() { expect(1) assertFailsWith { withContext(Dispatchers.Main) { - withTimeout(100) { + kotlinx.coroutines.time.withTimeout(100) { assertTrue(isMainThread()) expect(2) delay(1000) diff --git a/kotlinx-coroutines-debug/test/StartModeProbesTest.kt b/kotlinx-coroutines-debug/test/StartModeProbesTest.kt index c2656d346b..bb595d9aec 100644 --- a/kotlinx-coroutines-debug/test/StartModeProbesTest.kt +++ b/kotlinx-coroutines-debug/test/StartModeProbesTest.kt @@ -59,7 +59,7 @@ class StartModeProbesTest : DebugTestBase() { } private suspend fun withTimeoutHelper() { - withTimeout(Long.MAX_VALUE) { + kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { expect(2) delay(Long.MAX_VALUE) } @@ -69,7 +69,7 @@ class StartModeProbesTest : DebugTestBase() { @Test fun testWithTimeout() = runTest { - withTimeout(Long.MAX_VALUE) { + kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { testActiveDump( false, "StartModeProbesTest\$testWithTimeout\$1.invokeSuspend", @@ -80,7 +80,7 @@ class StartModeProbesTest : DebugTestBase() { @Test fun testWithTimeoutAfterYield() = runTest { - withTimeout(Long.MAX_VALUE) { + kotlinx.coroutines.time.withTimeout(Long.MAX_VALUE) { testActiveDump( true, "StartModeProbesTest\$testWithTimeoutAfterYield\$1.invokeSuspend", @@ -127,7 +127,8 @@ class StartModeProbesTest : DebugTestBase() { verifyPartialDump( 2, "StartModeProbesTest\$runScope\$2.invokeSuspend", - "StartModeProbesTest\$testCoroutineScope\$1\$job\$1.invokeSuspend") + "StartModeProbesTest\$testCoroutineScope\$1\$job\$1.invokeSuspend" + ) job.cancelAndJoin() finish(4) } @@ -141,13 +142,15 @@ class StartModeProbesTest : DebugTestBase() { @Test fun testLazy() = runTest({ it is CancellationException }) { - launch(start = CoroutineStart.LAZY) { } - actor(start = CoroutineStart.LAZY) { } - broadcast(start = CoroutineStart.LAZY) { } + launch(start = CoroutineStart.LAZY) { } + actor(start = CoroutineStart.LAZY) { } + broadcast(start = CoroutineStart.LAZY) { } async(start = CoroutineStart.LAZY) { 1 } - verifyPartialDump(5, "BlockingCoroutine", + verifyPartialDump( + 5, "BlockingCoroutine", "LazyStandaloneCoroutine", "LazyActorCoroutine", - "LazyBroadcastCoroutine", "LazyDeferredCoroutine") + "LazyBroadcastCoroutine", "LazyDeferredCoroutine" + ) cancel() } } diff --git a/kotlinx-coroutines-test/common/test/RunTestTest.kt b/kotlinx-coroutines-test/common/test/RunTestTest.kt index 0315543d54..b13fabeb3b 100644 --- a/kotlinx-coroutines-test/common/test/RunTestTest.kt +++ b/kotlinx-coroutines-test/common/test/RunTestTest.kt @@ -245,7 +245,7 @@ class RunTestTest { assertFailsWith { it() } }) { runTest { - withTimeout(50) { + kotlinx.coroutines.time.withTimeout(50) { launch { delay(1000) } diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt index d050e9c8c0..21e2fb2d03 100644 --- a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt +++ b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt @@ -241,7 +241,7 @@ class TestCoroutineSchedulerTest { asSpecificImplementation().enter() launch { try { - withTimeout(timeoutMillis) { + kotlinx.coroutines.time.withTimeout(timeoutMillis) { block() } } catch (e: TimeoutCancellationException) { diff --git a/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt b/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt index 806592079c..151aba3d2f 100644 --- a/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt +++ b/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt @@ -81,7 +81,7 @@ class RunBlockingTestOnTestScopeTest { fun testTimeout() { assertFailsWith { runBlockingTestOnTestScope { - withTimeout(50) { + kotlinx.coroutines.time.withTimeout(50) { launch { delay(1000) } diff --git a/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt b/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt index ed5b1577f5..db5566998c 100644 --- a/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt +++ b/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt @@ -181,7 +181,7 @@ class RunTestLegacyScopeTest { assertFailsWith { it() } }) { runTestWithLegacyScope { - withTimeout(50) { + kotlinx.coroutines.time.withTimeout(50) { launch { delay(1000) } diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt index af3b24892a..5a17e5f024 100644 --- a/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt +++ b/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt @@ -57,7 +57,7 @@ class TestRunBlockingTest { assertFailsWith { runBlockingTest { assertRunsFast { - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { delay(SLOW) } } @@ -68,7 +68,7 @@ class TestRunBlockingTest { @Test fun whenUsingTimeout_doesNotTriggerWhenFast() = runBlockingTest { assertRunsFast { - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { delay(0) } } @@ -80,7 +80,7 @@ class TestRunBlockingTest { runBlockingTest { val uncompleted = CompletableDeferred() assertRunsFast { - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { uncompleted.await() } } @@ -93,7 +93,7 @@ class TestRunBlockingTest { val completed = CompletableDeferred() assertRunsFast { completed.complete(Unit) - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { completed.await() } } @@ -115,7 +115,7 @@ class TestRunBlockingTest { assertFailsWith { runBlockingTest { val deferred = async { - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { delay(SLOW) } } @@ -130,7 +130,7 @@ class TestRunBlockingTest { @Test fun whenUsingTimeout_inAsync_doesNotTriggerWhenNotDelayed() = runBlockingTest { val deferred = async { - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { delay(0) } } @@ -145,7 +145,7 @@ class TestRunBlockingTest { assertFailsWith { runBlockingTest { val job = launch { - withTimeout(1) { + kotlinx.coroutines.time.withTimeout(1) { delay(SLOW + 1) } } @@ -161,7 +161,7 @@ class TestRunBlockingTest { @Test fun whenUsingTimeout_inLaunch_doesNotTriggerWhenNotDelayed() = runBlockingTest { val job = launch { - withTimeout(SLOW) { + kotlinx.coroutines.time.withTimeout(SLOW) { delay(0) } } @@ -437,4 +437,4 @@ class TestRunBlockingTest { } } } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt b/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt index b860e16209..8c80f80636 100644 --- a/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt +++ b/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt @@ -80,7 +80,7 @@ class FlowAsPublisherTest : TestBase() { fun testFlowWithTimeout() = runTest { val publisher = flow { expect(2) - withTimeout(1) { delay(Long.MAX_VALUE) } + kotlinx.coroutines.time.withTimeout(1) { delay(Long.MAX_VALUE) } }.asPublisher() try { expect(1) diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt index 8462df2c6f..077fb7bf6b 100644 --- a/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt +++ b/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt @@ -22,7 +22,7 @@ class PublisherCompletionStressTest : TestBase() { repeat(N_REPEATS) { val count = rnd.nextInt(5) runBlocking { - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { var received = 0 range(Dispatchers.Default, 1, count).collect { x -> received++ @@ -33,4 +33,4 @@ class PublisherCompletionStressTest : TestBase() { } } } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt b/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt index 02c9e242e9..364bcc6aa4 100644 --- a/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt @@ -155,7 +155,7 @@ class FlowAsPublisherTest : TestBase() { fun testFlowWithTimeout() = runTest { val publisher = flow { expect(2) - withTimeout(1) { delay(Long.MAX_VALUE) } + kotlinx.coroutines.time.withTimeout(1) { delay(Long.MAX_VALUE) } }.asPublisher() try { expect(1) diff --git a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt index fa039897d7..757f750c27 100644 --- a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt @@ -214,7 +214,7 @@ class IntegrationTest( fun testPublishWithTimeout() = runTest { val publisher = publish { expect(2) - withTimeout(1) { delay(100) } + kotlinx.coroutines.time.withTimeout(1) { delay(100) } } try { expect(1) diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt index b16310d0cd..4ec6a6b83e 100644 --- a/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt @@ -22,7 +22,7 @@ class PublisherCompletionStressTest : TestBase() { repeat(N_REPEATS) { val count = rnd.nextInt(5) runBlocking { - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { var received = 0 range(Dispatchers.Default, 1, count).collect { x -> received++ @@ -33,4 +33,4 @@ class PublisherCompletionStressTest : TestBase() { } } } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt index 6090408f97..140363305d 100644 --- a/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt @@ -23,7 +23,7 @@ class FluxCompletionStressTest : TestBase() { repeat(N_REPEATS) { val count = rnd.nextInt(5) runBlocking { - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { var received = 0 range(Dispatchers.Default, 1, count).collect { x -> received++ @@ -34,4 +34,4 @@ class FluxCompletionStressTest : TestBase() { } } } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt index 2a5e5dc107..028ff533c1 100644 --- a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt @@ -314,7 +314,7 @@ class MonoTest : TestBase() { @Test fun testTimeout() { val mono = mono { - withTimeout(1) { delay(100) } + kotlinx.coroutines.time.withTimeout(1) { delay(100) } } try { mono.doOnSubscribe { expect(1) } diff --git a/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt index 8a6362ad99..e2efa8253d 100644 --- a/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt @@ -129,7 +129,7 @@ class IntegrationTest( fun testObservableWithTimeout() = runTest { val observable = rxObservable { expect(2) - withTimeout(1) { delay(100) } + kotlinx.coroutines.time.withTimeout(1) { delay(100) } } try { expect(1) diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt index 7e1d335028..572d629893 100644 --- a/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt @@ -22,7 +22,7 @@ class ObservableCompletionStressTest : TestBase() { repeat(N_REPEATS) { val count = rnd.nextInt(5) runBlocking { - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { var received = 0 range(Dispatchers.Default, 1, count).collect { x -> received++ diff --git a/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt index 1302124f50..c7b94bba8f 100644 --- a/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt +++ b/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt @@ -129,7 +129,7 @@ class IntegrationTest( fun testObservableWithTimeout() = runTest { val observable = rxObservable { expect(2) - withTimeout(1) { delay(100) } + kotlinx.coroutines.time.withTimeout(1) { delay(100) } } try { expect(1) diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt index c1d25bcb51..e8c234aee8 100644 --- a/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt +++ b/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt @@ -22,7 +22,7 @@ class ObservableCompletionStressTest : TestBase() { repeat(N_REPEATS) { val count = rnd.nextInt(5) runBlocking { - withTimeout(5000) { + kotlinx.coroutines.time.withTimeout(5000) { var received = 0 range(Dispatchers.Default, 1, count).collect { x -> received++ diff --git a/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt b/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt index afe6cff2f6..4d881c4eed 100644 --- a/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt +++ b/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt @@ -61,7 +61,7 @@ class HandlerDispatcherTest : TestBase() { mainLooper.pause() assertFalse { mainLooper.scheduler.areAnyRunnable() } val job = launch(Dispatchers.Main, start = CoroutineStart.UNDISPATCHED) { - withTimeout(1) { + kotlinx.coroutines.time.withTimeout(1) { expect(1) hang { expect(3) } } From 7267280e04d778fa5a989e55a1aaed173a615d28 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Mon, 31 Oct 2022 16:19:24 +0100 Subject: [PATCH 3/4] Use TimeoutException instead of TimeoutCancellationException --- kotlinx-coroutines-core/common/src/JobSupport.kt | 1 + kotlinx-coroutines-core/common/src/Timeout.kt | 8 ++++++++ .../common/src/flow/operators/Delay.kt | 7 ++++--- .../common/src/intrinsics/Undispatched.kt | 6 ++++-- .../common/test/WithTimeoutDurationTest.kt | 3 ++- .../common/test/WithTimeoutOrNullDurationTest.kt | 3 ++- .../common/test/WithTimeoutOrNullTest.kt | 3 ++- .../common/test/WithTimeoutTest.kt | 3 ++- .../common/test/flow/channels/ChannelFlowTest.kt | 3 ++- .../common/test/flow/operators/DebounceTest.kt | 5 +++-- .../common/test/flow/operators/FlowOnTest.kt | 5 +++-- .../common/test/flow/operators/TimeoutTest.kt | 9 +++++---- ...RecoveredFromLexicalBlockWhenTriggeredByChild.txt | 12 ++++++------ .../testStacktraceIsRecoveredFromSuspensionPoint.txt | 8 ++++---- ...ktraceIsRecoveredFromSuspensionPointWithChild.txt | 8 ++++---- .../exceptions/StackTraceRecoveryWithTimeoutTest.kt | 7 ++++--- .../jvm/test/guide/example-cancel-07.kt | 2 +- .../jvm/test/guide/example-cancel-09.kt | 6 +++--- .../jvm/test/guide/example-cancel-10.kt | 8 ++++---- .../jvm/test/jdk8/time/DurationOverflowTest.kt | 4 ++-- .../jvm/test/jdk8/time/WithTimeoutTest.kt | 4 ++-- .../nativeDarwin/test/MainDispatcherTest.kt | 5 +++-- kotlinx-coroutines-test/common/test/RunTestTest.kt | 5 +++-- .../common/test/TestCoroutineSchedulerTest.kt | 3 ++- 24 files changed, 76 insertions(+), 52 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index 2950ed9814..3b2f6d499f 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -260,6 +260,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren val firstNonCancellation = exceptions.firstOrNull { it !is CancellationException } if (firstNonCancellation != null) return firstNonCancellation val first = exceptions[0] + @Suppress("DEPRECATION") if (first is TimeoutCancellationException) { val detailedTimeoutException = exceptions.firstOrNull { it !== first && it is TimeoutCancellationException } if (detailedTimeoutException != null) return detailedTimeoutException diff --git a/kotlinx-coroutines-core/common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt index b3e4b9025d..b6f6c88bc2 100644 --- a/kotlinx-coroutines-core/common/src/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/Timeout.kt @@ -48,6 +48,7 @@ public suspend fun withTimeout(timeMillis: Long, block: suspend CoroutineSco contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + @Suppress("DEPRECATION") if (timeMillis <= 0L) throw TimeoutCancellationException("Timed out immediately") return suspendCoroutineUninterceptedOrReturn { uCont -> setupTimeout(TimeoutCoroutine(timeMillis, uCont), block) @@ -113,6 +114,7 @@ public suspend fun withTimeoutOrNull(timeMillis: Long, block: suspend Corout if (timeMillis <= 0L) return null var coroutine: TimeoutCoroutine? = null + @Suppress("DEPRECATION") try { return suspendCoroutineUninterceptedOrReturn { uCont -> val timeoutCoroutine = TimeoutCoroutine(timeMillis, uCont) @@ -179,6 +181,11 @@ private class TimeoutCoroutine( /** * This exception is thrown by [withTimeout] to indicate timeout. */ +@Deprecated("Use TimeoutException from the 'kotlinx-coroutines-time' package instead.", + ReplaceWith("kotlinx.coroutines.time.TimeoutException", + "kotlinx.coroutines.time"), + level = DeprecationLevel.WARNING) +@Suppress("DEPRECATION") public class TimeoutCancellationException internal constructor( message: String, @JvmField @Transient internal val coroutine: Job? @@ -195,6 +202,7 @@ public class TimeoutCancellationException internal constructor( TimeoutCancellationException(message ?: "", coroutine).also { it.initCause(this) } } +@Suppress("DEPRECATION") internal fun TimeoutCancellationException( time: Long, coroutine: Job diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt b/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt index 738fef79be..c68322d29d 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.channels.* import kotlinx.coroutines.flow.internal.* import kotlinx.coroutines.selects.* +import kotlinx.coroutines.time.* import kotlin.jvm.* import kotlin.time.* @@ -346,7 +347,7 @@ internal fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMil public fun Flow.sample(period: Duration): Flow = sample(period.toDelayMillis()) /** - * Returns a flow that will emit a [TimeoutCancellationException] if the upstream doesn't emit an item within the given time. + * Returns a flow that will emit a [TimeoutException] if the upstream doesn't emit an item within the given time. * * Example: * @@ -386,7 +387,7 @@ public fun Flow.timeout( private fun Flow.timeoutInternal( timeout: Duration ): Flow = scopedFlow { downStream -> - if (timeout <= Duration.ZERO) throw TimeoutCancellationException("Timed out immediately") + if (timeout <= Duration.ZERO) throw TimeoutException("Timed out immediately") val values = buffer(Channel.RENDEZVOUS).produceIn(this) whileSelect { values.onReceiveCatching { value -> @@ -398,7 +399,7 @@ private fun Flow.timeoutInternal( return@onReceiveCatching true } onTimeout(timeout) { - throw TimeoutCancellationException("Timed out waiting for $timeout") + throw TimeoutException("Timed out waiting for $timeout") } } } diff --git a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt index 157e623f36..072dbc7fd0 100644 --- a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt +++ b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt @@ -27,7 +27,7 @@ internal fun (suspend () -> T).startCoroutineUnintercepted(completion: Conti * It does not use [ContinuationInterceptor] and does not update the context of the current thread. */ internal fun (suspend (R) -> T).startCoroutineUnintercepted(receiver: R, completion: Continuation) { - startDirect(completion) { actualCompletion -> + startDirect(completion) { actualCompletion -> startCoroutineUninterceptedOrReturn(receiver, actualCompletion) } } @@ -97,7 +97,9 @@ internal fun ScopeCoroutine.startUndispatchedOrReturn(receiver: R, blo internal fun ScopeCoroutine.startUndispatchedOrReturnIgnoreTimeout( receiver: R, block: suspend R.() -> T ): Any? { - return undispatchedResult({ e -> !(e is TimeoutCancellationException && e.coroutine === this) }) { + return undispatchedResult({ e -> + @Suppress("DEPRECATION") !(e is TimeoutCancellationException && e.coroutine === this) + }) { block.startCoroutineUninterceptedOrReturn(receiver, this) } } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt index afe3e74170..89d9180a21 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.time.* import kotlin.test.* import kotlin.time.* import kotlin.time.Duration.Companion.milliseconds @@ -177,7 +178,7 @@ class WithTimeoutDurationTest : TestBase() { expectUnreached() "OK" } - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { assertEquals("Timed out immediately", e.message) finish(2) } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt index 7a8773bb22..6c93208636 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt @@ -8,6 +8,7 @@ package kotlinx.coroutines import kotlinx.coroutines.channels.* +import kotlinx.coroutines.time.* import kotlin.test.* import kotlin.time.* import kotlin.time.Duration.Companion.milliseconds @@ -117,7 +118,7 @@ class WithTimeoutOrNullDurationTest : TestBase() { } @Test - fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { + fun testNestedTimeout() = runTest(expected = { it is TimeoutException }) { withTimeoutOrNull(Duration.INFINITE) { // Exception from this withTimeout is not suppressed by withTimeoutOrNull kotlinx.coroutines.time.withTimeout(10.milliseconds) { diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt index 593c4a647c..1ef955b01d 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt @@ -8,6 +8,7 @@ package kotlinx.coroutines import kotlinx.coroutines.channels.* +import kotlinx.coroutines.time.* import kotlin.test.* class WithTimeoutOrNullTest : TestBase() { @@ -114,7 +115,7 @@ class WithTimeoutOrNullTest : TestBase() { } @Test - fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) { + fun testNestedTimeout() = runTest(expected = { it is TimeoutException }) { withTimeoutOrNull(Long.MAX_VALUE) { // Exception from this withTimeout is not suppressed by withTimeoutOrNull kotlinx.coroutines.time.withTimeout(10) { diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt index a2e178fbaa..5a00b09026 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.time.* import kotlin.test.* class WithTimeoutTest : TestBase() { @@ -169,7 +170,7 @@ class WithTimeoutTest : TestBase() { expectUnreached() "OK" } - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { assertEquals("Timed out immediately", e.message) finish(2) } diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt index 6b77c3e40a..f0984eaeef 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow import kotlinx.coroutines.* import kotlinx.coroutines.channels.* +import kotlinx.coroutines.time.* import kotlin.test.* class ChannelFlowTest : TestBase() { @@ -137,7 +138,7 @@ class ChannelFlowTest : TestBase() { val flow = flowOf(1, 2, 3).bufferWithTimeout() expect(1) - assertFailsWith(flow) + assertFailsWith(flow) finish(6) } diff --git a/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt index 0268a232a4..4e48c49eee 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow import kotlinx.coroutines.* import kotlinx.coroutines.channels.* +import kotlinx.coroutines.time.* import kotlin.test.* import kotlin.time.Duration.Companion.milliseconds @@ -96,10 +97,10 @@ class DebounceTest : TestBase() { } @Test - fun testUpstreamError()= testUpstreamError(TimeoutCancellationException("")) + fun testUpstreamError()= testUpstreamError(TimeoutException("")) @Test - fun testUpstreamErrorCancellation() = testUpstreamError(TimeoutCancellationException("")) + fun testUpstreamErrorCancellation() = testUpstreamError(TimeoutException("")) private inline fun testUpstreamError(cause: T) = runTest { val latch = Channel() diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt index 60179fc977..75f425288f 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow import kotlinx.coroutines.* import kotlinx.coroutines.channels.* +import kotlinx.coroutines.time.* import kotlin.test.* class FlowOnTest : TestBase() { @@ -244,7 +245,7 @@ class FlowOnTest : TestBase() { }.flowOn(NamedDispatchers("foo")).onEach { expect(1) } - assertFailsWith(flow) + assertFailsWith(flow) finish(2) } @@ -257,7 +258,7 @@ class FlowOnTest : TestBase() { expect(1) kotlinx.coroutines.time.withTimeout(-1) {} } - assertFailsWith(flow) + assertFailsWith(flow) finish(3) } diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt index 854e331f1a..5f79511659 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow.operators import kotlinx.coroutines.* import kotlinx.coroutines.flow.* +import kotlinx.coroutines.time.* import kotlin.test.* import kotlin.time.Duration.Companion.milliseconds @@ -27,7 +28,7 @@ class TimeoutTest : TestBase() { expect(2) val list = mutableListOf() - assertFailsWith(flow.timeout(300.milliseconds).onEach { list.add(it) }) + assertFailsWith(flow.timeout(300.milliseconds).onEach { list.add(it) }) assertEquals(listOf("A", "B", "C"), list) finish(5) } @@ -60,7 +61,7 @@ class TimeoutTest : TestBase() { expect(2) val list = mutableListOf() - flow.timeout(300.milliseconds).catch { if (it is TimeoutCancellationException) emit("-1") }.collect { list.add(it) } + flow.timeout(300.milliseconds).catch { if (it is TimeoutException) emit("-1") }.collect { list.add(it) } assertEquals(listOf("A", "B", "C", "-1"), list) finish(5) } @@ -164,7 +165,7 @@ class TimeoutTest : TestBase() { expectUnreached() }.flowOn(NamedDispatchers("upstream")).timeout(100.milliseconds) - assertFailsWith(flow) + assertFailsWith(flow) finish(3) } @@ -192,7 +193,7 @@ class TimeoutTest : TestBase() { try { MutableSharedFlow().asSharedFlow().timeout(100.milliseconds).collect() expectUnreached() - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { finish(1) } } diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild.txt index ac40dc152b..5c47e4246d 100644 --- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild.txt +++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild.txt @@ -1,7 +1,7 @@ -kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms +kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt) - at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerChildWithTimeout(StackTraceRecoveryWithTimeoutTest.kt:48) - at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:40) -Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms - at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:116) - at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:86) + at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerChildWithTimeout(StackTraceRecoveryWithTimeoutTest.kt) + at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt) +Caused by: kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms + at kotlinx.coroutines.time.TimeoutKt.TimeoutException(Timeout.kt) + at kotlinx.coroutines.time.TimeoutCoroutine.run(Timeout.kt) diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPoint.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPoint.txt index 9d5ddb6621..9d6c5997d4 100644 --- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPoint.txt +++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPoint.txt @@ -1,10 +1,10 @@ -kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms +kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.suspendForever(StackTraceRecoveryWithTimeoutTest.kt:42) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$outerWithTimeout$2.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:32) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerWithTimeout(StackTraceRecoveryWithTimeoutTest.kt:31) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromSuspensionPoint$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:19) -Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms - at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:116) - at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:86) +Caused by: kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms + at kotlinx.coroutines.time.TimeoutKt.TimeoutException(Timeout.kt:116) + at kotlinx.coroutines.time.TimeoutCoroutine.run(Timeout.kt:86) at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.common.kt:492) diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPointWithChild.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPointWithChild.txt index 6f21cc6b30..5d6a8fbe9f 100644 --- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPointWithChild.txt +++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/timeout/testStacktraceIsRecoveredFromSuspensionPointWithChild.txt @@ -1,9 +1,9 @@ -kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms +kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.suspendForever(StackTraceRecoveryWithTimeoutTest.kt:92) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$outerChild$2.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:78) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerChild(StackTraceRecoveryWithTimeoutTest.kt:74) at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromSuspensionPointWithChild$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:66) -Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms - at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:116) - at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:86) +Caused by: kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms + at kotlinx.coroutines.time.TimeoutKt.TimeoutException(Timeout.kt:116) + at kotlinx.coroutines.time.TimeoutCoroutine.run(Timeout.kt:86) diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt index 2e80b5cbe2..e674ac6065 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.exceptions import kotlinx.coroutines.* +import kotlinx.coroutines.time.* import org.junit.* import org.junit.rules.* @@ -17,7 +18,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { fun testStacktraceIsRecoveredFromSuspensionPoint() = runTest { try { outerWithTimeout() - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { verifyStackTrace("timeout/${name.methodName}", e) } } @@ -38,7 +39,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { fun testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild() = runTest { try { outerChildWithTimeout() - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { verifyStackTrace("timeout/${name.methodName}", e) } } @@ -64,7 +65,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { fun testStacktraceIsRecoveredFromSuspensionPointWithChild() = runTest { try { outerChild() - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { verifyStackTrace("timeout/${name.methodName}", e) } } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt index 26f4b68b22..ea4a10353f 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt @@ -8,7 +8,7 @@ package kotlinx.coroutines.guide.exampleCancel07 import kotlinx.coroutines.* fun main() = runBlocking { - kotlinx.coroutines.time.withTimeout(1300L) { + withTimeout(1300L) { repeat(1000) { i -> println("I'm sleeping $i ...") delay(500L) diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt index b554d09f2d..13910a6c8a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt @@ -17,10 +17,10 @@ class Resource { fun main() { runBlocking { repeat(100_000) { // Launch 100K coroutines - launch { - val resource = kotlinx.coroutines.time.withTimeout(60) { // Timeout of 60 ms + launch { + val resource = withTimeout(60) { // Timeout of 60 ms delay(50) // Delay for 50 ms - Resource() // Acquire a resource and return it from withTimeout block + Resource() // Acquire a resource and return it from withTimeout block } resource.close() // Release the resource } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt index beee797c7a..336f5e3a3a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt @@ -17,15 +17,15 @@ class Resource { fun main() { runBlocking { repeat(100_000) { // Launch 100K coroutines - launch { + launch { var resource: Resource? = null // Not acquired yet try { - kotlinx.coroutines.time.withTimeout(60) { // Timeout of 60 ms + withTimeout(60) { // Timeout of 60 ms delay(50) // Delay for 50 ms - resource = Resource() // Store a resource to the variable if acquired + resource = Resource() // Store a resource to the variable if acquired } // We can do something else with the resource here - } finally { + } finally { resource?.close() // Release the resource if it was acquired } } diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt index 9ab0ccf95f..a864fdd262 100644 --- a/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt +++ b/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt @@ -67,8 +67,8 @@ class DurationOverflowTest : TestBase() { @Test fun testZeroDurationWithTimeout() = runTest { - assertFailsWith { withTimeout(0L) {} } - assertFailsWith { withTimeout(Duration.ZERO) {} } + assertFailsWith { withTimeout(0L) {} } + assertFailsWith { withTimeout(Duration.ZERO) {} } } @Test diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt index d33eaac124..1ab4f71ad3 100644 --- a/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt +++ b/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt @@ -61,8 +61,8 @@ class WithTimeoutTest : TestBase() { delay(Duration.ofSeconds(Long.MAX_VALUE)) expectUnreached() } - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { finish(3) } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt b/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt index 933ee5f086..cdab806958 100644 --- a/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt +++ b/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt @@ -4,6 +4,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.time.* import platform.CoreFoundation.* import platform.darwin.* import kotlin.coroutines.* @@ -78,7 +79,7 @@ class MainDispatcherTest : TestBase() { @Test fun testWithTimeoutContextDelayTimeout() = runTestNotOnMainDispatcher { expect(1) - assertFailsWith { + assertFailsWith { kotlinx.coroutines.time.withTimeout(100) { withContext(Dispatchers.Main) { assertTrue(isMainThread()) @@ -112,7 +113,7 @@ class MainDispatcherTest : TestBase() { @Test fun testWithContextTimeoutDelayTimeout() = runTestNotOnMainDispatcher { expect(1) - assertFailsWith { + assertFailsWith { withContext(Dispatchers.Main) { kotlinx.coroutines.time.withTimeout(100) { assertTrue(isMainThread()) diff --git a/kotlinx-coroutines-test/common/test/RunTestTest.kt b/kotlinx-coroutines-test/common/test/RunTestTest.kt index b13fabeb3b..9306eec0ca 100644 --- a/kotlinx-coroutines-test/common/test/RunTestTest.kt +++ b/kotlinx-coroutines-test/common/test/RunTestTest.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines.test import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.flow.* +import kotlinx.coroutines.time.* import kotlin.coroutines.* import kotlin.test.* @@ -239,10 +240,10 @@ class RunTestTest { } } - /** Tests that [runTest] reports [TimeoutCancellationException]. */ + /** Tests that [runTest] reports [TimeoutException]. */ @Test fun testTimeout() = testResultMap({ - assertFailsWith { it() } + assertFailsWith { it() } }) { runTest { kotlinx.coroutines.time.withTimeout(50) { diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt index 21e2fb2d03..c2c558a243 100644 --- a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt +++ b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.test import kotlinx.coroutines.* +import kotlinx.coroutines.time.* import kotlin.test.* import kotlin.time.* import kotlin.time.Duration.Companion.seconds @@ -244,7 +245,7 @@ class TestCoroutineSchedulerTest { kotlinx.coroutines.time.withTimeout(timeoutMillis) { block() } - } catch (e: TimeoutCancellationException) { + } catch (e: TimeoutException) { caughtException = true } } From 0d818f42345fc60db8902b2963e098664bb6c5c1 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Sat, 3 Dec 2022 12:46:54 +0100 Subject: [PATCH 4/4] Make TimeoutException not a CancellationException --- kotlinx-coroutines-core/common/src/JobSupport.kt | 1 + kotlinx-coroutines-core/common/src/time/Timeout.kt | 2 +- .../common/test/WithTimeoutDurationTest.kt | 8 ++++---- .../common/test/WithTimeoutOrNullDurationTest.kt | 6 +++--- .../common/test/WithTimeoutOrNullTest.kt | 6 +++--- .../common/test/WithTimeoutTest.kt | 10 +++++----- .../jvm/test/WithTimeoutOrNullThreadDispatchTest.kt | 5 +++-- .../jvm/test/WithTimeoutThreadDispatchTest.kt | 5 +++-- .../exceptions/StackTraceRecoveryWithTimeoutTest.kt | 1 + .../test/HandlerDispatcherTest.kt | 13 +++++++++---- 10 files changed, 33 insertions(+), 24 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index 3b2f6d499f..7dcf21e5f2 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -8,6 +8,7 @@ package kotlinx.coroutines import kotlinx.atomicfu.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.selects.* +import kotlinx.coroutines.time.* import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* import kotlin.js.* diff --git a/kotlinx-coroutines-core/common/src/time/Timeout.kt b/kotlinx-coroutines-core/common/src/time/Timeout.kt index c7933bb479..e35f9eaf36 100644 --- a/kotlinx-coroutines-core/common/src/time/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/time/Timeout.kt @@ -106,7 +106,7 @@ private class TimeoutCoroutine( public class TimeoutException internal constructor( message: String, @JvmField @Transient internal val coroutine: Job? -) : CancellationException(message), CopyableThrowable { +): IllegalStateException(message), CopyableThrowable { /** * Creates a timeout exception with the given message. * This constructor is needed for exception stack-traces recovery. diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt index 89d9180a21..f54e3212cd 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt @@ -74,7 +74,7 @@ class WithTimeoutDurationTest : TestBase() { */ @Test fun testYieldBlockingWithTimeout() = runTest( - expected = { it is CancellationException } + expected = { it is TimeoutException } ) { kotlinx.coroutines.time.withTimeout(100.milliseconds) { while (true) { @@ -126,7 +126,7 @@ class WithTimeoutDurationTest : TestBase() { expectUnreached() "OK" } - } catch (e: CancellationException) { + } catch (e: TimeoutException) { assertEquals("Timed out waiting for 100 ms", e.message) finish(3) } @@ -134,7 +134,7 @@ class WithTimeoutDurationTest : TestBase() { @Test fun testSuppressExceptionWithResult() = runTest( - expected = { it is CancellationException } + expected = { it is TimeoutException } ) { expect(1) kotlinx.coroutines.time.withTimeout(100.milliseconds) { @@ -157,7 +157,7 @@ class WithTimeoutDurationTest : TestBase() { expect(2) try { delay(1000.milliseconds) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(3) throw TestException() } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt index 6c93208636..944565af36 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt @@ -103,7 +103,7 @@ class WithTimeoutOrNullDurationTest : TestBase() { @Test fun testInnerTimeout() = runTest( - expected = { it is CancellationException } + expected = { it is TimeoutException } ) { withTimeoutOrNull(1000.milliseconds) { kotlinx.coroutines.time.withTimeout(10.milliseconds) { @@ -184,7 +184,7 @@ class WithTimeoutOrNullDurationTest : TestBase() { expect(2) try { delay(1000.milliseconds) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(3) } "OK" @@ -201,7 +201,7 @@ class WithTimeoutOrNullDurationTest : TestBase() { expect(2) try { delay(1000.milliseconds) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(3) throw TestException() } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt index 1ef955b01d..747b6500d5 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt @@ -100,7 +100,7 @@ class WithTimeoutOrNullTest : TestBase() { @Test fun testInnerTimeout() = runTest( - expected = { it is CancellationException } + expected = { it is TimeoutException } ) { withTimeoutOrNull(1000) { kotlinx.coroutines.time.withTimeout(10) { @@ -175,7 +175,7 @@ class WithTimeoutOrNullTest : TestBase() { expect(2) try { delay(1000) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(3) } "OK" @@ -192,7 +192,7 @@ class WithTimeoutOrNullTest : TestBase() { expect(2) try { delay(1000) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(3) throw TestException() } diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt index 5a00b09026..305dcb8410 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt @@ -72,7 +72,7 @@ class WithTimeoutTest : TestBase() { */ @Test fun testYieldBlockingWithTimeout() = runTest( - expected = { it is CancellationException } + expected = { it is TimeoutException } ) { kotlinx.coroutines.time.withTimeout(100) { while (true) { @@ -118,7 +118,7 @@ class WithTimeoutTest : TestBase() { expectUnreached() "OK" } - } catch (e: CancellationException) { + } catch (e: TimeoutException) { assertEquals("Timed out waiting for 100 ms", e.message) finish(3) } @@ -126,14 +126,14 @@ class WithTimeoutTest : TestBase() { @Test fun testSuppressExceptionWithResult() = runTest( - expected = { it is CancellationException } + expected = { it is TimeoutException } ) { expect(1) kotlinx.coroutines.time.withTimeout(100) { expect(2) try { delay(1000) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { finish(3) } "OK" @@ -149,7 +149,7 @@ class WithTimeoutTest : TestBase() { expect(2) try { delay(1000) - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(3) throw TestException() } diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt index ea1ba1a9bb..06ccb8560d 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt @@ -4,6 +4,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.time.* import kotlin.test.* import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -67,7 +68,7 @@ class WithTimeoutOrNullThreadDispatchTest : TestBase() { expect(3) delay(1000) expectUnreached() - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(4) assertEquals(thread, Thread.currentThread()) throw e // rethrow @@ -79,4 +80,4 @@ class WithTimeoutOrNullThreadDispatchTest : TestBase() { } finish(6) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt index 95703dfef0..8530262346 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt @@ -4,6 +4,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.time.* import kotlin.test.* import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -68,13 +69,13 @@ class WithTimeoutThreadDispatchTest : TestBase() { expect(3) delay(1000) expectUnreached() - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(4) assertEquals(thread, Thread.currentThread()) throw e // rethrow } } - } catch (e: CancellationException) { + } catch (e: TimeoutException) { expect(5) assertEquals(thread, Thread.currentThread()) } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt index e674ac6065..bb4ab1ebcd 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt @@ -19,6 +19,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() { try { outerWithTimeout() } catch (e: TimeoutException) { + println(e.stackTraceToString()) verifyStackTrace("timeout/${name.methodName}", e) } } diff --git a/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt b/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt index 4d881c4eed..df4906510a 100644 --- a/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt +++ b/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt @@ -61,9 +61,14 @@ class HandlerDispatcherTest : TestBase() { mainLooper.pause() assertFalse { mainLooper.scheduler.areAnyRunnable() } val job = launch(Dispatchers.Main, start = CoroutineStart.UNDISPATCHED) { - kotlinx.coroutines.time.withTimeout(1) { - expect(1) - hang { expect(3) } + try { + kotlinx.coroutines.time.withTimeout(1) { + expect(1) + hang { expect(3) } + } + } catch (e: kotlinx.coroutines.time.TimeoutException) { + expect(4) + throw CancellationException("successfully timed out", e) } expectUnreached() } @@ -72,7 +77,7 @@ class HandlerDispatcherTest : TestBase() { // Schedule cancellation mainLooper.runToEndOfTasks() job.join() - finish(4) + finish(5) } @Test