Snap for 12517605 from 480ad0c5cf1ba681af6954bcfb3ade6e09f86270 to 25Q1-release
Change-Id: I1b31b8d399259f1f91f6f3524b6566f66aa70038
diff --git a/.github/ISSUE_TEMPLATE/rc_feedback.md b/.github/ISSUE_TEMPLATE/rc_feedback.md
new file mode 100644
index 0000000..02f06dd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/rc_feedback.md
@@ -0,0 +1,28 @@
+---
+name: Release Candidate release feedback
+about: Something used to work, but broke in an RC release?
+title: 'RC:'
+labels: bug
+assignees: ''
+
+---
+
+<!--
+Thank you for participating in the Release Candidate program, and even better,
+finding a problem!
+
+Please double-check that this problem is not present in the latest stable
+release.
+-->
+
+**What broke?**
+
+Even a vague description suffices. If you want to search for a reproducer or
+narrow the issue down, this would help a lot, but the most important thing is
+letting us know that there is a problem at all as soon as possible. Otherwise,
+we'll just publish a stable release with this problem while you're looking for a
+reproducer!
+
+**Did I check that setting the version to the latest stable release fixes the problem?**
+
+Yes.
diff --git a/.idea/copyright/kotlinx_coroutines.xml b/.idea/copyright/kotlinx_coroutines.xml
deleted file mode 100644
index f175624..0000000
--- a/.idea/copyright/kotlinx_coroutines.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<component name="CopyrightManager">
- <copyright>
- <option name="notice" value="Copyright 2016-&#36;today.year JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license." />
- <option name="myName" value="kotlinx.coroutines" />
- </copyright>
-</component>
\ No newline at end of file
diff --git a/CHANGES.md b/CHANGES.md
index 1ed133f..cf1e73e 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,74 @@
# Change log for kotlinx.coroutines
+## Version 1.8.1
+
+* Remove the `@ExperimentalTime` annotation from usages of `TimeSource` (#4046). Thanks, @hfhbd!
+* Introduce a workaround for an Android bug that caused an occasional `NullPointerException` when setting the `StateFlow` value on old Android devices (#3820).
+* No longer use `kotlin.random.Random` as part of `Dispatchers.Default` and `Dispatchers.IO` initialization (#4051).
+* `Flow.timeout` throws the exception with which the channel was closed (#4071).
+* Small tweaks and documentation fixes.
+
+### Changelog relative to version 1.8.1-Beta
+
+* `Flow.timeout` throws the exception with which the channel was closed (#4071).
+* Small documentation fixes.
+
+## Version 1.8.1-Beta
+
+* Remove the `@ExperimentalTime` annotation from usages of `TimeSource` (#4046). Thanks, @hfhbd!
+* Attempt a workaround for an Android bug that caused an occasional `NullPointerException` when setting the `StateFlow` value on old Android devices (#3820).
+* No longer use `kotlin.random.Random` as part of `Dispatchers.Default` and `Dispatchers.IO` initialization (#4051).
+* Small tweaks.
+
+## Version 1.8.0
+
+* Implement the library for the Web Assembly (Wasm) for JavaScript (#3713). Thanks @igoriakovlev!
+* Major Kotlin version update: was 1.8.20, became 1.9.21.
+* On Android, ensure that `Dispatchers.Main != Dispatchers.Main.immediate` (#3545, #3963).
+* Fixed a bug that caused `Flow` operators that limit cancel the upstream flow to forget that they were already finished if there is another such operator upstream (#4035, #4038)
+* `kotlinx-coroutines-debug` is published with the correct Java 9 module info (#3944).
+* `kotlinx-coroutines-debug` no longer requires manually setting `DebugProbes.enableCoroutineCreationStackTraces` to `false`, it's the default (#3783).
+* `kotlinx-coroutines-test`: set the default timeout of `runTest` to 60 seconds, added the ability to configure it on the JVM with the `kotlinx.coroutines.test.default_timeout=10s` (#3800).
+* `kotlinx-coroutines-test`: fixed a bug that could lead to not all uncaught exceptions being reported after some tests failed (#3800).
+* `delay(Duration)` rounds nanoseconds up to whole milliseconds and not down (#3920). Thanks @kevincianfarini!
+* `Dispatchers.Default` and the default thread for background work are guaranteed to use the same context classloader as the object containing it them (#3832).
+* It is guaranteed that by the time `SharedFlow.collect` suspends for the first time, it's registered as a subscriber for that `SharedFlow` (#3885). Before, it was also true, but not documented.
+* Atomicfu version is updated to 0.23.1, and Kotlin/Native atomic transformations are enabled, reducing the footprint of coroutine-heavy code (#3954).
+* Added a workaround for miscompilation of `withLock` on JS (#3881). Thanks @CLOVIS-AI!
+* Small tweaks and documentation fixes.
+
+### Changelog relative to version 1.8.0-RC2
+
+* `kotlinx-coroutines-debug` no longer requires manually setting `DebugProbes.enableCoroutineCreationStackTraces` to `false`, it's the default (#3783).
+* Fixed a bug that caused `Flow` operators that limit cancel the upstream flow to forget that they were already finished if there is another such operator upstream (#4035, #4038)
+* Small documentation fixes.
+
+## Version 1.8.0-RC2
+
+* Fixed a bug introduced in 1.8.0-RC where `Mutex.onLock` would not unlock if a non-local return was performed (#3985).
+* Fixed a bug introduced in 1.8.0-RC where depending on kotlinx-coroutines in Native code failed with a compilation error `Could not find "org.jetbrains.kotlinx:atomicfu-cinterop-interop"` (#3968).
+* Small documentation fixes.
+
+## Version 1.8.0-RC
+
+* Implement the library for the Web Assembly (Wasm) for JavaScript (#3713). Thanks @igoriakovlev!
+* On Android, ensure that `Dispatchers.Main != Dispatchers.Main.immediate` (#3545, #3963).
+* `kotlinx-coroutines-debug` is published with the correct Java 9 module info (#3944).
+* Major Kotlin version update: was 1.8.20, became 1.9.21.
+* `kotlinx-coroutines-test`: set the default timeout of `runTest` to 60 seconds, added the ability to configure it on the JVM with the `kotlinx.coroutines.test.default_timeout=10s` (#3800).
+* `kotlinx-coroutines-test`: fixed a bug that could lead to not all uncaught exceptions being reported after some tests failed (#3800).
+* `delay(Duration)` rounds nanoseconds up to whole milliseconds and not down (#3920). Thanks @kevincianfarini!
+* `Dispatchers.Default` and the default thread for background work are guaranteed to use the same context classloader as the object containing it them (#3832).
+* It is guaranteed that by the time `SharedFlow.collect` suspends for the first time, it's registered as a subscriber for that `SharedFlow` (#3885). Before, it was also true, but not documented.
+* Atomicfu version is updated to 0.23.1, and Kotlin/Native atomic transformations are enabled, reducing the footprint of coroutine-heavy code (#3954).
+* Added a workaround for miscompilation of `withLock` on JS (#3881). Thanks @CLOVIS-AI!
+* Small tweaks and documentation fixes.
+
+## Version 1.7.3
+
+* Disabled the publication of the multiplatform library metadata for the old (1.6 and earlier) KMP Gradle plugin (#3809).
+* Fixed a bug introduced in 1.7.2 that disabled the coroutine debugger in IDEA (#3822).
+
## Version 1.7.2
### Bug fixes and improvements
diff --git a/METADATA b/METADATA
index 9c26192..68041d8 100644
--- a/METADATA
+++ b/METADATA
@@ -1,19 +1,19 @@
# This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update kotlinx.coroutines
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/kotlinx.coroutines
+# For more info, check https://cs.android.com/android/platform/superproject/main/+/main:tools/external_updater/README.md
name: "kotlinx.coroutines"
description: "Library support for Kotlin coroutines"
third_party {
- url {
- type: GIT
- value: "https://github.com/Kotlin/kotlinx.coroutines"
- }
- version: "1.7.2"
license_type: NOTICE
last_upgrade_date {
- year: 2023
- month: 7
- day: 12
+ year: 2024
+ month: 10
+ day: 17
+ }
+ identifier {
+ type: "Git"
+ value: "https://github.com/Kotlin/kotlinx.coroutines"
+ version: "1.8.1"
}
}
diff --git a/README.md b/README.md
index d82b786..0cf3c19 100644
--- a/README.md
+++ b/README.md
@@ -3,12 +3,12 @@
[](https://kotlinlang.org/docs/components-stability.html)
[](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[](https://www.apache.org/licenses/LICENSE-2.0)
-[](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.7.2)
-[](http://kotlinlang.org)
+[](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.8.1)
+[](http://kotlinlang.org)
[](https://kotlinlang.slack.com/messages/coroutines/)
Library support for Kotlin coroutines with [multiplatform](#multiplatform) support.
-This is a companion version for the Kotlin `1.8.20` release.
+This is a companion version for the Kotlin `1.9.21` release.
```kotlin
suspend fun main() = coroutineScope {
@@ -26,7 +26,7 @@
* [core](kotlinx-coroutines-core/README.md) — common coroutines across all platforms:
* [launch] and [async] coroutine builders returning [Job] and [Deferred] light-weight futures with cancellation support;
- * [Dispatchers] object with [Main][Dispatchers.Main] dispatcher for Android/Swing/JavaFx, and [Default][Dispatchers.Default] dispatcher for background coroutines;
+ * [Dispatchers] object with [Main][Dispatchers.Main] dispatcher for Android/Swing/JavaFx (which require the corresponding artifacts in runtime) and Darwin (included out of the box), and [Default][Dispatchers.Default] dispatcher for background coroutines;
* [delay] and [yield] top-level suspending functions;
* [Flow] — cold asynchronous stream with [flow][_flow] builder and comprehensive operator set ([filter], [map], etc);
* [Channel], [Mutex], and [Semaphore] communication and synchronization primitives;
@@ -36,7 +36,7 @@
* [select] expression support and more.
* [core/jvm](kotlinx-coroutines-core/jvm/) — additional core features available on Kotlin/JVM:
* [Dispatchers.IO] dispatcher for blocking coroutines;
- * [Executor.asCoroutineDispatcher][asCoroutineDispatcher] extension, custom thread pools, and more.
+ * [Executor.asCoroutineDispatcher][asCoroutineDispatcher] extension, custom thread pools, and more;
* Integrations with `CompletableFuture` and JVM-specific extensions.
* [core/js](kotlinx-coroutines-core/js/) — additional core features available on Kotlin/JS:
* Integration with `Promise` via [Promise.await] and [promise] builder;
@@ -54,7 +54,7 @@
* RxJava 2.x ([rxFlowable], [rxSingle], etc), and
* RxJava 3.x ([rxFlowable], [rxSingle], etc), and
* Project Reactor ([flux], [mono], etc).
-* [ui](ui/README.md) — modules that provide coroutine dispatchers for various single-threaded UI libraries:
+* [ui](ui/README.md) — modules that provide the [Main][Dispatchers.Main] dispatcher for various single-threaded UI libraries:
* Android, JavaFX, and Swing.
* [integration](integration/README.md) — modules that provide integration with various asynchronous callback- and future-based libraries:
* Guava [ListenableFuture.await], and Google Play Services [Task.await];
@@ -85,7 +85,7 @@
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
- <version>1.7.2</version>
+ <version>1.8.1</version>
</dependency>
```
@@ -93,7 +93,7 @@
```xml
<properties>
- <kotlin.version>1.8.20</kotlin.version>
+ <kotlin.version>1.9.21</kotlin.version>
</properties>
```
@@ -103,7 +103,7 @@
```kotlin
dependencies {
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}
```
@@ -112,10 +112,10 @@
```kotlin
plugins {
// For build.gradle.kts (Kotlin DSL)
- kotlin("jvm") version "1.8.20"
+ kotlin("jvm") version "1.9.21"
// For build.gradle (Groovy DSL)
- id "org.jetbrains.kotlin.jvm" version "1.8.20"
+ id "org.jetbrains.kotlin.jvm" version "1.9.21"
}
```
@@ -133,7 +133,7 @@
module as a dependency when using `kotlinx.coroutines` on Android:
```kotlin
-implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2")
+implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
```
This gives you access to the Android [Dispatchers.Main]
@@ -168,20 +168,18 @@
```kotlin
commonMain {
dependencies {
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}
}
```
-No more additional dependencies are needed, platform-specific artifacts will be resolved automatically via Gradle metadata available since Gradle 5.3.
-
Platform-specific dependencies are recommended to be used only for non-multiplatform projects that are compiled only for target platform.
#### JS
Kotlin/JS version of `kotlinx.coroutines` is published as
-[`kotlinx-coroutines-core-js`](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.7.2)
-(follow the link to get the dependency declaration snippet) and as [`kotlinx-coroutines-core`](https://www.npmjs.com/package/kotlinx-coroutines-core) NPM package.
+[`kotlinx-coroutines-core-js`](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.8.1)
+(follow the link to get the dependency declaration snippet).
#### Native
@@ -215,7 +213,7 @@
[Dispatchers.IO]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-i-o.html
[asCoroutineDispatcher]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/as-coroutine-dispatcher.html
[Promise.await]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/await.html
-[promise]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/promise.html
+[promise]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/[js]promise.html
[Window.asCoroutineDispatcher]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/as-coroutine-dispatcher.html
<!--- INDEX kotlinx.coroutines.flow -->
diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts
index e64f189..7006c91 100644
--- a/benchmarks/build.gradle.kts
+++ b/benchmarks/build.gradle.kts
@@ -1,11 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UnstableApiUsage")
-import me.champeau.jmh.*
import org.jetbrains.kotlin.gradle.tasks.*
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.github.johnrengelman.shadow")
@@ -22,18 +18,18 @@
}
tasks.named<KotlinCompile>("compileJmhKotlin") {
- kotlinOptions {
- jvmTarget = "1.8"
- freeCompilerArgs += "-Xjvm-default=all"
+ compilerOptions {
+ jvmTarget = JvmTarget.JVM_1_8
+ freeCompilerArgs.add("-Xjvm-default=all")
}
}
val jmhJarTask = tasks.named<Jar>("jmhJar") {
- archiveBaseName by "benchmarks"
- archiveClassifier by null
- archiveVersion by null
+ archiveBaseName = "benchmarks"
+ archiveClassifier = null
+ archiveVersion = null
archiveVersion.convention(null as String?)
- destinationDirectory.set(file("$rootDir"))
+ destinationDirectory = rootDir
}
tasks {
diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java
index 6d9169d..c5530f5 100644
--- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java
+++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble;
import benchmarks.flow.scrabble.IterableSpliterator;
diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java
index 2d900ca..bf40759 100644
--- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java
+++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble;
import java.util.*;
diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java
index 0acf98d..63f347f 100644
--- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java
+++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble.optimizations;
import io.reactivex.Flowable;
diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java
index 1c78f5e..020285c 100644
--- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java
+++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble.optimizations;
import io.reactivex.Flowable;
diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java
index f51112b..ee40a5a 100644
--- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java
+++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble.optimizations;
import io.reactivex.Flowable;
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt
index f706d3a..51061cc 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt
index d3f6be6..18a140f 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkNoAllocationsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkNoAllocationsBenchmark.kt
index dcba838..8dec5f2 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkNoAllocationsBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkNoAllocationsBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt b/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt
index ce64c6a..da80958 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks
import benchmarks.akka.CORES_COUNT
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/SequentialSemaphoreBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/SequentialSemaphoreBenchmark.kt
index 6926db7..ed1a4ed 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/SequentialSemaphoreBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/SequentialSemaphoreBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt
index df94075..30e590b 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.akka
import akka.actor.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt
index fef641a..d7be75a 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.akka
import akka.actor.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugSequenceOverheadBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugSequenceOverheadBenchmark.kt
index 16e93e1..ec37840 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugSequenceOverheadBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugSequenceOverheadBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.debug
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt
index be37154..207b245 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt
index bc8d868..dd38535 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt
index 32d3547..772e1bb 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt
index 09d841e..f89ed9d 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow
import benchmarks.common.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt
index 636b334..697b876 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt
@@ -1,8 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-
package benchmarks.flow
import benchmarks.flow.scrabble.flow
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt
index d957bdb..f1b0faf 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt
index a0a2dec..b22e5a2 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt
index b8e1f45..fc2923d 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt
index cd27cca..16190f8 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt
index e78d7bd..cce343c 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import java.util.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt
index 1db4dae..3ab22da 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import reactor.core.publisher.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt
index 533bc5e..596a2ad 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt
index acfb3f3..eca01df 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import kotlinx.coroutines.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt
index 10433fc..a2e5d2c 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.flow.scrabble
import org.openjdk.jmh.annotations.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt
index 1fe7092..fba0510 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler
import benchmarks.akka.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt
index 20bdfa3..5572858 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler
import benchmarks.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt
index d64fdd2..18c58cd 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler
import benchmarks.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt
index c5b34ed..14bc44b 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler
import benchmarks.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt
index 1ffb520..76a674f 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler.actors
import benchmarks.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt
index cd212cc..653b769 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler.actors
import benchmarks.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt
index d696c64..9c524e8 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler.actors
import benchmarks.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt
index d874f3b..9bebea7 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler.actors
import benchmarks.akka.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt
index eebcec0..0b03dba 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.scheduler.actors
import benchmarks.*
diff --git a/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt b/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt
index 858ecfa..21c92c1 100644
--- a/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt
+++ b/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package benchmarks.common
import java.util.concurrent.*
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index 84d7770..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-
-import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
-import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
-import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
-import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
-import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
-import org.jetbrains.kotlin.konan.target.HostManager
-import org.jetbrains.dokka.gradle.DokkaTaskPartial
-
-import static Projects.*
-
-apply plugin: 'jdk-convention'
-
-buildscript {
- /*
- * These property group is used to build kotlinx.coroutines against Kotlin compiler snapshot.
- * How does it work:
- * When build_snapshot_train is set to true, kotlin_version property is overridden with kotlin_snapshot_version,
- * atomicfu_version is overwritten by TeamCity environment (AFU is built with snapshot and published to mavenLocal
- * as previous step or the snapshot build).
- * Additionally, mavenLocal and Sonatype snapshots are added to repository list and stress tests are disabled.
- * DO NOT change the name of these properties without adapting kotlinx.train build chain.
- */
- def prop = rootProject.properties['build_snapshot_train']
- ext.build_snapshot_train = prop != null && prop != ""
- if (build_snapshot_train) {
- ext.kotlin_version = rootProject.properties['kotlin_snapshot_version']
- if (kotlin_version == null) {
- throw new IllegalArgumentException("'kotlin_snapshot_version' should be defined when building with snapshot compiler")
- }
- }
- ext.native_targets_enabled = rootProject.properties['disable_native_targets'] == null
-
- // Determine if any project dependency is using a snapshot version
- ext.using_snapshot_version = build_snapshot_train
- rootProject.properties.each { key, value ->
- if (key.endsWith("_version") && value instanceof String && value.endsWith("-SNAPSHOT")) {
- println("NOTE: USING SNAPSHOT VERSION: $key=$value")
- ext.using_snapshot_version = true
- }
- }
-
- if (using_snapshot_version) {
- repositories {
- mavenLocal()
- }
- }
-
- repositories {
- mavenCentral()
- maven { url "https://plugins.gradle.org/m2/" }
- CommunityProjectsBuild.addDevRepositoryIfEnabled(delegate, project)
- mavenLocal()
- }
-
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
- classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
- classpath "org.jetbrains.kotlinx:kotlinx-knit:$knit_version"
- classpath "com.github.node-gradle:gradle-node-plugin:$gradle_node_version"
- classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version"
- classpath "ru.vyarus:gradle-animalsniffer-plugin:1.5.4" // Android API check
- classpath "org.jetbrains.kotlin:atomicfu:$kotlin_version"
- classpath "org.jetbrains.kotlinx:kover-gradle-plugin:$kover_version"
-
- // JMH plugins
- classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.2"
- }
-
- CacheRedirector.configureBuildScript(buildscript, rootProject)
-}
-// todo:KLUDGE: Hierarchical project structures are not fully supported in IDEA, enable only for a regular built
-if (!Idea.active) {
- ext.set("kotlin.mpp.enableGranularSourceSetsMetadata", "true")
-}
-
-// todo:KLUDGE: This is needed to workaround dependency resolution between Java and MPP modules
-def configureKotlinJvmPlatform(configuration) {
- configuration.attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.jvm)
-}
-
-// Configure subprojects with Kotlin sources
-apply plugin: "configure-compilation-conventions"
-
-allprojects {
- // the only place where HostManager could be instantiated
- project.ext.hostManager = new HostManager()
- def deployVersion = properties['DeployVersion']
- if (deployVersion != null) version = deployVersion
-
- if (build_snapshot_train) {
- ext.kotlin_version = rootProject.properties['kotlin_snapshot_version']
- println "Using Kotlin $kotlin_version for project $it"
-
- def skipSnapshotChecks = rootProject.properties['skip_snapshot_checks'] != null
- if (!skipSnapshotChecks && version != atomicfu_version) {
- throw new IllegalStateException("Current deploy version is $version, but atomicfu version is not overridden ($atomicfu_version) for $it")
- }
-
- kotlin_version = rootProject.properties['kotlin_snapshot_version']
- }
-
- if (using_snapshot_version) {
- repositories {
- mavenLocal()
- }
- }
-
- ext.unpublished = unpublished
-
- // This project property is set during nightly stress test
- def stressTest = project.properties['stressTest']
-
- // Copy it to all test tasks
- tasks.withType(Test) {
- systemProperty 'stressTest', stressTest
- }
-}
-
-apply plugin: "binary-compatibility-validator"
-apply plugin: "base"
-apply plugin: "kover-conventions"
-
-apiValidation {
- ignoredProjects += unpublished + ["kotlinx-coroutines-bom"]
- if (build_snapshot_train) {
- ignoredProjects.remove("example-frontend-js")
- ignoredProjects.add(coreModule)
- }
- ignoredPackages += "kotlinx.coroutines.internal"
-}
-
-// Configure repositories
-allprojects {
- repositories {
- /*
- * google should be first in the repository list because some of the play services
- * transitive dependencies was removed from jcenter, thus breaking gradle dependency resolution
- */
- google()
- mavenCentral()
- CommunityProjectsBuild.addDevRepositoryIfEnabled(delegate, project)
- }
-}
-
-// needs to be before evaluationDependsOn due to weird Gradle ordering
-apply plugin: "animalsniffer-conventions"
-
-// Add dependency to core source sets. Core is configured in kx-core/build.gradle
-configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != coreModule }) {
- evaluationDependsOn(":$coreModule")
- if (isMultiplatform(it)) {
- apply plugin: "kotlin-multiplatform"
- apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle")
- apply from: rootProject.file("gradle/compile-common.gradle")
-
- if (rootProject.ext["native_targets_enabled"] as Boolean) {
- apply from: rootProject.file("gradle/compile-native-multiplatform.gradle")
- }
-
- apply from: rootProject.file("gradle/compile-js-multiplatform.gradle")
- apply from: rootProject.file("gradle/publish-npm-js.gradle")
- kotlin.sourceSets.commonMain.dependencies {
- api project(":$coreModule")
- }
- kotlin.sourceSets.jvmTest.dependencies {
- implementation project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs
- }
- } else {
- def platform = PlatformKt.platformOf(it)
- apply plugin: "kotlin-${platform}-conventions"
- dependencies {
- api project(":$coreModule")
- // the only way IDEA can resolve test classes
- testImplementation project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs
- }
- }
-}
-
-apply plugin: "bom-conventions"
-apply plugin: "java-modularity-conventions"
-
-if (build_snapshot_train) {
- println "Hacking test tasks, removing stress and flaky tests"
- allprojects {
- tasks.withType(Test).all {
- exclude '**/*LinearizabilityTest*'
- exclude '**/*LFTest*'
- exclude '**/*StressTest*'
- exclude '**/*scheduling*'
- exclude '**/*Timeout*'
- exclude '**/*definitely/not/kotlinx*'
- // Disable because of KT-11567 in 1.4
- exclude '**/*CasesPublicAPITest*'
- // Kotlin
- exclude '**/*PrecompiledDebugProbesTest*'
- }
- }
-
- println "Manifest of kotlin-compiler-embeddable.jar for coroutines"
- configure(subprojects.findAll { it.name == coreModule }) {
- configurations.matching { it.name == "kotlinCompilerClasspath" }.all {
- resolvedConfiguration.getFiles().findAll { it.name.contains("kotlin-compiler-embeddable") }.each {
- def manifest = zipTree(it).matching {
- include 'META-INF/MANIFEST.MF'
- }.getFiles().first()
-
- manifest.readLines().each {
- println it
- }
- }
- }
- }
-}
-
-// Redefine source sets because we are not using 'kotlin/main/fqn' folder convention
-configure(subprojects.findAll {
- !sourceless.contains(it.name) && !isMultiplatform(it) &&
- it.name != "benchmarks" &&
- it.name != "example-frontend-js"
-}) {
- // Pure JS and pure MPP doesn't have this notion and are configured separately
- // TODO detect it via platformOf and migrate benchmarks to the same scheme
- sourceSets {
- main.kotlin.srcDirs = ['src']
- test.kotlin.srcDirs = ['test']
- main.resources.srcDirs = ['resources']
- test.resources.srcDirs = ['test-resources']
- }
-}
-
-def core_docs_url = "https://kotlinlang.org/api/kotlinx.coroutines/$coreModule/"
-def core_docs_file = "$projectDir/kotlinx-coroutines-core/build/dokka/htmlPartial/package-list"
-apply plugin: "org.jetbrains.dokka"
-
-configure(subprojects.findAll { !unpublished.contains(it.name)
- && it.name != coreModule }) {
- if (it.name != 'kotlinx-coroutines-bom' && it.name != jdk8ObsoleteModule) {
- apply from: rootProject.file('gradle/dokka.gradle.kts')
- }
- apply from: rootProject.file('gradle/publish.gradle')
-}
-
-configure(subprojects.findAll { !unpublished.contains(it.name) }) {
- if (it.name != "kotlinx-coroutines-bom") {
- if (it.name != coreModule && it.name != jdk8ObsoleteModule) {
- tasks.withType(DokkaTaskPartial.class) {
- dokkaSourceSets.configureEach {
- externalDocumentationLink {
- url.set(new URL(core_docs_url))
- packageListUrl.set(new File(core_docs_file).toURI().toURL())
- }
- }
- }
- }
- }
-
- def thisProject = it
- if (thisProject.name in sourceless) {
- return
- }
-
- def versionFileTask = thisProject.tasks.register("versionFileTask") {
- def name = thisProject.name.replace("-", "_")
- def versionFile = thisProject.layout.buildDirectory.file("${name}.version")
- it.outputs.file(versionFile)
-
- it.doLast {
- versionFile.get().asFile.text = version.toString()
- }
- }
-
- List<String> jarTasks
- if (isMultiplatform(it)) {
- jarTasks = ["jvmJar", "metadataJar"]
- } else if (it.name == "kotlinx-coroutines-debug") {
- // We shadow debug module instead of just packaging it
- jarTasks = ["shadowJar"]
- } else {
- jarTasks = ["jar"]
- }
-
- for (name in jarTasks) {
- thisProject.tasks.named(name, Jar) {
- it.dependsOn versionFileTask
- it.from(versionFileTask) {
- into("META-INF")
- }
- }
- }
-}
-
-// Report Kotlin compiler version when building project
-println("Using Kotlin compiler version: $KotlinCompilerVersion.VERSION")
-
-// --------------- Cache redirector ---------------
-
-allprojects {
- CacheRedirector.configure(project)
-}
-
-// --------------- Configure sub-projects that are published ---------------
-
-def publishTasks = getTasksByName("publish", true) + getTasksByName("publishNpm", true)
-
-task deploy(dependsOn: publishTasks)
-
-clean.dependsOn gradle.includedBuilds.collect { it.task(':clean') }
-
-// --------------- Knit configuration ---------------
-
-apply plugin: 'kotlinx-knit'
-
-knit {
- siteRoot = "https://kotlinlang.org/api/kotlinx.coroutines"
- moduleRoots = [".", "integration", "reactive", "ui"]
- moduleDocs = "build/dokka/htmlPartial"
- dokkaMultiModuleRoot = "build/dokka/htmlMultiModule/"
-}
-
-knitPrepare.dependsOn getTasksByName("dokkaHtmlMultiModule", true)
-
-dependencies {
- dokkaHtmlMultiModulePlugin("org.jetbrains.kotlinx:dokka-pathsaver-plugin:$knit_version")
-}
-
-// Opt-in for build scan in order to troubleshoot Gradle on TC
-if (hasProperty('buildScan')) {
- buildScan {
- termsOfServiceUrl = 'https://gradle.com/terms-of-service'
- termsOfServiceAgree = 'yes'
- }
-}
-
-/*
- * kotlinx-coroutines-core dependency leaks into test runtime classpath via kotlin-compiler-embeddable
- * and conflicts with our own test/runtime incompatibilities (e.g. when class is moved from a main to test),
- * so we do substitution here
- */
-allprojects { subProject ->
- subProject
- .configurations
- .matching {
- // Excluding substituted project itself because of circular dependencies, but still do it
- // for "*Test*" configurations
- subProject.name != coreModule || it.name.contains("Test")
- }
- .configureEach { conf ->
- conf.resolutionStrategy.dependencySubstitution {
- substitute(module("org.jetbrains.kotlinx:$coreModule"))
- .using(project(":$coreModule"))
- .because("Because Kotlin compiler embeddable leaks coroutines into the runtime classpath, " +
- "triggering all sort of incompatible class changes errors")
- }
- }
-}
-
-tasks.named("dokkaHtmlMultiModule") {
- pluginsMapConfiguration.set(["org.jetbrains.dokka.base.DokkaBase": """{ "templatesDir": "${projectDir.toString().replace('\\', '/')}/dokka-templates" }"""])
-}
-
-if (CacheRedirector.enabled) {
- def yarnRootExtension = rootProject.extensions.findByType(YarnRootExtension.class)
- if (yarnRootExtension != null) {
- yarnRootExtension.downloadBaseUrl = CacheRedirector.maybeRedirect(yarnRootExtension.downloadBaseUrl)
- }
-
- def nodeJsExtension = rootProject.extensions.findByType(NodeJsRootExtension.class)
- if (nodeJsExtension != null) {
- nodeJsExtension.nodeDownloadBaseUrl = CacheRedirector.maybeRedirect(nodeJsExtension.nodeDownloadBaseUrl)
- }
-}
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..002a1d8
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,159 @@
+import org.jetbrains.kotlin.config.KotlinCompilerVersion
+import org.jetbrains.kotlin.gradle.dsl.*
+import org.gradle.kotlin.dsl.*
+
+buildscript {
+ if (shouldUseLocalMaven(rootProject)) {
+ repositories {
+ mavenLocal()
+ }
+ }
+
+ repositories {
+ mavenCentral()
+ maven(url = "https://plugins.gradle.org/m2/")
+ addDevRepositoryIfEnabled(this, project)
+ mavenLocal()
+ }
+
+ dependencies {
+ // Please ensure that atomicfu-gradle-plugin is added to the classpath first, do not change the order, for details see #3984.
+ // The corresponding issue in kotlinx-atomicfu: https://github.com/Kotlin/kotlinx-atomicfu/issues/384
+ classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${version("atomicfu")}")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${version("kotlin")}")
+ classpath("org.jetbrains.dokka:dokka-gradle-plugin:${version("dokka")}")
+ classpath("org.jetbrains.kotlinx:kotlinx-knit:${version("knit")}")
+ classpath("org.jetbrains.kotlinx:binary-compatibility-validator:${version("binary_compatibility_validator")}")
+ classpath("ru.vyarus:gradle-animalsniffer-plugin:${version("animalsniffer")}") // Android API check
+ classpath("org.jetbrains.kotlin:atomicfu:${version("kotlin")}")
+ classpath("org.jetbrains.kotlinx:kover-gradle-plugin:${version("kover")}")
+
+ // JMH plugins
+ classpath("gradle.plugin.com.github.johnrengelman:shadow:${version("shadow")}")
+ }
+
+ with(CacheRedirector) { buildscript.configureBuildScript(rootProject) }
+}
+
+// Configure subprojects with Kotlin sources
+apply(plugin = "configure-compilation-conventions")
+
+allprojects {
+ val deployVersion = properties["DeployVersion"]
+ if (deployVersion != null) version = deployVersion
+
+ if (isSnapshotTrainEnabled(rootProject)) {
+ val skipSnapshotChecks = rootProject.properties["skip_snapshot_checks"] != null
+ if (!skipSnapshotChecks && version != version("atomicfu")) {
+ throw IllegalStateException("Current deploy version is $version, but atomicfu version is not overridden (${version("atomicfu")}) for $this")
+ }
+ }
+
+ if (shouldUseLocalMaven(rootProject)) {
+ repositories {
+ mavenLocal()
+ }
+ }
+
+ // This project property is set during nightly stress test
+ val stressTest = project.properties["stressTest"]
+ // Copy it to all test tasks
+ tasks.withType(Test::class).configureEach {
+ if (stressTest != null) {
+ systemProperty("stressTest", stressTest)
+ }
+ }
+}
+
+plugins {
+ id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2"
+}
+
+apply(plugin = "base")
+apply(plugin = "kover-conventions")
+
+apiValidation {
+ ignoredProjects += unpublished + listOf("kotlinx-coroutines-bom")
+ if (isSnapshotTrainEnabled(rootProject)) {
+ ignoredProjects += coreModule
+ }
+ ignoredPackages += "kotlinx.coroutines.internal"
+}
+
+// Configure repositories
+allprojects {
+ repositories {
+ /*
+ * google should be first in the repository list because some of the play services
+ * transitive dependencies was removed from jcenter, thus breaking gradle dependency resolution
+ */
+ google()
+ mavenCentral()
+ addDevRepositoryIfEnabled(this, project)
+ }
+}
+
+// needs to be before evaluationDependsOn due to weird Gradle ordering
+apply(plugin = "animalsniffer-conventions")
+
+configure(subprojects.filter { !sourceless.contains(it.name) }) {
+ if (isMultiplatform) {
+ apply(plugin = "kotlin-multiplatform")
+ apply(plugin = "kotlin-multiplatform-conventions")
+ } else if (platformOf(this) == "jvm") {
+ apply(plugin = "kotlin-jvm-conventions")
+ } else {
+ val platform = platformOf(this)
+ throw IllegalStateException("No configuration rules for $platform")
+ }
+}
+
+configure(subprojects.filter { !sourceless.contains(it.name) && it.name != testUtilsModule }) {
+ if (isMultiplatform) {
+ configure<KotlinMultiplatformExtension> {
+ sourceSets.commonTest.dependencies { implementation(project(":$testUtilsModule")) }
+ }
+ } else {
+ dependencies { add("testImplementation", project(":$testUtilsModule")) }
+ }
+}
+
+// Add dependency to the core module in all the other subprojects.
+configure(subprojects.filter { !sourceless.contains(it.name) && it.name != coreModule }) {
+ evaluationDependsOn(":$coreModule")
+ if (isMultiplatform) {
+ configure<KotlinMultiplatformExtension> {
+ sourceSets.commonMain.dependencies { api(project(":$coreModule")) }
+ }
+ } else {
+ dependencies { add("api", project(":$coreModule")) }
+ }
+}
+
+apply(plugin = "bom-conventions")
+apply(plugin = "java-modularity-conventions")
+apply(plugin = "version-file-conventions")
+
+rootProject.configureCommunityBuildTweaks()
+
+apply(plugin = "source-set-conventions")
+apply(plugin = "dokka-conventions")
+apply(plugin = "knit-conventions")
+
+/*
+ * TODO: core and non-core cannot be configured via 'configure(subprojects)'
+ * because of 'afterEvaluate' issue. This one should be migrated to
+ * `plugins { id("pub-conventions") }` eventually
+ */
+configure(subprojects.filter {
+ !unpublished.contains(it.name) && it.name != coreModule
+}) {
+ apply(plugin = "pub-conventions")
+}
+
+AuxBuildConfiguration.configure(rootProject)
+rootProject.registerTopLevelDeployTask()
+
+// Report Kotlin compiler version when building project
+println("Using Kotlin compiler version: ${KotlinCompilerVersion.VERSION}")
+
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index ae54ad0..96d718e 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import java.util.*
plugins {
@@ -59,10 +55,12 @@
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
}
- implementation("ru.vyarus:gradle-animalsniffer-plugin:1.5.3") // Android API check
+ implementation("ru.vyarus:gradle-animalsniffer-plugin:${version("animalsniffer")}") // Android API check
implementation("org.jetbrains.kotlinx:kover-gradle-plugin:${version("kover")}") {
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
}
+ implementation("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.9")
+ implementation("org.jetbrains.kotlinx:kotlinx-knit:${version("knit")}")
}
diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts
index c2e859f..2ad2ddb 100644
--- a/buildSrc/settings.gradle.kts
+++ b/buildSrc/settings.gradle.kts
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
pluginManagement {
val build_snapshot_train: String? by settings
repositories {
diff --git a/buildSrc/src/main/kotlin/AuxBuildConfiguration.kt b/buildSrc/src/main/kotlin/AuxBuildConfiguration.kt
new file mode 100644
index 0000000..3acba9a
--- /dev/null
+++ b/buildSrc/src/main/kotlin/AuxBuildConfiguration.kt
@@ -0,0 +1,67 @@
+import CacheRedirector.configure
+import org.gradle.api.Project
+import org.gradle.api.tasks.*
+import org.gradle.kotlin.dsl.*
+
+/**
+ * Auxiliary build configuration that is grouped in a single place for convenience:
+ * - Workarounds for Gradle/KGP issues
+ * - Cache redirector
+ */
+object AuxBuildConfiguration {
+
+ @JvmStatic
+ fun configure(rootProject: Project) {
+ rootProject.allprojects {
+ workaroundForCleanTask()
+ CacheRedirector.configure(this)
+ workaroundForCoroutinesLeakageToClassPath()
+ }
+
+ CacheRedirector.configureJsPackageManagers(rootProject)
+ CacheRedirector.configureWasmNodeRepositories(rootProject)
+
+ // Sigh, there is no BuildScanExtension in classpath when there is no --scan
+ rootProject.extensions.findByName("buildScan")?.withGroovyBuilder {
+ setProperty("termsOfServiceUrl", "https://gradle.com/terms-of-service")
+ setProperty("termsOfServiceAgree", "yes")
+ }
+ }
+
+ private fun Project.workaroundForCleanTask() {
+ // the 'clean' task cannot delete expanded.lock file on Windows as it is still held by Gradle, failing the build
+ // Gradle issue: https://github.com/gradle/gradle/issues/25752
+ tasks {
+ val clean by existing(Delete::class) {
+ setDelete(fileTree(layout.buildDirectory) {
+ exclude("tmp/.cache/expanded/expanded.lock")
+ })
+ }
+ }
+ }
+
+ /*
+ * 'kotlinx-coroutines-core' dependency leaks into test runtime classpath via 'kotlin-compiler-embeddable'
+ * and conflicts with our own test/runtime incompatibilities (e.g. when class is moved from a main to test),
+ * so we do substitution here.
+ * TODO figure out if it's still the problem
+ */
+ private fun Project.workaroundForCoroutinesLeakageToClassPath() {
+ configurations
+ .matching {
+ // Excluding substituted project itself because of circular dependencies, but still do it
+ // for "*Test*" configurations
+ name != coreModule || it.name.contains("Test")
+ }
+ .configureEach {
+ resolutionStrategy.dependencySubstitution {
+ substitute(module("org.jetbrains.kotlinx:$coreModule"))
+ .using(project(":$coreModule"))
+ .because(
+ "Because Kotlin compiler embeddable leaks coroutines into the runtime classpath, " +
+ "triggering all sort of incompatible class changes errors"
+ )
+ }
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/CacheRedirector.kt b/buildSrc/src/main/kotlin/CacheRedirector.kt
index c0d8351..5b00bd0 100644
--- a/buildSrc/src/main/kotlin/CacheRedirector.kt
+++ b/buildSrc/src/main/kotlin/CacheRedirector.kt
@@ -1,11 +1,11 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import org.gradle.api.*
import org.gradle.api.artifacts.dsl.*
import org.gradle.api.artifacts.repositories.*
import org.gradle.api.initialization.dsl.*
+import org.gradle.kotlin.dsl.*
+import org.jetbrains.kotlin.gradle.targets.js.nodejs.*
+import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.*
+import org.jetbrains.kotlin.gradle.targets.js.yarn.*
import java.net.*
/**
@@ -73,9 +73,9 @@
}
private fun URI.isCachedOrLocal() = scheme == "file" ||
- host == "cache-redirector.jetbrains.com" ||
- host == "teamcity.jetbrains.com" ||
- host == "buildserver.labs.intellij.net"
+ host == "cache-redirector.jetbrains.com" ||
+ host == "teamcity.jetbrains.com" ||
+ host == "buildserver.labs.intellij.net"
private fun Project.checkRedirectUrl(url: URI, containerName: String): URI {
val redirected = url.maybeRedirect()
@@ -100,7 +100,22 @@
}
}
+private fun Project.configureYarnAndNodeRedirects() {
+ if (CacheRedirector.isEnabled) {
+ val yarnRootExtension = extensions.findByType<YarnRootExtension>()
+ yarnRootExtension?.downloadBaseUrl?.let {
+ yarnRootExtension.downloadBaseUrl = CacheRedirector.maybeRedirect(it)
+ }
+
+ val nodeJsExtension = rootProject.extensions.findByType<NodeJsRootExtension>()
+ nodeJsExtension?.nodeDownloadBaseUrl?.let {
+ nodeJsExtension.nodeDownloadBaseUrl = CacheRedirector.maybeRedirect(it)
+ }
+ }
+}
+
// Used from Groovy scripts
+// TODO get rid of Groovy, come up with a proper convention for rootProject vs arbitrary project argument
object CacheRedirector {
/**
* Substitutes repositories in buildScript { } block.
@@ -110,12 +125,34 @@
rootProject.checkRedirect(repositories, "${rootProject.displayName} buildscript")
}
+ @JvmStatic
+ fun configure(project: Project) {
+ project.checkRedirect(project.repositories, project.displayName)
+ }
+
/**
- * Substitutes repositories in a project.
+ * Configures JS-specific extensions to use
*/
@JvmStatic
- fun Project.configure() {
- checkRedirect(repositories, displayName)
+ fun configureJsPackageManagers(project: Project) {
+ project.configureYarnAndNodeRedirects()
+ }
+
+ /**
+ * Temporary repositories to depend on until GC milestone 4 in KGP
+ * and stable Node release. Safe to remove when its removal does not break WASM tests.
+ */
+ @JvmStatic
+ fun configureWasmNodeRepositories(project: Project) {
+ val extension = project.extensions.findByType<NodeJsRootExtension>()
+ if (extension != null) {
+ extension.nodeVersion = "21.0.0-v8-canary202309167e82ab1fa2"
+ extension.nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary"
+ }
+
+ project.tasks.withType<KotlinNpmInstallTask>().configureEach {
+ args.add("--ignore-engines")
+ }
}
@JvmStatic
diff --git a/buildSrc/src/main/kotlin/CommunityProjectsBuild.kt b/buildSrc/src/main/kotlin/CommunityProjectsBuild.kt
index 155c9e4..fb86422 100644
--- a/buildSrc/src/main/kotlin/CommunityProjectsBuild.kt
+++ b/buildSrc/src/main/kotlin/CommunityProjectsBuild.kt
@@ -1,34 +1,44 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:JvmName("CommunityProjectsBuild")
import org.gradle.api.*
import org.gradle.api.artifacts.dsl.*
+import org.gradle.api.tasks.testing.Test
+import org.gradle.kotlin.dsl.*
import java.net.*
import java.util.logging.*
+import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
private val LOGGER: Logger = Logger.getLogger("Kotlin settings logger")
-
/**
* Functions in this file are responsible for configuring kotlinx.coroutines build against a custom dev version
* of Kotlin compiler.
* Such configuration is used in a composite community build of Kotlin in order to check whether not-yet-released changes
- * are compatible with our libraries (aka "integration testing that substitues lack of unit testing").
- */
+ * are compatible with our libraries (aka "integration testing that substitutes lack of unit testing").
+ *
+ * When `build_snapshot_train` is set to true (and [isSnapshotTrainEnabled] returns `true`),
+ * - `kotlin_version property` is overridden with `kotlin_snapshot_version` (see [getOverriddenKotlinVersion]),
+ * - `atomicfu_version` is overwritten by TeamCity environment (AFU is built with snapshot and published to mavenLocal
+ * as previous step or the snapshot build).
+ * Additionally, mavenLocal and Sonatype snapshots are added to repository list and stress tests are disabled
+ * (see [configureCommunityBuildTweaks]).
+ *
+ * DO NOT change the name of these properties without adapting the kotlinx.train build chain.
+*/
/**
* Should be used for running against of non-released Kotlin compiler on a system test level.
*
* @return a Kotlin API version parametrized from command line nor gradle.properties, null otherwise
*/
-fun getOverriddenKotlinApiVersion(project: Project): String? {
+fun getOverriddenKotlinApiVersion(project: Project): KotlinVersion? {
val apiVersion = project.rootProject.properties["kotlin_api_version"] as? String
- if (apiVersion != null) {
+ return if (apiVersion != null) {
LOGGER.info("""Configured Kotlin API version: '$apiVersion' for project $${project.name}""")
+ KotlinVersion.fromVersion(apiVersion)
+ } else {
+ null
}
- return apiVersion
}
/**
@@ -36,12 +46,14 @@
*
* @return a Kotlin Language version parametrized from command line nor gradle.properties, null otherwise
*/
-fun getOverriddenKotlinLanguageVersion(project: Project): String? {
+fun getOverriddenKotlinLanguageVersion(project: Project): KotlinVersion? {
val languageVersion = project.rootProject.properties["kotlin_language_version"] as? String
- if (languageVersion != null) {
+ return if (languageVersion != null) {
LOGGER.info("""Configured Kotlin Language version: '$languageVersion' for project ${project.name}""")
+ KotlinVersion.fromVersion(languageVersion)
+ } else {
+ null
}
- return languageVersion
}
/**
@@ -70,3 +82,72 @@
url = devRepoUrl
}
}
+
+/**
+ * Changes the build config when 'build_snapshot_train' is enabled:
+ * Disables flaky and Kotlin-specific tests, prints the real version of Kotlin applied (to be sure overridden version of Kotlin is properly picked).
+ */
+fun Project.configureCommunityBuildTweaks() {
+ if (!isSnapshotTrainEnabled(this)) return
+ allprojects {
+ // Disable stress tests and tests that are flaky on Kotlin version specific
+ tasks.withType<Test>().configureEach {
+ exclude("**/*LinearizabilityTest*")
+ exclude("**/*LFTest*")
+ exclude("**/*StressTest*")
+ exclude("**/*scheduling*")
+ exclude("**/*Timeout*")
+ exclude("**/*definitely/not/kotlinx*")
+ exclude("**/*PrecompiledDebugProbesTest*")
+ }
+ }
+
+ println("Manifest of kotlin-compiler-embeddable.jar for coroutines")
+ val coreProject = subprojects.single { it.name == coreModule }
+ configure(listOf(coreProject)) {
+ configurations.matching { it.name == "kotlinCompilerClasspath" }.configureEach {
+ val config = resolvedConfiguration.files.single { it.name.contains("kotlin-compiler-embeddable") }
+
+ val manifest = zipTree(config).matching {
+ include("META-INF/MANIFEST.MF")
+ }.files.single()
+
+ manifest.readLines().forEach {
+ println(it)
+ }
+ }
+ }
+}
+
+/**
+ * Ensures that, if [isSnapshotTrainEnabled] is true, the project is built with a snapshot version of Kotlin compiler.
+ */
+fun getOverriddenKotlinVersion(project: Project): String? =
+ if (isSnapshotTrainEnabled(project)) {
+ val snapshotVersion = project.rootProject.properties["kotlin_snapshot_version"]
+ ?: error("'kotlin_snapshot_version' should be defined when building with a snapshot compiler")
+ snapshotVersion.toString()
+ } else {
+ null
+ }
+
+/**
+ * Checks if the project is built with a snapshot version of Kotlin compiler.
+ */
+fun isSnapshotTrainEnabled(project: Project): Boolean =
+ when (project.rootProject.properties["build_snapshot_train"]) {
+ null -> false
+ "" -> false
+ else -> true
+ }
+
+fun shouldUseLocalMaven(project: Project): Boolean {
+ var someDependencyIsSnapshot = false
+ project.rootProject.properties.forEach { key, value ->
+ if (key.endsWith("_version") && value is String && value.endsWith("-SNAPSHOT")) {
+ println("NOTE: USING SNAPSHOT VERSION: $key=$value")
+ someDependencyIsSnapshot = true
+ }
+ }
+ return isSnapshotTrainEnabled(project) || someDependencyIsSnapshot
+}
diff --git a/buildSrc/src/main/kotlin/Dokka.kt b/buildSrc/src/main/kotlin/Dokka.kt
index a6b06ee..9003752 100644
--- a/buildSrc/src/main/kotlin/Dokka.kt
+++ b/buildSrc/src/main/kotlin/Dokka.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import org.gradle.api.*
import org.gradle.kotlin.dsl.*
import org.jetbrains.dokka.gradle.*
@@ -18,8 +14,8 @@
tasks.withType<AbstractDokkaLeafTask>().configureEach {
dokkaSourceSets.configureEach {
externalDocumentationLink {
- this.url.set(URL(url))
- packageListUrl.set(packageList.toPath().toUri().toURL())
+ this.url = URL(url)
+ packageListUrl = packageList.toPath().toUri().toURL()
}
}
}
diff --git a/buildSrc/src/main/kotlin/Idea.kt b/buildSrc/src/main/kotlin/Idea.kt
index 28b4aa5..615b8aa 100644
--- a/buildSrc/src/main/kotlin/Idea.kt
+++ b/buildSrc/src/main/kotlin/Idea.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
object Idea {
@JvmStatic // for Gradle
val active: Boolean
diff --git a/buildSrc/src/main/kotlin/Java9Modularity.kt b/buildSrc/src/main/kotlin/Java9Modularity.kt
index ccd7ef3..17cf1fa 100644
--- a/buildSrc/src/main/kotlin/Java9Modularity.kt
+++ b/buildSrc/src/main/kotlin/Java9Modularity.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import org.gradle.api.*
import org.gradle.api.attributes.*
import org.gradle.api.file.*
@@ -83,8 +79,8 @@
}
val processModuleInfoFile by tasks.registering(ProcessModuleInfoFile::class) {
- moduleInfoFile.set(file("${target.name.ifEmpty { "." }}/src/module-info.java"))
- processedModuleInfoFile.set(project.layout.buildDirectory.file("generated-sources/module-info-processor/module-info.java"))
+ moduleInfoFile = file("${target.name.ifEmpty { "." }}/src/module-info.java")
+ processedModuleInfoFile = project.layout.buildDirectory.file("generated-sources/module-info-processor/module-info.java")
}
val compileJavaModuleInfo = tasks.register("compileModuleInfoJava", JavaCompile::class.java) {
@@ -95,9 +91,9 @@
val targetDir = compileKotlinTask.destinationDirectory.dir("../java9")
// Use a Java 11 compiler for the module-info.
- javaCompiler.set(javaToolchains.compilerFor {
- languageVersion.set(JavaLanguageVersion.of(11))
- })
+ javaCompiler = javaToolchains.compilerFor {
+ languageVersion = JavaLanguageVersion.of(11)
+ }
// Always compile kotlin classes before the module descriptor.
dependsOn(compileKotlinTask)
@@ -112,14 +108,14 @@
// Set the task outputs and destination directory
outputs.dir(targetDir)
- destinationDirectory.set(targetDir)
+ destinationDirectory = targetDir
// Configure JVM compatibility
sourceCompatibility = JavaVersion.VERSION_1_9.toString()
targetCompatibility = JavaVersion.VERSION_1_9.toString()
// Set the Java release version.
- options.release.set(9)
+ options.release = 9
// Ignore warnings about using 'requires transitive' on automatic modules.
// not needed when compiling with recent JDKs, e.g. 17
@@ -135,7 +131,7 @@
// Use the classpath of the compileKotlinJvm task.
// Also ensure that the module path is used instead of classpath.
classpath = compileKotlinTask.libraries
- modularity.inferModulePath.set(true)
+ modularity.inferModulePath = true
}
tasks.named<Jar>(target.artifactsTaskName) {
diff --git a/buildSrc/src/main/kotlin/OptInPreset.kt b/buildSrc/src/main/kotlin/OptInPreset.kt
deleted file mode 100644
index fdcdb8e..0000000
--- a/buildSrc/src/main/kotlin/OptInPreset.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-@file:JvmName("OptInPreset")
-
-val optInAnnotations = listOf(
- "kotlin.RequiresOptIn",
- "kotlin.experimental.ExperimentalTypeInference",
- "kotlin.ExperimentalMultiplatform",
- "kotlinx.coroutines.DelicateCoroutinesApi",
- "kotlinx.coroutines.ExperimentalCoroutinesApi",
- "kotlinx.coroutines.ObsoleteCoroutinesApi",
- "kotlinx.coroutines.InternalCoroutinesApi",
- "kotlinx.coroutines.FlowPreview")
diff --git a/buildSrc/src/main/kotlin/Platform.kt b/buildSrc/src/main/kotlin/Platform.kt
index f22c161..b667a13 100644
--- a/buildSrc/src/main/kotlin/Platform.kt
+++ b/buildSrc/src/main/kotlin/Platform.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import org.gradle.api.Project
// Use from Groovy for now
diff --git a/buildSrc/src/main/kotlin/Projects.kt b/buildSrc/src/main/kotlin/Projects.kt
index 2442c50..48bb938 100644
--- a/buildSrc/src/main/kotlin/Projects.kt
+++ b/buildSrc/src/main/kotlin/Projects.kt
@@ -1,24 +1,39 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:JvmName("Projects")
-import org.gradle.api.*
-fun Project.version(target: String): String =
- property("${target}_version") as String
+import org.gradle.api.*
+import org.gradle.api.tasks.*
+
+fun Project.version(target: String): String {
+ if (target == "kotlin") {
+ getOverriddenKotlinVersion(this)?.let { return it }
+ }
+ return property("${target}_version") as String
+}
+
+val Project.jdkToolchainVersion: Int get() = property("jdk_toolchain_version").toString().toInt()
+
+/**
+ * TODO: check if this is still relevant.
+ * It was introduced in <https://github.com/Kotlin/kotlinx.coroutines/pull/2389>, and the project for which this was
+ * done is already long finished.
+ */
+val Project.nativeTargetsAreEnabled: Boolean get() = rootProject.properties["disable_native_targets"] == null
+
+val Project.sourceSets: SourceSetContainer
+ get() = extensions.getByName("sourceSets") as SourceSetContainer
val coreModule = "kotlinx-coroutines-core"
val jdk8ObsoleteModule = "kotlinx-coroutines-jdk8"
-val testModule = "kotlinx-coroutines-test"
+val testUtilsModule = "test-utils"
-val multiplatform = setOf(coreModule, testModule)
// Not applicable for Kotlin plugin
val sourceless = setOf("kotlinx.coroutines", "kotlinx-coroutines-bom")
-val internal = setOf("kotlinx.coroutines", "benchmarks")
-// Not published
-val unpublished = internal + setOf("example-frontend-js", "android-unit-tests")
-val Project.isMultiplatform: Boolean get() = name in multiplatform
+// Not published
+val unpublished = setOf("kotlinx.coroutines", "benchmarks", "android-unit-tests", testUtilsModule)
+
+val Project.isMultiplatform: Boolean get() = name in setOf(coreModule, "kotlinx-coroutines-test", testUtilsModule)
+val Project.isBom: Boolean get() = name == "kotlinx-coroutines-bom"
// Projects that we do not check for Android API level 14 check due to various limitations
val androidNonCompatibleProjects = setOf(
diff --git a/buildSrc/src/main/kotlin/Properties.kt b/buildSrc/src/main/kotlin/Properties.kt
deleted file mode 100644
index 3431450..0000000
--- a/buildSrc/src/main/kotlin/Properties.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("UnstableApiUsage")
-
-import org.gradle.api.provider.*
-
-infix fun <T> Property<T>.by(value: T) {
- set(value)
-}
diff --git a/buildSrc/src/main/kotlin/Publishing.kt b/buildSrc/src/main/kotlin/Publishing.kt
index cb612c5..2e5028a 100644
--- a/buildSrc/src/main/kotlin/Publishing.kt
+++ b/buildSrc/src/main/kotlin/Publishing.kt
@@ -1,12 +1,15 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UnstableApiUsage")
+import groovy.util.Node
+import groovy.util.NodeList
import org.gradle.api.Project
+import org.gradle.api.XmlProvider
import org.gradle.api.artifacts.dsl.*
+import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.*
+import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
+import org.gradle.api.tasks.*
+import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.*
import org.gradle.plugins.signing.*
import java.net.*
@@ -14,33 +17,44 @@
// Pom configuration
fun MavenPom.configureMavenCentralMetadata(project: Project) {
- name by project.name
- description by "Coroutines support libraries for Kotlin"
- url by "https://github.com/Kotlin/kotlinx.coroutines"
+ name = project.name
+ description = "Coroutines support libraries for Kotlin"
+ url = "https://github.com/Kotlin/kotlinx.coroutines"
licenses {
license {
- name by "The Apache Software License, Version 2.0"
- url by "https://www.apache.org/licenses/LICENSE-2.0.txt"
- distribution by "repo"
+ name = "The Apache Software License, Version 2.0"
+ url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ distribution = "repo"
}
}
developers {
developer {
- id by "JetBrains"
- name by "JetBrains Team"
- organization by "JetBrains"
- organizationUrl by "https://www.jetbrains.com"
+ id = "JetBrains"
+ name = "JetBrains Team"
+ organization = "JetBrains"
+ organizationUrl = "https://www.jetbrains.com"
}
}
scm {
- url by "https://github.com/Kotlin/kotlinx.coroutines"
+ url = "https://github.com/Kotlin/kotlinx.coroutines"
}
}
+/**
+ * 'libs.space.pub' is a dev option that is set on our CI in order to publish
+ * dev build into 'https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven' Maven repository.
+ * In order to use it, pass the corresponding ENV to the TC 'Deploy' task.
+ */
+private val spacePublicationEnabled = System.getenv("libs.space.pub")?.equals("true") ?: false
+
fun mavenRepositoryUri(): URI {
+ if (spacePublicationEnabled) {
+ return URI("https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven")
+ }
+
val repositoryId: String? = System.getenv("libs.repository.id")
return if (repositoryId == null) {
URI("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
@@ -53,15 +67,17 @@
rh.maven {
url = mavenRepositoryUri()
credentials {
- username = project.getSensitiveProperty("libs.sonatype.user")
- password = project.getSensitiveProperty("libs.sonatype.password")
+ if (spacePublicationEnabled) {
+ // Configure space credentials
+ username = project.getSensitiveProperty("libs.space.user")
+ password = project.getSensitiveProperty("libs.space.password")
+ } else {
+ // Configure sonatype credentials
+ username = project.getSensitiveProperty("libs.sonatype.user")
+ password = project.getSensitiveProperty("libs.sonatype.password")
+ }
}
}
-
- // Something that's easy to "clean" for development, not mavenLocal
- rh.maven("${project.rootProject.buildDir}/repo") {
- name = "buildRepo"
- }
}
fun signPublicationIfKeyPresent(project: Project, publication: MavenPublication) {
@@ -79,3 +95,118 @@
private fun Project.getSensitiveProperty(name: String): String? {
return project.findProperty(name) as? String ?: System.getenv(name)
}
+
+/**
+ * This unbelievable piece of engineering^W programming is a workaround for the following issues:
+ * - https://github.com/gradle/gradle/issues/26132
+ * - https://youtrack.jetbrains.com/issue/KT-61313/
+ *
+ * Long story short:
+ * 1) Single module produces multiple publications
+ * 2) 'Sign' plugin signs them
+ * 3) Signature files are re-used, which Gradle detects and whines about an implicit dependency
+ *
+ * There are three patterns that we workaround:
+ * 1) 'Sign' does not depend on 'publish'
+ * 2) Empty 'javadoc.jar.asc' got reused between publications (kind of a implication of the previous one)
+ * 3) `klib` signatures are reused where appropriate
+ *
+ * It addresses the following failures:
+ * ```
+ * Gradle detected a problem with the following location: 'kotlinx.coroutines/kotlinx-coroutines-core/build/classes/kotlin/macosArm64/main/klib/kotlinx-coroutines-core.klib.asc'.
+ * Reason: Task ':kotlinx-coroutines-core:linkWorkerTestDebugTestMacosArm64' uses this output of task ':kotlinx-coroutines-core:signMacosArm64Publication' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
+ *
+ * ```
+ * and
+ * ```
+ * Gradle detected a problem with the following location: 'kotlinx-coroutines-core/build/libs/kotlinx-coroutines-core-1.7.2-SNAPSHOT-javadoc.jar.asc'.
+ * Reason: Task ':kotlinx-coroutines-core:publishAndroidNativeArm32PublicationToMavenLocal' uses this output of task ':kotlinx-coroutines-core:signAndroidNativeArm64Publication' without declaring an explicit or implicit dependency.
+ * ```
+ */
+fun Project.establishSignDependencies() {
+ tasks.withType<Sign>().configureEach {
+ val pubName = name.removePrefix("sign").removeSuffix("Publication")
+ // Gradle#26132 -- establish dependency between sign and link tasks, as well as compile ones
+ mustRunAfter(tasks.matching { it.name == "linkDebugTest$pubName" })
+ mustRunAfter(tasks.matching { it.name == "linkWorkerTestDebugTest$pubName" })
+ mustRunAfter(tasks.matching { it.name == "compileTestKotlin$pubName" })
+ }
+
+ // Sign plugin issues and publication:
+ // Establish dependency between 'sign' and 'publish*' tasks
+ tasks.withType<AbstractPublishToMaven>().configureEach {
+ dependsOn(tasks.withType<Sign>())
+ }
+}
+
+/**
+ * Re-configure common publication to depend on JVM artifact only in pom.xml.
+ * It allows us to keep backwards compatibility with pre-multiplatform 'kotlinx-coroutines' publication scheme
+ * for Maven consumers:
+ * - Previously, we published 'kotlinx-coroutines-core' as the JVM artifact
+ * - With a multiplatform enabled as is, 'kotlinx-coroutines-core' is a common artifact not consumable from Maven,
+ * instead, users should depend on 'kotlinx-coroutines-core-jvm'
+ * - To keep the compatibility and experience, we do add dependency on 'kotlinx-coroutines-core-jvm' for
+ * 'kotlinx-coroutines-core' in pom.xml only (e.g. Gradle will keep using the metadata), so Maven users can
+ * depend on previous coordinates.
+ *
+ * Original code comment:
+ * Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module
+ * metadata can still get the platform artifact and transitive dependencies from the POM.
+ */
+public fun Project.reconfigureMultiplatformPublication(jvmPublication: MavenPublication) {
+ val mavenPublications =
+ extensions.getByType(PublishingExtension::class.java).publications.withType<MavenPublication>()
+ val kmpPublication = mavenPublications.getByName("kotlinMultiplatform")
+
+ var jvmPublicationXml: XmlProvider? = null
+ jvmPublication.pom.withXml { jvmPublicationXml = this }
+
+ kmpPublication.pom.withXml {
+ val root = asNode()
+ // Remove the original content and add the content from the platform POM:
+ root.children().toList().forEach { root.remove(it as Node) }
+ jvmPublicationXml!!.asNode().children().forEach { root.append(it as Node) }
+
+ // Adjust the self artifact ID, as it should match the root module's coordinates:
+ ((root["artifactId"] as NodeList).first() as Node).setValue(kmpPublication.artifactId)
+
+ // Set packaging to POM to indicate that there's no artifact:
+ root.appendNode("packaging", "pom")
+
+ // Remove the original platform dependencies and add a single dependency on the platform module:
+ val dependencies = (root["dependencies"] as NodeList).first() as Node
+ dependencies.children().toList().forEach { dependencies.remove(it as Node) }
+ dependencies.appendNode("dependency").apply {
+ appendNode("groupId", jvmPublication.groupId)
+ appendNode("artifactId", jvmPublication.artifactId)
+ appendNode("version", jvmPublication.version)
+ appendNode("scope", "compile")
+ }
+ }
+
+ // TODO verify if this is still relevant
+ tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }.configureEach {
+ @Suppress("DEPRECATION")
+ dependsOn(tasks["generatePomFileFor${jvmPublication.name.capitalize()}Publication"])
+ }
+}
+
+// Top-level deploy task that publishes all artifacts
+public fun Project.registerTopLevelDeployTask() {
+ assert(this === rootProject)
+ tasks.register("deploy") {
+ allprojects {
+ val publishTasks = tasks.matching { it.name == "publish" }
+ dependsOn(publishTasks)
+ }
+ }
+}
+
+public fun Project.registerEmptyJavadocArtifact(): TaskProvider<Jar> {
+ return tasks.register("javadocJar", Jar::class) {
+ archiveClassifier = "javadoc"
+ // contents are deliberately left empty
+ }
+}
+
diff --git a/buildSrc/src/main/kotlin/SourceSets.kt b/buildSrc/src/main/kotlin/SourceSets.kt
index 3ad1dd4..340fd65 100644
--- a/buildSrc/src/main/kotlin/SourceSets.kt
+++ b/buildSrc/src/main/kotlin/SourceSets.kt
@@ -1,19 +1,56 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+import org.gradle.api.*
import org.jetbrains.kotlin.gradle.plugin.*
+import org.gradle.kotlin.dsl.*
-fun KotlinSourceSet.configureMultiplatform() {
- val srcDir = if (name.endsWith("Main")) "src" else "test"
- val platform = name.dropLast(4)
- kotlin.srcDir("$platform/$srcDir")
- if (name == "jvmMain") {
- resources.srcDir("$platform/resources")
- } else if (name == "jvmTest") {
- resources.srcDir("$platform/test-resources")
+fun KotlinSourceSet.configureDirectoryPaths() {
+ if (project.isMultiplatform) {
+ val srcDir = if (name.endsWith("Main")) "src" else "test"
+ val platform = name.dropLast(4)
+ kotlin.srcDir("$platform/$srcDir")
+ if (name == "jvmMain") {
+ resources.srcDir("$platform/resources")
+ } else if (name == "jvmTest") {
+ resources.srcDir("$platform/test-resources")
+ }
+ } else if (platformOf(project) == "jvm") {
+ when (name) {
+ "main" -> {
+ kotlin.srcDir("src")
+ resources.srcDir("resources")
+ }
+ "test" -> {
+ kotlin.srcDir("test")
+ resources.srcDir("test-resources")
+ }
+ }
+ } else {
+ throw IllegalArgumentException("Unclear how to configure source sets for ${project.name}")
}
- languageSettings {
- optInAnnotations.forEach { optIn(it) }
- progressiveMode = true
+}
+
+/**
+ * Creates shared source sets for a group of source sets.
+ *
+ * [reverseDependencies] is a list of prefixes of names of source sets that depend on the new source set.
+ * [dependencies] is a list of prefixes of names of source sets that the new source set depends on.
+ * [groupName] is the prefix of the names of the new source sets.
+ *
+ * The suffixes of the source sets are "Main" and "Test".
+ */
+fun NamedDomainObjectContainer<KotlinSourceSet>.groupSourceSets(
+ groupName: String,
+ reverseDependencies: List<String>,
+ dependencies: List<String>
+) {
+ val sourceSetSuffixes = listOf("Main", "Test")
+ for (suffix in sourceSetSuffixes) {
+ register(groupName + suffix) {
+ for (dep in dependencies) {
+ dependsOn(get(dep + suffix))
+ }
+ for (revDep in reverseDependencies) {
+ get(revDep + suffix).dependsOn(this)
+ }
+ }
}
}
diff --git a/buildSrc/src/main/kotlin/UnpackAar.kt b/buildSrc/src/main/kotlin/UnpackAar.kt
index afe2627..88948ac 100644
--- a/buildSrc/src/main/kotlin/UnpackAar.kt
+++ b/buildSrc/src/main/kotlin/UnpackAar.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import org.gradle.api.*
import org.gradle.api.artifacts.transform.InputArtifact
import org.gradle.api.artifacts.transform.TransformAction
diff --git a/buildSrc/src/main/kotlin/VersionFile.kt b/buildSrc/src/main/kotlin/VersionFile.kt
new file mode 100644
index 0000000..46d1984
--- /dev/null
+++ b/buildSrc/src/main/kotlin/VersionFile.kt
@@ -0,0 +1,25 @@
+import org.gradle.api.*
+import org.gradle.api.tasks.*
+
+/**
+ * Adds 'module_name.version' file to the project's JAR META-INF
+ * for the better toolability. See #2941
+ */
+object VersionFile {
+ fun registerVersionFileTask(project: Project): TaskProvider<Task> {
+ val versionFile = project.layout.buildDirectory.file("${project.name.replace('-', '_')}.version")
+ val version = project.version.toString()
+ return project.tasks.register("versionFileTask") {
+ outputs.file(versionFile)
+ doLast {
+ versionFile.get().asFile.writeText(version)
+ }
+ }
+ }
+
+ fun fromVersionFile(target: AbstractCopyTask, versionFileTask: TaskProvider<Task>) {
+ target.from(versionFileTask) {
+ into("META-INF")
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/animalsniffer-conventions.gradle.kts b/buildSrc/src/main/kotlin/animalsniffer-conventions.gradle.kts
index 639245b..74693f9 100644
--- a/buildSrc/src/main/kotlin/animalsniffer-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/animalsniffer-conventions.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import ru.vyarus.gradle.plugin.animalsniffer.*
configure(subprojects) {
diff --git a/buildSrc/src/main/kotlin/bom-conventions.gradle.kts b/buildSrc/src/main/kotlin/bom-conventions.gradle.kts
index 45f30ed..14f365c 100644
--- a/buildSrc/src/main/kotlin/bom-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/bom-conventions.gradle.kts
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.dsl.*
diff --git a/buildSrc/src/main/kotlin/configure-compilation-conventions.gradle.kts b/buildSrc/src/main/kotlin/configure-compilation-conventions.gradle.kts
index 9e22b45..26ffe11 100644
--- a/buildSrc/src/main/kotlin/configure-compilation-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/configure-compilation-conventions.gradle.kts
@@ -1,31 +1,56 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
+import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
-import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
+import org.jetbrains.kotlin.gradle.tasks.*
+import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
configure(subprojects) {
val project = this
if (name in sourceless) return@configure
apply(plugin = "kotlinx-atomicfu")
- tasks.withType<KotlinCompile<*>>().configureEach {
- val isMainTaskName = name == "compileKotlin" || name == "compileKotlinJvm"
- kotlinOptions {
- languageVersion = getOverriddenKotlinLanguageVersion(project)
- apiVersion = getOverriddenKotlinApiVersion(project)
- if (isMainTaskName && versionsAreNotOverridden) {
- allWarningsAsErrors = true
+ tasks.withType<KotlinCompilationTask<*>>().configureEach {
+ val isMainTaskName = name.startsWith("compileKotlin")
+ compilerOptions {
+ var versionsAreNotOverridden = true
+ getOverriddenKotlinLanguageVersion(project)?.let {
+ languageVersion = it
+ versionsAreNotOverridden = false
}
- val newOptions =
- listOf(
- "-progressive", "-Xno-param-assertions", "-Xno-receiver-assertions",
- "-Xno-call-assertions"
- ) + optInAnnotations.map { "-opt-in=$it" }
- freeCompilerArgs = freeCompilerArgs + newOptions
+ getOverriddenKotlinApiVersion(project)?.let {
+ apiVersion = it
+ versionsAreNotOverridden = false
+ }
+ if (isMainTaskName && versionsAreNotOverridden && !unpublished.contains(project.name)) {
+ allWarningsAsErrors = true
+ freeCompilerArgs.add("-Xexplicit-api=strict")
+ }
+ /* Coroutines do not interop with Java and these flags provide a significant
+ * (i.e. close to double-digit) reduction in both bytecode and optimized dex size */
+ if (this@configureEach is KotlinJvmCompile) {
+ freeCompilerArgs.addAll(
+ "-Xno-param-assertions",
+ "-Xno-call-assertions",
+ "-Xno-receiver-assertions"
+ )
+ }
+ if (this@configureEach is KotlinNativeCompile) {
+ optIn.addAll(
+ "kotlinx.cinterop.ExperimentalForeignApi",
+ "kotlinx.cinterop.UnsafeNumber",
+ "kotlin.experimental.ExperimentalNativeApi",
+ )
+ }
+ freeCompilerArgs.addAll("-progressive", "-Xexpect-actual-classes")
+ optIn.addAll(
+ "kotlin.experimental.ExperimentalTypeInference",
+ "kotlin.ExperimentalMultiplatform",
+ // our own opt-ins that we don't want to bother with in our own code:
+ "kotlinx.coroutines.DelicateCoroutinesApi",
+ "kotlinx.coroutines.ExperimentalCoroutinesApi",
+ "kotlinx.coroutines.ObsoleteCoroutinesApi",
+ "kotlinx.coroutines.InternalCoroutinesApi",
+ "kotlinx.coroutines.FlowPreview"
+ )
}
+
}
}
-
-val KotlinCommonOptions.versionsAreNotOverridden: Boolean
- get() = languageVersion == null && apiVersion == null
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts b/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts
new file mode 100644
index 0000000..966aa98
--- /dev/null
+++ b/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts
@@ -0,0 +1,99 @@
+import org.jetbrains.dokka.gradle.*
+import java.net.*
+
+
+plugins {
+ id("org.jetbrains.dokka")
+}
+
+val knit_version: String by project
+private val projetsWithoutDokka = unpublished + "kotlinx-coroutines-bom" + jdk8ObsoleteModule
+private val coreModuleDocsUrl = "https://kotlinlang.org/api/kotlinx.coroutines/$coreModule/"
+private val coreModuleDocsPackageList = "$projectDir/kotlinx-coroutines-core/build/dokka/htmlPartial/package-list"
+
+configure(subprojects.filterNot { projetsWithoutDokka.contains(it.name) }) {
+ apply(plugin = "org.jetbrains.dokka")
+ configurePathsaver()
+ condigureDokkaSetup()
+ configureExternalLinks()
+}
+
+// Setup top-level 'dokkaHtmlMultiModule' with templates
+tasks.withType<DokkaMultiModuleTask>().named("dokkaHtmlMultiModule") {
+ setupDokkaTemplatesDir(this)
+}
+
+dependencies {
+ // Add explicit dependency between Dokka and Knit plugin
+ add("dokkaHtmlMultiModulePlugin", "org.jetbrains.kotlinx:dokka-pathsaver-plugin:$knit_version")
+}
+
+// Dependencies for Knit processing: Knit plugin to work with Dokka
+private fun Project.configurePathsaver() {
+ tasks.withType(DokkaTaskPartial::class).configureEach {
+ dependencies {
+ plugins("org.jetbrains.kotlinx:dokka-pathsaver-plugin:$knit_version")
+ }
+ }
+}
+
+// Configure Dokka setup
+private fun Project.condigureDokkaSetup() {
+ tasks.withType(DokkaTaskPartial::class).configureEach {
+ suppressInheritedMembers = true
+ setupDokkaTemplatesDir(this)
+
+ dokkaSourceSets.configureEach {
+ jdkVersion = 11
+ includes.from("README.md")
+ noStdlibLink = true
+
+ externalDocumentationLink {
+ url = URL("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ packageListUrl = rootProject.projectDir.toPath().resolve("site/stdlib.package.list").toUri().toURL()
+ }
+
+ // Something suspicious to figure out, probably legacy of earlier days
+ if (!project.isMultiplatform) {
+ dependsOn(project.configurations["compileClasspath"])
+ }
+ }
+
+ // Source links
+ dokkaSourceSets.configureEach {
+ sourceLink {
+ localDirectory = rootDir
+ remoteUrl = URL("https://github.com/kotlin/kotlinx.coroutines/tree/master")
+ remoteLineSuffix ="#L"
+ }
+ }
+ }
+}
+
+private fun Project.configureExternalLinks() {
+ tasks.withType<DokkaTaskPartial>() {
+ dokkaSourceSets.configureEach {
+ externalDocumentationLink {
+ url = URL(coreModuleDocsUrl)
+ packageListUrl = File(coreModuleDocsPackageList).toURI().toURL()
+ }
+ }
+ }
+}
+
+/**
+ * Setups Dokka templates. While this directory is empty in our repository,
+ * 'kotlinlang' build pipeline adds templates there when preparing our documentation
+ * to be published on kotlinlang.
+ *
+ * See:
+ * - Template setup: https://github.com/JetBrains/kotlin-web-site/blob/master/.teamcity/builds/apiReferences/kotlinx/coroutines/KotlinxCoroutinesPrepareDokkaTemplates.kt
+ * - Templates repository: https://github.com/JetBrains/kotlin-web-site/tree/master/dokka-templates
+ */
+private fun Project.setupDokkaTemplatesDir(dokkaTask: AbstractDokkaTask) {
+ dokkaTask.pluginsMapConfiguration = mapOf(
+ "org.jetbrains.dokka.base.DokkaBase" to """{ "templatesDir" : "${
+ project.rootProject.projectDir.toString().replace('\\', '/')
+ }/dokka-templates" }"""
+ )
+}
diff --git a/buildSrc/src/main/kotlin/java-modularity-conventions.gradle.kts b/buildSrc/src/main/kotlin/java-modularity-conventions.gradle.kts
index a5f72aa..e8df676 100644
--- a/buildSrc/src/main/kotlin/java-modularity-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/java-modularity-conventions.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// Currently the compilation of the module-info fails for
// kotlinx-coroutines-play-services because it depends on Android JAR's
// which do not have an explicit module-info descriptor.
diff --git a/buildSrc/src/main/kotlin/jdk-convention.gradle.kts b/buildSrc/src/main/kotlin/jdk-convention.gradle.kts
deleted file mode 100644
index 64bd90d..0000000
--- a/buildSrc/src/main/kotlin/jdk-convention.gradle.kts
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-import org.gradle.api.JavaVersion
-
-if (!JavaVersion.current().isJava11Compatible) {
- val message = "Project required JDK 11+, but found ${JavaVersion.current()}"
- if (Idea.active) {
- logger.error(message)
- } else {
- throw GradleException(message)
- }
-}
diff --git a/buildSrc/src/main/kotlin/knit-conventions.gradle.kts b/buildSrc/src/main/kotlin/knit-conventions.gradle.kts
new file mode 100644
index 0000000..e606a51
--- /dev/null
+++ b/buildSrc/src/main/kotlin/knit-conventions.gradle.kts
@@ -0,0 +1,20 @@
+plugins {
+ id("kotlinx-knit")
+}
+
+knit {
+ siteRoot = "https://kotlinlang.org/api/kotlinx.coroutines"
+ moduleRoots = listOf(".", "integration", "reactive", "ui")
+ moduleDocs = "build/dokka/htmlPartial"
+ dokkaMultiModuleRoot = "build/dokka/htmlMultiModule/"
+}
+
+tasks.named("knitPrepare").configure {
+ val knitTask = this
+ // In order for knit to operate, it should depend on and collect
+ // all Dokka outputs from each module
+ allprojects {
+ val dokkaTasks = tasks.matching { it.name == "dokkaHtmlMultiModule" }
+ knitTask.dependsOn(dokkaTasks)
+ }
+}
diff --git a/buildSrc/src/main/kotlin/kotlin-js-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-js-conventions.gradle.kts
deleted file mode 100644
index c1897ca..0000000
--- a/buildSrc/src/main/kotlin/kotlin-js-conventions.gradle.kts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-// Platform-specific configuration to compile JS modules
-
-import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
-
-plugins {
- kotlin("js")
-}
-
-dependencies {
- testImplementation(kotlin("test-js"))
-}
-
-kotlin {
- js(LEGACY) {
- moduleName = project.name.removeSuffix("-js")
- }
-
- sourceSets {
- main {
- kotlin.srcDirs("src")
- resources.srcDirs("resources")
- }
- test {
- kotlin.srcDirs("test")
- resources.srcDirs("test-resources")
- }
- }
-}
-
-tasks.withType<KotlinJsCompile> {
- kotlinOptions {
- moduleKind = "umd"
- sourceMap = true
- metaInfo = true
- }
-}
diff --git a/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts
index 90847f4..34c45d1 100644
--- a/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// Platform-specific configuration to compile JVM modules
import org.gradle.api.*
+import org.jetbrains.kotlin.gradle.dsl.*
plugins {
kotlin("jvm")
@@ -15,6 +12,13 @@
targetCompatibility = JavaVersion.VERSION_1_8
}
+kotlin {
+ compilerOptions {
+ jvmTarget = JvmTarget.JVM_1_8
+ }
+ jvmToolchain(jdkToolchainVersion)
+}
+
dependencies {
testImplementation(kotlin("test"))
// Workaround to make addSuppressed work in tests
@@ -24,12 +28,6 @@
testImplementation("junit:junit:${version("junit")}")
}
-tasks.compileKotlin {
- kotlinOptions {
- freeCompilerArgs += listOf("-Xexplicit-api=strict")
- }
-}
-
tasks.withType<Test> {
testLogging {
showStandardStreams = true
diff --git a/buildSrc/src/main/kotlin/kotlin-multiplatform-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-multiplatform-conventions.gradle.kts
new file mode 100644
index 0000000..fd2d3fd
--- /dev/null
+++ b/buildSrc/src/main/kotlin/kotlin-multiplatform-conventions.gradle.kts
@@ -0,0 +1,121 @@
+import org.gradle.api.*
+import org.gradle.api.tasks.testing.logging.*
+import org.jetbrains.kotlin.gradle.dsl.*
+
+plugins {
+ kotlin("multiplatform")
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+kotlin {
+ jvm {
+ compilations.all {
+ compilerOptions.configure {
+ jvmTarget = JvmTarget.JVM_1_8
+ }
+ }
+ }
+ jvmToolchain(jdkToolchainVersion)
+ if (nativeTargetsAreEnabled) {
+ // According to https://kotlinlang.org/docs/native-target-support.html
+ // Tier 1
+ linuxX64()
+ macosX64()
+ macosArm64()
+ iosSimulatorArm64()
+ iosX64()
+ // Tier 2
+ linuxArm64()
+ watchosSimulatorArm64()
+ watchosX64()
+ watchosArm32()
+ watchosArm64()
+ tvosSimulatorArm64()
+ tvosX64()
+ tvosArm64()
+ iosArm64()
+ // Tier 3
+ androidNativeArm32()
+ androidNativeArm64()
+ androidNativeX86()
+ androidNativeX64()
+ mingwX64()
+ watchosDeviceArm64()
+ }
+ js {
+ moduleName = project.name
+ nodejs()
+ compilations["main"]?.dependencies {
+ api("org.jetbrains.kotlinx:atomicfu-js:${version("atomicfu")}")
+ }
+ }
+ @OptIn(org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl::class)
+ wasmJs {
+ // Module name should be different from the one from JS
+ // otherwise IC tasks that start clashing different modules with the same module name
+ moduleName = project.name + "Wasm"
+ nodejs()
+ compilations["main"]?.dependencies {
+ api("org.jetbrains.kotlinx:atomicfu-wasm-js:${version("atomicfu")}")
+ }
+ }
+ applyDefaultHierarchyTemplate()
+ sourceSets {
+ commonTest {
+ dependencies {
+ api("org.jetbrains.kotlin:kotlin-test-common:${version("kotlin")}")
+ api("org.jetbrains.kotlin:kotlin-test-annotations-common:${version("kotlin")}")
+ }
+ }
+ jvmMain.dependencies {
+ compileOnly("org.codehaus.mojo:animal-sniffer-annotations:1.20")
+ // Workaround until https://github.com/JetBrains/kotlin/pull/4999 is picked up
+ api("org.jetbrains:annotations:23.0.0")
+ }
+ jvmTest.dependencies {
+ api("org.jetbrains.kotlin:kotlin-test:${version("kotlin")}")
+ // Workaround to make addSuppressed work in tests
+ api("org.jetbrains.kotlin:kotlin-reflect:${version("kotlin")}")
+ api("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${version("kotlin")}")
+ api("org.jetbrains.kotlin:kotlin-test-junit:${version("kotlin")}")
+ api("junit:junit:${version("junit")}")
+ }
+ nativeMain.dependencies {
+ // workaround for #3968 until this is fixed on atomicfu's side
+ api("org.jetbrains.kotlinx:atomicfu:0.23.1")
+ }
+ jsMain { }
+ jsTest {
+ dependencies {
+ api("org.jetbrains.kotlin:kotlin-test-js:${version("kotlin")}")
+ }
+ }
+ val wasmJsMain by getting {
+ }
+ val wasmJsTest by getting {
+ dependencies {
+ api("org.jetbrains.kotlin:kotlin-test-wasm-js:${version("kotlin")}")
+ }
+ }
+ groupSourceSets("jsAndWasmShared", listOf("js", "wasmJs"), listOf("common"))
+ }
+}
+
+// Disable intermediate sourceSet compilation because we do not need js-wasmJs artifact
+tasks.configureEach {
+ if (name == "compileJsAndWasmSharedMainKotlinMetadata") {
+ enabled = false
+ }
+}
+
+tasks.named("jvmTest", Test::class) {
+ testLogging {
+ showStandardStreams = true
+ events = setOf(TestLogEvent.PASSED, TestLogEvent.FAILED)
+ }
+ project.properties["stressTest"]?.let { systemProperty("stressTest", it) }
+}
diff --git a/buildSrc/src/main/kotlin/kover-conventions.gradle.kts b/buildSrc/src/main/kotlin/kover-conventions.gradle.kts
index 7a0a62f..d87e132 100644
--- a/buildSrc/src/main/kotlin/kover-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/kover-conventions.gradle.kts
@@ -1,13 +1,10 @@
import kotlinx.kover.gradle.plugin.dsl.*
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
plugins {
id("org.jetbrains.kotlinx.kover")
}
-val notCovered = sourceless + internal + unpublished
+val notCovered = sourceless + unpublished
val expectedCoverage = mutableMapOf(
// These have lower coverage in general, it can be eventually fixed
@@ -40,33 +37,37 @@
}
}
- extensions.configure<KoverReportExtension>("koverReport") {
- defaults {
- html {
- setReportDir(conventionProject.layout.buildDirectory.dir("kover/${project.name}/html"))
- }
+ extensions.configure<KoverProjectExtension>("kover") {
+ reports {
+ total {
+ html {
+ htmlDir = conventionProject.layout.buildDirectory.dir("kover/${project.name}/html")
+ }
- verify {
- rule {
- /*
- * 85 is our baseline that we aim to raise to 90+.
- * Missing coverage is typically due to bugs in the agent
- * (e.g. signatures deprecated with an error are counted),
- * sometimes it's various diagnostic `toString` or `catch` for OOMs/VerificationErrors,
- * but some places are definitely worth visiting.
- */
- minBound(expectedCoverage[projectName] ?: 85) // COVERED_LINES_PERCENTAGE
+ verify {
+ rule {
+ /*
+ * 85 is our baseline that we aim to raise to 90+.
+ * Missing coverage is typically due to bugs in the agent
+ * (e.g. signatures deprecated with an error are counted),
+ * sometimes it's various diagnostic `toString` or `catch` for OOMs/VerificationErrors,
+ * but some places are definitely worth visiting.
+ */
+ minBound(expectedCoverage[projectName] ?: 85) // COVERED_LINES_PERCENTAGE
+ }
}
}
}
}
}
-koverReport {
- defaults {
- verify {
- rule {
- minBound(85) // COVERED_LINES_PERCENTAGE
+kover {
+ reports {
+ total {
+ verify {
+ rule {
+ minBound(85) // COVERED_LINES_PERCENTAGE
+ }
}
}
}
diff --git a/buildSrc/src/main/kotlin/pub-conventions.gradle.kts b/buildSrc/src/main/kotlin/pub-conventions.gradle.kts
new file mode 100644
index 0000000..4aa9999
--- /dev/null
+++ b/buildSrc/src/main/kotlin/pub-conventions.gradle.kts
@@ -0,0 +1,72 @@
+import org.gradle.kotlin.dsl.*
+
+/*
+ * For some absolutely cursed reason the name 'publication-conventions' doesn't work in my IDE.
+ * TODO: recheck after full repair
+ */
+plugins {
+ id("maven-publish")
+ id("signing")
+}
+
+apply(plugin = "maven-publish")
+apply(plugin = "signing")
+
+publishing {
+ repositories {
+ configureMavenPublication(this, project)
+ }
+
+ if (!isMultiplatform && !isBom) {
+ // Configure java publications for regular non-MPP modules
+ apply(plugin = "java-library")
+
+ // MPP projects pack their sources automatically, java libraries need to explicitly pack them
+ val sources = tasks.register("sourcesJar", Jar::class) {
+ archiveClassifier = "sources"
+ from(sourceSets.named("main").get().allSource)
+ }
+
+ publications {
+ register("mavenJava", MavenPublication::class) {
+ from(components["java"])
+ artifact(sources)
+ }
+ }
+ }
+
+ val emptyJavadoc = if (!isBom) registerEmptyJavadocArtifact() else null
+ publications.withType(MavenPublication::class).all {
+ pom.configureMavenCentralMetadata(project)
+ signPublicationIfKeyPresent(project, this)
+ if (!isBom && name != "kotlinMultiplatform") {
+ artifact(emptyJavadoc)
+ }
+
+ val type = name
+ when (type) {
+ "kotlinMultiplatform" -> {
+ // With Kotlin 1.4 & HMPP, the root module should have no suffix in the ID, but for compatibility with
+ // the consumers who can't read Gradle module metadata, we publish the JVM artifacts in it, too
+ artifactId = project.name
+ project.reconfigureMultiplatformPublication(publications.getByName("jvm") as MavenPublication)
+ }
+
+ "metadata", "jvm", "js", "native" -> {
+ artifactId = "${project.name}-$type"
+ }
+ }
+ }
+
+ project.establishSignDependencies()
+}
+
+
+// Legacy from https://github.com/Kotlin/kotlinx.coroutines/pull/2031
+// Should be fixed with the rest of the hacks around publication
+tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }.configureEach {
+ dependsOn(tasks.matching { it.name == "generatePomFileForJvmPublication" })
+}
+
+// Compatibility with old TeamCity configurations that perform :kotlinx-coroutines-core:bintrayUpload
+tasks.register("bintrayUpload") { dependsOn(tasks.matching { it.name == "publish" }) }
diff --git a/buildSrc/src/main/kotlin/source-set-conventions.gradle.kts b/buildSrc/src/main/kotlin/source-set-conventions.gradle.kts
new file mode 100644
index 0000000..b9b080f
--- /dev/null
+++ b/buildSrc/src/main/kotlin/source-set-conventions.gradle.kts
@@ -0,0 +1,9 @@
+import org.jetbrains.kotlin.gradle.dsl.*
+
+// Redefine source sets because we are not using 'kotlin/main/fqn' folder convention
+// TODO: port benchmarks to the same scheme
+configure(subprojects.filter { !sourceless.contains(it.name) && it.name != "benchmarks" }) {
+ kotlinExtension.sourceSets.forEach {
+ it.configureDirectoryPaths()
+ }
+}
diff --git a/buildSrc/src/main/kotlin/version-file-conventions.gradle.kts b/buildSrc/src/main/kotlin/version-file-conventions.gradle.kts
new file mode 100644
index 0000000..587e184
--- /dev/null
+++ b/buildSrc/src/main/kotlin/version-file-conventions.gradle.kts
@@ -0,0 +1,17 @@
+import org.gradle.api.tasks.bundling.*
+
+configure(subprojects.filter { !unpublished.contains(it.name) && it.name !in sourceless }) {
+ val project = this
+ val jarTaskName = when {
+ project.name == "kotlinx-coroutines-debug" -> {
+ project.apply(plugin = "com.github.johnrengelman.shadow")
+ "shadowJar"
+ }
+ isMultiplatform -> "jvmJar"
+ else -> "jar"
+ }
+ val versionFileTask = VersionFile.registerVersionFileTask(project)
+ tasks.withType(Jar::class.java).named(jarTaskName) {
+ VersionFile.fromVersionFile(this, versionFileTask)
+ }
+}
diff --git a/docs/knit.code.include b/docs/knit.code.include
index 42f2b50..8db8d74 100644
--- a/docs/knit.code.include
+++ b/docs/knit.code.include
@@ -1,6 +1,2 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from ${file.name} by Knit tool. Do not edit.
package ${knit.package}.${knit.name}
\ No newline at end of file
diff --git a/docs/knit.test.template b/docs/knit.test.template
index 727493c..b416374 100644
--- a/docs/knit.test.template
+++ b/docs/knit.test.template
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from ${file.name} by Knit tool. Do not edit.
package ${test.package}
diff --git a/docs/topics/channels.md b/docs/topics/channels.md
index 3b8b11f..6820f4c 100644
--- a/docs/topics/channels.md
+++ b/docs/topics/channels.md
@@ -19,7 +19,8 @@
//sampleStart
val channel = Channel<Int>()
launch {
- // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
+ // this might be heavy CPU-consuming computation or async logic,
+ // we'll just send five squares
for (x in 1..5) channel.send(x * x)
}
// here we print five received integers:
@@ -103,12 +104,12 @@
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+//sampleStart
fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
for (x in 1..5) send(x * x)
}
fun main() = runBlocking {
-//sampleStart
val squares = produceSquares()
squares.consumeEach { println(it) }
println("Done!")
@@ -575,25 +576,25 @@
//sampleStart
fun main() = runBlocking<Unit> {
- val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
+ val tickerChannel = ticker(delayMillis = 200, initialDelayMillis = 0) // create a ticker channel
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
println("Initial element is available immediately: $nextElement") // no initial delay
- nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
- println("Next element is not ready in 50 ms: $nextElement")
+ nextElement = withTimeoutOrNull(100) { tickerChannel.receive() } // all subsequent elements have 200ms delay
+ println("Next element is not ready in 100 ms: $nextElement")
- nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
- println("Next element is ready in 100 ms: $nextElement")
+ nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
+ println("Next element is ready in 200 ms: $nextElement")
// Emulate large consumption delays
- println("Consumer pauses for 150ms")
- delay(150)
+ println("Consumer pauses for 300ms")
+ delay(300)
// Next element is available immediately
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
println("Next element is available immediately after large consumer delay: $nextElement")
// Note that the pause between `receive` calls is taken into account and next element arrives faster
- nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
- println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
+ nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
+ println("Next element is ready in 100ms after consumer pause in 300ms: $nextElement")
tickerChannel.cancel() // indicate that no more elements are needed
}
@@ -609,11 +610,11 @@
```text
Initial element is available immediately: kotlin.Unit
-Next element is not ready in 50 ms: null
-Next element is ready in 100 ms: kotlin.Unit
-Consumer pauses for 150ms
+Next element is not ready in 100 ms: null
+Next element is ready in 200 ms: kotlin.Unit
+Consumer pauses for 300ms
Next element is available immediately after large consumer delay: kotlin.Unit
-Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
+Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit
```
<!--- TEST -->
diff --git a/docs/topics/composing-suspending-functions.md b/docs/topics/composing-suspending-functions.md
index 8ed7336..e1255c8 100644
--- a/docs/topics/composing-suspending-functions.md
+++ b/docs/topics/composing-suspending-functions.md
@@ -189,6 +189,12 @@
## Async-style functions
+> This programming style with async functions is provided here only for illustration, because it is a popular style
+> in other programming languages. Using this style with Kotlin coroutines is **strongly discouraged** for the
+> reasons explained below.
+>
+{type="note"}
+
We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
_asynchronously_ using the [async] coroutine builder using a [GlobalScope] reference to
opt-out of the structured concurrency.
@@ -275,12 +281,6 @@
Completed in 1085 ms
-->
-> This programming style with async functions is provided here only for illustration, because it is a popular style
-> in other programming languages. Using this style with Kotlin coroutines is **strongly discouraged** for the
-> reasons explained below.
->
-{type="note"}
-
Consider what happens if between the `val one = somethingUsefulOneAsync()` line and `one.await()` expression there is some logic
error in the code, and the program throws an exception, and the operation that was being performed by the program aborts.
Normally, a global error-handler could catch this exception, log and report the error for developers, but the program
diff --git a/docs/topics/coroutine-context-and-dispatchers.md b/docs/topics/coroutine-context-and-dispatchers.md
index 32d1891..ffbb364 100644
--- a/docs/topics/coroutine-context-and-dispatchers.md
+++ b/docs/topics/coroutine-context-and-dispatchers.md
@@ -227,7 +227,6 @@
fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
fun main() {
-//sampleStart
newSingleThreadContext("Ctx1").use { ctx1 ->
newSingleThreadContext("Ctx2").use { ctx2 ->
runBlocking(ctx1) {
@@ -239,10 +238,8 @@
}
}
}
-//sampleEnd
}
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt).
>
@@ -421,14 +418,14 @@
val v1 = async(CoroutineName("v1coroutine")) {
delay(500)
log("Computing v1")
- 252
+ 6
}
val v2 = async(CoroutineName("v2coroutine")) {
delay(1000)
log("Computing v2")
- 6
+ 7
}
- log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
+ log("The answer for v1 * v2 = ${v1.await() * v2.await()}")
//sampleEnd
}
```
@@ -444,7 +441,7 @@
[main @main#1] Started main coroutine
[main @v1coroutine#2] Computing v1
[main @v2coroutine#3] Computing v2
-[main @main#1] The answer for v1 / v2 = 42
+[main @main#1] The answer for v1 * v2 = 42
```
<!--- TEST FLEXIBLE_THREAD -->
@@ -505,7 +502,7 @@
// to be continued ...
```
-Now, we can launch coroutines in the scope of this `Activity` using the defined `scope`.
+Now, we can launch coroutines in the scope of this `Activity` using the defined `mainScope`.
For the demo, we launch ten coroutines that delay for a different time:
```kotlin
diff --git a/docs/topics/coroutines-and-channels.md b/docs/topics/coroutines-and-channels.md
index b60d898..e3cb7e5 100644
--- a/docs/topics/coroutines-and-channels.md
+++ b/docs/topics/coroutines-and-channels.md
@@ -91,7 +91,10 @@
1. Open `src/tasks/Request1Blocking.kt` to see its implementation:
```kotlin
- fun loadContributorsBlocking(service: GitHubService, req: RequestData): List<User> {
+ fun loadContributorsBlocking(
+ service: GitHubService,
+ req: RequestData
+ ): List<User> {
val repos = service
.getOrgReposCall(req.org) // #1
.execute() // #2
@@ -328,7 +331,8 @@
* The logic for handling the responses is extracted into callbacks: the corresponding lambdas start at lines `#1` and `#2`.
However, the provided solution doesn't work. If you run the program and load contributors by choosing the _CALLBACKS_
-option, you'll see that nothing is shown. However, the tests that immediately return the result pass.
+option, you'll see that nothing is shown. However, the test from `Request3CallbacksKtTest` immediately returns the result
+that it successfully passed.
Think about why the given code doesn't work as expected and try to fix it, or see the solutions below.
@@ -1206,8 +1210,8 @@
<def title="Rendezvous channel">
<p>The "Rendezvous" channel is a channel without a buffer, the same as a buffered channel with zero size.
One of the functions (<code>send()</code> or <code>receive()</code>) is always suspended until the other is called. </p>
- <p>If the <code>send()</code> function is called and there's no suspended <code>receive</code> call ready to process the element, then <code>send()</code>
-is suspended. Similarly, if the <code>receive</code> function is called and the channel is empty or, in other words, there's no
+ <p>If the <code>send()</code> function is called and there's no suspended <code>receive()</code> call ready to process the element, then <code>send()</code>
+is suspended. Similarly, if the <code>receive()</code> function is called and the channel is empty or, in other words, there's no
suspended <code>send()</code> call ready to send the element, the <code>receive()</code> call is suspended. </p>
<p>The "rendezvous" name ("a meeting at an agreed time and place") refers to the fact that <code>send()</code> and <code>receive()</code>
should "meet on time".</p>
diff --git a/docs/topics/coroutines-basics.md b/docs/topics/coroutines-basics.md
index d7d6700..8a5b430 100644
--- a/docs/topics/coroutines-basics.md
+++ b/docs/topics/coroutines-basics.md
@@ -6,7 +6,7 @@
## Your first coroutine
-A _coroutine_ is an instance of suspendable computation. It is conceptually similar to a thread, in the sense that it
+A _coroutine_ is an instance of a suspendable computation. It is conceptually similar to a thread, in the sense that it
takes a block of code to run that works concurrently with the rest of the code.
However, a coroutine is not bound to any particular thread. It may suspend its execution in one thread and resume in another one.
diff --git a/docs/topics/exception-handling.md b/docs/topics/exception-handling.md
index 8bf8c10..f79740c 100644
--- a/docs/topics/exception-handling.md
+++ b/docs/topics/exception-handling.md
@@ -9,7 +9,7 @@
## Exception propagation
-Coroutine builders come in two flavors: propagating exceptions automatically ([launch] and [actor]) or
+Coroutine builders come in two flavors: propagating exceptions automatically ([launch]) or
exposing them to users ([async] and [produce]).
When these builders are used to create a _root_ coroutine, that is not a _child_ of another coroutine,
the former builders treat exceptions as **uncaught** exceptions, similar to Java's `Thread.uncaughtExceptionHandler`,
@@ -60,7 +60,7 @@
```text
Throwing exception from launch
-Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
+Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IndexOutOfBoundsException
Joined failed job
Throwing exception from async
Caught ArithmeticException
@@ -73,7 +73,7 @@
It is possible to customize the default behavior of printing **uncaught** exceptions to the console.
[CoroutineExceptionHandler] context element on a _root_ coroutine can be used as a generic `catch` block for
this root coroutine and all its children where custom exception handling may take place.
-It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
+It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler-java.lang.Thread.UncaughtExceptionHandler-).
You cannot recover from the exception in the `CoroutineExceptionHandler`. The coroutine had already completed
with the corresponding exception when the handler is called. Normally, the handler is used to
log the exception, show some kind of error message, terminate, and/or restart the application.
@@ -276,10 +276,6 @@
>
{type="note"}
-> Note: This above code will work properly only on JDK7+ that supports `suppressed` exceptions
->
-{type="note"}
-
The output of this code is:
```text
@@ -306,7 +302,7 @@
println("CoroutineExceptionHandler got $exception")
}
val job = GlobalScope.launch(handler) {
- val inner = launch { // all this stack of coroutines will get cancelled
+ val innerJob = launch { // all this stack of coroutines will get cancelled
launch {
launch {
throw IOException() // the original exception
@@ -314,7 +310,7 @@
}
}
try {
- inner.join()
+ innerJob.join()
} catch (e: CancellationException) {
println("Rethrowing CancellationException with original cause")
throw e // cancellation exception is rethrown, yet the original IOException gets to the handler
@@ -523,7 +519,6 @@
<!--- INDEX kotlinx.coroutines.channels -->
-[actor]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
[produce]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
[ReceiveChannel.receive]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
diff --git a/docs/topics/knit.properties b/docs/topics/knit.properties
index 562b412..f71ccf2 100644
--- a/docs/topics/knit.properties
+++ b/docs/topics/knit.properties
@@ -1,7 +1,3 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
knit.package=kotlinx.coroutines.guide
knit.dir=../../kotlinx-coroutines-core/jvm/test/guide/
diff --git a/gradle.properties b/gradle.properties
index 9e6dc02..59063db 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,50 +1,42 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
# Kotlin
-version=1.7.2-SNAPSHOT
+version=1.8.1-SNAPSHOT
group=org.jetbrains.kotlinx
-kotlin_version=1.8.20
+kotlin_version=1.9.21
+# DO NOT rename this property without adapting kotlinx.train build chain:
+atomicfu_version=0.23.1
# Dependencies
junit_version=4.12
junit5_version=5.7.0
-atomicfu_version=0.21.0
-knit_version=0.4.0
+knit_version=0.5.0
html_version=0.7.2
lincheck_version=2.18.1
-dokka_version=1.8.10
+dokka_version=1.9.20
byte_buddy_version=1.10.9
reactor_version=3.4.1
+reactor_docs_version=3.4.5
reactive_streams_version=1.0.3
rxjava2_version=2.2.8
rxjava3_version=3.0.2
javafx_version=17.0.2
javafx_plugin_version=0.0.8
binary_compatibility_validator_version=0.13.2
-kover_version=0.7.0-Beta
+kover_version=0.8.0-Beta
blockhound_version=1.0.8.RELEASE
jna_version=5.9.0
+# Gradle
+jdk_toolchain_version=11
+animalsniffer_version=1.7.1
+shadow_version=7.1.2
+#shadow_version=8.1.1 For Gradle 8, not compatible with Gradle 7
+
# Android versions
android_version=4.1.1.4
androidx_annotation_version=1.1.0
robolectric_version=4.9
baksmali_version=2.2.7
-# JS
-kotlin.js.compiler=both
-gradle_node_version=3.1.1
-node_version=10.0.0
-npm_version=5.7.1
-mocha_version=6.2.2
-mocha_headless_chrome_version=1.8.2
-mocha_teamcity_reporter_version=3.0.0
-source_map_support_version=0.5.16
-jsdom_version=15.2.1
-jsdom_global_version=3.0.2
-
# Settings
kotlin.incremental.multiplatform=true
kotlin.native.ignoreDisabledTargets=true
@@ -53,9 +45,9 @@
# TODO: Remove once KT-37187 is fixed
org.gradle.jvmargs=-Xmx3g
-kotlin.mpp.enableCompatibilityMetadataVariant=true
kotlin.mpp.stability.nowarn=true
kotlinx.atomicfu.enableJvmIrTransformation=true
# When the flag below is set to `true`, AtomicFU cannot process
# usages of `moveForward` in `ConcurrentLinkedList.kt` correctly.
kotlinx.atomicfu.enableJsIrTransformation=false
+kotlinx.atomicfu.enableNativeIrTransformation=true
diff --git a/gradle/compile-common.gradle b/gradle/compile-common.gradle
deleted file mode 100644
index 6c3777b..0000000
--- a/gradle/compile-common.gradle
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-kotlin.sourceSets {
- commonTest.dependencies {
- api "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
- api "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
- }
-}
-
-
-kotlin.sourceSets.matching({ it.name.contains("Main") }).all { srcSet ->
- project.ext.set("kotlin.mpp.freeCompilerArgsForSourceSet.${srcSet.name}", "-Xexplicit-api=strict")
-}
diff --git a/gradle/compile-js-multiplatform.gradle b/gradle/compile-js-multiplatform.gradle
deleted file mode 100644
index c6fc757..0000000
--- a/gradle/compile-js-multiplatform.gradle
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-apply from: rootProject.file('gradle/node-js.gradle')
-
-kotlin {
- js {
- moduleName = project.name
-
- // In 1.4.x it has in `both` and `legacy` mode and js() is of type `KotlinJsTarget`
- // `irTarget` is non-null in `both` mode
- // and contains appropriate `irTarget` with type `KotlinJsIrTarget`
- // `irTarget` is null in `legacy` mode
- if (it.irTarget != null) {
- irTarget.nodejs()
- irTarget.compilations['main']?.dependencies {
- api "org.jetbrains.kotlinx:atomicfu-js:$atomicfu_version"
- }
- }
- }
-
- sourceSets {
- jsTest.dependencies {
- api "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
- }
- }
-}
-
-// When source sets are configured
-apply from: rootProject.file('gradle/test-mocha-js.gradle')
-
-def compileJsLegacy = tasks.hasProperty("compileKotlinJsLegacy")
- ? compileKotlinJsLegacy
- : compileKotlinJs
-
-def compileTestJsLegacy = tasks.hasProperty("compileTestKotlinJsLegacy")
- ? compileTestKotlinJsLegacy
- : compileTestKotlinJs
-
-compileJsLegacy.configure {
- kotlinOptions.metaInfo = true
- kotlinOptions.sourceMap = true
- kotlinOptions.moduleKind = 'umd'
-
- kotlinOptions {
- // drop -js suffix from outputFile
- def baseName = project.name - "-js"
- outputFile = new File(outputFileProperty.get().parent, baseName + ".js")
- }
-}
-
-compileTestJsLegacy.configure {
- kotlinOptions.metaInfo = true
- kotlinOptions.sourceMap = true
- kotlinOptions.moduleKind = 'umd'
-}
-
-
-task populateNodeModules(type: Copy, dependsOn: compileTestJsLegacy) {
- // we must copy output that is transformed by atomicfu
- from(kotlin.js().compilations.main.output.allOutputs)
- into node.nodeProjectDir.dir("node_modules")
-
- def configuration = configurations.hasProperty("jsLegacyTestRuntimeClasspath")
- ? configurations.jsLegacyTestRuntimeClasspath
- : configurations.jsTestRuntimeClasspath
-
- from(files {
- configuration.collect { File file ->
- file.name.endsWith(".jar") ?
- zipTree(file.absolutePath).matching {
- include '*.js'
- include '*.js.map'
- } : files()
- }
- }.builtBy(configuration))
-}
-
-npmInstall.dependsOn populateNodeModules
diff --git a/gradle/compile-jvm-multiplatform.gradle b/gradle/compile-jvm-multiplatform.gradle
deleted file mode 100644
index cb8325c..0000000
--- a/gradle/compile-jvm-multiplatform.gradle
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-sourceCompatibility = 1.8
-targetCompatibility = 1.8
-
-kotlin {
- jvm {}
- sourceSets {
- jvmMain.dependencies {
- compileOnly "org.codehaus.mojo:animal-sniffer-annotations:1.20"
- // Workaround until https://github.com/JetBrains/kotlin/pull/4999 is picked up
- api "org.jetbrains:annotations:23.0.0"
- }
-
- jvmTest.dependencies {
- api "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
- // Workaround to make addSuppressed work in tests
- api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
- api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- api "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
- api "junit:junit:$junit_version"
- }
- }
-}
-
-jvmTest {
- testLogging {
- showStandardStreams = true
- events "passed", "failed"
- }
- def stressTest = project.properties['stressTest']
- if (stressTest != null) systemProperties['stressTest'] = stressTest
-}
diff --git a/gradle/compile-native-multiplatform.gradle b/gradle/compile-native-multiplatform.gradle
deleted file mode 100644
index 3b27588..0000000
--- a/gradle/compile-native-multiplatform.gradle
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-project.ext.nativeMainSets = []
-project.ext.nativeTestSets = []
-
-kotlin {
- targets {
- delegate.metaClass.addTarget = { preset ->
- def target = delegate.fromPreset(preset, preset.name)
- project.ext.nativeMainSets.add(target.compilations['main'].kotlinSourceSets.first())
- project.ext.nativeTestSets.add(target.compilations['test'].kotlinSourceSets.first())
- }
- }
-
- targets {
- // According to https://kotlinlang.org/docs/native-target-support.html
- // Tier 1
- addTarget(presets.linuxX64)
- addTarget(presets.macosX64)
- addTarget(presets.macosArm64)
- addTarget(presets.iosSimulatorArm64)
- addTarget(presets.iosX64)
-
- // Tier 2
- addTarget(presets.linuxArm64)
- addTarget(presets.watchosSimulatorArm64)
- addTarget(presets.watchosX64)
- addTarget(presets.watchosArm32)
- addTarget(presets.watchosArm64)
- addTarget(presets.tvosSimulatorArm64)
- addTarget(presets.tvosX64)
- addTarget(presets.tvosArm64)
- addTarget(presets.iosArm64)
-
- // Tier 3
- addTarget(presets.androidNativeArm32)
- addTarget(presets.androidNativeArm64)
- addTarget(presets.androidNativeX86)
- addTarget(presets.androidNativeX64)
- addTarget(presets.mingwX64)
- addTarget(presets.watchosDeviceArm64)
-
- // Deprecated, but were provided by coroutine; can be removed only when K/N drops the target
- addTarget(presets.iosArm32)
- addTarget(presets.watchosX86)
- }
-
- sourceSets {
- nativeMain { dependsOn commonMain }
- nativeTest { dependsOn commonTest }
-
- configure(nativeMainSets) { dependsOn nativeMain }
- configure(nativeTestSets) { dependsOn nativeTest }
- }
-}
diff --git a/gradle/dokka.gradle.kts b/gradle/dokka.gradle.kts
deleted file mode 100644
index ba6956a..0000000
--- a/gradle/dokka.gradle.kts
+++ /dev/null
@@ -1,69 +0,0 @@
-import org.jetbrains.dokka.gradle.*
-import java.net.*
-
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-// Configures generation of JavaDoc & Dokka artifacts
-apply<DokkaPlugin>()
-//apply<JavaPlugin>()
-
-fun GradleDokkaSourceSetBuilder.makeLinkMapping(projectDir: File) {
- sourceLink {
- val relPath = rootProject.projectDir.toPath().relativize(projectDir.toPath())
- localDirectory.set(projectDir.resolve("src"))
- remoteUrl.set(URL("https://github.com/kotlin/kotlinx.coroutines/tree/master/$relPath/src"))
- remoteLineSuffix.set("#L")
- }
-}
-
-val knit_version: String by project
-tasks.withType(DokkaTaskPartial::class).configureEach {
- dependencies {
- plugins("org.jetbrains.kotlinx:dokka-pathsaver-plugin:$knit_version")
- }
-}
-
-tasks.withType(DokkaTaskPartial::class).configureEach {
- suppressInheritedMembers.set(true)
- pluginsMapConfiguration.set(mapOf("org.jetbrains.dokka.base.DokkaBase" to """{ "templatesDir" : "${rootProject.projectDir.toString().replace('\\', '/')}/dokka-templates" }"""))
-
- dokkaSourceSets.configureEach {
- jdkVersion.set(11)
- includes.from("README.md")
- noStdlibLink.set(true)
-
- externalDocumentationLink {
- url.set(URL("https://kotlinlang.org/api/latest/jvm/stdlib/"))
- packageListUrl.set(rootProject.projectDir.toPath().resolve("site/stdlib.package.list").toUri().toURL())
- }
-
- if (!project.isMultiplatform) {
- dependsOn(project.configurations["compileClasspath"])
- }
- }
-}
-
-if (project.name == "kotlinx-coroutines-core") {
- // Custom configuration for MPP modules
- tasks.withType(DokkaTaskPartial::class).configureEach {
- dokkaSourceSets {
- val commonMain by getting {
- makeLinkMapping(project.file("common"))
- }
-
- val nativeMain by getting {
- makeLinkMapping(project.file("native"))
- }
-
- val jsMain by getting {
- makeLinkMapping(project.file("js"))
- }
-
- val jvmMain by getting {
- makeLinkMapping(project.file("jvm"))
- }
- }
- }
-}
diff --git a/gradle/node-js.gradle b/gradle/node-js.gradle
deleted file mode 100644
index 5eddc5f..0000000
--- a/gradle/node-js.gradle
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-apply plugin: 'com.github.node-gradle.node'
-
-node {
- version = "$node_version"
- npmVersion = "$npm_version"
- download = true
- nodeProjectDir = file(buildDir)
-}
-
-// Configures testing for JS modules
-
-task prepareNodePackage(type: Copy) {
- from("npm") {
- include 'package.json'
- // Postpone expansion of package.json until we configure version property in build.gradle
- def copySpec = it
- afterEvaluate {
- copySpec.expand(project.properties + [kotlinDependency: ""])
- }
- }
- from("npm") {
- exclude 'package.json'
- }
- into node.nodeProjectDir
-}
-
-npmInstall.dependsOn prepareNodePackage
-
-// Workaround the problem with Node downloading
-repositories.whenObjectAdded {
- if (it instanceof IvyArtifactRepository) {
- metadataSources {
- artifact()
- }
- }
-}
diff --git a/gradle/publish-mpp-root-module-in-platform.gradle b/gradle/publish-mpp-root-module-in-platform.gradle
deleted file mode 100644
index 8036bea..0000000
--- a/gradle/publish-mpp-root-module-in-platform.gradle
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-
-/** Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module
- metadata can still get the platform artifact and transitive dependencies from the POM: */
-project.ext.publishPlatformArtifactsInRootModule = { MavenPublication platformPublication ->
-
- XmlProvider platformXml = null
-
- platformPublication.pom.withXml { platformXml = it }
-
- publishing.publications.kotlinMultiplatform {
- pom.withXml {
- Node root = asNode()
- // Remove the original content and add the content from the platform POM:
- root.children().toList().each { root.remove(it as Node) }
- platformXml.asNode().children().each { root.append(it as Node) }
-
- // Adjust the self artifact ID, as it should match the root module's coordinates:
- ((root.get("artifactId") as NodeList).get(0) as Node).setValue(artifactId)
-
- // Set packaging to POM to indicate that there's no artifact:
- root.appendNode("packaging", "pom")
-
- // Remove the original platform dependencies and add a single dependency on the platform module:
- Node dependencies = (root.get("dependencies") as NodeList).get(0) as Node
- dependencies.children().toList().each { dependencies.remove(it as Node) }
- Node singleDependency = dependencies.appendNode("dependency")
- singleDependency.appendNode("groupId", platformPublication.groupId)
- singleDependency.appendNode("artifactId", platformPublication.artifactId)
- singleDependency.appendNode("version", platformPublication.version)
- singleDependency.appendNode("scope", "compile")
- }
- }
-
- tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }.configureEach {
- dependsOn(tasks["generatePomFileFor${platformPublication.name.capitalize()}Publication"])
- }
-
-}
diff --git a/gradle/publish-npm-js.gradle b/gradle/publish-npm-js.gradle
deleted file mode 100644
index 9d41527..0000000
--- a/gradle/publish-npm-js.gradle
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-def prop(name, defVal) {
- def value = project.properties[name]
- if (value == null) return defVal
- return value
-}
-
-def distTag(version) {
- def i = version.indexOf('-')
- if (i > 0) return version.substring(i + 1)
- return "latest"
-}
-
-def npmTemplateDir = file("$projectDir/npm")
-def npmDeployDir = file("$buildDir/npm")
-
-def authToken = prop("kotlin.npmjs.auth.token", "")
-def dryRun = prop("dryRun", "false")
-
-def jsLegacy = kotlin.targets.hasProperty("jsLegacy")
- ? kotlin.targets.jsLegacy
- : kotlin.targets.js
-
-// Note: publish transformed files using dependency on sourceSets.main.output
-task preparePublishNpm(type: Copy) {
- from(npmTemplateDir) {
- // Postpone expansion of package.json until we configure version property in build.gradle
- def copySpec = it
- afterEvaluate {
- copySpec.expand(project.properties + [kotlinDependency: "\"kotlin\": \"$kotlin_version\""])
- }
- }
- // we must publish output that is transformed by atomicfu
- from(jsLegacy.compilations.main.output.allOutputs)
- into npmDeployDir
-}
-
-task publishNpm(type: NpmTask, dependsOn: [preparePublishNpm]) {
- workingDir = npmDeployDir
-
- def npmDeployTag = distTag(version)
- def deployArgs = ['publish',
- "--//registry.npmjs.org/:_authToken=$authToken",
- "--tag=$npmDeployTag"]
- if (dryRun == "true") {
- println("$npmDeployDir \$ npm arguments: $deployArgs")
- args = ['pack']
- } else {
- args = deployArgs
- }
-}
diff --git a/gradle/publish.gradle b/gradle/publish.gradle
deleted file mode 100644
index f3b1561..0000000
--- a/gradle/publish.gradle
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-import org.gradle.util.VersionNumber
-
-// Configures publishing of Maven artifacts to Maven Central
-
-apply plugin: 'maven-publish'
-apply plugin: 'signing'
-
-// ------------- tasks
-
-def isMultiplatform = project.name == "kotlinx-coroutines-core" || project.name == "kotlinx-coroutines-test"
-def isBom = project.name == "kotlinx-coroutines-bom"
-
-if (!isBom) {
- if (project.name == "kotlinx-coroutines-debug") {
- apply plugin: "com.github.johnrengelman.shadow"
- }
-
- // empty xxx-javadoc.jar
- task javadocJar(type: Jar) {
- archiveClassifier = 'javadoc'
- }
-}
-
-if (!isMultiplatform && !isBom) {
- // Regular java modules need 'java-library' plugin for proper publication
- apply plugin: 'java-library'
-
- // MPP projects pack their sources automatically, java libraries need to explicitly pack them
- task sourcesJar(type: Jar) {
- archiveClassifier = 'sources'
- from sourceSets.main.allSource
- }
-}
-
-publishing {
- repositories {
- PublishingKt.configureMavenPublication(delegate, project)
- }
-
- if (!isMultiplatform && !isBom) {
- // Configure java publications for regular non-MPP modules
- publications {
- maven(MavenPublication) {
- from components.java
- artifact sourcesJar
- }
- }
- }
-
- publications.all {
- PublishingKt.configureMavenCentralMetadata(pom, project)
- PublishingKt.signPublicationIfKeyPresent(project, it)
- // add empty javadocs
- if (!isBom && it.name != "kotlinMultiplatform") {
- it.artifact(javadocJar)
- }
-
- def type = it.name
- switch (type) {
- case 'kotlinMultiplatform':
- // With Kotlin 1.4 & HMPP, the root module should have no suffix in the ID, but for compatibility with
- // the consumers who can't read Gradle module metadata, we publish the JVM artifacts in it, too
- it.artifactId = project.name
- apply from: "$rootDir/gradle/publish-mpp-root-module-in-platform.gradle"
- publishPlatformArtifactsInRootModule(publications["jvm"])
- break
- case 'metadata':
- case 'jvm':
- case 'js':
- case 'native':
- it.artifactId = "$project.name-$type"
- break
- }
- }
-}
-
-tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication"}.configureEach {
- dependsOn(tasks["generatePomFileForJvmPublication"])
-}
-
-// Compatibility with old TeamCity configurations that perform :kotlinx-coroutines-core:bintrayUpload
-task bintrayUpload(dependsOn: publish)
diff --git a/gradle/test-mocha-js.gradle b/gradle/test-mocha-js.gradle
deleted file mode 100644
index 1ec297e..0000000
--- a/gradle/test-mocha-js.gradle
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-// -- Testing with Mocha under Node
-
-task installDependenciesMochaNode(type: NpmTask, dependsOn: [npmInstall]) {
- args = ['install',
- "mocha@$mocha_version",
- "source-map-support@$source_map_support_version",
- '--no-save']
- if (project.hasProperty("teamcity")) args.addAll(["mocha-teamcity-reporter@$mocha_teamcity_reporter_version"])
-}
-
-def compileJsLegacy = tasks.hasProperty("compileKotlinJsLegacy")
- ? compileKotlinJsLegacy
- : compileKotlinJs
-
-def compileTestJsLegacy = tasks.hasProperty("compileTestKotlinJsLegacy")
- ? compileTestKotlinJsLegacy
- : compileTestKotlinJs
-
-// todo: use atomicfu-transformed test files here (not critical)
-task testMochaNode(type: NodeTask, dependsOn: [compileTestJsLegacy, installDependenciesMochaNode]) {
- script = file("${node.nodeProjectDir.getAsFile().get()}/node_modules/mocha/bin/mocha")
- args = [compileTestJsLegacy.outputFileProperty.get().path, '--require', 'source-map-support/register']
- if (project.hasProperty("teamcity")) args.addAll(['--reporter', 'mocha-teamcity-reporter'])
-}
-
-def jsLegacyTestTask = project.tasks.findByName('jsLegacyTest') ? jsLegacyTest : jsTest
-
-// TODO
-//jsLegacyTestTask.dependsOn testMochaNode
-
-// -- Testing with Mocha under headless Chrome
-
-task installDependenciesMochaChrome(type: NpmTask, dependsOn: [npmInstall]) {
- args = ['install',
- "mocha@$mocha_version",
- "mocha-headless-chrome@$mocha_headless_chrome_version",
- "kotlin@$kotlin_version",
- "kotlin-test@$kotlin_version",
- '--no-save']
- if (project.hasProperty("teamcity")) args.addAll([
- "mocha-teamcity-reporter@$mocha_teamcity_reporter_version"])
-}
-
-def mochaChromeTestPage = file("$buildDir/test-page.html")
-
-task prepareMochaChrome(dependsOn: [compileTestJsLegacy, installDependenciesMochaChrome]) {
- outputs.file(mochaChromeTestPage)
-}
-
-prepareMochaChrome.doLast {
- def nodeProjDir = node.nodeProjectDir.getAsFile().get()
- mochaChromeTestPage.text = """<!DOCTYPE html>
- <html>
- <head>
- <title>Mocha Tests</title>
- <meta charset="utf-8">
- <link rel="stylesheet" href="$nodeProjDir/node_modules/mocha/mocha.css">
- </head>
- <body>
- <div id="mocha"></div>
- <script src="$nodeProjDir/node_modules/mocha/mocha.js"></script>
- <script>mocha.setup('bdd');</script>
- <script src="$nodeProjDir/node_modules/kotlin/kotlin.js"></script>
- <script src="$nodeProjDir/node_modules/kotlin-test/kotlin-test.js"></script>
- <script src="${compileJsLegacy.outputFileProperty.get().path}"></script>
- <script src="${compileTestJsLegacy.outputFileProperty.get().path}"></script>
- <script>mocha.run();</script>
- </body>
- </html>
- """
-}
-
-task testMochaChrome(type: NodeTask, dependsOn: prepareMochaChrome) {
- script = file("${node.nodeProjectDir.getAsFile().get()}/node_modules/mocha-headless-chrome/bin/start")
- args = [compileTestJsLegacy.outputFileProperty.get().path, '--file', mochaChromeTestPage]
- if (project.hasProperty("teamcity")) args.addAll(['--reporter', 'mocha-teamcity-reporter'])
-}
-
-// todo: Commented out because mocha-headless-chrome does not work on TeamCity
-//jsTest.dependsOn testMochaChrome
-
-// -- Testing with Mocha under jsdom
-
-task installDependenciesMochaJsdom(type: NpmTask, dependsOn: [npmInstall]) {
- args = ['install',
- "mocha@$mocha_version",
- "jsdom@$jsdom_version",
- "jsdom-global@$jsdom_global_version",
- "source-map-support@$source_map_support_version",
- '--no-save']
- if (project.hasProperty("teamcity")) args.addAll(["mocha-teamcity-reporter@$mocha_teamcity_reporter_version"])
-}
-
-task testMochaJsdom(type: NodeTask, dependsOn: [compileTestJsLegacy, installDependenciesMochaJsdom]) {
- script = file("${node.nodeProjectDir.getAsFile().get()}/node_modules/mocha/bin/mocha")
- args = [compileTestJsLegacy.outputFileProperty.get().path, '--require', 'source-map-support/register', '--require', 'jsdom-global/register']
- if (project.hasProperty("teamcity")) args.addAll(['--reporter', 'mocha-teamcity-reporter'])
-}
-
-// TODO
-//jsLegacyTestTask.dependsOn testMochaJsdom
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e708b1c..d64cd49 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index f57489c..e6aba25 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,9 +1,7 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index ea79e0a..1aa94a4 100755
--- a/gradlew
+++ b/gradlew
@@ -1,71 +1,115 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -75,9 +119,9 @@
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -86,88 +130,120 @@
location of your Java installation."
fi
else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index 107acd3..6689b85 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,89 +1,92 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-testing/build.gradle b/integration-testing/build.gradle
index 26ee9d9..64301dd 100644
--- a/integration-testing/build.gradle
+++ b/integration-testing/build.gradle
@@ -1,8 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-
buildscript {
/*
@@ -179,3 +174,8 @@
jvmTarget = "1.8"
}
}
+
+// Drop this when node js version become stable
+tasks.withType(org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask.class).configureEach {
+ it.args.add("--ignore-engines")
+}
diff --git a/integration-testing/gradle.properties b/integration-testing/gradle.properties
index 30b2b5e..af5497e 100644
--- a/integration-testing/gradle.properties
+++ b/integration-testing/gradle.properties
@@ -1,5 +1,5 @@
-kotlin_version=1.8.20
-coroutines_version=1.7.2-SNAPSHOT
+kotlin_version=1.9.21
+coroutines_version=1.8.1-SNAPSHOT
asm_version=9.3
kotlin.code.style=official
diff --git a/integration-testing/smokeTest/build.gradle b/integration-testing/smokeTest/build.gradle
index 26cd02b..16c8663 100644
--- a/integration-testing/smokeTest/build.gradle
+++ b/integration-testing/smokeTest/build.gradle
@@ -3,10 +3,10 @@
}
repositories {
- // Coroutines from the outer project are published by previous CI buils step
- mavenLocal()
mavenCentral()
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
+ // Coroutines from the outer project are published by previous CI buils step
+ mavenLocal()
}
kotlin {
@@ -14,6 +14,15 @@
js(IR) {
nodejs()
}
+ wasmJs() {
+ nodejs()
+ }
+
+ macosArm64()
+ macosX64()
+ linuxArm64()
+ linuxX64()
+ mingwX64()
sourceSets {
commonMain {
@@ -34,6 +43,11 @@
implementation kotlin('test-js')
}
}
+ wasmJsTest {
+ dependencies {
+ implementation kotlin('test-wasm-js')
+ }
+ }
jvmTest {
dependencies {
implementation kotlin('test')
@@ -50,3 +64,11 @@
}
}
+// Drop this configuration when the Node.JS version in KGP will support wasm gc milestone 4
+// check it here:
+// https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt
+rootProject.extensions.findByType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension.class).with {
+ // canary nodejs that supports recent Wasm GC changes
+ it.nodeVersion = "21.0.0-v8-canary202309167e82ab1fa2"
+ it.nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary"
+}
\ No newline at end of file
diff --git a/integration-testing/smokeTest/src/commonTest/kotlin/SampleTest.kt b/integration-testing/smokeTest/src/commonTest/kotlin/SampleTest.kt
index a8c6598..98366d8 100644
--- a/integration-testing/smokeTest/src/commonTest/kotlin/SampleTest.kt
+++ b/integration-testing/smokeTest/src/commonTest/kotlin/SampleTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import kotlinx.coroutines.test.*
import kotlin.test.*
diff --git a/integration-testing/src/coreAgentTest/kotlin/CoreAgentTest.kt b/integration-testing/src/coreAgentTest/kotlin/CoreAgentTest.kt
index 359338b..3b4dc34 100644
--- a/integration-testing/src/coreAgentTest/kotlin/CoreAgentTest.kt
+++ b/integration-testing/src/coreAgentTest/kotlin/CoreAgentTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
import org.junit.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
diff --git a/integration-testing/src/debugAgentTest/kotlin/DebugAgentTest.kt b/integration-testing/src/debugAgentTest/kotlin/DebugAgentTest.kt
index 779cd5b..111d4c7 100644
--- a/integration-testing/src/debugAgentTest/kotlin/DebugAgentTest.kt
+++ b/integration-testing/src/debugAgentTest/kotlin/DebugAgentTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
import org.junit.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.*
diff --git a/integration-testing/src/debugAgentTest/kotlin/DebugProbes.kt b/integration-testing/src/debugAgentTest/kotlin/DebugProbes.kt
index 8174156..849d4d4 100644
--- a/integration-testing/src/debugAgentTest/kotlin/DebugProbes.kt
+++ b/integration-testing/src/debugAgentTest/kotlin/DebugProbes.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package kotlin.coroutines.jvm.internal
diff --git a/integration-testing/src/debugAgentTest/kotlin/PrecompiledDebugProbesTest.kt b/integration-testing/src/debugAgentTest/kotlin/PrecompiledDebugProbesTest.kt
index ab207e0..2a63dff 100644
--- a/integration-testing/src/debugAgentTest/kotlin/PrecompiledDebugProbesTest.kt
+++ b/integration-testing/src/debugAgentTest/kotlin/PrecompiledDebugProbesTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
import org.junit.Test
import java.io.*
import kotlin.test.*
diff --git a/integration-testing/src/debugDynamicAgentTest/kotlin/DynamicAttachDebugTest.kt b/integration-testing/src/debugDynamicAgentTest/kotlin/DynamicAttachDebugTest.kt
index ff9cac8..0469519 100644
--- a/integration-testing/src/debugDynamicAgentTest/kotlin/DynamicAttachDebugTest.kt
+++ b/integration-testing/src/debugDynamicAgentTest/kotlin/DynamicAttachDebugTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
import org.junit.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.*
diff --git a/integration-testing/src/jvmCoreTest/kotlin/Jdk8InCoreIntegration.kt b/integration-testing/src/jvmCoreTest/kotlin/Jdk8InCoreIntegration.kt
index 91eef7e..a733f06 100644
--- a/integration-testing/src/jvmCoreTest/kotlin/Jdk8InCoreIntegration.kt
+++ b/integration-testing/src/jvmCoreTest/kotlin/Jdk8InCoreIntegration.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
import kotlinx.coroutines.future.*
diff --git a/integration-testing/src/jvmCoreTest/kotlin/ListAllCoroutineThrowableSubclassesTest.kt b/integration-testing/src/jvmCoreTest/kotlin/ListAllCoroutineThrowableSubclassesTest.kt
index 7253658..5c564c8 100644
--- a/integration-testing/src/jvmCoreTest/kotlin/ListAllCoroutineThrowableSubclassesTest.kt
+++ b/integration-testing/src/jvmCoreTest/kotlin/ListAllCoroutineThrowableSubclassesTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import com.google.common.reflect.*
diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt
index 13bac01..a1449c1 100644
--- a/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt
+++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.validator
import org.junit.Test
diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationMetaInfValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationMetaInfValidator.kt
index 8ed2b82..6033686 100644
--- a/integration-testing/src/mavenTest/kotlin/MavenPublicationMetaInfValidator.kt
+++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationMetaInfValidator.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.validator
import org.junit.Test
diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt
index 11529d2..0728c41 100644
--- a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt
+++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.validator
import org.junit.Test
diff --git a/integration/kotlinx-coroutines-guava/build.gradle.kts b/integration/kotlinx-coroutines-guava/build.gradle.kts
index 2a84ca9..72f34e9 100644
--- a/integration/kotlinx-coroutines-guava/build.gradle.kts
+++ b/integration/kotlinx-coroutines-guava/build.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
val guavaVersion = "31.0.1-jre"
dependencies {
diff --git a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt
index 0820f1f..fdf24bc 100644
--- a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt
+++ b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.guava
import com.google.common.util.concurrent.*
@@ -220,7 +216,7 @@
*
* This suspend function is cancellable.
*
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* stops waiting for the future and immediately resumes with [CancellationException][kotlinx.coroutines.CancellationException].
*
* This method is intended to be used with one-shot Futures, so on coroutine cancellation, the Future is cancelled as well.
diff --git a/integration/kotlinx-coroutines-guava/test/FutureAsDeferredUnhandledCompletionExceptionTest.kt b/integration/kotlinx-coroutines-guava/test/FutureAsDeferredUnhandledCompletionExceptionTest.kt
index d6469a9..5637493 100644
--- a/integration/kotlinx-coroutines-guava/test/FutureAsDeferredUnhandledCompletionExceptionTest.kt
+++ b/integration/kotlinx-coroutines-guava/test/FutureAsDeferredUnhandledCompletionExceptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.guava
+import kotlinx.coroutines.testing.*
import com.google.common.util.concurrent.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureExceptionsTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureExceptionsTest.kt
index 7417168..374f698 100644
--- a/integration/kotlinx-coroutines-guava/test/ListenableFutureExceptionsTest.kt
+++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureExceptionsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.guava
+import kotlinx.coroutines.testing.*
import com.google.common.base.*
import com.google.common.util.concurrent.*
import kotlinx.coroutines.*
diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt
index 511b1b0..a873206 100644
--- a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt
+++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.guava
+import kotlinx.coroutines.testing.*
import com.google.common.util.concurrent.*
import kotlinx.coroutines.*
import org.junit.*
@@ -87,7 +84,7 @@
try {
toAwait.await()
} catch (e: RuntimeException) {
- assertTrue(e is IllegalArgumentException)
+ assertIs<IllegalArgumentException>(e)
e.message!!
} + "K"
}
@@ -101,7 +98,7 @@
try {
toAwait.await()
} catch (e: RuntimeException) {
- assertTrue(e is IllegalArgumentException)
+ assertIs<IllegalArgumentException>(e)
e.message!!
} + "K"
}
@@ -123,7 +120,7 @@
future.get()
fail("'get' should've throw an exception")
} catch (e: ExecutionException) {
- assertTrue(e.cause is IllegalStateException)
+ assertIs<IllegalStateException>(e.cause)
assertEquals("OK", e.cause!!.message)
}
}
@@ -176,7 +173,7 @@
future.get()
} catch (e: ExecutionException) {
assertTrue(future.isDone)
- assertTrue(e.cause is OutOfMemoryError)
+ assertIs<OutOfMemoryError>(e.cause)
}
}
@@ -356,11 +353,11 @@
val asFuture = deferred.asListenableFuture()
val outputCancellationException =
- assertFailsWith<CancellationException> { asFuture.get() }
+ assertFailsWith<CancellationException> { asFuture.get() }
val cause = outputCancellationException.cause
assertNotNull(cause)
assertEquals(cause.message, "Foobar")
- assertTrue(cause.cause is OutOfMemoryError)
+ assertIs<OutOfMemoryError>(cause.cause)
assertEquals(cause.cause?.message, "Foobaz")
}
@@ -396,7 +393,7 @@
assertTrue(asFutureAsDeferred.isCompleted)
// By documentation, join() shouldn't throw when asDeferred is already complete.
asFutureAsDeferred.join()
- assertTrue(asFutureAsDeferred.getCompletionExceptionOrNull() is CancellationException)
+ assertIs<CancellationException>(asFutureAsDeferred.getCompletionExceptionOrNull())
}
@Test
@@ -419,7 +416,7 @@
assertTrue(asDeferred.isCompleted)
// By documentation, join() shouldn't throw when asDeferred is already complete.
asDeferred.join()
- assertTrue(asDeferred.getCompletionExceptionOrNull() is CancellationException)
+ assertIs<CancellationException>(asDeferred.getCompletionExceptionOrNull())
}
@Test
@@ -447,13 +444,13 @@
val deferred = future.asDeferred()
assertTrue(deferred.isCancelled && deferred.isCompleted)
val completionException = deferred.getCompletionExceptionOrNull()!!
- assertTrue(completionException is TestException)
+ assertIs<TestException>(completionException)
try {
deferred.await()
expectUnreached()
} catch (e: Throwable) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
}
}
@@ -493,7 +490,7 @@
future.asDeferred().await()
expectUnreached()
} catch (e: Throwable) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
}
}
@@ -610,9 +607,9 @@
val thrown = assertFailsWith<CancellationException> { future.get() }
val cause = thrown.cause
assertNotNull(cause)
- assertTrue(cause is CancellationException)
+ assertIs<CancellationException>(cause)
assertEquals("Parent cancelled", cause.message)
- assertTrue(cause.cause is TestException)
+ assertIs<TestException>(cause.cause)
finish(5)
}
@@ -707,7 +704,7 @@
private inline fun <reified T: Throwable> ListenableFuture<*>.checkFutureException() {
val e = assertFailsWith<ExecutionException> { get() }
val cause = e.cause!!
- assertTrue(cause is T)
+ assertIs<T>(cause)
}
@Suppress("SuspendFunctionOnCoroutineScope")
diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt
index 13ac299..c70c760 100644
--- a/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt
+++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.guava
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/integration/kotlinx-coroutines-jdk8/build.gradle.kts b/integration/kotlinx-coroutines-jdk8/build.gradle.kts
index 791bd95..e69de29 100644
--- a/integration/kotlinx-coroutines-jdk8/build.gradle.kts
+++ b/integration/kotlinx-coroutines-jdk8/build.gradle.kts
@@ -1,4 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
diff --git a/integration/kotlinx-coroutines-play-services/build.gradle.kts b/integration/kotlinx-coroutines-play-services/build.gradle.kts
index 9f8a128..2a03440 100644
--- a/integration/kotlinx-coroutines-play-services/build.gradle.kts
+++ b/integration/kotlinx-coroutines-play-services/build.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
val tasksVersion = "16.0.1"
project.configureAar()
diff --git a/integration/kotlinx-coroutines-play-services/src/Tasks.kt b/integration/kotlinx-coroutines-play-services/src/Tasks.kt
index 0451d7b..be4069d 100644
--- a/integration/kotlinx-coroutines-play-services/src/Tasks.kt
+++ b/integration/kotlinx-coroutines-play-services/src/Tasks.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("RedundantVisibilityModifier")
package kotlinx.coroutines.tasks
@@ -48,8 +44,8 @@
/**
* Converts this task to an instance of [Deferred] with a [CancellationTokenSource] to control cancellation.
* The cancellation of this function is bi-directional:
- * * If the given task is cancelled, the resulting deferred will be cancelled.
- * * If the resulting deferred is cancelled, the provided [cancellationTokenSource] will be cancelled.
+ * - If the given task is cancelled, the resulting deferred will be cancelled.
+ * - If the resulting deferred is cancelled, the provided [cancellationTokenSource] will be cancelled.
*
* Providing a [CancellationTokenSource] that is unrelated to the receiving [Task] is not supported and
* leads to an unspecified behaviour.
@@ -98,7 +94,7 @@
* Awaits the completion of the task without blocking a thread.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* stops waiting for the completion stage and immediately resumes with [CancellationException].
*
* For bi-directional cancellation, an overload that accepts [CancellationTokenSource] can be used.
@@ -109,9 +105,9 @@
* Awaits the completion of the task that is linked to the given [CancellationTokenSource] to control cancellation.
*
* This suspending function is cancellable and cancellation is bi-directional:
- * * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * - If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* cancels the [cancellationTokenSource] and throws a [CancellationException].
- * * If the task is cancelled, then this function will throw a [CancellationException].
+ * - If the task is cancelled, then this function will throw a [CancellationException].
*
* Providing a [CancellationTokenSource] that is unrelated to the receiving [Task] is not supported and
* leads to an unspecified behaviour.
diff --git a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt
index 34fbe23..e364383 100644
--- a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt
+++ b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.tasks
+import kotlinx.coroutines.testing.*
import com.google.android.gms.tasks.*
import kotlinx.coroutines.*
import org.junit.*
@@ -54,7 +51,7 @@
try {
runTest { task.await() }
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
assertTrue(task.isCanceled)
}
}
@@ -106,7 +103,7 @@
deferred.await()
fail("deferred.await() should be cancelled")
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
}
}
@@ -116,14 +113,14 @@
assertTrue(deferred.isCancelled && deferred.isCompleted)
val completionException = deferred.getCompletionExceptionOrNull()!!
- assertTrue(completionException is TestException)
+ assertIs<TestException>(completionException)
assertEquals("something went wrong", completionException.message)
try {
deferred.await()
fail("deferred.await() should throw an exception")
} catch (e: Exception) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("something went wrong", e.message)
}
}
@@ -143,7 +140,7 @@
deferred.await()
fail("deferred.await() should throw an exception")
} catch (e: Exception) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("something went wrong", e.message)
assertSame(e.cause, deferred.getCompletionExceptionOrNull()) // debug mode stack augmentation
}
@@ -174,7 +171,7 @@
deferred.await()
fail("deferred.await() should be cancelled")
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
}
assertTrue(cancellationTokenSource.token.isCancellationRequested)
}
@@ -190,7 +187,7 @@
deferred.await()
fail("deferred.await() should be cancelled")
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
}
assertTrue(cancellationTokenSource.token.isCancellationRequested)
}
@@ -207,7 +204,7 @@
deferred.await()
fail("deferred.await() should be cancelled")
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
}
assertTrue(cancellationTokenSource.token.isCancellationRequested)
}
@@ -226,18 +223,19 @@
@Test
fun testFailedCancellableTaskAsDeferred() = runTest {
val cancellationTokenSource = CancellationTokenSource()
- val deferred = Tasks.forException<Int>(TestException("something went wrong")).asDeferred(cancellationTokenSource)
+ val deferred =
+ Tasks.forException<Int>(TestException("something went wrong")).asDeferred(cancellationTokenSource)
assertTrue(deferred.isCancelled && deferred.isCompleted)
val completionException = deferred.getCompletionExceptionOrNull()!!
- assertTrue(completionException is TestException)
+ assertIs<TestException>(completionException)
assertEquals("something went wrong", completionException.message)
try {
deferred.await()
fail("deferred.await() should throw an exception")
} catch (e: Exception) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("something went wrong", e.message)
}
assertTrue(cancellationTokenSource.token.isCancellationRequested)
@@ -259,7 +257,7 @@
deferred.await()
fail("deferred.await() should throw an exception")
} catch (e: Exception) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("something went wrong", e.message)
assertSame(e.cause, deferred.getCompletionExceptionOrNull()) // debug mode stack augmentation
}
@@ -322,7 +320,7 @@
deferred.await()
fail("deferred.await() should be cancelled")
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
}
assertTrue(cancellationTokenSource.token.isCancellationRequested)
@@ -345,7 +343,7 @@
deferred.await()
fail("deferred.await() should be cancelled")
} catch (e: Exception) {
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
}
assertTrue(cancellationTokenSource.token.isCancellationRequested)
diff --git a/integration/kotlinx-coroutines-slf4j/build.gradle.kts b/integration/kotlinx-coroutines-slf4j/build.gradle.kts
index 3552333..aaf0a42 100644
--- a/integration/kotlinx-coroutines-slf4j/build.gradle.kts
+++ b/integration/kotlinx-coroutines-slf4j/build.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
dependencies {
implementation("org.slf4j:slf4j-api:1.7.32")
testImplementation("io.github.microutils:kotlin-logging:2.1.0")
diff --git a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt
index 0fbfece..fb4bdfe 100644
--- a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt
+++ b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.slf4j
import kotlinx.coroutines.*
@@ -32,8 +28,47 @@
* using [MDC.put]. These updates are going to be lost on the next suspension and
* reinstalled to the MDC context that was captured or explicitly specified in
* [contextMap] when this object was created on the next resumption.
- * Use `withContext(MDCContext()) { ... }` to capture updated map of MDC keys and values
- * for the specified block of code.
+ *
+ * For example, the following code will not work as expected:
+ *
+ * ```
+ * launch(MDCContext()) {
+ * MDC.put("key", "value") // This update will be lost
+ * delay(100)
+ * println(MDC.get("key")) // This will print null
+ * }
+ * ```
+ *
+ * Instead, you should use [withContext] to capture the updated MDC context:
+ *
+ * ```
+ * launch(MDCContext()) {
+ * MDC.put("key", "value") // This update will be captured
+ * withContext(MDCContext()) {
+ * delay(100)
+ * println(MDC.get("key")) // This will print "value"
+ * }
+ * }
+ * ```
+ *
+ * There is no way to implicitly propagate MDC context updates from inside the coroutine to the outer scope.
+ * You have to capture the updated MDC context and restore it explicitly. For example:
+ *
+ * ```
+ * MDC.put("a", "b")
+ * val contextMap = withContext(MDCContext()) {
+ * MDC.put("key", "value")
+ * withContext(MDCContext()) {
+ * MDC.put("key2", "value2")
+ * withContext(MDCContext()) {
+ * yield()
+ * MDC.getCopyOfContextMap()
+ * }
+ * }
+ * }
+ * // contextMap contains: {"a"="b", "key"="value", "key2"="value2"}
+ * MDC.setContextMap(contextMap)
+ * ```
*
* @param contextMap the value of [MDC] context map.
* Default value is the copy of the current thread's context map that is acquired via
diff --git a/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt b/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt
index 532c47e..dd3b34c 100644
--- a/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt
+++ b/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.slf4j
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
@@ -108,4 +105,40 @@
}
}
}
+
+ /** Tests that the initially captured MDC context gets restored after suspension. */
+ @Test
+ fun testSuspensionsUndoingMdcContextUpdates() = runTest {
+ MDC.put("a", "b")
+ withContext(MDCContext()) {
+ MDC.put("key", "value")
+ assertEquals("b", MDC.get("a"))
+ yield()
+ assertNull(MDC.get("key"))
+ assertEquals("b", MDC.get("a"))
+ }
+ }
+
+ /** Tests capturing and restoring the MDC context. */
+ @Test
+ fun testRestoringMdcContext() = runTest {
+ MDC.put("a", "b")
+ val contextMap = withContext(MDCContext()) {
+ MDC.put("key", "value")
+ assertEquals("b", MDC.get("a"))
+ withContext(MDCContext()) {
+ assertEquals("value", MDC.get("key"))
+ MDC.put("key2", "value2")
+ assertEquals("value2", MDC.get("key2"))
+ withContext(MDCContext()) {
+ yield()
+ MDC.getCopyOfContextMap()
+ }
+ }
+ }
+ MDC.setContextMap(contextMap)
+ assertEquals("value2", MDC.get("key2"))
+ assertEquals("value", MDC.get("key"))
+ assertEquals("b", MDC.get("a"))
+ }
}
diff --git a/js/README.md b/js/README.md
deleted file mode 100644
index 4717a70..0000000
--- a/js/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Example of Kotlin JS application with coroutines
-
-[example-frontend-js](example-frontend-js/README.md) -- frontend application written in Kotlin/JS
-that uses coroutines to implement animations in imperative style.
\ No newline at end of file
diff --git a/js/example-frontend-js/README.md b/js/example-frontend-js/README.md
deleted file mode 100644
index 55e7088..0000000
--- a/js/example-frontend-js/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Example JS frontend application with coroutines
-
-Build application with
-
-```
-gradlew :example-frontend-js:build
-```
-
-The resulting application can be found in `build/dist` subdirectory.
-
-You can start application with webpack-dev-server using:
-
-```
-gradlew :example-frontend-js:run
-```
-
-Built and deployed application is available at the library documentation site
-[here](https://kotlinlang.org/api/kotlinx.coroutines/example-frontend-js/index.html).
diff --git a/js/example-frontend-js/build.gradle.kts b/js/example-frontend-js/build.gradle.kts
deleted file mode 100644
index 1cc587b..0000000
--- a/js/example-frontend-js/build.gradle.kts
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-kotlin {
- js(LEGACY) {
- binaries.executable()
- browser {
- distribution {
- directory = directory.parentFile.resolve("dist")
- }
- commonWebpackConfig {
- cssSupport {
- enabled.set(true)
- }
- }
- testTask {
- useKarma {
- useChromeHeadless()
- }
- }
- }
- }
-}
-
-// For kotlinx-html
-repositories {
- maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
-}
-
-dependencies {
- implementation("org.jetbrains.kotlinx:kotlinx-html-js:${version("html")}")
- implementation(devNpm("html-webpack-plugin", "5.3.1"))
-}
diff --git a/js/example-frontend-js/src/ExampleMain.kt b/js/example-frontend-js/src/ExampleMain.kt
deleted file mode 100644
index 67c6ef0..0000000
--- a/js/example-frontend-js/src/ExampleMain.kt
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-import kotlinx.coroutines.*
-import kotlinx.html.*
-import kotlinx.html.div
-import kotlinx.html.dom.*
-import kotlinx.html.js.onClickFunction
-import org.w3c.dom.*
-import kotlinx.browser.*
-import kotlin.coroutines.*
-import kotlin.math.*
-import kotlin.random.Random
-
-external fun require(resource: String)
-
-fun main() {
- require("style.css")
- println("Starting example application...")
- document.addEventListener("DOMContentLoaded", {
- Application().start()
- })
-}
-
-val Double.px get() = "${this}px"
-
-private fun HTMLElement.setSize(w: Double, h: Double) {
- with(style) {
- width = w.px
- height = h.px
- }
-}
-
-private fun HTMLElement.setPosition(x: Double, y: Double) {
- with(style) {
- left = x.px
- top = y.px
- }
-}
-
-class Application : CoroutineScope {
- private val body get() = document.body!!
- private val scene get() = document.getElementById("scene") as HTMLElement
- private val sw = 800.0
- private val sh = 600.0
- private var animationIndex = 0
- private var job = Job()
- override val coroutineContext: CoroutineContext
- get() = job
-
- fun start() {
- body.append.div("content") {
- h1 {
- +"Kotlin Coroutines JS Example"
- }
- div {
- button {
- +"Rect"
- onClickFunction = { onRect() }
- }
- button {
- +"Circle"
- onClickFunction = { onCircle() }
- }
- button {
- +"Clear"
- onClickFunction = { onClear() }
- }
- }
- div {
- id = "scene"
- }
- }
- scene.setSize(sw, sh)
- }
-
- private fun animation(cls: String, size: Double, block: suspend CoroutineScope.(HTMLElement) -> Unit) {
- val elem = scene.append.div(cls)
- elem.setSize(size, size)
- val job = launch {
- block(elem)
- }
-
- job.invokeOnCompletion { scene.removeChild(elem) }
- }
-
- private fun onRect() {
- val index = ++animationIndex
- val speed = 0.3
- val rs = 20.0
- val turnAfter = 5000.0 // seconds
- val maxX = sw - rs
- val maxY = sh - rs
- animation("rect", rs) { rect ->
- println("Started new 'rect' coroutine #$index")
- val timer = AnimationTimer()
- var turnTime = timer.time + turnAfter
- val turnTimePhase = turnTime - floor(turnTime / turnAfter) * turnAfter
- var vx = speed
- var vy = speed
- var x = 0.0
- var y = 0.0
- while (true) {
- val dt = timer.await()
- x += vx * dt
- y += vy * dt
- if (x > maxX) {
- x = 2 * maxX - x
- vx = -vx
- }
- if (x < 0) {
- x = -x
- vx = -vx
- }
- if (y > maxY) {
- y = 2 * maxY - y
- vy = -vy
- }
- if (y < 0) {
- y = -y
- vy = -vy
- }
- rect.setPosition(x, y)
- if (timer.time >= turnTime) {
- timer.delay(1000) // pause a bit
- // flip direction
- val t = vx
- if (Random.nextDouble() > 0.5) {
- vx = vy
- vy = -t
- } else {
- vx = -vy
- vy = t
- }
- // reset time, but keep turning time phase
- turnTime = ceil(timer.reset() / turnAfter) * turnAfter + turnTimePhase
- println("Delayed #$index for a while at ${timer.time}, resumed and turned")
- }
- }
- }
- }
-
- private fun onCircle() {
- val index = ++animationIndex
- val acceleration = 5e-4
- val initialRange = 0.7
- val maxSpeed = 0.4
- val initialSpeed = 0.1
- val radius = 20.0
- animation("circle", radius) { circle ->
- println("Started new 'circle' coroutine #$index")
- val timer = AnimationTimer()
- val initialAngle = Random.nextDouble() * 2 * PI
- var vx = sin(initialAngle) * initialSpeed
- var vy = cos(initialAngle) * initialSpeed
- var x = (Random.nextDouble() * initialRange + (1 - initialRange) / 2) * sw
- var y = (Random.nextDouble() * initialRange + (1 - initialRange) / 2) * sh
- while (true) {
- val dt = timer.await()
- val dx = sw / 2 - x
- val dy = sh / 2 - y
- val dn = sqrt(dx * dx + dy * dy)
- vx += dx / dn * acceleration * dt
- vy += dy / dn * acceleration * dt
- val vn = sqrt(vx * vx + vy * vy)
- val trim = vn.coerceAtMost(maxSpeed)
- vx = vx / vn * trim
- vy = vy / vn * trim
- x += vx * dt
- y += vy * dt
- circle.setPosition(x, y)
- }
- }
-
- }
-
- private fun onClear() {
- job.cancel()
- job = Job()
- }
-}
-
-class AnimationTimer {
- var time = window.performance.now()
-
- suspend fun await(): Double {
- val newTime = window.awaitAnimationFrame()
- val dt = newTime - time
- time = newTime
- return dt.coerceAtMost(200.0) // at most 200ms
- }
-
- fun reset(): Double {
- time = window.performance.now()
- return time
- }
-
- suspend fun delay(i: Int) {
- var dt = 0.0
- while (dt < i) {
- dt += await()
- }
- }
-}
diff --git a/js/example-frontend-js/src/main/web/style.css b/js/example-frontend-js/src/main/web/style.css
deleted file mode 100644
index e2e777a..0000000
--- a/js/example-frontend-js/src/main/web/style.css
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-#scene {
- border: #000000 1px solid;
- position: relative;
-}
-
-.rect {
- position: absolute;
- background: red;
-}
-
-.circle {
- position: absolute;
- background: #ffa450;
- border-radius: 50%;
-}
diff --git a/js/example-frontend-js/webpack.config.d/custom-config.js b/js/example-frontend-js/webpack.config.d/custom-config.js
deleted file mode 100644
index 21939be..0000000
--- a/js/example-frontend-js/webpack.config.d/custom-config.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-;(function (config) {
- const HtmlWebpackPlugin = require('html-webpack-plugin');
-
- config.output.filename = "[name].bundle.js"
-
- config.plugins.push(
- new HtmlWebpackPlugin({
- title: 'Kotlin Coroutines JS Example'
- })
- )
-
- // path from <root-build>/js/packages/example-frontend-js to src/main/web
- config.resolve.modules.push("../../../../js/example-frontend-js/src/main/web");
-})(config);
diff --git a/knit.properties b/knit.properties
index 45b2216..486204b 100644
--- a/knit.properties
+++ b/knit.properties
@@ -1,7 +1,3 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
knit.include=docs/knit.code.include
test.template=docs/knit.test.template
diff --git a/kotlinx-coroutines-bom/build.gradle b/kotlinx-coroutines-bom/build.gradle
deleted file mode 100644
index ef87f3f..0000000
--- a/kotlinx-coroutines-bom/build.gradle
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-plugins {
- id 'java-platform'
-}
-
-def name = project.name
-
-dependencies {
- constraints {
- rootProject.subprojects.each {
- if (rootProject.ext.unpublished.contains(it.name)) return
- if (it.name == name) return
- if (!it.plugins.hasPlugin('maven-publish')) return
- evaluationDependsOn(it.path)
- it.publishing.publications.all {
- if (it.artifactId.endsWith("-kotlinMultiplatform")) return
- if (it.artifactId.endsWith("-metadata")) return
- // Skip platform artifacts (like *-linuxx64, *-macosx64)
- // It leads to inconsistent bom when publishing from different platforms
- // (e.g. on linux it will include only linuxx64 artifacts and no macosx64)
- // It shouldn't be a problem as usually consumers need to use generic *-native artifact
- // Gradle will choose correct variant by using metadata attributes
- if (it.artifacts.any { it.extension == 'klib' }) return
- api(group: it.groupId, name: it.artifactId, version: it.version)
- }
- }
- }
-}
-
-publishing {
- publications {
- mavenBom(MavenPublication) {
- from components.javaPlatform
- }
- // Disable metadata publication
- it.each { pub ->
- pub.moduleDescriptorGenerator = null
- tasks.matching { it.name == "generateMetadataFileFor${pub.name.capitalize()}Publication" }.all {
- onlyIf { false }
- }
- }
- }
-}
diff --git a/kotlinx-coroutines-bom/build.gradle.kts b/kotlinx-coroutines-bom/build.gradle.kts
new file mode 100644
index 0000000..3eb5926
--- /dev/null
+++ b/kotlinx-coroutines-bom/build.gradle.kts
@@ -0,0 +1,52 @@
+import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication
+
+plugins {
+ id("java-platform")
+}
+
+val name = project.name
+
+dependencies {
+ constraints {
+ rootProject.subprojects.forEach {
+ if (unpublished.contains(it.name)) return@forEach
+ if (it.name == name) return@forEach
+ if (!it.plugins.hasPlugin("maven-publish")) return@forEach
+ evaluationDependsOn(it.path)
+ it.publishing.publications.all {
+ this as MavenPublication
+ if (artifactId.endsWith("-kotlinMultiplatform")) return@all
+ if (artifactId.endsWith("-metadata")) return@all
+ // Skip platform artifacts (like *-linuxx64, *-macosx64)
+ // It leads to inconsistent bom when publishing from different platforms
+ // (e.g. on linux it will include only linuxx64 artifacts and no macosx64)
+ // It shouldn't be a problem as usually consumers need to use generic *-native artifact
+ // Gradle will choose correct variant by using metadata attributes
+ if (artifacts.any { it.extension == "klib" }) return@all
+ [email protected](mapOf("group" to groupId, "name" to artifactId, "version" to version))
+ }
+ }
+ }
+}
+
+publishing {
+ publications {
+ val mavenBom by creating(MavenPublication::class) {
+ from(components["javaPlatform"])
+ }
+ // Disable metadata publication
+ forEach { pub ->
+ pub as DefaultMavenPublication
+ pub.unsetModuleDescriptorGenerator()
+ tasks.matching { it.name == "generateMetadataFileFor${pub.name.capitalize()}Publication" }.all {
+ onlyIf { false }
+ }
+ }
+ }
+}
+
+fun DefaultMavenPublication.unsetModuleDescriptorGenerator() {
+ @Suppress("NULL_FOR_NONNULL_TYPE")
+ val generator: TaskProvider<Task> = null
+ setModuleDescriptorGenerator(generator)
+}
diff --git a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api
index 9b548ac..2674d73 100644
--- a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api
+++ b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api
@@ -87,7 +87,6 @@
public final class kotlinx/coroutines/ChildContinuation {
public final field child Lkotlinx/coroutines/CancellableContinuationImpl;
public fun <init> (Lkotlinx/coroutines/CancellableContinuationImpl;)V
- public synthetic fun invoke (Ljava/lang/Object;)Ljava/lang/Object;
public fun invoke (Ljava/lang/Throwable;)V
}
@@ -264,7 +263,7 @@
public static final field DEFAULT Lkotlinx/coroutines/CoroutineStart;
public static final field LAZY Lkotlinx/coroutines/CoroutineStart;
public static final field UNDISPATCHED Lkotlinx/coroutines/CoroutineStart;
- public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)V
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun invoke (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
public final fun isLazy ()Z
public static fun valueOf (Ljava/lang/String;)Lkotlinx/coroutines/CoroutineStart;
@@ -276,6 +275,11 @@
public static final field DEBUG_PROPERTY_VALUE_AUTO Ljava/lang/String;
public static final field DEBUG_PROPERTY_VALUE_OFF Ljava/lang/String;
public static final field DEBUG_PROPERTY_VALUE_ON Ljava/lang/String;
+ public static final fun getRECOVER_STACK_TRACES ()Z
+}
+
+public final class kotlinx/coroutines/DefaultExecutorKt {
+ public static final fun getDefaultDelay ()Lkotlinx/coroutines/Delay;
}
public abstract interface class kotlinx/coroutines/Deferred : kotlinx/coroutines/Job {
@@ -315,7 +319,7 @@
}
public final class kotlinx/coroutines/DispatchedCoroutine {
- public static final fun get_decision$FU ()Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;
+ public static final synthetic fun get_decision$volatile$FU$kotlinx_coroutines_core ()Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;
}
public abstract class kotlinx/coroutines/DispatchedTask : kotlinx/coroutines/scheduling/Task {
@@ -667,6 +671,7 @@
public static final field DROP_LATEST Lkotlinx/coroutines/channels/BufferOverflow;
public static final field DROP_OLDEST Lkotlinx/coroutines/channels/BufferOverflow;
public static final field SUSPEND Lkotlinx/coroutines/channels/BufferOverflow;
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lkotlinx/coroutines/channels/BufferOverflow;
public static fun values ()[Lkotlinx/coroutines/channels/BufferOverflow;
}
@@ -907,6 +912,7 @@
public final class kotlinx/coroutines/channels/TickerMode : java/lang/Enum {
public static final field FIXED_DELAY Lkotlinx/coroutines/channels/TickerMode;
public static final field FIXED_PERIOD Lkotlinx/coroutines/channels/TickerMode;
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lkotlinx/coroutines/channels/TickerMode;
public static fun values ()[Lkotlinx/coroutines/channels/TickerMode;
}
@@ -939,7 +945,7 @@
public final fun enhanceStackTraceWithThreadDump (Lkotlinx/coroutines/debug/internal/DebugCoroutineInfo;Ljava/util/List;)Ljava/util/List;
public final fun enhanceStackTraceWithThreadDumpAsJson (Lkotlinx/coroutines/debug/internal/DebugCoroutineInfo;)Ljava/lang/String;
public final fun getIgnoreCoroutinesWithEmptyContext ()Z
- public final fun isInstalled ()Z
+ public final fun isInstalled$kotlinx_coroutines_debug ()Z
public final fun setIgnoreCoroutinesWithEmptyContext (Z)V
}
@@ -1178,6 +1184,7 @@
public static final field START Lkotlinx/coroutines/flow/SharingCommand;
public static final field STOP Lkotlinx/coroutines/flow/SharingCommand;
public static final field STOP_AND_RESET_REPLAY_CACHE Lkotlinx/coroutines/flow/SharingCommand;
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lkotlinx/coroutines/flow/SharingCommand;
public static fun values ()[Lkotlinx/coroutines/flow/SharingCommand;
}
@@ -1324,12 +1331,11 @@
public abstract interface class kotlinx/coroutines/selects/SelectClause2 : kotlinx/coroutines/selects/SelectClause {
}
-public class kotlinx/coroutines/selects/SelectImplementation : kotlinx/coroutines/selects/SelectBuilder, kotlinx/coroutines/selects/SelectInstanceInternal {
+public class kotlinx/coroutines/selects/SelectImplementation : kotlinx/coroutines/CancelHandler, kotlinx/coroutines/selects/SelectBuilder, kotlinx/coroutines/selects/SelectInstanceInternal {
public fun <init> (Lkotlin/coroutines/CoroutineContext;)V
public fun disposeOnCompletion (Lkotlinx/coroutines/DisposableHandle;)V
public fun doSelect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun getContext ()Lkotlin/coroutines/CoroutineContext;
- public synthetic fun invoke (Ljava/lang/Object;)Ljava/lang/Object;
public fun invoke (Ljava/lang/Throwable;)V
public fun invoke (Lkotlinx/coroutines/selects/SelectClause0;Lkotlin/jvm/functions/Function1;)V
public fun invoke (Lkotlinx/coroutines/selects/SelectClause1;Lkotlin/jvm/functions/Function2;)V
diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle
deleted file mode 100644
index 001df3a..0000000
--- a/kotlinx-coroutines-core/build.gradle
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-apply plugin: 'org.jetbrains.kotlin.multiplatform'
-apply plugin: 'org.jetbrains.dokka'
-
-// apply plugin to use autocomplete for Kover DSL
-apply plugin: 'org.jetbrains.kotlinx.kover'
-
-apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle")
-apply from: rootProject.file("gradle/compile-common.gradle")
-
-if (rootProject.ext.native_targets_enabled) {
- apply from: rootProject.file("gradle/compile-native-multiplatform.gradle")
-}
-
-apply from: rootProject.file("gradle/compile-js-multiplatform.gradle")
-apply from: rootProject.file('gradle/publish-npm-js.gradle')
-
-apply from: rootProject.file('gradle/dokka.gradle.kts')
-apply from: rootProject.file('gradle/publish.gradle')
-/* ==========================================================================
- Configure source sets structure for kotlinx-coroutines-core:
-
- TARGETS SOURCE SETS
- ------- ----------------------------------------------
-
- js -----------------------------------------------------+
- |
- V
- jvmCore\ --------> jvm ---------> concurrent -------> common
- jdk8 / ^
- |
- ios \ |
- macos | ---> nativeDarwin ---> native ---+
- tvos | ^
- watchos / |
- |
- linux \ ---> nativeOther -------+
- mingw /
-
-
-Explanation of JVM source sets structure:
-
-The overall structure is just a hack to support the scenario we are interested in:
-
-* We would like to have two source-sets "core" and "jdk8"
-* "jdk8" is allowed to use API from Java 8 and from "core"
-* "core" is prohibited to use any API from "jdk8"
-* It is okay to have tests in a single test source-set
-* And we want to publish a **single** artifact kotlinx-coroutines-core.jar that contains classes from both source-sets
-* Current limitation: only classes from "core" are checked with animal-sniffer
-
-For that, we have following compilations:
-* jvmMain compilation: [jvmCoreMain, jdk8Main]
-* jvmCore compilation: [commonMain]
-* jdk8 compilation: [commonMain, jvmCoreMain]
-
-Theoretically, "jvmCore" could've been "jvmMain", it is not for technical reasons,
-here is the explanation from Seb:
-
-"""
-The jvmCore is theoretically not necessary. All code for jdk6 compatibility can be in jvmMain and jdk8 dependent code can be in jdk8Main.
-Effectively there is no reason for ever putting code into jvmCoreMain.
-However, when creating a new compilation, we have to take care of creating a defaultSourceSet. Without creating the jvmCoreMain source set,
- the creation of the compilation fails. That is the only reason for this source set.
-"""
- ========================================================================== */
-
-project.ext.sourceSetSuffixes = ["Main", "Test"]
-
-void defineSourceSet(newName, dependsOn, includedInPred) {
- for (suffix in project.ext.sourceSetSuffixes) {
- def newSS = kotlin.sourceSets.maybeCreate(newName + suffix)
- for (dep in dependsOn) {
- newSS.dependsOn(kotlin.sourceSets[dep + suffix])
- }
- for (curSS in kotlin.sourceSets) {
- def curName = curSS.name
- if (curName.endsWith(suffix)) {
- def prefix = curName.substring(0, curName.length() - suffix.length())
- if (includedInPred(prefix)) curSS.dependsOn(newSS)
- }
- }
- }
-}
-
-static boolean isNativeDarwin(String name) { return ["ios", "macos", "tvos", "watchos"].any { name.startsWith(it) } }
-
-static boolean isNativeOther(String name) { return ["linux", "mingw", "androidNative"].any { name.startsWith(it) } }
-
-defineSourceSet("concurrent", ["common"]) { it in ["jvm", "native"] }
-
-if (rootProject.ext.native_targets_enabled) {
- defineSourceSet("nativeDarwin", ["native"]) { isNativeDarwin(it) }
- defineSourceSet("nativeOther", ["native"]) { isNativeOther(it) }
-}
-
-/* ========================================================================== */
-
-
-/*
- * All platform plugins and configuration magic happens here instead of build.gradle
- * because JMV-only projects depend on core, thus core should always be initialized before configuration.
- */
-kotlin {
- /*
- * Configure two test runs:
- * 1) New memory model, Main thread
- * 2) New memory model, BG thread (required for Dispatchers.Main tests on Darwin)
- *
- * All new MM targets are build with optimize = true to have stress tests properly run.
- */
- targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests.class).configureEach {
- binaries.getTest("DEBUG").with {
- optimized = true
- // Test for memory leaks using a special entry point that does not exit but returns from main
- freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
- binaryOptions["memoryModel"] = "experimental"
- }
-
- binaries.test("workerWithNewMM", [DEBUG]) {
- def thisTest = it
- optimized = true
- freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"]
- binaryOptions["memoryModel"] = "experimental"
- testRuns.create("workerWithNewMM") {
- setExecutionSourceFrom(thisTest)
- executionTask.configure { targetName = "$targetName worker with new MM" }
- }
- }
- }
-
- def jvmMain = sourceSets.jvmMain
- def jvmCoreMain = sourceSets.create('jvmCoreMain')
- def jdk8Main = sourceSets.create('jdk8Main')
- jvmCoreMain.dependsOn(jvmMain)
- jdk8Main.dependsOn(jvmMain)
-
- sourceSets.forEach {
- SourceSetsKt.configureMultiplatform(it)
- }
-
- jvm {
- def main = compilations.main
- main.source(jvmCoreMain)
- main.source(jdk8Main)
-
- /* Create compilation for jvmCore to prove that jvmMain does not rely on jdk8 */
- compilations.create('CoreMain') {
- /* jvmCore is automatically matched as 'defaultSourceSet' for the compilation, due to its name */
- tasks.getByName('check').dependsOn(compileKotlinTaskProvider)
- }
-
- // For animal sniffer
- withJava()
- }
-}
-
-configurations {
- configureKotlinJvmPlatform(kotlinCompilerPluginClasspath)
-}
-
-// Update module name for metadata artifact to avoid conflicts
-// see https://github.com/Kotlin/kotlinx.coroutines/issues/1797
-compileKotlinMetadata {
- kotlinOptions {
- freeCompilerArgs += ["-module-name", "kotlinx-coroutines-core-common"]
- }
-}
-
-// :KLUDGE: Idea.active: This is needed to workaround resolve problems after importing this project to IDEA
-def configureNativeSourceSetPreset(name, preset) {
- def hostMainCompilation = project.kotlin.targetFromPreset(preset).compilations.main
- // Look for platform libraries in "implementation" for default source set
- def implementationConfiguration = configurations[hostMainCompilation.defaultSourceSet.implementationMetadataConfigurationName]
- // Now find the libraries: Finds platform libs & stdlib, but platform declarations are still not resolved due to IDE bugs
- def hostNativePlatformLibs = files(
- provider {
- implementationConfiguration.findAll {
- it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib")
- }
- }
- )
- // Add all those dependencies
- for (suffix in sourceSetSuffixes) {
- configure(kotlin.sourceSets[name + suffix]) {
- dependencies.add(implementationMetadataConfigurationName, hostNativePlatformLibs)
- }
- }
-}
-
-// :KLUDGE: Idea.active: Configure platform libraries for native source sets when working in IDEA
-if (Idea.active && rootProject.ext.native_targets_enabled) {
- def manager = project.ext.hostManager
- def linuxPreset = kotlin.presets.linuxX64
- def macosPreset = kotlin.presets.macosX64
- // linux should be always available (cross-compilation capable) -- use it as default
- assert manager.isEnabled(linuxPreset.konanTarget)
- // use macOS libs for nativeDarwin if available
- def macosAvailable = manager.isEnabled(macosPreset.konanTarget)
- // configure source sets
- configureNativeSourceSetPreset("native", linuxPreset)
- configureNativeSourceSetPreset("nativeOther", linuxPreset)
- configureNativeSourceSetPreset("nativeDarwin", macosAvailable ? macosPreset : linuxPreset)
-}
-
-kotlin.sourceSets {
- jvmMain.dependencies {
- compileOnly "com.google.android:annotations:4.1.1.4"
- }
-
- jvmTest.dependencies {
- api "org.jetbrains.kotlinx:lincheck:$lincheck_version"
- api "org.jetbrains.kotlinx:kotlinx-knit-test:$knit_version"
- implementation project(":android-unit-tests")
- implementation "org.openjdk.jol:jol-core:0.16"
- }
-}
-
-kotlin.sourceSets.configureEach {
- // Do not apply 'ExperimentalForeignApi' where we have allWarningsAsErrors set
- if (it.name in ["jvmMain", "jsMain", "concurrentMain", "commonMain"]) return
- languageSettings {
- optIn('kotlinx.cinterop.ExperimentalForeignApi')
- optIn('kotlin.experimental.ExperimentalNativeApi')
- }
-}
-
-jvmTest {
- minHeapSize = '1g'
- maxHeapSize = '1g'
- enableAssertions = true
- if (!Idea.active) {
- // We should not set this security manager when `jvmTest`
- // is invoked by IntelliJ IDEA since we need to pass
- // system properties for Lincheck and stress tests.
- // TODO Remove once IDEA is smart enough to select between `jvmTest`/`jvmStressTest`/`jvmLincheckTest` #KTIJ-599
- systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager'
- }
- // 'stress' is required to be able to run all subpackage tests like ":jvmTests --tests "*channels*" -Pstress=true"
- if (!Idea.active && rootProject.properties['stress'] == null) {
- exclude '**/*LincheckTest*'
- exclude '**/*StressTest.*'
- }
- if (Idea.active) {
- // Configure the IDEA runner for Lincheck
- configureJvmForLincheck(jvmTest)
- }
-}
-
-// Setup manifest for kotlinx-coroutines-core-jvm.jar
-jvmJar { setupManifest(it) }
-
-/*
- * Setup manifest for kotlinx-coroutines-core.jar
- * This is convenient for users that pass -javaagent arg manually and also is a workaround #2619 and KTIJ-5659.
- * This manifest contains reference to AgentPremain that belongs to
- * kotlinx-coroutines-core-jvm, but our resolving machinery guarantees that
- * any JVM project that depends on -core artifact also depends on -core-jvm one.
- */
-metadataJar { setupManifest(it) }
-
-static def setupManifest(Jar jar) {
- jar.manifest {
- attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain"
- attributes "Can-Retransform-Classes": "true"
- }
-}
-
-task jvmStressTest(type: Test, dependsOn: compileTestKotlinJvm) {
- classpath = files { jvmTest.classpath }
- testClassesDirs = files { jvmTest.testClassesDirs }
- minHeapSize = '1g'
- maxHeapSize = '1g'
- include '**/*StressTest.*'
- enableAssertions = true
- testLogging.showStandardStreams = true
- systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test
- // Adjust internal algorithmic parameters to increase the testing quality instead of performance.
- systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '1'
- systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '10'
- systemProperty 'kotlinx.coroutines.bufferedChannel.segmentSize', '2'
- systemProperty 'kotlinx.coroutines.bufferedChannel.expandBufferCompletionWaitIterations', '1'
-}
-
-task jvmLincheckTest(type: Test, dependsOn: compileTestKotlinJvm) {
- classpath = files { jvmTest.classpath }
- testClassesDirs = files { jvmTest.testClassesDirs }
- include '**/*LincheckTest*'
- enableAssertions = true
- testLogging.showStandardStreams = true
- configureJvmForLincheck(jvmLincheckTest)
-}
-
-// Additional Lincheck tests with `segmentSize = 2`.
-// Some bugs cannot be revealed when storing one request per segment,
-// and some are hard to detect when storing multiple requests.
-task jvmLincheckTestAdditional(type: Test, dependsOn: compileTestKotlinJvm) {
- classpath = files { jvmTest.classpath }
- testClassesDirs = files { jvmTest.testClassesDirs }
- include '**/RendezvousChannelLincheckTest*'
- include '**/Buffered1ChannelLincheckTest*'
- include '**/Semaphore*LincheckTest*'
- enableAssertions = true
- testLogging.showStandardStreams = true
- configureJvmForLincheck(jvmLincheckTestAdditional, true)
-}
-
-static void configureJvmForLincheck(task, additional = false) {
- task.minHeapSize = '1g'
- task.maxHeapSize = '4g' // we may need more space for building an interleaving tree in the model checking mode
- task.jvmArgs = ['--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED', // required for transformation
- '--add-exports', 'java.base/jdk.internal.util=ALL-UNNAMED'] // in the model checking mode
- // Adjust internal algorithmic parameters to increase the testing quality instead of performance.
- var segmentSize = additional ? '2' : '1'
- task.systemProperty 'kotlinx.coroutines.semaphore.segmentSize', segmentSize
- task.systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '1' // better for the model checking mode
- task.systemProperty 'kotlinx.coroutines.bufferedChannel.segmentSize', segmentSize
- task.systemProperty 'kotlinx.coroutines.bufferedChannel.expandBufferCompletionWaitIterations', '1'
-}
-
-// Always check additional test sets
-task moreTest(dependsOn: [jvmStressTest, jvmLincheckTest, jvmLincheckTestAdditional])
-check.dependsOn moreTest
-
-def commonKoverExcludes =
- ["kotlinx.coroutines.debug.*", // Tested by debug module
- "kotlinx.coroutines.channels.ChannelsKt__DeprecatedKt.*", // Deprecated
- "kotlinx.coroutines.scheduling.LimitingDispatcher", // Deprecated
- "kotlinx.coroutines.scheduling.ExperimentalCoroutineDispatcher" // Deprecated
- ]
-
-kover {
- excludeTests {
- // Always disabled, lincheck doesn't really support coverage
- tasks("jvmLincheckTest")
- }
-
- excludeInstrumentation {
- // lincheck has NPE error on `ManagedStrategyStateHolder` class
- classes("org.jetbrains.kotlinx.lincheck.*")
- }
-}
-
-koverReport {
- filters {
- excludes {
- classes(
- "kotlinx.coroutines.debug.*", // Tested by debug module
- "kotlinx.coroutines.channels.ChannelsKt__DeprecatedKt.*", // Deprecated
- "kotlinx.coroutines.scheduling.LimitingDispatcher", // Deprecated
- "kotlinx.coroutines.scheduling.ExperimentalCoroutineDispatcher" // Deprecated
- )
- }
- }
-}
-
-task testsJar(type: Jar, dependsOn: jvmTestClasses) {
- classifier = 'tests'
- from(compileTestKotlinJvm.destinationDirectory)
-}
-
-artifacts {
- archives testsJar
-}
diff --git a/kotlinx-coroutines-core/build.gradle.kts b/kotlinx-coroutines-core/build.gradle.kts
new file mode 100644
index 0000000..0c6f65c
--- /dev/null
+++ b/kotlinx-coroutines-core/build.gradle.kts
@@ -0,0 +1,317 @@
+import org.gradle.api.tasks.testing.*
+import org.gradle.kotlin.dsl.*
+import org.jetbrains.kotlin.gradle.plugin.mpp.*
+import org.jetbrains.kotlin.gradle.targets.native.tasks.*
+import org.jetbrains.kotlin.gradle.tasks.*
+import org.jetbrains.kotlin.gradle.testing.*
+
+plugins {
+ kotlin("multiplatform")
+ id("org.jetbrains.kotlinx.benchmark")
+ id("org.jetbrains.dokka")
+ id("org.jetbrains.kotlinx.kover")
+}
+
+apply(plugin = "pub-conventions")
+
+/* ==========================================================================
+ Configure source sets structure for kotlinx-coroutines-core:
+
+ TARGETS SOURCE SETS
+ ------- ----------------------------------------------
+ wasmJs \----------> jsAndWasmShared --------------------+
+ js / |
+ V
+ jvmCore\ --------> jvm ---------> concurrent -------> common
+ jdk8 / ^
+ |
+ ios \ |
+ macos | ---> nativeDarwin ---> native ---+
+ tvos | ^
+ watchos / |
+ |
+ linux \ ---> nativeOther -------+
+ mingw /
+
+
+Explanation of JVM source sets structure:
+
+The overall structure is just a hack to support the scenario we are interested in:
+
+* We would like to have two source-sets "core" and "jdk8"
+* "jdk8" is allowed to use API from Java 8 and from "core"
+* "core" is prohibited to use any API from "jdk8"
+* It is okay to have tests in a single test source-set
+* And we want to publish a **single** artifact kotlinx-coroutines-core.jar that contains classes from both source-sets
+* Current limitation: only classes from "core" are checked with animal-sniffer
+
+For that, we have following compilations:
+* jvmMain compilation: [jvmCoreMain, jdk8Main]
+* jvmCore compilation: [commonMain]
+* jdk8 compilation: [commonMain, jvmCoreMain]
+
+Theoretically, "jvmCore" could've been "jvmMain", it is not for technical reasons,
+here is the explanation from Seb:
+
+"""
+The jvmCore is theoretically not necessary. All code for jdk6 compatibility can be in jvmMain and jdk8 dependent code can be in jdk8Main.
+Effectively there is no reason for ever putting code into jvmCoreMain.
+However, when creating a new compilation, we have to take care of creating a defaultSourceSet. Without creating the jvmCoreMain source set,
+ the creation of the compilation fails. That is the only reason for this source set.
+"""
+ ========================================================================== */
+
+kotlin {
+ sourceSets {
+ // using the source set names from <https://kotlinlang.org/docs/multiplatform-hierarchy.html#see-the-full-hierarchy-template>
+ groupSourceSets("concurrent", listOf("jvm", "native"), listOf("common"))
+ if (project.nativeTargetsAreEnabled) {
+ // TODO: 'nativeDarwin' behaves exactly like 'apple', we can remove it
+ groupSourceSets("nativeDarwin", listOf("apple"), listOf("native"))
+ groupSourceSets("nativeOther", listOf("linux", "mingw", "androidNative"), listOf("native"))
+ }
+ jvmMain {
+ dependencies {
+ compileOnly("com.google.android:annotations:4.1.1.4")
+ }
+ }
+ jvmTest {
+ dependencies {
+ api("org.jetbrains.kotlinx:lincheck:${version("lincheck")}")
+ api("org.jetbrains.kotlinx:kotlinx-knit-test:${version("knit")}")
+ implementation(project(":android-unit-tests"))
+ implementation("org.openjdk.jol:jol-core:0.16")
+ }
+ }
+ }
+ /*
+ * Configure two test runs for Native:
+ * 1) Main thread
+ * 2) BG thread (required for Dispatchers.Main tests on Darwin)
+ *
+ * All new MM targets are build with optimize = true to have stress tests properly run.
+ */
+ targets.withType(KotlinNativeTargetWithTests::class).configureEach {
+ binaries.getTest(DEBUG).apply {
+ optimized = true
+ }
+
+ binaries.test("workerTest", listOf(DEBUG)) {
+ val thisTest = this
+ optimized = true
+ freeCompilerArgs = freeCompilerArgs + listOf("-e", "kotlinx.coroutines.mainBackground")
+ testRuns.create("workerTest") {
+ this as KotlinTaskTestRun<*, *>
+ setExecutionSourceFrom(thisTest)
+ executionTask.configure {
+ this as KotlinNativeTest
+ targetName = "$targetName worker with new MM"
+ }
+ }
+ }
+ }
+
+ /**
+ * See: https://youtrack.jetbrains.com/issue/KTIJ-25959
+ * The introduction of jvmCore is only for CLI builds and not intended for the IDE.
+ * In the current setup there are two tooling unfriendly configurations used:
+ * 1: - jvmMain, despite being a platform source set, is not a leaf (jvmCoreMain and jdk8Main dependOn it)
+ * 2: - jvmMain effectively becomes a 'shared jvm' source set
+ *
+ * Using this kludge here, will prevent issue 2 from being visible to the IDE.
+ * Therefore jvmMain will resolve using the 'single' compilation it participates in (from the perspective of the IDE)
+ */
+ val jvmCoreMain = if (Idea.active) null else sourceSets.create("jvmCoreMain") {
+ dependsOn(sourceSets.jvmMain.get())
+ }
+ val jdk8Main = sourceSets.create("jdk8Main") {
+ dependsOn(sourceSets.jvmMain.get())
+ }
+
+ jvm {
+ compilations.named("main") {
+ jvmCoreMain?.let { source(it) }
+ source(jdk8Main)
+ }
+
+ /* Create compilation for jvmCore to prove that jvmMain does not rely on jdk8 */
+ compilations.create("CoreMain") {
+ /* jvmCore is automatically matched as 'defaultSourceSet' for the compilation, due to its name */
+ tasks.getByName("check").dependsOn(compileTaskProvider)
+ }
+
+ // For animal sniffer
+ withJava()
+ compilations.create("benchmark") { associateWith([email protected]("main")) }
+ }
+}
+
+benchmark {
+ targets {
+ register("jvmBenchmark")
+ }
+}
+
+// Update module name for metadata artifact to avoid conflicts
+// see https://github.com/Kotlin/kotlinx.coroutines/issues/1797
+val compileKotlinMetadata by tasks.getting(KotlinCompilationTask::class) {
+ compilerOptions {
+ freeCompilerArgs.addAll("-module-name", "kotlinx-coroutines-core-common")
+ }
+}
+
+val jvmTest by tasks.getting(Test::class) {
+ minHeapSize = "1g"
+ maxHeapSize = "1g"
+ enableAssertions = true
+ if (!Idea.active) {
+ // We should not set this security manager when `jvmTest`
+ // is invoked by IntelliJ IDEA since we need to pass
+ // system properties for Lincheck and stress tests.
+ // TODO Remove once IDEA is smart enough to select between `jvmTest`/`jvmStressTest`/`jvmLincheckTest` #KTIJ-599
+ systemProperty("java.security.manager", "kotlinx.coroutines.TestSecurityManager")
+ }
+ // 'stress' is required to be able to run all subpackage tests like ":jvmTests --tests "*channels*" -Pstress=true"
+ if (!Idea.active && rootProject.properties["stress"] == null) {
+ exclude("**/*LincheckTest*")
+ exclude("**/*StressTest.*")
+ }
+ if (Idea.active) {
+ // Configure the IDEA runner for Lincheck
+ configureJvmForLincheck()
+ }
+}
+
+// Setup manifest for kotlinx-coroutines-core-jvm.jar
+val jvmJar by tasks.getting(Jar::class) { setupManifest(this) }
+
+/*
+ * Setup manifest for kotlinx-coroutines-core.jar
+ * This is convenient for users that pass -javaagent arg manually and also is a workaround #2619 and KTIJ-5659.
+ * This manifest contains reference to AgentPremain that belongs to
+ * kotlinx-coroutines-core-jvm, but our resolving machinery guarantees that
+ * any JVM project that depends on -core artifact also depends on -core-jvm one.
+ */
+val allMetadataJar by tasks.getting(Jar::class) { setupManifest(this) }
+
+fun setupManifest(jar: Jar) {
+ jar.manifest {
+ attributes(mapOf(
+ "Premain-Class" to "kotlinx.coroutines.debug.AgentPremain",
+ "Can-Retransform-Classes" to "true",
+ ))
+ }
+}
+
+val compileTestKotlinJvm by tasks.getting(KotlinJvmCompile::class)
+val jvmTestClasses by tasks.getting
+
+val jvmStressTest by tasks.registering(Test::class) {
+ dependsOn(compileTestKotlinJvm)
+ classpath = jvmTest.classpath
+ testClassesDirs = jvmTest.testClassesDirs
+ minHeapSize = "1g"
+ maxHeapSize = "1g"
+ include("**/*StressTest.*")
+ enableAssertions = true
+ testLogging.showStandardStreams = true
+ systemProperty("kotlinx.coroutines.scheduler.keep.alive.sec", 100000) // any unpark problem hangs test
+ // Adjust internal algorithmic parameters to increase the testing quality instead of performance.
+ systemProperty("kotlinx.coroutines.semaphore.segmentSize", 1)
+ systemProperty("kotlinx.coroutines.semaphore.maxSpinCycles", 10)
+ systemProperty("kotlinx.coroutines.bufferedChannel.segmentSize", 2)
+ systemProperty("kotlinx.coroutines.bufferedChannel.expandBufferCompletionWaitIterations", 1)
+}
+
+val jvmLincheckTest by tasks.registering(Test::class) {
+ dependsOn(compileTestKotlinJvm)
+ classpath = jvmTest.classpath
+ testClassesDirs = jvmTest.testClassesDirs
+ include("**/*LincheckTest*")
+ enableAssertions = true
+ testLogging.showStandardStreams = true
+ configureJvmForLincheck()
+}
+
+// Additional Lincheck tests with `segmentSize = 2`.
+// Some bugs cannot be revealed when storing one request per segment,
+// and some are hard to detect when storing multiple requests.
+val jvmLincheckTestAdditional by tasks.registering(Test::class) {
+ dependsOn(compileTestKotlinJvm)
+ classpath = jvmTest.classpath
+ testClassesDirs = jvmTest.testClassesDirs
+ include("**/RendezvousChannelLincheckTest*")
+ include("**/Buffered1ChannelLincheckTest*")
+ include("**/Semaphore*LincheckTest*")
+ enableAssertions = true
+ testLogging.showStandardStreams = true
+ configureJvmForLincheck(segmentSize = 2)
+}
+
+fun Test.configureJvmForLincheck(segmentSize: Int = 1) {
+ minHeapSize = "1g"
+ maxHeapSize = "4g" // we may need more space for building an interleaving tree in the model checking mode
+ // https://github.com/JetBrains/lincheck#java-9
+ jvmArgs = listOf("--add-opens", "java.base/jdk.internal.misc=ALL-UNNAMED", // required for transformation
+ "--add-exports", "java.base/sun.security.action=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.util=ALL-UNNAMED") // in the model checking mode
+ // Adjust internal algorithmic parameters to increase the testing quality instead of performance.
+ systemProperty("kotlinx.coroutines.semaphore.segmentSize", segmentSize)
+ systemProperty("kotlinx.coroutines.semaphore.maxSpinCycles", 1) // better for the model checking mode
+ systemProperty("kotlinx.coroutines.bufferedChannel.segmentSize", segmentSize)
+ systemProperty("kotlinx.coroutines.bufferedChannel.expandBufferCompletionWaitIterations", 1)
+}
+
+// Always check additional test sets
+val moreTest by tasks.registering {
+ dependsOn(listOf(jvmStressTest, jvmLincheckTest, jvmLincheckTestAdditional))
+}
+
+val check by tasks.getting {
+ dependsOn(moreTest)
+}
+
+kover {
+ currentProject {
+ instrumentation {
+ // Always disabled, lincheck doesn't really support coverage
+ disabledForTestTasks.addAll("jvmLincheckTest")
+
+ // lincheck has NPE error on `ManagedStrategyStateHolder` class
+ excludedClasses.addAll("org.jetbrains.kotlinx.lincheck.*")
+ }
+ }
+
+ reports {
+ filters {
+ excludes {
+ classes(
+ "kotlinx.coroutines.debug.*", // Tested by debug module
+ "kotlinx.coroutines.channels.ChannelsKt__DeprecatedKt*", // Deprecated
+ "kotlinx.coroutines.scheduling.LimitingDispatcher", // Deprecated
+ "kotlinx.coroutines.scheduling.ExperimentalCoroutineDispatcher", // Deprecated
+ "kotlinx.coroutines.flow.FlowKt__MigrationKt*", // Migrations
+ "kotlinx.coroutines.flow.LintKt*", // Migrations
+ "kotlinx.coroutines.internal.WeakMapCtorCache", // Fallback implementation that we never test
+ "_COROUTINE._CREATION", // For IDE navigation
+ "_COROUTINE._BOUNDARY", // For IDE navigation
+ )
+ }
+ }
+ }
+}
+
+val testsJar by tasks.registering(Jar::class) {
+ dependsOn(jvmTestClasses)
+ archiveClassifier = "tests"
+ from(compileTestKotlinJvm.destinationDirectory)
+}
+
+artifacts {
+ archives(testsJar)
+}
+
+// Workaround for https://github.com/Kotlin/dokka/issues/1833: make implicit dependency explicit
+tasks.named("dokkaHtmlPartial") {
+ dependsOn(jvmJar)
+}
diff --git a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt
index 439a9ac..56e9608 100644
--- a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt
+++ b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.coroutines
@@ -19,10 +16,10 @@
*
* The following methods are available for override:
*
- * * [onStart] is invoked when the coroutine was created in non-active state and is being [started][Job.start].
- * * [onCancelling] is invoked as soon as the coroutine starts being cancelled for any reason (or completes).
- * * [onCompleted] is invoked when the coroutine completes with a value.
- * * [onCancelled] in invoked when the coroutine completes with an exception (cancelled).
+ * - [onStart] is invoked when the coroutine was created in non-active state and is being [started][Job.start].
+ * - [onCancelling] is invoked as soon as the coroutine starts being cancelled for any reason (or completes).
+ * - [onCompleted] is invoked when the coroutine completes with a value.
+ * - [onCancelled] in invoked when the coroutine completes with an exception (cancelled).
*
* @param parentContext the context of the parent coroutine.
* @param initParentJob specifies whether the parent-child relationship should be instantiated directly
@@ -117,10 +114,10 @@
* Starts this coroutine with the given code [block] and [start] strategy.
* This function shall be invoked at most once on this coroutine.
*
- * * [DEFAULT] uses [startCoroutineCancellable].
- * * [ATOMIC] uses [startCoroutine].
- * * [UNDISPATCHED] uses [startCoroutineUndispatched].
- * * [LAZY] does nothing.
+ * - [DEFAULT] uses [startCoroutineCancellable].
+ * - [ATOMIC] uses [startCoroutine].
+ * - [UNDISPATCHED] uses [startCoroutineUndispatched].
+ * - [LAZY] does nothing.
*/
public fun <R> start(start: CoroutineStart, receiver: R, block: suspend R.() -> T) {
start(block, receiver, this)
diff --git a/kotlinx-coroutines-core/common/src/Annotations.kt b/kotlinx-coroutines-core/common/src/Annotations.kt
index bacce39..b35da67 100644
--- a/kotlinx-coroutines-core/common/src/Annotations.kt
+++ b/kotlinx-coroutines-core/common/src/Annotations.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.flow.*
diff --git a/kotlinx-coroutines-core/common/src/Await.kt b/kotlinx-coroutines-core/common/src/Await.kt
index c1669e2..b8a76f1 100644
--- a/kotlinx-coroutines-core/common/src/Await.kt
+++ b/kotlinx-coroutines-core/common/src/Await.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
@@ -15,11 +11,10 @@
* This function is **not** equivalent to `deferreds.map { it.await() }` which fails only when it sequentially
* gets to wait for the failing deferred, while this `awaitAll` fails immediately as soon as any of the deferreds fail.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
- * this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*/
public suspend fun <T> awaitAll(vararg deferreds: Deferred<T>): List<T> =
if (deferreds.isEmpty()) emptyList() else AwaitAll(deferreds).await()
@@ -32,11 +27,10 @@
* This function is **not** equivalent to `this.map { it.await() }` which fails only when it sequentially
* gets to wait for the failing deferred, while this `awaitAll` fails immediately as soon as any of the deferreds fail.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
- * this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*/
public suspend fun <T> Collection<Deferred<T>>.awaitAll(): List<T> =
if (isEmpty()) emptyList() else AwaitAll(toTypedArray()).await()
@@ -45,11 +39,10 @@
* Suspends current coroutine until all given jobs are complete.
* This method is semantically equivalent to joining all given jobs one by one with `jobs.forEach { it.join() }`.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
- * this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*/
public suspend fun joinAll(vararg jobs: Job): Unit = jobs.forEach { it.join() }
@@ -57,11 +50,10 @@
* Suspends current coroutine until all given jobs are complete.
* This method is semantically equivalent to joining all given jobs one by one with `forEach { it.join() }`.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
- * this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*/
public suspend fun Collection<Job>.joinAll(): Unit = forEach { it.join() }
@@ -75,7 +67,7 @@
val deferred = deferreds[i]
deferred.start() // To properly await lazily started deferreds
AwaitAllNode(cont).apply {
- handle = deferred.invokeOnCompletion(asHandler)
+ handle = deferred.invokeOnCompletion(handler = this)
}
}
val disposer = DisposeHandlersOnCancel(nodes)
@@ -87,11 +79,11 @@
// it is already complete while handlers were being installed -- dispose them all
disposer.disposeAll()
} else {
- cont.invokeOnCancellation(handler = disposer.asHandler)
+ cont.invokeOnCancellation(handler = disposer)
}
}
- private inner class DisposeHandlersOnCancel(private val nodes: Array<AwaitAllNode>) : CancelHandler() {
+ private inner class DisposeHandlersOnCancel(private val nodes: Array<AwaitAllNode>) : CancelHandler {
fun disposeAll() {
nodes.forEach { it.handle.dispose() }
}
diff --git a/kotlinx-coroutines-core/common/src/Builders.common.kt b/kotlinx-coroutines-core/common/src/Builders.common.kt
index bcb2dd8..95c1be8 100644
--- a/kotlinx-coroutines-core/common/src/Builders.common.kt
+++ b/kotlinx-coroutines-core/common/src/Builders.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("BuildersKt")
@file:OptIn(ExperimentalContracts::class)
diff --git a/kotlinx-coroutines-core/common/src/CancellableContinuation.kt b/kotlinx-coroutines-core/common/src/CancellableContinuation.kt
index e3237e5..4e3fc8a 100644
--- a/kotlinx-coroutines-core/common/src/CancellableContinuation.kt
+++ b/kotlinx-coroutines-core/common/src/CancellableContinuation.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -126,28 +122,27 @@
/**
* Registers a [handler] to be **synchronously** invoked on [cancellation][cancel] (regular or exceptional) of this continuation.
- * When the continuation is already cancelled, the handler is immediately invoked
- * with the cancellation exception. Otherwise, the handler will be invoked as soon as this
- * continuation is cancelled.
+ * When the continuation is already cancelled, the handler is immediately invoked with the cancellation exception.
+ * Otherwise, the handler will be invoked as soon as this continuation is cancelled.
*
* The installed [handler] should not throw any exceptions.
* If it does, they will get caught, wrapped into a [CompletionHandlerException] and
* processed as an uncaught exception in the context of the current coroutine
* (see [CoroutineExceptionHandler]).
*
- * At most one [handler] can be installed on a continuation. Attempt to call `invokeOnCancellation` second
- * time produces [IllegalStateException].
+ * At most one [handler] can be installed on a continuation.
+ * Attempting to call `invokeOnCancellation` a second time produces an [IllegalStateException].
*
* This handler is also called when this continuation [resumes][Continuation.resume] normally (with a value) and then
* is cancelled while waiting to be dispatched. More generally speaking, this handler is called whenever
* the caller of [suspendCancellableCoroutine] is getting a [CancellationException].
*
- * A typical example for `invokeOnCancellation` usage is given in
+ * A typical example of `invokeOnCancellation` usage is given in
* the documentation for the [suspendCancellableCoroutine] function.
*
- * **Note**: Implementation of `CompletionHandler` must be fast, non-blocking, and thread-safe.
- * This `handler` can be invoked concurrently with the surrounding code.
- * There is no guarantee on the execution context in which the `handler` will be invoked.
+ * **Note**: Implementations of [CompletionHandler] must be fast, non-blocking, and thread-safe.
+ * This [handler] can be invoked concurrently with the surrounding code.
+ * There is no guarantee on the execution context in which the [handler] will be invoked.
*/
public fun invokeOnCancellation(handler: CompletionHandler)
@@ -206,6 +201,15 @@
}
/**
+ * A version of `invokeOnCancellation` that accepts a class as a handler instead of a lambda, but identical otherwise.
+ * This allows providing a custom [toString] instance that will look better during debugging.
+ */
+internal fun <T> CancellableContinuation<T>.invokeOnCancellation(handler: CancelHandler) = when (this) {
+ is CancellableContinuationImpl -> invokeOnCancellationInternal(handler)
+ else -> throw UnsupportedOperationException("third-party implementation of CancellableContinuation is not supported")
+}
+
+/**
* Suspends the coroutine like [suspendCoroutine], but providing a [CancellableContinuation] to
* the [block]. This function throws a [CancellationException] if the [Job] of the coroutine is
* cancelled or completed while it is suspended.
@@ -242,28 +246,28 @@
*
* This function provides **prompt cancellation guarantee**.
* If the [Job] of the current coroutine was cancelled while this function was suspended it will not resume
- * successfully.
+ * successfully, even if [CancellableContinuation.resume] was already invoked.
*
* The cancellation of the coroutine's job is generally asynchronous with respect to the suspended coroutine.
- * The suspended coroutine is resumed with the call it to its [Continuation.resumeWith] member function or to
+ * The suspended coroutine is resumed with a call to its [Continuation.resumeWith] member function or to the
* [resume][Continuation.resume] extension function.
* However, when coroutine is resumed, it does not immediately start executing, but is passed to its
* [CoroutineDispatcher] to schedule its execution when dispatcher's resources become available for execution.
- * The job's cancellation can happen both before, after, and concurrently with the call to `resume`. In any
- * case, prompt cancellation guarantees that the the coroutine will not resume its code successfully.
+ * The job's cancellation can happen before, after, and concurrently with the call to `resume`. In any
+ * case, prompt cancellation guarantees that the coroutine will not resume its code successfully.
*
* If the coroutine was resumed with an exception (for example, using [Continuation.resumeWithException] extension
- * function) and cancelled, then the resulting exception of the `suspendCancellableCoroutine` function is determined
- * by whichever action (exceptional resume or cancellation) that happened first.
+ * function) and cancelled, then the exception thrown by the `suspendCancellableCoroutine` function is determined
+ * by what happened first: exceptional resume or cancellation.
*
* ### Returning resources from a suspended coroutine
*
- * As a result of a prompt cancellation guarantee, when a closeable resource
- * (like open file or a handle to another native resource) is returned from a suspended coroutine as a value
- * it can be lost when the coroutine is cancelled. In order to ensure that the resource can be properly closed
+ * As a result of the prompt cancellation guarantee, when a closeable resource
+ * (like open file or a handle to another native resource) is returned from a suspended coroutine as a value,
+ * it can be lost when the coroutine is cancelled. To ensure that the resource can be properly closed
* in this case, the [CancellableContinuation] interface provides two functions.
*
- * * [invokeOnCancellation][CancellableContinuation.invokeOnCancellation] installs a handler that is called
+ * - [invokeOnCancellation][CancellableContinuation.invokeOnCancellation] installs a handler that is called
* whenever a suspend coroutine is being cancelled. In addition to the example at the beginning, it can be
* used to ensure that a resource that was opened before the call to
* `suspendCancellableCoroutine` or in its body is closed in case of cancellation.
@@ -278,7 +282,7 @@
* }
* ```
*
- * * [resume(value) { ... }][CancellableContinuation.resume] method on a [CancellableContinuation] takes
+ * - [resume(value) { ... }][CancellableContinuation.resume] method on a [CancellableContinuation] takes
* an optional `onCancellation` block. It can be used when resuming with a resource that must be closed by
* the code that called the corresponding suspending function.
*
@@ -377,9 +381,9 @@
*/
@InternalCoroutinesApi
public fun CancellableContinuation<*>.disposeOnCancellation(handle: DisposableHandle): Unit =
- invokeOnCancellation(handler = DisposeOnCancel(handle).asHandler)
+ invokeOnCancellation(handler = DisposeOnCancel(handle))
-private class DisposeOnCancel(private val handle: DisposableHandle) : CancelHandler() {
+private class DisposeOnCancel(private val handle: DisposableHandle) : CancelHandler {
override fun invoke(cause: Throwable?) = handle.dispose()
override fun toString(): String = "DisposeOnCancel[$handle]"
}
diff --git a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt
index ed2d9f2..b7c6111 100644
--- a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt
+++ b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
@@ -88,11 +84,11 @@
* - installParentHandle publishes this instance on T1
*
* T1 writes:
- * * handle = installed; right after the installation
- * * Shortly after: if (isComplete) handle = NonDisposableHandle
+ * - handle = installed; right after the installation
+ * - Shortly after: if (isComplete) handle = NonDisposableHandle
*
* Any other T writes if the parent job is cancelled in detachChild:
- * * handle = NonDisposableHandle
+ * - handle = NonDisposableHandle
*
* We want to preserve a strict invariant on parentHandle transition, allowing only three of them:
* null -> anyHandle
@@ -238,12 +234,12 @@
}
}
- private fun callCancelHandler(handler: CompletionHandler, cause: Throwable?) =
+ private fun callCancelHandler(handler: InternalCompletionHandler, cause: Throwable?) =
/*
* :KLUDGE: We have to invoke a handler in platform-specific way via `invokeIt` extension,
* because we play type tricks on Kotlin/JS and handler is not necessarily a function there
*/
- callCancelHandlerSafely { handler.invokeIt(cause) }
+ callCancelHandlerSafely { handler.invoke(cause) }
fun callCancelHandler(handler: CancelHandler, cause: Throwable?) =
callCancelHandlerSafely { handler.invoke(cause) }
@@ -347,7 +343,7 @@
// Install the handle
val handle = parent.invokeOnCompletion(
onCancelling = true,
- handler = ChildContinuation(this).asHandler
+ handler = ChildContinuation(this)
)
_parentHandle.compareAndSet(null, handle)
return handle
@@ -394,10 +390,9 @@
invokeOnCancellationImpl(segment)
}
- public override fun invokeOnCancellation(handler: CompletionHandler) {
- val cancelHandler = makeCancelHandler(handler)
- invokeOnCancellationImpl(cancelHandler)
- }
+ override fun invokeOnCancellation(handler: CompletionHandler) = invokeOnCancellation(CancelHandler.UserSupplied(handler))
+
+ internal fun invokeOnCancellationInternal(handler: CancelHandler) = invokeOnCancellationImpl(handler)
private fun invokeOnCancellationImpl(handler: Any) {
assert { handler is CancelHandler || handler is Segment<*> }
@@ -465,9 +460,6 @@
error("It's prohibited to register multiple handlers, tried to register $handler, already has $state")
}
- private fun makeCancelHandler(handler: CompletionHandler): CancelHandler =
- if (handler is CancelHandler) handler else InvokeOnCancel(handler)
-
private fun dispatchResume(mode: Int) {
if (tryResume()) return // completed before getResult invocation -- bail out
// otherwise, getResult has already commenced, i.e. completed later or in other thread
@@ -629,19 +621,46 @@
}
/**
- * Base class for all [CancellableContinuation.invokeOnCancellation] handlers to avoid an extra instance
- * on JVM, yet support JS where you cannot extend from a functional type.
+ * Essentially the same as just a function from `Throwable?` to `Unit`.
+ * The only thing implementors can do is call [invoke].
+ * The reason this abstraction exists is to allow providing a readable [toString] in the list of completion handlers
+ * as seen from the debugger.
+ * Use [UserSupplied] to create an instance from a lambda.
+ * We can't avoid defining a separate type, because on JS, you can't inherit from a function type.
+ *
+ * @see InternalCompletionHandler for a very similar interface, but used for handling completion and not cancellation.
*/
-internal abstract class CancelHandler : CancelHandlerBase(), NotCompleted
+internal interface CancelHandler : NotCompleted {
+ /**
+ * Signals cancellation.
+ *
+ * This function:
+ * - Does not throw any exceptions.
+ * Violating this rule in an implementation leads to [handleUncaughtCoroutineException] being called with a
+ * [CompletionHandlerException] wrapping the thrown exception.
+ * - Is fast, non-blocking, and thread-safe.
+ * - Can be invoked concurrently with the surrounding code.
+ * - Can be invoked from any context.
+ *
+ * The meaning of `cause` that is passed to the handler is:
+ * - It is `null` if the continuation was cancelled directly via [CancellableContinuation.cancel] without a `cause`.
+ * - It is an instance of [CancellationException] if the continuation was _normally_ cancelled from the outside.
+ * **It should not be treated as an error**. In particular, it should not be reported to error logs.
+ * - Otherwise, the continuation had cancelled with an _error_.
+ */
+ fun invoke(cause: Throwable?)
-// Wrapper for lambdas, for the performance sake CancelHandler can be subclassed directly
-private class InvokeOnCancel( // Clashes with InvokeOnCancellation
- private val handler: CompletionHandler
-) : CancelHandler() {
- override fun invoke(cause: Throwable?) {
- handler.invoke(cause)
+ /**
+ * A lambda passed from outside the coroutine machinery.
+ *
+ * See the requirements for [CancelHandler.invoke] when implementing this function.
+ */
+ class UserSupplied(private val handler: (cause: Throwable?) -> Unit) : CancelHandler {
+ /** @suppress */
+ override fun invoke(cause: Throwable?) { handler(cause) }
+
+ override fun toString() = "CancelHandler.UserSupplied[${handler.classSimpleName}@$hexAddress]"
}
- override fun toString() = "InvokeOnCancel[${handler.classSimpleName}@$hexAddress]"
}
// Completed with additional metadata
diff --git a/kotlinx-coroutines-core/common/src/CloseableCoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/CloseableCoroutineDispatcher.kt
index 541b308..1ed0eb1 100644
--- a/kotlinx-coroutines-core/common/src/CloseableCoroutineDispatcher.kt
+++ b/kotlinx-coroutines-core/common/src/CloseableCoroutineDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt
index 293c516..abb6aea 100644
--- a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt
+++ b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.coroutines
diff --git a/kotlinx-coroutines-core/common/src/CompletableJob.kt b/kotlinx-coroutines-core/common/src/CompletableJob.kt
index beafdaf..f3ac8dc 100644
--- a/kotlinx-coroutines-core/common/src/CompletableJob.kt
+++ b/kotlinx-coroutines-core/common/src/CompletableJob.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt b/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt
index e712ff1..0a0176e 100644
--- a/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt
+++ b/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt
@@ -1,47 +1,71 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
-import kotlinx.coroutines.internal.*
-
/**
* Handler for [Job.invokeOnCompletion] and [CancellableContinuation.invokeOnCancellation].
*
- * Installed handler should not throw any exceptions. If it does, they will get caught,
- * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
- *
- * The meaning of `cause` that is passed to the handler:
- * * Cause is `null` when the job has completed normally.
- * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
+ * The meaning of `cause` that is passed to the handler is:
+ * - It is `null` if the job has completed normally or the continuation was cancelled without a `cause`.
+ * - It is an instance of [CancellationException] if the job or the continuation was cancelled _normally_.
* **It should not be treated as an error**. In particular, it should not be reported to error logs.
- * * Otherwise, the job had _failed_.
+ * - Otherwise, the job or the continuation had _failed_.
+ *
+ * A function used for this should not throw any exceptions.
+ * If it does, they will get caught, wrapped into [CompletionHandlerException], and then either
+ * - passed to [handleCoroutineException] for [CancellableContinuation.invokeOnCancellation]
+ * and, for [Job] instances that are coroutines, [Job.invokeOnCompletion], or
+ * - for [Job] instances that are not coroutines, simply thrown, potentially crashing unrelated code.
+ *
+ * Functions used for this must be fast, non-blocking, and thread-safe.
+ * This handler can be invoked concurrently with the surrounding code.
+ * There is no guarantee on the execution context in which the function is invoked.
*
* **Note**: This type is a part of internal machinery that supports parent-child hierarchies
* and allows for implementation of suspending functions that wait on the Job's state.
* This type should not be used in general application code.
- * Implementations of `CompletionHandler` must be fast and _lock-free_.
*/
+// TODO: deprecate. This doesn't seem better than a simple function type.
public typealias CompletionHandler = (cause: Throwable?) -> Unit
-// We want class that extends LockFreeLinkedListNode & CompletionHandler but we cannot do it on Kotlin/JS,
-// so this expect class provides us with the corresponding abstraction in a platform-agnostic way.
-internal expect abstract class CompletionHandlerBase() : LockFreeLinkedListNode {
- abstract fun invoke(cause: Throwable?)
+/**
+ * Essentially the same as just a function from `Throwable?` to `Unit`.
+ * The only thing implementors can do is call [invoke].
+ * The reason this abstraction exists is to allow providing a readable [toString] in the list of completion handlers
+ * as seen from the debugger.
+ * Use [UserSupplied] to create an instance from a lambda.
+ * We can't avoid defining a separate type, because on JS, you can't inherit from a function type.
+ *
+ * @see CancelHandler for a very similar interface, but used for handling cancellation and not completion.
+ */
+internal interface InternalCompletionHandler {
+ /**
+ * Signals completion.
+ *
+ * This function:
+ * - Does not throw any exceptions.
+ * For [Job] instances that are coroutines, exceptions thrown by this function will be caught, wrapped into
+ * [CompletionHandlerException], and passed to [handleCoroutineException], but for those that are not coroutines,
+ * they will just be rethrown, potentially crashing unrelated code.
+ * - Is fast, non-blocking, and thread-safe.
+ * - Can be invoked concurrently with the surrounding code.
+ * - Can be invoked from any context.
+ *
+ * The meaning of `cause` that is passed to the handler is:
+ * - It is `null` if the job has completed normally.
+ * - It is an instance of [CancellationException] if the job was cancelled _normally_.
+ * **It should not be treated as an error**. In particular, it should not be reported to error logs.
+ * - Otherwise, the job had _failed_.
+ */
+ fun invoke(cause: Throwable?)
+
+ /**
+ * A lambda passed from outside the coroutine machinery.
+ *
+ * See the requirements for [InternalCompletionHandler.invoke] when implementing this function.
+ */
+ class UserSupplied(private val handler: (cause: Throwable?) -> Unit) : InternalCompletionHandler {
+ /** @suppress */
+ override fun invoke(cause: Throwable?) { handler(cause) }
+
+ override fun toString() = "InternalCompletionHandler.UserSupplied[${handler.classSimpleName}@$hexAddress]"
+ }
}
-
-internal expect val CompletionHandlerBase.asHandler: CompletionHandler
-
-// More compact version of CompletionHandlerBase for CancellableContinuation with same workaround for JS
-internal expect abstract class CancelHandlerBase() {
- abstract fun invoke(cause: Throwable?)
-}
-
-internal expect val CancelHandlerBase.asHandler: CompletionHandler
-
-// :KLUDGE: We have to invoke a handler in platform-specific way via `invokeIt` extension,
-// because we play type tricks on Kotlin/JS and handler is not necessarily a function there
-internal expect fun CompletionHandler.invokeIt(cause: Throwable?)
-
-internal inline fun <reified T> CompletionHandler.isHandlerOf(): Boolean = this is T
diff --git a/kotlinx-coroutines-core/common/src/CompletionState.kt b/kotlinx-coroutines-core/common/src/CompletionState.kt
index 43330af..b9fefa5 100644
--- a/kotlinx-coroutines-core/common/src/CompletionState.kt
+++ b/kotlinx-coroutines-core/common/src/CompletionState.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt b/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt
index 9153f39..48e59fe 100644
--- a/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt
+++ b/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
@@ -20,7 +16,7 @@
@InternalCoroutinesApi
public expect fun CoroutineContext.newCoroutineContext(addedContext: CoroutineContext): CoroutineContext
-@PublishedApi
+@PublishedApi // to have unmangled name when using from other modules via suppress
@Suppress("PropertyName")
internal expect val DefaultDelay: Delay
diff --git a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt
index 568353b..e9d9f19 100644
--- a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt
+++ b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -13,18 +9,18 @@
* The following standard implementations are provided by `kotlinx.coroutines` as properties on
* the [Dispatchers] object:
*
- * * [Dispatchers.Default] — is used by all standard builders if no dispatcher or any other [ContinuationInterceptor]
+ * - [Dispatchers.Default] — is used by all standard builders if no dispatcher or any other [ContinuationInterceptor]
* is specified in their context. It uses a common pool of shared background threads.
* This is an appropriate choice for compute-intensive coroutines that consume CPU resources.
- * * [Dispatchers.IO] — uses a shared pool of on-demand created threads and is designed for offloading of IO-intensive _blocking_
+ * - [Dispatchers.IO] — uses a shared pool of on-demand created threads and is designed for offloading of IO-intensive _blocking_
* operations (like file I/O and blocking socket I/O).
- * * [Dispatchers.Unconfined] — starts coroutine execution in the current call-frame until the first suspension,
+ * - [Dispatchers.Unconfined] — starts coroutine execution in the current call-frame until the first suspension,
* whereupon the coroutine builder function returns.
* The coroutine will later resume in whatever thread used by the
* corresponding suspending function, without confining it to any specific thread or pool.
* **The `Unconfined` dispatcher should not normally be used in code**.
- * * Private thread pools can be created with [newSingleThreadContext] and [newFixedThreadPoolContext].
- * * An arbitrary [Executor][java.util.concurrent.Executor] can be converted to a dispatcher with the [asCoroutineDispatcher] extension function.
+ * - Private thread pools can be created with [newSingleThreadContext] and [newFixedThreadPoolContext].
+ * - An arbitrary [Executor][java.util.concurrent.Executor] can be converted to a dispatcher with the [asCoroutineDispatcher] extension function.
*
* This class ensures that debugging facilities in [newCoroutineContext] function work properly.
*/
diff --git a/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt b/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt
index e641447..db77c0d 100644
--- a/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt
+++ b/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -35,7 +31,7 @@
internal fun handlerException(originalException: Throwable, thrownException: Throwable): Throwable {
if (originalException === thrownException) return originalException
return RuntimeException("Exception while trying to handle coroutine exception", thrownException).apply {
- addSuppressedThrowable(originalException)
+ addSuppressed(originalException)
}
}
@@ -85,9 +81,9 @@
* ### Uncaught exceptions with no handler
*
* When no handler is installed, exception are handled in the following way:
- * * If exception is [CancellationException], it is ignored, as these exceptions are used to cancel coroutines.
- * * Otherwise, if there is a [Job] in the context, then [Job.cancel] is invoked.
- * * Otherwise, as a last resort, the exception is processed in a platform-specific manner:
+ * - If exception is [CancellationException], it is ignored, as these exceptions are used to cancel coroutines.
+ * - Otherwise, if there is a [Job] in the context, then [Job.cancel] is invoked.
+ * - Otherwise, as a last resort, the exception is processed in a platform-specific manner:
* - On JVM, all instances of [CoroutineExceptionHandler] found via [ServiceLoader], as well as
* the current thread's [Thread.uncaughtExceptionHandler], are invoked.
* - On Native, the whole application crashes with the exception.
diff --git a/kotlinx-coroutines-core/common/src/CoroutineName.kt b/kotlinx-coroutines-core/common/src/CoroutineName.kt
index dc3f1c0..82b45c8 100644
--- a/kotlinx-coroutines-core/common/src/CoroutineName.kt
+++ b/kotlinx-coroutines-core/common/src/CoroutineName.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.AbstractCoroutineContextElement
diff --git a/kotlinx-coroutines-core/common/src/CoroutineScope.kt b/kotlinx-coroutines-core/common/src/CoroutineScope.kt
index b0928d5..2d37d15 100644
--- a/kotlinx-coroutines-core/common/src/CoroutineScope.kt
+++ b/kotlinx-coroutines-core/common/src/CoroutineScope.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:OptIn(ExperimentalContracts::class)
package kotlinx.coroutines
@@ -45,9 +42,9 @@
* responsible for launching child coroutines. The corresponding instance of `CoroutineScope` shall be created
* with either `CoroutineScope()` or `MainScope()`:
*
- * * `CoroutineScope()` uses the [context][CoroutineContext] provided to it as a parameter for its coroutines
+ * - `CoroutineScope()` uses the [context][CoroutineContext] provided to it as a parameter for its coroutines
* and adds a [Job] if one is not provided as part of the context.
- * * `MainScope()` uses [Dispatchers.Main] for its coroutines and has a [SupervisorJob].
+ * - `MainScope()` uses [Dispatchers.Main] for its coroutines and has a [SupervisorJob].
*
* **The key part of custom usage of `CoroutineScope` is cancelling it at the end of the lifecycle.**
* The [CoroutineScope.cancel] extension function shall be used when the entity that was launching coroutines
@@ -90,7 +87,7 @@
* Adds the specified coroutine context to this scope, overriding existing elements in the current
* scope's context with the corresponding keys.
*
- * This is a shorthand for `CoroutineScope(thisScope + context)`.
+ * This is a shorthand for `CoroutineScope(thisScope.coroutineContext + context)`.
*/
public operator fun CoroutineScope.plus(context: CoroutineContext): CoroutineScope =
ContextScope(coroutineContext + context)
@@ -223,13 +220,13 @@
/**
* Creates a [CoroutineScope] and calls the specified suspend block with this scope.
- * The provided scope inherits its [coroutineContext][CoroutineScope.coroutineContext] from the outer scope, but overrides
- * the context's [Job].
+ * The provided scope inherits its [coroutineContext][CoroutineScope.coroutineContext] from the outer scope, using the
+ * [Job] from that context as the parent for a new [Job].
*
- * This function is designed for _parallel decomposition_ of work. When any child coroutine in this scope fails,
- * this scope fails and all the rest of the children are cancelled (for a different behavior see [supervisorScope]).
- * This function returns as soon as the given block and all its children coroutines are completed.
- * A usage example of a scope looks like this:
+ * This function is designed for _concurrent decomposition_ of work. When any child coroutine in this scope fails,
+ * this scope fails, cancelling all the other children (for a different behavior, see [supervisorScope]).
+ * This function returns as soon as the given block and all its child coroutines are completed.
+ * A usage of a scope looks like this:
*
* ```
* suspend fun showSomeData() = coroutineScope {
@@ -251,8 +248,8 @@
* 3) If the outer scope of `showSomeData` is cancelled, both started `async` and `withContext` blocks are cancelled.
* 4) If the `async` block fails, `withContext` will be cancelled.
*
- * The method may throw a [CancellationException] if the current job was cancelled externally
- * or may throw a corresponding unhandled [Throwable] if there is any unhandled exception in this scope
+ * The method may throw a [CancellationException] if the current job was cancelled externally,
+ * rethrow the exception thrown by [block], or throw an unhandled [Throwable] if there is one
* (for example, from a crashed coroutine that was started with [launch][CoroutineScope.launch] in this scope).
*/
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R {
diff --git a/kotlinx-coroutines-core/common/src/CoroutineStart.kt b/kotlinx-coroutines-core/common/src/CoroutineStart.kt
index 6059829..640e156 100644
--- a/kotlinx-coroutines-core/common/src/CoroutineStart.kt
+++ b/kotlinx-coroutines-core/common/src/CoroutineStart.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
import kotlinx.coroutines.CoroutineStart.*
@@ -12,10 +9,10 @@
* It is used in `start` parameter of [launch][CoroutineScope.launch], [async][CoroutineScope.async], and other coroutine builder functions.
*
* The summary of coroutine start options is:
- * * [DEFAULT] -- immediately schedules coroutine for execution according to its context;
- * * [LAZY] -- starts coroutine lazily, only when it is needed;
- * * [ATOMIC] -- atomically (in a non-cancellable way) schedules coroutine for execution according to its context;
- * * [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_.
+ * - [DEFAULT] -- immediately schedules coroutine for execution according to its context;
+ * - [LAZY] -- starts coroutine lazily, only when it is needed;
+ * - [ATOMIC] -- atomically (in a non-cancellable way) schedules coroutine for execution according to its context;
+ * - [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_.
*/
public enum class CoroutineStart {
/**
@@ -76,31 +73,12 @@
UNDISPATCHED;
/**
- * Starts the corresponding block as a coroutine with this coroutine's start strategy.
- *
- * * [DEFAULT] uses [startCoroutineCancellable].
- * * [ATOMIC] uses [startCoroutine].
- * * [UNDISPATCHED] uses [startCoroutineUndispatched].
- * * [LAZY] does nothing.
- *
- * @suppress **This an internal API and should not be used from general code.**
- */
- @InternalCoroutinesApi
- public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>): Unit =
- when (this) {
- DEFAULT -> block.startCoroutineCancellable(completion)
- ATOMIC -> block.startCoroutine(completion)
- UNDISPATCHED -> block.startCoroutineUndispatched(completion)
- LAZY -> Unit // will start lazily
- }
-
- /**
* Starts the corresponding block with receiver as a coroutine with this coroutine start strategy.
*
- * * [DEFAULT] uses [startCoroutineCancellable].
- * * [ATOMIC] uses [startCoroutine].
- * * [UNDISPATCHED] uses [startCoroutineUndispatched].
- * * [LAZY] does nothing.
+ * - [DEFAULT] uses [startCoroutineCancellable].
+ * - [ATOMIC] uses [startCoroutine].
+ * - [UNDISPATCHED] uses [startCoroutineUndispatched].
+ * - [LAZY] does nothing.
*
* @suppress **This an internal API and should not be used from general code.**
*/
diff --git a/kotlinx-coroutines-core/common/src/Debug.common.kt b/kotlinx-coroutines-core/common/src/Debug.common.kt
index 185ad29..07ba28b 100644
--- a/kotlinx-coroutines-core/common/src/Debug.common.kt
+++ b/kotlinx-coroutines-core/common/src/Debug.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
internal expect val DEBUG: Boolean
diff --git a/kotlinx-coroutines-core/common/src/Deferred.kt b/kotlinx-coroutines-core/common/src/Deferred.kt
index 2f106e9..afec2cc 100644
--- a/kotlinx-coroutines-core/common/src/Deferred.kt
+++ b/kotlinx-coroutines-core/common/src/Deferred.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.selects.*
@@ -37,24 +33,46 @@
public interface Deferred<out T> : Job {
/**
- * Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete,
- * returning the resulting value or throwing the corresponding exception if the deferred was cancelled.
+ * Awaits for completion of this value without blocking the thread and returns the resulting value or throws
+ * the exception if the deferred was cancelled.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * Unless the calling coroutine is cancelled, [await] will return the same result on each invocation:
+ * if the [Deferred] completed successfully, [await] will return the same value every time;
+ * if the [Deferred] completed exceptionally, [await] will rethrow the same exception.
*
- * This function can be used in [select] invocation with [onAwait] clause.
- * Use [isCompleted] to check for completion of this deferred value without waiting.
+ * This suspending function is itself cancellable: if the [Job] of the current coroutine is cancelled or completed
+ * while this suspending function is waiting, this function immediately resumes with [CancellationException].
+ *
+ * This means that [await] can throw [CancellationException] in two cases:
+ * - if the coroutine in which [await] was called got cancelled,
+ * - or if the [Deferred] itself got completed with a [CancellationException].
+ *
+ * In both cases, the [CancellationException] will cancel the coroutine calling [await], unless it's caught.
+ * The following idiom may be helpful to avoid this:
+ * ```
+ * try {
+ * deferred.await()
+ * } catch (e: CancellationException) {
+ * currentCoroutineContext().ensureActive() // throws if the current coroutine was cancelled
+ * processException(e) // if this line executes, the exception is the result of `await` itself
+ * }
+ * ```
+ *
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
+ *
+ * This function can be used in [select] invocations with an [onAwait] clause.
+ * Use [isCompleted] to check for completion of this deferred value without waiting, and
+ * [join] to wait for completion without returning the result.
*/
public suspend fun await(): T
/**
- * Clause for [select] expression of [await] suspending function that selects with the deferred value when it is
- * resolved. The [select] invocation fails if the deferred value completes exceptionally (either fails or
- * it cancelled).
+ * Clause using the [await] suspending function as a [select] clause.
+ * It selects with the deferred value when the [Deferred] completes.
+ * If [Deferred] completes with an exception, the whole the [select] invocation fails with the same exception.
+ * Note that, if [Deferred] completed with a [CancellationException], throwing it may have unintended
+ * consequences. See [await] for details.
*/
public val onAwait: SelectClause1<T>
diff --git a/kotlinx-coroutines-core/common/src/Delay.kt b/kotlinx-coroutines-core/common/src/Delay.kt
index ba06d97..67d3d16 100644
--- a/kotlinx-coroutines-core/common/src/Delay.kt
+++ b/kotlinx-coroutines-core/common/src/Delay.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.selects.*
import kotlin.coroutines.*
import kotlin.time.*
+import kotlin.time.Duration.Companion.nanoseconds
/**
* This dispatcher _feature_ is implemented by [CoroutineDispatcher] implementations that natively support
@@ -106,14 +103,13 @@
public suspend fun awaitCancellation(): Nothing = suspendCancellableCoroutine {}
/**
- * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
+ * Delays coroutine for at least the given time without blocking a thread and resumes it after a specified time.
* If the given [timeMillis] is non-positive, this function returns immediately.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*
* If you want to delay forever (until cancellation), consider using [awaitCancellation] instead.
*
@@ -133,14 +129,13 @@
}
/**
- * Delays coroutine for a given [duration] without blocking a thread and resumes it after the specified time.
+ * Delays coroutine for at least the given [duration] without blocking a thread and resumes it after the specified time.
* If the given [duration] is non-positive, this function returns immediately.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*
* If you want to delay forever (until cancellation), consider using [awaitCancellation] instead.
*
@@ -154,8 +149,10 @@
internal val CoroutineContext.delay: Delay get() = get(ContinuationInterceptor) as? Delay ?: DefaultDelay
/**
- * Convert this duration to its millisecond value.
- * Positive durations are coerced at least `1`.
+ * Convert this duration to its millisecond value. Durations which have a nanosecond component less than
+ * a single millisecond will be rounded up to the next largest millisecond.
*/
-internal fun Duration.toDelayMillis(): Long =
- if (this > Duration.ZERO) inWholeMilliseconds.coerceAtLeast(1) else 0
+internal fun Duration.toDelayMillis(): Long = when (isPositive()) {
+ true -> plus(999_999L.nanoseconds).inWholeMilliseconds
+ false -> 0L
+}
diff --git a/kotlinx-coroutines-core/common/src/Dispatchers.common.kt b/kotlinx-coroutines-core/common/src/Dispatchers.common.kt
index bb85d86..7c34ead 100644
--- a/kotlinx-coroutines-core/common/src/Dispatchers.common.kt
+++ b/kotlinx-coroutines-core/common/src/Dispatchers.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
@@ -31,13 +27,13 @@
* [`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
* - On JS it is equivalent to the [Default] dispatcher with [immediate][MainCoroutineDispatcher.immediate] support.
* - On Native Darwin-based targets, it is a dispatcher backed by Darwin's main queue.
- * - On other Native targets, it is a single-threaded dispatcher backed by a standalone worker.
+ * - On other Native targets, it is not available.
+ * - `Dispatchers.setMain` from the `kotlinx-coroutines-test` artifact can replace the main dispatcher with a mock one for testing.
*
- * In order to work with the `Main` dispatcher, the following artifact should be added to the project runtime dependencies:
+ * In order to work with the `Main` dispatcher on the JVM, the following artifact should be added to the project runtime dependencies:
* - `kotlinx-coroutines-android` — for Android Main thread dispatcher
* - `kotlinx-coroutines-javafx` — for JavaFx Application thread dispatcher
* - `kotlinx-coroutines-swing` — for Swing EDT dispatcher
- * - `kotlinx-coroutines-test` — for mocking the `Main` dispatcher in tests via `Dispatchers.setMain`
*/
public val Main: MainCoroutineDispatcher
diff --git a/kotlinx-coroutines-core/common/src/EventLoop.common.kt b/kotlinx-coroutines-core/common/src/EventLoop.common.kt
index 8d9eed2..914cc8e 100644
--- a/kotlinx-coroutines-core/common/src/EventLoop.common.kt
+++ b/kotlinx-coroutines-core/common/src/EventLoop.common.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
import kotlinx.coroutines.internal.*
+import kotlin.concurrent.Volatile
import kotlin.coroutines.*
import kotlin.jvm.*
@@ -42,9 +39,9 @@
* Processes next event in this event loop.
*
* The result of this function is to be interpreted like this:
- * * `<= 0` -- there are potentially more events for immediate processing;
- * * `> 0` -- a number of nanoseconds to wait for next scheduled event;
- * * [Long.MAX_VALUE] -- no more events.
+ * - `<= 0` -- there are potentially more events for immediate processing;
+ * - `> 0` -- a number of nanoseconds to wait for next scheduled event;
+ * - [Long.MAX_VALUE] -- no more events.
*
* **NOTE**: Must be invoked only from the event loop's thread
* (no check for performance reasons, may be added in the future).
diff --git a/kotlinx-coroutines-core/common/src/Exceptions.common.kt b/kotlinx-coroutines-core/common/src/Exceptions.common.kt
index 6d5442d..ed20d02 100644
--- a/kotlinx-coroutines-core/common/src/Exceptions.common.kt
+++ b/kotlinx-coroutines-core/common/src/Exceptions.common.kt
@@ -1,11 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
- * This exception gets thrown if an exception is caught while processing [CompletionHandler] invocation for [Job].
+ * This exception gets thrown if an exception is caught while processing [InternalCompletionHandler] invocation for [Job].
*
* @suppress **This an internal API and should not be used from general code.**
*/
@@ -14,7 +10,6 @@
public expect open class CancellationException(message: String?) : IllegalStateException
-@Suppress("FunctionName", "NO_ACTUAL_FOR_EXPECT")
public expect fun CancellationException(message: String?, cause: Throwable?) : CancellationException
internal expect class JobCancellationException(
@@ -27,6 +22,5 @@
internal class CoroutinesInternalError(message: String, cause: Throwable) : Error(message, cause)
-internal expect fun Throwable.addSuppressedThrowable(other: Throwable)
// For use in tests
internal expect val RECOVER_STACK_TRACES: Boolean
diff --git a/kotlinx-coroutines-core/common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt
index 5f40dfc..e9a935c 100644
--- a/kotlinx-coroutines-core/common/src/Job.kt
+++ b/kotlinx-coroutines-core/common/src/Job.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("JobKt")
@file:Suppress("DEPRECATION_ERROR", "RedundantUnitReturnType")
@@ -25,9 +21,9 @@
*
* The most basic instances of `Job` interface are created like this:
*
- * * **Coroutine job** is created with [launch][CoroutineScope.launch] coroutine builder.
+ * - **Coroutine job** is created with [launch][CoroutineScope.launch] coroutine builder.
* It runs a specified block of code and completes on completion of this block.
- * * **[CompletableJob]** is created with a `Job()` factory function.
+ * - **[CompletableJob]** is created with a `Job()` factory function.
* It is completed by calling [CompletableJob.complete].
*
* Conceptually, an execution of a job does not produce a result value. Jobs are launched solely for their
@@ -220,11 +216,11 @@
*
* A parent-child relation has the following effect:
*
- * * Cancellation of parent with [cancel] or its exceptional completion (failure)
+ * - Cancellation of parent with [cancel] or its exceptional completion (failure)
* immediately cancels all its children.
- * * Parent cannot complete until all its children are complete. Parent waits for all its children to
+ * - Parent cannot complete until all its children are complete. Parent waits for all its children to
* complete in _completing_ or _cancelling_ state.
- * * Uncaught exception in a child, by default, cancels parent. This applies even to
+ * - Uncaught exception in a child, by default, cancels parent. This applies even to
* children created with [async][CoroutineScope.async] and other future-like
* coroutine builders, even though their exceptions are caught and are encapsulated in their result.
* This default behavior can be overridden with [SupervisorJob].
@@ -236,9 +232,9 @@
* returns a handle that should be used to detach it.
*
* A parent-child relation has the following effect:
- * * Cancellation of parent with [cancel] or its exceptional completion (failure)
+ * - Cancellation of parent with [cancel] or its exceptional completion (failure)
* immediately cancels all its children.
- * * Parent cannot complete until all its children are complete. Parent waits for all its children to
+ * - Parent cannot complete until all its children are complete. Parent waits for all its children to
* complete in _completing_ or _cancelling_ states.
*
* **A child must store the resulting [ChildHandle] and [dispose][DisposableHandle.dispose] the attachment
@@ -294,10 +290,10 @@
* job is complete.
*
* The meaning of `cause` that is passed to the handler:
- * * Cause is `null` when the job has completed normally.
- * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
+ * - Cause is `null` when the job has completed normally.
+ * - Cause is an instance of [CancellationException] when the job was cancelled _normally_.
* **It should not be treated as an error**. In particular, it should not be reported to error logs.
- * * Otherwise, the job had _failed_.
+ * - Otherwise, the job had _failed_.
*
* The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
* registration of this handler and release its memory if its invocation is no longer needed.
@@ -314,44 +310,8 @@
public fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
/**
- * Registers handler that is **synchronously** invoked once on cancellation or completion of this job.
- * when the job was already cancelled and is completed its execution, then the handler is immediately invoked
- * with the job's cancellation cause or `null` unless [invokeImmediately] is set to false.
- * Otherwise, handler will be invoked once when this job is cancelled or is complete.
- *
- * The meaning of `cause` that is passed to the handler:
- * * Cause is `null` when the job has completed normally.
- * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
- * **It should not be treated as an error**. In particular, it should not be reported to error logs.
- * * Otherwise, the job had _failed_.
- *
- * Invocation of this handler on a transition to a _cancelling_ state
- * is controlled by [onCancelling] boolean parameter.
- * The handler is invoked when the job becomes _cancelling_ if [onCancelling] parameter is set to `true`.
- *
- * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
- * registration of this handler and release its memory if its invocation is no longer needed.
- * There is no need to dispose the handler after completion of this job. The references to
- * all the handlers are released when this job completes.
- *
- * Installed [handler] should not throw any exceptions. If it does, they will get caught,
- * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
- *
- * **Note**: This function is a part of internal machinery that supports parent-child hierarchies
- * and allows for implementation of suspending functions that wait on the Job's state.
- * This function should not be used in general application code.
- * Implementation of `CompletionHandler` must be fast, non-blocking, and thread-safe.
- * This handler can be invoked concurrently with the surrounding code.
- * There is no guarantee on the execution context in which the [handler] is invoked.
- *
- * @param onCancelling when `true`, then the [handler] is invoked as soon as this job transitions to _cancelling_ state;
- * when `false` then the [handler] is invoked only when it transitions to _completed_ state.
- * @param invokeImmediately when `true` and this job is already in the desired state (depending on [onCancelling]),
- * then the [handler] is immediately and synchronously invoked and no-op [DisposableHandle] is returned;
- * when `false` then no-op [DisposableHandle] is returned, but the [handler] is not invoked.
- * @param handler the handler.
- *
- * @suppress **This an internal API and should not be used from general code.**
+ * Kept for preserving compatibility. Shouldn't be used by anyone.
+ * @suppress
*/
@InternalCoroutinesApi
public fun invokeOnCompletion(
@@ -375,6 +335,36 @@
}
/**
+ * Registers a handler that is **synchronously** invoked once on cancellation or completion of this job.
+ *
+ * If the handler would have been invoked earlier if it was registered at that time, then it is invoked immediately,
+ * unless [invokeImmediately] is set to `false`.
+ *
+ * The handler is scheduled to be invoked once the job is cancelled or is complete.
+ * This behavior can be changed by setting the [onCancelling] parameter to `true`.
+ * In this case, the handler is invoked as soon as the job becomes _cancelling_ instead.
+ *
+ * The meaning of `cause` that is passed to the handler is:
+ * - It is `null` if the job has completed normally.
+ * - It is an instance of [CancellationException] if the job was cancelled _normally_.
+ * **It should not be treated as an error**. In particular, it should not be reported to error logs.
+ * - Otherwise, the job had _failed_.
+ *
+ * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] of the registration of this
+ * handler and release its memory if its invocation is no longer needed.
+ * There is no need to dispose of the handler after completion of this job. The references to
+ * all the handlers are released when this job completes.
+ */
+internal fun Job.invokeOnCompletion(
+ onCancelling: Boolean = false,
+ invokeImmediately: Boolean = true,
+ handler: InternalCompletionHandler
+): DisposableHandle = when (this) {
+ is JobSupport -> invokeOnCompletionInternal(onCancelling, invokeImmediately, handler)
+ else -> invokeOnCompletion(onCancelling, invokeImmediately, handler::invoke)
+}
+
+/**
* Creates a job object in an active state.
* A failure of any child of this job immediately causes this job to fail, too, and cancels the rest of its children.
*
@@ -491,7 +481,7 @@
* ```
*/
internal fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
- invokeOnCompletion(handler = DisposeOnCompletion(handle).asHandler)
+ invokeOnCompletion(handler = DisposeOnCompletion(handle))
/**
* Cancels the job and suspends the invoking coroutine until the cancelled job is complete.
diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt
index 0c63b6a..a4a5a29 100644
--- a/kotlinx-coroutines-core/common/src/JobSupport.kt
+++ b/kotlinx-coroutines-core/common/src/JobSupport.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.coroutines
@@ -253,9 +250,9 @@
/*
* 1) If we have non-CE, use it as root cause
* 2) If our original cause was TCE, use *non-original* TCE because of the special nature of TCE
- * * It is a CE, so it's not reported by children
- * * The first instance (cancellation cause) is created by timeout coroutine and has no meaningful stacktrace
- * * The potential second instance is thrown by withTimeout lexical block itself, then it has recovered stacktrace
+ * - It is a CE, so it's not reported by children
+ * - The first instance (cancellation cause) is created by timeout coroutine and has no meaningful stacktrace
+ * - The potential second instance is thrown by withTimeout lexical block itself, then it has recovered stacktrace
* 3) Just return the very first CE
*/
val firstNonCancellation = exceptions.firstOrNull { it !is CancellationException }
@@ -281,7 +278,7 @@
val unwrapped = unwrap(exception)
if (unwrapped !== rootCause && unwrapped !== unwrappedCause &&
unwrapped !is CancellationException && seenExceptions.add(unwrapped)) {
- rootCause.addSuppressedThrowable(unwrapped)
+ rootCause.addSuppressed(unwrapped)
}
}
}
@@ -369,7 +366,7 @@
try {
node.invoke(cause)
} catch (ex: Throwable) {
- exception?.apply { addSuppressedThrowable(ex) } ?: run {
+ exception?.apply { addSuppressed(ex) } ?: run {
exception = CompletionHandlerException("Exception in completion handler $node for $this", ex)
}
}
@@ -446,14 +443,24 @@
protected val completionCauseHandled: Boolean
get() = state.let { it is CompletedExceptionally && it.handled }
- @Suppress("OverridingDeprecatedMember")
public final override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle =
- invokeOnCompletion(onCancelling = false, invokeImmediately = true, handler = handler)
+ invokeOnCompletionInternal(
+ onCancelling = false,
+ invokeImmediately = true,
+ handler = InternalCompletionHandler.UserSupplied(handler)
+ )
- public final override fun invokeOnCompletion(
+ public final override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle =
+ invokeOnCompletionInternal(
+ onCancelling = onCancelling,
+ invokeImmediately = invokeImmediately,
+ handler = InternalCompletionHandler.UserSupplied(handler)
+ )
+
+ internal fun invokeOnCompletionInternal(
onCancelling: Boolean,
invokeImmediately: Boolean,
- handler: CompletionHandler
+ handler: InternalCompletionHandler
): DisposableHandle {
// Create node upfront -- for common cases it just initializes JobNode.job field,
// for user-defined handlers it allocates a JobNode object that we might not need, but this is Ok.
@@ -480,7 +487,7 @@
rootCause = state.rootCause // != null if cancelling job
// We add node to the list in two cases --- either the job is not being cancelled
// or we are adding a child to a coroutine that is not completing yet
- if (rootCause == null || handler.isHandlerOf<ChildHandleNode>() && !state.isCompleting) {
+ if (rootCause == null || handler is ChildHandleNode && !state.isCompleting) {
// Note: add node the list while holding lock on state (make sure it cannot change)
if (!addLastAtomic(state, list, node)) return@loopOnState // retry
// just return node if we don't have to invoke handler (not cancelling yet)
@@ -492,7 +499,7 @@
}
if (rootCause != null) {
// Note: attachChild uses invokeImmediately, so it gets invoked when adding to cancelled job
- if (invokeImmediately) handler.invokeIt(rootCause)
+ if (invokeImmediately) handler.invoke(rootCause)
return handle
} else {
if (addLastAtomic(state, list, node)) return node
@@ -502,14 +509,14 @@
else -> { // is complete
// :KLUDGE: We have to invoke a handler in platform-specific way via `invokeIt` extension,
// because we play type tricks on Kotlin/JS and handler is not necessarily a function there
- if (invokeImmediately) handler.invokeIt((state as? CompletedExceptionally)?.cause)
+ if (invokeImmediately) handler.invoke((state as? CompletedExceptionally)?.cause)
return NonDisposableHandle
}
}
}
}
- private fun makeNode(handler: CompletionHandler, onCancelling: Boolean): JobNode {
+ private fun makeNode(handler: InternalCompletionHandler, onCancelling: Boolean): JobNode {
val node = if (onCancelling) {
(handler as? JobCancellingNode)
?: InvokeOnCancelling(handler)
@@ -558,7 +565,7 @@
private suspend fun joinSuspend() = suspendCancellableCoroutine<Unit> { cont ->
// We have to invoke join() handler only on cancellation, on completion we will be resumed regularly without handlers
- cont.disposeOnCancellation(invokeOnCompletion(handler = ResumeOnCompletion(cont).asHandler))
+ cont.disposeOnCancellation(invokeOnCompletion(handler = ResumeOnCompletion(cont)))
}
@Suppress("UNCHECKED_CAST")
@@ -574,7 +581,7 @@
select.selectInRegistrationPhase(Unit)
return
}
- val disposableHandle = invokeOnCompletion(SelectOnJoinCompletionHandler(select).asHandler)
+ val disposableHandle = invokeOnCompletion(handler = SelectOnJoinCompletionHandler(select))
select.disposeOnCompletion(disposableHandle)
}
@@ -824,8 +831,8 @@
* Completes this job. Used by [AbstractCoroutine.resume].
* It throws [IllegalStateException] on repeated invocation (when this job is already completing).
* Returns:
- * * [COMPLETING_WAITING_CHILDREN] if started waiting for children.
- * * Final state otherwise (caller should do [afterCompletion])
+ * - [COMPLETING_WAITING_CHILDREN] if started waiting for children.
+ * - Final state otherwise (caller should do [afterCompletion])
*/
internal fun makeCompletingOnce(proposedUpdate: Any?): Any? {
loopOnState { state ->
@@ -921,7 +928,7 @@
private tailrec fun tryWaitForChild(state: Finishing, child: ChildHandleNode, proposedUpdate: Any?): Boolean {
val handle = child.childJob.invokeOnCompletion(
invokeImmediately = false,
- handler = ChildCompletion(this, state, child, proposedUpdate).asHandler
+ handler = ChildCompletion(this, state, child, proposedUpdate)
)
if (handle !== NonDisposableHandle) return true // child is not complete and we've started waiting for it
val nextChild = child.nextChild() ?: return false
@@ -971,7 +978,7 @@
* If child is attached when the job is already being cancelled, such child will receive immediate notification on
* cancellation, but parent *will* wait for that child before completion and will handle its exception.
*/
- return invokeOnCompletion(onCancelling = true, handler = ChildHandleNode(child).asHandler) as ChildHandle
+ return invokeOnCompletion(onCancelling = true, handler = ChildHandleNode(child)) as ChildHandle
}
/**
@@ -989,10 +996,10 @@
* similarly to [invokeOnCompletion] with `onCancelling` set to `true`.
*
* The meaning of [cause] parameter:
- * * Cause is `null` when the job has completed normally.
- * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
+ * - Cause is `null` when the job has completed normally.
+ * - Cause is an instance of [CancellationException] when the job was cancelled _normally_.
* **It should not be treated as an error**. In particular, it should not be reported to error logs.
- * * Otherwise, the job had been cancelled or failed with exception.
+ * - Otherwise, the job had been cancelled or failed with exception.
*
* The specified [cause] is not the final cancellation cause of this job.
* A job may produce other exceptions while it is failing and the final cause might be different.
@@ -1234,7 +1241,7 @@
val cont = AwaitContinuation(uCont.intercepted(), this)
// we are mimicking suspendCancellableCoroutine here and call initCancellability, too.
cont.initCancellability()
- cont.disposeOnCancellation(invokeOnCompletion(ResumeAwaitOnCompletion(cont).asHandler))
+ cont.disposeOnCancellation(invokeOnCompletion(handler = ResumeAwaitOnCompletion(cont)))
cont.getResult()
}
@@ -1256,7 +1263,7 @@
}
if (startInternal(state) >= 0) break // break unless needs to retry
}
- val disposableHandle = invokeOnCompletion(SelectOnAwaitCompletionHandler(select).asHandler)
+ val disposableHandle = invokeOnCompletion(handler = SelectOnAwaitCompletionHandler(select))
select.disposeOnCompletion(disposableHandle)
}
@@ -1341,7 +1348,7 @@
val list: NodeList? // is null only for Empty and JobNode incomplete state objects
}
-internal abstract class JobNode : CompletionHandlerBase(), DisposableHandle, Incomplete {
+internal abstract class JobNode : LockFreeLinkedListNode(), InternalCompletionHandler, DisposableHandle, Incomplete {
/**
* Initialized by [JobSupport.makeNode].
*/
@@ -1380,7 +1387,7 @@
}
private class InvokeOnCompletion(
- private val handler: CompletionHandler
+ private val handler: InternalCompletionHandler
) : JobNode() {
override fun invoke(cause: Throwable?) = handler.invoke(cause)
}
@@ -1423,7 +1430,7 @@
internal abstract class JobCancellingNode : JobNode()
private class InvokeOnCancelling(
- private val handler: CompletionHandler
+ private val handler: InternalCompletionHandler
) : JobCancellingNode() {
// delegate handler shall be invoked at most once, so here is an additional flag
private val _invoked = atomic(0) // todo: replace with atomic boolean after migration to recent atomicFu
diff --git a/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt
index 9150bd0..8644474 100644
--- a/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt
+++ b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/common/src/NonCancellable.kt b/kotlinx-coroutines-core/common/src/NonCancellable.kt
index 9fb72dd..afc1f6a 100644
--- a/kotlinx-coroutines-core/common/src/NonCancellable.kt
+++ b/kotlinx-coroutines-core/common/src/NonCancellable.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.coroutines
diff --git a/kotlinx-coroutines-core/common/src/Runnable.common.kt b/kotlinx-coroutines-core/common/src/Runnable.common.kt
index 5a7f667..462ed6a 100644
--- a/kotlinx-coroutines-core/common/src/Runnable.common.kt
+++ b/kotlinx-coroutines-core/common/src/Runnable.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt b/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt
index ae3ffcc..3eea46c 100644
--- a/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt
+++ b/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
internal expect abstract class SchedulerTask internal constructor() : Runnable
diff --git a/kotlinx-coroutines-core/common/src/Supervisor.kt b/kotlinx-coroutines-core/common/src/Supervisor.kt
index 8411c5c..730050b 100644
--- a/kotlinx-coroutines-core/common/src/Supervisor.kt
+++ b/kotlinx-coroutines-core/common/src/Supervisor.kt
@@ -1,6 +1,3 @@
-/*
- * 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("DEPRECATION_ERROR")
@@ -20,14 +17,11 @@
* A failure or cancellation of a child does not cause the supervisor job to fail and does not affect its other children,
* so a supervisor can implement a custom policy for handling failures of its children:
*
- * * A failure of a child job that was created using [launch][CoroutineScope.launch] can be handled via [CoroutineExceptionHandler] in the context.
- * * A failure of a child job that was created using [async][CoroutineScope.async] can be handled via [Deferred.await] on the resulting deferred value.
+ * - A failure of a child job that was created using [launch][CoroutineScope.launch] can be handled via [CoroutineExceptionHandler] in the context.
+ * - A failure of a child job that was created using [async][CoroutineScope.async] can be handled via [Deferred.await] on the resulting deferred value.
*
- * If [parent] job is specified, then this supervisor job becomes a child job of its parent and is cancelled when its
- * parent fails or is cancelled. All this supervisor's children are cancelled in this case, too. The invocation of
- * [cancel][Job.cancel] with exception (other than [CancellationException]) on this supervisor job also cancels parent.
- *
- * @param parent an optional parent job.
+ * If a [parent] job is specified, then this supervisor job becomes a child job of [parent] and is cancelled when the
+ * parent fails or is cancelled. All this supervisor's children are cancelled in this case, too.
*/
@Suppress("FunctionName")
public fun SupervisorJob(parent: Job? = null) : CompletableJob = SupervisorJobImpl(parent)
@@ -39,15 +33,16 @@
public fun SupervisorJob0(parent: Job? = null) : Job = SupervisorJob(parent)
/**
- * Creates a [CoroutineScope] with [SupervisorJob] and calls the specified suspend block with this scope.
- * The provided scope inherits its [coroutineContext][CoroutineScope.coroutineContext] from the outer scope, but overrides
- * context's [Job] with [SupervisorJob].
+ * Creates a [CoroutineScope] with [SupervisorJob] and calls the specified suspend [block] with this scope.
+ * The provided scope inherits its [coroutineContext][CoroutineScope.coroutineContext] from the outer scope, using the
+ * [Job] from that context as the parent for the new [SupervisorJob].
* This function returns as soon as the given block and all its child coroutines are completed.
*
* Unlike [coroutineScope], a failure of a child does not cause this scope to fail and does not affect its other children,
* so a custom policy for handling failures of its children can be implemented. See [SupervisorJob] for additional details.
- * A failure of the scope itself (exception thrown in the [block] or external cancellation) fails the scope with all its children,
- * but does not cancel parent job.
+ *
+ * If an exception happened in [block], then the supervisor job is failed and all its children are cancelled.
+ * If the current coroutine was cancelled, then both the supervisor job itself and all its children are cancelled.
*
* The method may throw a [CancellationException] if the current job was cancelled externally,
* or rethrow an exception thrown by the given [block].
diff --git a/kotlinx-coroutines-core/common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt
index 3ce74c0..930b39c 100644
--- a/kotlinx-coroutines-core/common/src/Timeout.kt
+++ b/kotlinx-coroutines-core/common/src/Timeout.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:OptIn(ExperimentalContracts::class)
package kotlinx.coroutines
diff --git a/kotlinx-coroutines-core/common/src/Unconfined.kt b/kotlinx-coroutines-core/common/src/Unconfined.kt
index 5837ae8..46ea4ea 100644
--- a/kotlinx-coroutines-core/common/src/Unconfined.kt
+++ b/kotlinx-coroutines-core/common/src/Unconfined.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/Waiter.kt b/kotlinx-coroutines-core/common/src/Waiter.kt
index 79d3dbf..cc037d9 100644
--- a/kotlinx-coroutines-core/common/src/Waiter.kt
+++ b/kotlinx-coroutines-core/common/src/Waiter.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.Segment
diff --git a/kotlinx-coroutines-core/common/src/Yield.kt b/kotlinx-coroutines-core/common/src/Yield.kt
index db3bfa5..0598228 100644
--- a/kotlinx-coroutines-core/common/src/Yield.kt
+++ b/kotlinx-coroutines-core/common/src/Yield.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -10,12 +6,11 @@
/**
* Yields the thread (or thread pool) of the current coroutine dispatcher
* to other coroutines on the same dispatcher to run if possible.
- *
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed when this suspending function is invoked or while
- * this function is waiting for dispatch, it resumes with a [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ *
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while
+ * [yield] is invoked or while waiting for dispatch, it immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*
* **Note**: This function always [checks for cancellation][ensureActive] even when it does not suspend.
*
diff --git a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt
index e7a58cc..eba767d 100644
--- a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt
+++ b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("DEPRECATION")
package kotlinx.coroutines.channels
@@ -78,10 +74,10 @@
* the resulting channel becomes _failed_, so that any attempt to receive from such a channel throws exception.
*
* The kind of the resulting channel depends on the specified [capacity] parameter:
- * * when `capacity` is positive (1 by default), but less than [UNLIMITED] -- uses [BroadcastChannel] with a buffer of given capacity,
- * * when `capacity` is [CONFLATED] -- uses [ConflatedBroadcastChannel] that conflates back-to-back sends;
+ * - when `capacity` is positive (1 by default), but less than [UNLIMITED] -- uses [BroadcastChannel] with a buffer of given capacity,
+ * - when `capacity` is [CONFLATED] -- uses [ConflatedBroadcastChannel] that conflates back-to-back sends;
* Note that resulting channel behaves like [ConflatedBroadcastChannel] but is not an instance of [ConflatedBroadcastChannel].
- * * otherwise -- throws [IllegalArgumentException].
+ * - otherwise -- throws [IllegalArgumentException].
*
* **Note:** By default, the coroutine does not start until the first subscriber appears via [BroadcastChannel.openSubscription]
* as [start] parameter has a value of [CoroutineStart.LAZY] by default.
@@ -147,12 +143,14 @@
override val channel: SendChannel<E>
get() = this
+ @Suppress("MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION_WARNING") // do not remove the MULTIPLE_DEFAULTS suppression: required in K2
@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
final override fun cancel(cause: Throwable?): Boolean {
cancelInternal(cause ?: defaultCancellationException())
return true
}
+ @Suppress("MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION_WARNING") // do not remove the MULTIPLE_DEFAULTS suppression: required in K2
final override fun cancel(cause: CancellationException?) {
cancelInternal(cause ?: defaultCancellationException())
}
diff --git a/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt
index e3c3a30..b90f17e 100644
--- a/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("FunctionName", "DEPRECATION")
package kotlinx.coroutines.channels
@@ -59,11 +55,11 @@
*
* The resulting channel type depends on the specified [capacity] parameter:
*
- * * when `capacity` positive, but less than [UNLIMITED] -- creates `ArrayBroadcastChannel` with a buffer of given capacity.
+ * - when `capacity` positive, but less than [UNLIMITED] -- creates `ArrayBroadcastChannel` with a buffer of given capacity.
* **Note:** this channel looses all items that have been sent to it until the first subscriber appears;
- * * when `capacity` is [CONFLATED] -- creates [ConflatedBroadcastChannel] that conflates back-to-back sends;
- * * when `capacity` is [BUFFERED] -- creates `ArrayBroadcastChannel` with a default capacity.
- * * otherwise -- throws [IllegalArgumentException].
+ * - when `capacity` is [CONFLATED] -- creates [ConflatedBroadcastChannel] that conflates back-to-back sends;
+ * - when `capacity` is [BUFFERED] -- creates `ArrayBroadcastChannel` with a default capacity.
+ * - otherwise -- throws [IllegalArgumentException].
*
* **Note: This API is obsolete since 1.5.0 and deprecated for removal since 1.7.0**
* It is replaced with [SharedFlow][kotlinx.coroutines.flow.SharedFlow] and [StateFlow][kotlinx.coroutines.flow.StateFlow].
@@ -136,6 +132,7 @@
*
* This channel is created by `BroadcastChannel(capacity)` factory function invocation.
*/
+@Suppress("MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION_WARNING", "MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE_DEPRECATION_WARNING") // do not remove the MULTIPLE_DEFAULTS suppression: required in K2
internal class BroadcastChannelImpl<E>(
/**
* Buffer capacity; [Channel.CONFLATED] when this broadcast is conflated.
diff --git a/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt b/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt
index 8af2c84..d4c131e 100644
--- a/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt
+++ b/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt
@@ -1,17 +1,13 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
/**
* A strategy for buffer overflow handling in [channels][Channel] and [flows][kotlinx.coroutines.flow.Flow] that
* controls what is going to be sacrificed on buffer overflow:
*
- * * [SUSPEND] — the upstream that is [sending][SendChannel.send] or
+ * - [SUSPEND] — the upstream that is [sending][SendChannel.send] or
* is [emitting][kotlinx.coroutines.flow.FlowCollector.emit] a value is **suspended** while the buffer is full.
- * * [DROP_OLDEST] — drop **the oldest** value in the buffer on overflow, add the new value to the buffer, do not suspend.
- * * [DROP_LATEST] — drop **the latest** value that is being added to the buffer right now on buffer overflow
+ * - [DROP_OLDEST] — drop **the oldest** value in the buffer on overflow, add the new value to the buffer, do not suspend.
+ * - [DROP_LATEST] — drop **the latest** value that is being added to the buffer right now on buffer overflow
* (so that buffer contents stay the same), do not suspend.
*/
public enum class BufferOverflow {
diff --git a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
index 4fc7d43..fb6846e 100644
--- a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
@@ -241,7 +241,7 @@
/**
* Abstract send implementation.
*/
- protected inline fun <R> sendImpl(
+ private inline fun <R> sendImpl(
/* The element to be sent. */
element: E,
/* The waiter to be stored in case of suspension,
@@ -350,6 +350,29 @@
}
}
+ // Note: this function is temporarily moved from ConflatedBufferedChannel to BufferedChannel class, because of this issue: KT-65554.
+ // For now, an inline function, which invokes atomic operations, may only be called within a parent class.
+ protected fun trySendDropOldest(element: E): ChannelResult<Unit> =
+ sendImpl( // <-- this is an inline function
+ element = element,
+ // Put the element into the logical buffer even
+ // if this channel is already full, the `onSuspend`
+ // callback below extract the first (oldest) element.
+ waiter = BUFFERED,
+ // Finish successfully when a rendezvous has happened
+ // or the element has been buffered.
+ onRendezvousOrBuffered = { return success(Unit) },
+ // In case the algorithm decided to suspend, the element
+ // was added to the buffer. However, as the buffer is now
+ // overflowed, the first (oldest) element has to be extracted.
+ onSuspend = { segm, i ->
+ dropFirstElementUntilTheSpecifiedCellIsInTheBuffer(segm.id * SEGMENT_SIZE + i)
+ return success(Unit)
+ },
+ // If the channel is closed, return the corresponding result.
+ onClosed = { return closed(sendException) }
+ )
+
private inline fun sendImplOnNoWaiter(
/* The working cell is specified by
the segment and the index in it. */
@@ -1582,7 +1605,12 @@
* When [hasNext] suspends, this field stores the corresponding
* continuation. The [tryResumeHasNext] and [tryResumeHasNextOnClosedChannel]
* function resume this continuation when the [hasNext] invocation should complete.
+ *
+ * This property is the subject to bening data race:
+ * It is nulled-out on both completion and cancellation paths that
+ * could happen concurrently.
*/
+ @BenignDataRace
private var continuation: CancellableContinuationImpl<Boolean>? = null
// `hasNext()` is just a special receive operation.
@@ -1690,8 +1718,11 @@
}
fun tryResumeHasNextOnClosedChannel() {
- // Read the current continuation and clean
- // the corresponding field to avoid memory leaks.
+ /*
+ * Read the current continuation of the suspended `hasNext()` call and clean the corresponding field to avoid memory leaks.
+ * While this nulling out is unnecessary, it eliminates memory leaks (through the continuation)
+ * if the channel iterator accidentally remains GC-reachable after the channel is closed.
+ */
val cont = this.continuation!!
this.continuation = null
// Update the `hasNext()` internal result and inform
diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt
index b14e61b..af906ef 100644
--- a/kotlinx-coroutines-core/common/src/channels/Channel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("FunctionName")
package kotlinx.coroutines.channels
@@ -45,11 +41,12 @@
* All elements sent over the channel are delivered in first-in first-out order. The sent element
* will be delivered to receivers before the close token.
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
- * function is suspended, this function immediately resumes with a [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. The `send` call can send the element to the channel,
- * but then throw [CancellationException], thus an exception should not be treated as a failure to deliver the element.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if [send] managed to send the element, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
+ *
+ * Because of the prompt cancellation guarantee, an exception does not always mean a failure to deliver the element.
* See "Undelivered elements" section in [Channel] documentation for details on handling undelivered elements.
*
* Note that this function does not check for cancellation when it is not suspended.
@@ -147,13 +144,13 @@
* This method was deprecated in the favour of [trySend].
* It has proven itself as the most error-prone method in Channel API:
*
- * * `Boolean` return type creates the false sense of security, implying that `false`
+ * - `Boolean` return type creates the false sense of security, implying that `false`
* is returned instead of throwing an exception.
- * * It was used mostly from non-suspending APIs where CancellationException triggered
+ * - It was used mostly from non-suspending APIs where CancellationException triggered
* internal failures in the application (the most common source of bugs).
- * * Due to signature and explicit `if (ch.offer(...))` checks it was easy to
+ * - Due to signature and explicit `if (ch.offer(...))` checks it was easy to
* oversee such error during code review.
- * * Its name was not aligned with the rest of the API and tried to mimic Java's queue instead.
+ * - Its name was not aligned with the rest of the API and tried to mimic Java's queue instead.
*
* **NB** Automatic migration provides best-effort for the user experience, but requires removal
* or adjusting of the code that relied on the exception handling.
@@ -215,13 +212,22 @@
* If the channel was closed because of an exception, it is called a _failed_ channel and this function
* will throw the original [close][SendChannel.close] cause exception.
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
+ * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled while this
* function is suspended, this function immediately resumes with a [CancellationException].
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
* suspended, it will not resume successfully. The `receive` call can retrieve the element from the channel,
* but then throw [CancellationException], thus failing to deliver the element.
* See "Undelivered elements" section in [Channel] documentation for details on handling undelivered elements.
*
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if [receive] managed to retrieve the element from the channel,
+ * but was cancelled while suspended, [CancellationException] will be thrown.
+ * See [suspendCancellableCoroutine] for low-level details.
+ *
+ * Because of the prompt cancellation guarantee, some values retrieved from the channel can become lost.
+ * See "Undelivered elements" section in [Channel] documentation for details on handling undelivered elements.
+ *
* Note that this function does not check for cancellation when it is not suspended.
* Use [yield] or [CoroutineScope.isActive] to periodically check for cancellation in tight loops if needed.
*
@@ -244,11 +250,13 @@
* or the close cause if the channel was closed. Closed cause may be `null` if the channel was closed normally.
* The result cannot be [failed][ChannelResult.isFailure] without being [closed][ChannelResult.isClosed].
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
- * function is suspended, this function immediately resumes with a [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. The `receiveCatching` call can retrieve the element from the channel,
- * but then throw [CancellationException], thus failing to deliver the element.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if [receiveCatching] managed to retrieve the element from the
+ * channel, but was cancelled while suspended, [CancellationException] will be thrown.
+ * See [suspendCancellableCoroutine] for low-level details.
+ *
+ * Because of the prompt cancellation guarantee, some values retrieved from the channel can become lost.
* See "Undelivered elements" section in [Channel] documentation for details on handling undelivered elements.
*
* Note that this function does not check for cancellation when it is not suspended.
@@ -314,11 +322,11 @@
* This method was deprecated in the favour of [tryReceive].
* It has proven itself as error-prone method in Channel API:
*
- * * Nullable return type creates the false sense of security, implying that `null`
+ * - Nullable return type creates the false sense of security, implying that `null`
* is returned instead of throwing an exception.
- * * It was used mostly from non-suspending APIs where CancellationException triggered
+ * - It was used mostly from non-suspending APIs where CancellationException triggered
* internal failures in the application (the most common source of bugs).
- * * Its name was not aligned with the rest of the API and tried to mimic Java's queue instead.
+ * - Its name was not aligned with the rest of the API and tried to mimic Java's queue instead.
*
* See https://github.com/Kotlin/kotlinx.coroutines/issues/974 for more context.
*
@@ -565,11 +573,13 @@
* This function retrieves and removes an element from this channel for the subsequent invocation
* of [next].
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
- * function is suspended, this function immediately resumes with a [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. The `hasNext` call can retrieve the element from the channel,
- * but then throw [CancellationException], thus failing to deliver the element.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if [hasNext] retrieves the element from the channel during
+ * its operation, but was cancelled while suspended, [CancellationException] will be thrown.
+ * See [suspendCancellableCoroutine] for low-level details.
+ *
+ * Because of the prompt cancellation guarantee, some values retrieved from the channel can become lost.
* See "Undelivered elements" section in [Channel] documentation for details on handling undelivered elements.
*
* Note that this function does not check for cancellation when it is not suspended.
@@ -617,35 +627,35 @@
* The `Channel(capacity)` factory function is used to create channels of different kinds depending on
* the value of the `capacity` integer:
*
- * * When `capacity` is 0 — it creates a _rendezvous_ channel.
+ * - When `capacity` is 0 — it creates a _rendezvous_ channel.
* This channel does not have any buffer at all. An element is transferred from the sender
* to the receiver only when [send] and [receive] invocations meet in time (rendezvous), so [send] suspends
* until another coroutine invokes [receive], and [receive] suspends until another coroutine invokes [send].
*
- * * When `capacity` is [Channel.UNLIMITED] — it creates a channel with effectively unlimited buffer.
+ * - When `capacity` is [Channel.UNLIMITED] — it creates a channel with effectively unlimited buffer.
* This channel has a linked-list buffer of unlimited capacity (limited only by available memory).
* [Sending][send] to this channel never suspends, and [trySend] always succeeds.
*
- * * When `capacity` is [Channel.CONFLATED] — it creates a _conflated_ channel
+ * - When `capacity` is [Channel.CONFLATED] — it creates a _conflated_ channel
* This channel buffers at most one element and conflates all subsequent `send` and `trySend` invocations,
* so that the receiver always gets the last element sent.
* Back-to-back sent elements are conflated — only the last sent element is received,
* while previously sent elements **are lost**.
* [Sending][send] to this channel never suspends, and [trySend] always succeeds.
*
- * * When `capacity` is positive but less than [UNLIMITED] — it creates an array-based channel with the specified capacity.
+ * - When `capacity` is positive but less than [UNLIMITED] — it creates an array-based channel with the specified capacity.
* This channel has an array buffer of a fixed `capacity`.
* [Sending][send] suspends only when the buffer is full, and [receiving][receive] suspends only when the buffer is empty.
*
* Buffered channels can be configured with an additional [`onBufferOverflow`][BufferOverflow] parameter. It controls the behaviour
* of the channel's [send][Channel.send] function on buffer overflow:
*
- * * [SUSPEND][BufferOverflow.SUSPEND] — the default, suspend `send` on buffer overflow until there is
+ * - [SUSPEND][BufferOverflow.SUSPEND] — the default, suspend `send` on buffer overflow until there is
* free space in the buffer.
- * * [DROP_OLDEST][BufferOverflow.DROP_OLDEST] — do not suspend the `send`, add the latest value to the buffer,
+ * - [DROP_OLDEST][BufferOverflow.DROP_OLDEST] — do not suspend the `send`, add the latest value to the buffer,
* drop the oldest one from the buffer.
* A channel with `capacity = 1` and `onBufferOverflow = DROP_OLDEST` is a _conflated_ channel.
- * * [DROP_LATEST][BufferOverflow.DROP_LATEST] — do not suspend the `send`, drop the value that is being sent,
+ * - [DROP_LATEST][BufferOverflow.DROP_LATEST] — do not suspend the `send`, drop the value that is being sent,
* keep the buffer contents intact.
*
* A non-default `onBufferOverflow` implicitly creates a channel with at least one buffered element and
@@ -655,11 +665,10 @@
* ### Prompt cancellation guarantee
*
* All suspending functions with channels provide **prompt cancellation guarantee**.
- * If the job was cancelled while send or receive function was suspended, it will not resume successfully,
- * but throws a [CancellationException].
- * With a single-threaded [dispatcher][CoroutineDispatcher] like [Dispatchers.Main] this gives a
- * guarantee that if a piece code running in this thread cancels a [Job], then a coroutine running this job cannot
- * resume successfully and continue to run, ensuring a prompt response to its cancellation.
+ * If the job was cancelled while send or receive function was suspended, it will not resume successfully, even if it
+ * already changed the channel's state, but throws a [CancellationException].
+ * With a single-threaded [dispatcher][CoroutineDispatcher] like [Dispatchers.Main], this gives a
+ * guarantee that the coroutine promptly reacts to the cancellation of its [Job] and does not resume its execution.
*
* > **Prompt cancellation guarantee** for channel operations was added since `kotlinx.coroutines` version `1.4.0`
* > and had replaced a channel-specific atomic-cancellation that was not consistent with other suspending functions.
@@ -667,21 +676,21 @@
*
* ### Undelivered elements
*
- * As a result of a prompt cancellation guarantee, when a closeable resource
- * (like open file or a handle to another native resource) is transferred via channel from one coroutine to another
- * it can fail to be delivered and will be lost if either send or receive operations are cancelled in transit.
+ * As a result of the prompt cancellation guarantee, when a closeable resource
+ * (like open file or a handle to another native resource) is transferred via a channel from one coroutine to another,
+ * it can fail to be delivered and will be lost if the receiving operation is cancelled in transit.
*
* A `Channel()` constructor function has an `onUndeliveredElement` optional parameter.
* When `onUndeliveredElement` parameter is set, the corresponding function is called once for each element
* that was sent to the channel with the call to the [send][SendChannel.send] function but failed to be delivered,
* which can happen in the following cases:
*
- * * When [send][SendChannel.send] operation throws an exception because it was cancelled before it had a chance to actually
+ * - When [send][SendChannel.send] operation throws an exception because it was cancelled before it had a chance to actually
* send the element or because the channel was [closed][SendChannel.close] or [cancelled][ReceiveChannel.cancel].
- * * When [receive][ReceiveChannel.receive], [receiveOrNull][ReceiveChannel.receiveOrNull], or [hasNext][ChannelIterator.hasNext]
+ * - When [receive][ReceiveChannel.receive], [receiveOrNull][ReceiveChannel.receiveOrNull], or [hasNext][ChannelIterator.hasNext]
* operation throws an exception when it had retrieved the element from the
* channel but was cancelled before the code following the receive call resumed.
- * * The channel was [cancelled][ReceiveChannel.cancel], in which case `onUndeliveredElement` is called on every
+ * - The channel was [cancelled][ReceiveChannel.cancel], in which case `onUndeliveredElement` is called on every
* remaining element in the channel's buffer.
*
* Note, that `onUndeliveredElement` function is called synchronously in an arbitrary context. It should be fast, non-blocking,
diff --git a/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt
index 3fcf388..44bbf53 100644
--- a/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt
+++ b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
import kotlinx.coroutines.*
@@ -21,12 +17,14 @@
cancelInternal(defaultCancellationException())
}
+ @Suppress("MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION_WARNING") // do not remove the MULTIPLE_DEFAULTS suppression: required in K2
@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
final override fun cancel(cause: Throwable?): Boolean {
cancelInternal(defaultCancellationException())
return true
}
+ @Suppress("MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION_WARNING") // do not remove the MULTIPLE_DEFAULTS suppression: required in K2
final override fun cancel(cause: CancellationException?) {
if (isCancelled) return // Do not create an exception if the coroutine (-> the channel) is already cancelled
cancelInternal(cause ?: defaultCancellationException())
diff --git a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt
index ce454ff..f8ea04c 100644
--- a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt
+++ b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:JvmMultifileClass
@file:JvmName("ChannelsKt")
@file:OptIn(ExperimentalContracts::class)
@@ -18,33 +15,12 @@
// -------- Operations on BroadcastChannel --------
/**
- * Opens subscription to this [BroadcastChannel] and makes sure that the given [block] consumes all elements
- * from it by always invoking [cancel][ReceiveChannel.cancel] after the execution of the block.
- *
- * **Note: This API is obsolete since 1.5.0 and deprecated for removal since 1.7.0**
- * It is replaced with [SharedFlow][kotlinx.coroutines.flow.SharedFlow].
- *
- * Safe to remove in 1.9.0 as was inline before.
- */
-@ObsoleteCoroutinesApi
-@Suppress("DEPRECATION")
-@Deprecated(level = DeprecationLevel.WARNING, message = "BroadcastChannel is deprecated in the favour of SharedFlow and is no longer supported")
-public inline fun <E, R> BroadcastChannel<E>.consume(block: ReceiveChannel<E>.() -> R): R {
- val channel = openSubscription()
- try {
- return channel.block()
- } finally {
- channel.cancel()
- }
-}
-
-/**
* This function is deprecated in the favour of [ReceiveChannel.receiveCatching].
*
* This function is considered error-prone for the following reasons;
- * * Is throwing if the channel has failed even though its signature may suggest it returns 'null'
- * * It is easy to forget that exception handling still have to be explicit
- * * During code reviews and code reading, intentions of the code are frequently unclear:
+ * - Is throwing if the channel has failed even though its signature may suggest it returns 'null'
+ * - It is easy to forget that exception handling still have to be explicit
+ * - During code reviews and code reading, intentions of the code are frequently unclear:
* are potential exceptions ignored deliberately or not?
*
* @suppress doc
@@ -118,19 +94,6 @@
}
}
-/**
- * Subscribes to this [BroadcastChannel] and performs the specified action for each received element.
- *
- * **Note: This API is obsolete since 1.5.0 and deprecated for removal since 1.7.0**
- */
-@Deprecated(level = DeprecationLevel.WARNING, message = "BroadcastChannel is deprecated in the favour of SharedFlow and is no longer supported")
-@Suppress("DEPRECATION")
-public suspend inline fun <E> BroadcastChannel<E>.consumeEach(action: (E) -> Unit): Unit =
- consume {
- for (element in this) action(element)
- }
-
-
@PublishedApi
internal fun ReceiveChannel<*>.cancelConsumed(cause: Throwable?) {
cancel(cause?.let {
diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt
index 6990307..5c7f151 100644
--- a/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
import kotlinx.atomicfu.*
@@ -76,27 +72,6 @@
return success(Unit)
}
- private fun trySendDropOldest(element: E): ChannelResult<Unit> =
- sendImpl( // <-- this is an inline function
- element = element,
- // Put the element into the logical buffer even
- // if this channel is already full, the `onSuspend`
- // callback below extract the first (oldest) element.
- waiter = BUFFERED,
- // Finish successfully when a rendezvous has happened
- // or the element has been buffered.
- onRendezvousOrBuffered = { return success(Unit) },
- // In case the algorithm decided to suspend, the element
- // was added to the buffer. However, as the buffer is now
- // overflowed, the first (oldest) element has to be extracted.
- onSuspend = { segm, i ->
- dropFirstElementUntilTheSpecifiedCellIsInTheBuffer(segm.id * SEGMENT_SIZE + i)
- return success(Unit)
- },
- // If the channel is closed, return the corresponding result.
- onClosed = { return closed(sendException) }
- )
-
@Suppress("UNCHECKED_CAST")
override fun registerSelectForSend(select: SelectInstance<*>, element: Any?) {
// The plain `send(..)` operation never suspends. Thus, either this
diff --git a/kotlinx-coroutines-core/common/src/channels/Deprecated.kt b/kotlinx-coroutines-core/common/src/channels/Deprecated.kt
index 2b9ed42..acb8daf 100644
--- a/kotlinx-coroutines-core/common/src/channels/Deprecated.kt
+++ b/kotlinx-coroutines-core/common/src/channels/Deprecated.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:JvmMultifileClass
@file:JvmName("ChannelsKt")
@file:Suppress("unused")
@@ -11,6 +8,39 @@
import kotlin.coroutines.*
import kotlin.jvm.*
+/**
+ * Opens subscription to this [BroadcastChannel] and makes sure that the given [block] consumes all elements
+ * from it by always invoking [cancel][ReceiveChannel.cancel] after the execution of the block.
+ *
+ * **Note: This API is obsolete since 1.5.0 and deprecated for removal since 1.7.0**
+ * It is replaced with [SharedFlow][kotlinx.coroutines.flow.SharedFlow].
+ *
+ * Safe to remove in 1.9.0 as was inline before.
+ */
+@ObsoleteCoroutinesApi
+@Suppress("DEPRECATION")
+@Deprecated(level = DeprecationLevel.ERROR, message = "BroadcastChannel is deprecated in the favour of SharedFlow and is no longer supported")
+public inline fun <E, R> BroadcastChannel<E>.consume(block: ReceiveChannel<E>.() -> R): R {
+ val channel = openSubscription()
+ try {
+ return channel.block()
+ } finally {
+ channel.cancel()
+ }
+}
+
+/**
+ * Subscribes to this [BroadcastChannel] and performs the specified action for each received element.
+ *
+ * **Note: This API is obsolete since 1.5.0 and deprecated for removal since 1.7.0**
+ */
+@Deprecated(level = DeprecationLevel.ERROR, message = "BroadcastChannel is deprecated in the favour of SharedFlow and is no longer supported")
+@Suppress("DEPRECATION", "DEPRECATION_ERROR")
+public suspend inline fun <E> BroadcastChannel<E>.consumeEach(action: (E) -> Unit): Unit =
+ consume {
+ for (element in this) action(element)
+ }
+
/** @suppress **/
@PublishedApi // Binary compatibility
internal fun consumesAll(vararg channels: ReceiveChannel<*>): CompletionHandler =
@@ -23,7 +53,7 @@
if (exception == null) {
exception = e
} else {
- exception.addSuppressedThrowable(e)
+ exception.addSuppressed(e)
}
}
exception?.let { throw it }
diff --git a/kotlinx-coroutines-core/common/src/channels/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt
index da8f884..3dd0bb4 100644
--- a/kotlinx-coroutines-core/common/src/channels/Produce.kt
+++ b/kotlinx-coroutines-core/common/src/channels/Produce.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
import kotlinx.coroutines.*
@@ -26,9 +22,10 @@
* Suspends the current coroutine until the channel is either [closed][SendChannel.close] or [cancelled][ReceiveChannel.cancel]
* and invokes the given [block] before resuming the coroutine.
*
- * This suspending function is cancellable.
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*
* Note that when the producer channel is cancelled, this function resumes with a cancellation exception.
* Therefore, in case of cancellation, no code after the call to this function will be executed.
diff --git a/kotlinx-coroutines-core/common/src/flow/Builders.kt b/kotlinx-coroutines-core/common/src/flow/Builders.kt
index 350cc4b..d56666f 100644
--- a/kotlinx-coroutines-core/common/src/flow/Builders.kt
+++ b/kotlinx-coroutines-core/common/src/flow/Builders.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/Channels.kt b/kotlinx-coroutines-core/common/src/flow/Channels.kt
index a956662..7bfa499 100644
--- a/kotlinx-coroutines-core/common/src/flow/Channels.kt
+++ b/kotlinx-coroutines-core/common/src/flow/Channels.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@@ -52,9 +48,9 @@
*
* ### Cancellation semantics
*
- * * Flow collectors are cancelled when the original channel is [closed][SendChannel.close] with an exception.
- * * Flow collectors complete normally when the original channel is [closed][SendChannel.close] normally.
- * * Failure or cancellation of the flow collector does not affect the channel.
+ * - Flow collectors are cancelled when the original channel is [closed][SendChannel.close] with an exception.
+ * - Flow collectors complete normally when the original channel is [closed][SendChannel.close] normally.
+ * - Failure or cancellation of the flow collector does not affect the channel.
*
* ### Operator fusion
*
@@ -73,9 +69,9 @@
*
* ### Cancellation semantics
*
- * * Flow collector is cancelled when the original channel is [closed][SendChannel.close] with an exception.
- * * Flow collector completes normally when the original channel is [closed][SendChannel.close] normally.
- * * If the flow collector fails with an exception, the source channel is [cancelled][ReceiveChannel.cancel].
+ * - Flow collector is cancelled when the original channel is [closed][SendChannel.close] with an exception.
+ * - Flow collector completes normally when the original channel is [closed][SendChannel.close] normally.
+ * - If the flow collector fails with an exception, the source channel is [cancelled][ReceiveChannel.cancel].
*
* ### Operator fusion
*
@@ -160,9 +156,9 @@
* This transformation is **stateful**, it launches a [produce] coroutine
* that collects the given flow, and has the same behavior:
*
- * * if collecting the flow throws, the channel will be closed with that exception
- * * if the [ReceiveChannel] is cancelled, the collection of the flow will be cancelled
- * * if collecting the flow completes normally, the [ReceiveChannel] will be closed normally
+ * - if collecting the flow throws, the channel will be closed with that exception
+ * - if the [ReceiveChannel] is cancelled, the collection of the flow will be cancelled
+ * - if collecting the flow completes normally, the [ReceiveChannel] will be closed normally
*
* A channel with [default][Channel.Factory.BUFFERED] buffer size is created.
* Use [buffer] operator on the flow before calling `produceIn` to specify a value other than
diff --git a/kotlinx-coroutines-core/common/src/flow/Flow.kt b/kotlinx-coroutines-core/common/src/flow/Flow.kt
index 92006d4..44e5d7f 100644
--- a/kotlinx-coroutines-core/common/src/flow/Flow.kt
+++ b/kotlinx-coroutines-core/common/src/flow/Flow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
@@ -49,21 +45,21 @@
*
* There are the following basic ways to create a flow:
*
- * * [flowOf(...)][flowOf] functions to create a flow from a fixed set of values.
- * * [asFlow()][asFlow] extension functions on various types to convert them into flows.
- * * [flow { ... }][flow] builder function to construct arbitrary flows from
+ * - [flowOf(...)][flowOf] functions to create a flow from a fixed set of values.
+ * - [asFlow()][asFlow] extension functions on various types to convert them into flows.
+ * - [flow { ... }][flow] builder function to construct arbitrary flows from
* sequential calls to [emit][FlowCollector.emit] function.
- * * [channelFlow { ... }][channelFlow] builder function to construct arbitrary flows from
+ * - [channelFlow { ... }][channelFlow] builder function to construct arbitrary flows from
* potentially concurrent calls to the [send][kotlinx.coroutines.channels.SendChannel.send] function.
- * * [MutableStateFlow] and [MutableSharedFlow] define the corresponding constructor functions to create
+ * - [MutableStateFlow] and [MutableSharedFlow] define the corresponding constructor functions to create
* a _hot_ flow that can be directly updated.
*
* ### Flow constraints
*
* All implementations of the `Flow` interface must adhere to two key properties described in detail below:
*
- * * Context preservation.
- * * Exception transparency.
+ * - Context preservation.
+ * - Exception transparency.
*
* These properties ensure the ability to perform local reasoning about the code with flows and modularize the code
* in such a way that upstream flow emitters can be developed separately from downstream flow collectors.
diff --git a/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt b/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt
index 2877fe5..2110a82 100644
--- a/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt
+++ b/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
/**
diff --git a/kotlinx-coroutines-core/common/src/flow/Migration.kt b/kotlinx-coroutines-core/common/src/flow/Migration.kt
index e398740..da36bf6 100644
--- a/kotlinx-coroutines-core/common/src/flow/Migration.kt
+++ b/kotlinx-coroutines-core/common/src/flow/Migration.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@file:Suppress("unused", "DeprecatedCallableAddReplaceWith", "UNUSED_PARAMETER", "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE")
diff --git a/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt b/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt
index b4833fe..55caefd 100644
--- a/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt
+++ b/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
@@ -89,11 +85,11 @@
* and is designed to completely replace it.
* It has the following important differences:
*
- * * `SharedFlow` is simpler, because it does not have to implement all the [Channel] APIs, which allows
+ * - `SharedFlow` is simpler, because it does not have to implement all the [Channel] APIs, which allows
* for faster and simpler implementation.
- * * `SharedFlow` supports configurable replay and buffer overflow strategy.
- * * `SharedFlow` has a clear separation into a read-only `SharedFlow` interface and a [MutableSharedFlow].
- * * `SharedFlow` cannot be closed like `BroadcastChannel` and can never represent a failure.
+ * - `SharedFlow` supports configurable replay and buffer overflow strategy.
+ * - `SharedFlow` has a clear separation into a read-only `SharedFlow` interface and a [MutableSharedFlow].
+ * - `SharedFlow` cannot be closed like `BroadcastChannel` and can never represent a failure.
* All errors and completion signals should be explicitly _materialized_ if needed.
*
* To migrate [BroadcastChannel] usage to [SharedFlow], start by replacing usages of the `BroadcastChannel(capacity)`
@@ -137,6 +133,16 @@
* **A shared flow never completes**. A call to [Flow.collect] or any other terminal operator
* on a shared flow never completes normally.
*
+ * It is guaranteed that, by the time the first suspension happens, [collect] has already subscribed to the
+ * [SharedFlow] and is eligible for receiving emissions. In particular, the following code will always print `1`:
+ * ```
+ * val flow = MutableSharedFlow<Int>()
+ * launch(start = CoroutineStart.UNDISPATCHED) {
+ * flow.collect { println(1) }
+ * }
+ * flow.emit(1)
+ * ```
+ *
* @see [Flow.collect] for implementation and inheritance details.
*/
override suspend fun collect(collector: FlowCollector<T>): Nothing
@@ -221,7 +227,11 @@
* .launchIn(scope) // launch it
* ```
*
- * Implementation note: the resulting flow **does not** conflate subscription count.
+ * Usually, [StateFlow] conflates values, but [subscriptionCount] is not conflated.
+ * This is done so that any subscribers that need to be notified when subscribers appear do
+ * reliably observe it. With conflation, if a single subscriber appeared and immediately left, those
+ * collecting [subscriptionCount] could fail to notice it due to `0` immediately conflating the
+ * subscription count.
*/
public val subscriptionCount: StateFlow<Int>
diff --git a/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt b/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt
index 0554142..b9b7360 100644
--- a/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt
+++ b/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
@@ -58,9 +54,9 @@
* [`command`][command] flow implementation function. Back-to-back emissions of the same command have no effect.
* Only emission of a different command has effect:
*
- * * [START][SharingCommand.START] — the upstream flow is started.
- * * [STOP][SharingCommand.STOP] — the upstream flow is stopped.
- * * [STOP_AND_RESET_REPLAY_CACHE][SharingCommand.STOP_AND_RESET_REPLAY_CACHE] —
+ * - [START][SharingCommand.START] — the upstream flow is started.
+ * - [STOP][SharingCommand.STOP] — the upstream flow is stopped.
+ * - [STOP_AND_RESET_REPLAY_CACHE][SharingCommand.STOP_AND_RESET_REPLAY_CACHE] —
* the upstream flow is stopped and the [SharedFlow.replayCache] is reset to its initial state.
* The [shareIn] operator calls [MutableSharedFlow.resetReplayCache];
* the [stateIn] operator resets the value to its original `initialValue`.
@@ -90,9 +86,9 @@
*
* It has the following optional parameters:
*
- * * [stopTimeoutMillis] — configures a delay (in milliseconds) between the disappearance of the last
+ * - [stopTimeoutMillis] — configures a delay (in milliseconds) between the disappearance of the last
* subscriber and the stopping of the sharing coroutine. It defaults to zero (stop immediately).
- * * [replayExpirationMillis] — configures a delay (in milliseconds) between the stopping of
+ * - [replayExpirationMillis] — configures a delay (in milliseconds) between the stopping of
* the sharing coroutine and the resetting of the replay cache (which makes the cache empty for the [shareIn] operator
* and resets the cached value to the original `initialValue` for the [stateIn] operator).
* It defaults to `Long.MAX_VALUE` (keep replay cache forever, never reset buffer).
@@ -123,9 +119,9 @@
*
* It has the following optional parameters:
*
- * * [stopTimeout] — configures a delay between the disappearance of the last
+ * - [stopTimeout] — configures a delay between the disappearance of the last
* subscriber and the stopping of the sharing coroutine. It defaults to zero (stop immediately).
- * * [replayExpiration] — configures a delay between the stopping of
+ * - [replayExpiration] — configures a delay between the stopping of
* the sharing coroutine and the resetting of the replay cache (which makes the cache empty for the [shareIn] operator
* and resets the cached value to the original `initialValue` for the [stateIn] operator).
* It defaults to [Duration.INFINITE] (keep replay cache forever, never reset buffer).
diff --git a/kotlinx-coroutines-core/common/src/flow/StateFlow.kt b/kotlinx-coroutines-core/common/src/flow/StateFlow.kt
index 2f3de15..dbb9507 100644
--- a/kotlinx-coroutines-core/common/src/flow/StateFlow.kt
+++ b/kotlinx-coroutines-core/common/src/flow/StateFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.atomicfu.*
@@ -90,15 +86,15 @@
* and is designed to completely replace it.
* It has the following important differences:
*
- * * `StateFlow` is simpler, because it does not have to implement all the [Channel] APIs, which allows
+ * - `StateFlow` is simpler, because it does not have to implement all the [Channel] APIs, which allows
* for faster, garbage-free implementation, unlike `ConflatedBroadcastChannel` implementation that
* allocates objects on each emitted value.
- * * `StateFlow` always has a value which can be safely read at any time via [value] property.
+ * - `StateFlow` always has a value which can be safely read at any time via [value] property.
* Unlike `ConflatedBroadcastChannel`, there is no way to create a state flow without a value.
- * * `StateFlow` has a clear separation into a read-only `StateFlow` interface and a [MutableStateFlow].
- * * `StateFlow` conflation is based on equality like [distinctUntilChanged] operator,
+ * - `StateFlow` has a clear separation into a read-only `StateFlow` interface and a [MutableStateFlow].
+ * - `StateFlow` conflation is based on equality like [distinctUntilChanged] operator,
* unlike conflation in `ConflatedBroadcastChannel` that is based on reference identity.
- * * `StateFlow` cannot be closed like `ConflatedBroadcastChannel` and can never represent a failure.
+ * - `StateFlow` cannot be closed like `ConflatedBroadcastChannel` and can never represent a failure.
* All errors and completion signals should be explicitly _materialized_ if needed.
*
* `StateFlow` is designed to better cover typical use-cases of keeping track of state changes in time, taking
@@ -247,15 +243,21 @@
/**
* Each slot can have one of the following states:
*
- * * `null` -- it is not used right now. Can [allocateLocked] to new collector.
- * * `NONE` -- used by a collector, but neither suspended nor has pending value.
- * * `PENDING` -- pending to process new value.
- * * `CancellableContinuationImpl<Unit>` -- suspended waiting for new value.
+ * - `null` -- it is not used right now. Can [allocateLocked] to new collector.
+ * - `NONE` -- used by a collector, but neither suspended nor has pending value.
+ * - `PENDING` -- pending to process new value.
+ * - `CancellableContinuationImpl<Unit>` -- suspended waiting for new value.
*
* It is important that default `null` value is used, because there can be a race between allocation
* of a new slot and trying to do [makePending] on this slot.
+ *
+ * ===
+ * This should be `atomic<Any?>(null)` instead of the atomic reference, but because of #3820
+ * it is used as a **temporary** solution starting from 1.8.1 version.
+ * Depending on the fix rollout on Android, it will be removed in 1.9.0 or 2.0.0.
+ * See https://issuetracker.google.com/issues/325123736
*/
- private val _state = atomic<Any?>(null)
+ private val _state = WorkaroundAtomicReference<Any?>(null)
override fun allocateLocked(flow: StateFlowImpl<*>): Boolean {
// No need for atomic check & update here, since allocated happens under StateFlow lock
@@ -294,7 +296,6 @@
return state === PENDING
}
- @Suppress("UNCHECKED_CAST")
suspend fun awaitPending(): Unit = suspendCancellableCoroutine sc@ { cont ->
assert { _state.value !is CancellableContinuationImpl<*> } // can be NONE or PENDING
if (_state.compareAndSet(NONE, cont)) return@sc // installed continuation, waiting for pending
@@ -310,7 +311,6 @@
private val _state = atomic(initialState) // T | NULL
private var sequence = 0 // serializes updates, value update is in process when sequence is odd
- @Suppress("UNCHECKED_CAST")
public override var value: T
get() = NULL.unbox(_state.value)
set(value) { updateState(null, value ?: NULL) }
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt
index 5dcf0d0..da239ff 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.channels.*
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt
index 8610cf5..e00c1fd 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt b/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt
index 63ea55a..60fcc8e 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("UNCHECKED_CAST") // KT-32203
package kotlinx.coroutines.flow.internal
@@ -105,7 +102,7 @@
val collectJob = Job()
(second as SendChannel<*>).invokeOnClose {
// Optimization to avoid AFE allocation when the other flow is done
- if (collectJob.isActive) collectJob.cancel(AbortFlowException(this@unsafeFlow))
+ if (collectJob.isActive) collectJob.cancel(AbortFlowException(collectJob))
}
try {
@@ -127,14 +124,14 @@
flow.collect { value ->
withContextUndispatched(scopeContext, Unit, cnt) {
val otherValue = second.receiveCatching().getOrElse {
- throw it ?:AbortFlowException(this@unsafeFlow)
+ throw it ?: AbortFlowException(collectJob)
}
emit(transform(value, NULL.unbox(otherValue)))
}
}
}
} catch (e: AbortFlowException) {
- e.checkOwnership(owner = this@unsafeFlow)
+ e.checkOwnership(owner = collectJob)
} finally {
second.cancel()
}
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt
index 9a81eef..9510ee8 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt b/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt
index 6a6c369..628296c 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt
@@ -1,23 +1,20 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
/**
- * This exception is thrown when operator need no more elements from the flow.
- * This exception should never escape outside of operator's implementation.
+ * This exception is thrown when an operator needs no more elements from the flow.
+ * The operator should never allow this exception to be thrown past its own boundary.
* This exception can be safely ignored by non-terminal flow operator if and only if it was caught by its owner
* (see usages of [checkOwnership]).
+ * Therefore, the [owner] parameter must be unique for every invocation of every operator.
*/
-internal expect class AbortFlowException(owner: FlowCollector<*>) : CancellationException {
- public val owner: FlowCollector<*>
+internal expect class AbortFlowException(owner: Any) : CancellationException {
+ val owner: Any
}
-internal fun AbortFlowException.checkOwnership(owner: FlowCollector<*>) {
+internal fun AbortFlowException.checkOwnership(owner: Any) {
if (this.owner !== owner) throw this
}
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt b/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt
index c18adba..986a41b 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt b/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt
index a2d7f04..c4e68ab 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.flow.*
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt
index 7b59e27..230f466 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt
index 006da41..4e82ca6 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
@@ -10,6 +6,8 @@
import kotlin.coroutines.*
import kotlin.jvm.*
+// Collector that ensures exception transparency and context preservation on a best-effort basis.
+// See an explanation in SafeCollector JVM actualization.
internal expect class SafeCollector<T>(
collector: FlowCollector<T>,
collectContext: CoroutineContext
@@ -18,6 +16,7 @@
internal val collectContext: CoroutineContext
internal val collectContextSize: Int
public fun releaseIntercepted()
+ public override suspend fun emit(value: T)
}
@JvmName("checkContext") // For prettier stack traces
diff --git a/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt b/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt
index 5188a96..a6a1557 100644
--- a/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt
+++ b/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Context.kt b/kotlinx-coroutines-core/common/src/flow/operators/Context.kt
index 8ed5606..99e2134 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Context.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Context.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt b/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt
index 37505dc..2a701c0 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@@ -111,7 +107,6 @@
* @param timeoutMillis [T] is the emitted value and the return value is timeout in milliseconds.
*/
@FlowPreview
-@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
public fun <T> Flow<T>.debounce(timeoutMillis: (T) -> Long): Flow<T> =
debounceInternal(timeoutMillis)
@@ -196,14 +191,13 @@
*/
@FlowPreview
@JvmName("debounceDuration")
-@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
public fun <T> Flow<T>.debounce(timeout: (T) -> Duration): Flow<T> =
debounceInternal { emittedItem ->
timeout(emittedItem).toDelayMillis()
}
-private fun <T> Flow<T>.debounceInternal(timeoutMillisSelector: (T) -> Long) : Flow<T> =
+private fun <T> Flow<T>.debounceInternal(timeoutMillisSelector: (T) -> Long): Flow<T> =
scopedFlow { downstream ->
// Produce the values using the default (rendezvous) channel
val values = produce {
@@ -306,11 +300,11 @@
/*
* TODO this design (and design of the corresponding operator) depends on #540
*/
-internal fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMillis: Long = delayMillis): ReceiveChannel<Unit> {
- require(delayMillis >= 0) { "Expected non-negative delay, but has $delayMillis ms" }
- require(initialDelayMillis >= 0) { "Expected non-negative initial delay, but has $initialDelayMillis ms" }
+internal fun CoroutineScope.fixedPeriodTicker(
+ delayMillis: Long,
+): ReceiveChannel<Unit> {
return produce(capacity = 0) {
- delay(initialDelayMillis)
+ delay(delayMillis)
while (true) {
channel.send(Unit)
delay(delayMillis)
@@ -359,8 +353,15 @@
* emit(3)
* delay(1000)
* emit(4)
- * }.timeout(100.milliseconds).catch {
- * emit(-1) // Item to emit on timeout
+ * }.timeout(100.milliseconds).catch { exception ->
+ * if (exception is TimeoutCancellationException) {
+ * // Catch the TimeoutCancellationException emitted above.
+ * // Emit desired item on timeout.
+ * emit(-1)
+ * } else {
+ * // Throw other exceptions.
+ * throw exception
+ * }
* }.onEach {
* delay(300) // This will not cause a timeout
* }
@@ -393,6 +394,7 @@
value.onSuccess {
downStream.emit(it)
}.onClosed {
+ it?.let { throw it }
return@onReceiveCatching false
}
return@onReceiveCatching true
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt b/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt
index 006d37e..78e4d71 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt
index 90879a9..ceeb336 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@file:Suppress("UNCHECKED_CAST")
@@ -215,7 +211,7 @@
try {
action(cause)
} catch (e: Throwable) {
- if (cause !== null && cause !== e) e.addSuppressedThrowable(cause)
+ if (cause !== null && cause !== e) e.addSuppressed(cause)
throw e
}
}
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt b/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt
index 30512f4..7da73bf 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt b/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt
index 1b8abad..d40a92d 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@@ -50,6 +46,7 @@
public fun <T> Flow<T>.take(count: Int): Flow<T> {
require(count > 0) { "Requested element count $count should be positive" }
return flow {
+ val ownershipMarker = Any()
var consumed = 0
try {
collect { value ->
@@ -60,18 +57,18 @@
if (++consumed < count) {
return@collect emit(value)
} else {
- return@collect emitAbort(value)
+ return@collect emitAbort(value, ownershipMarker)
}
}
} catch (e: AbortFlowException) {
- e.checkOwnership(owner = this)
+ e.checkOwnership(owner = ownershipMarker)
}
}
}
-private suspend fun <T> FlowCollector<T>.emitAbort(value: T) {
+private suspend fun <T> FlowCollector<T>.emitAbort(value: T, ownershipMarker: Any) {
emit(value)
- throw AbortFlowException(this)
+ throw AbortFlowException(ownershipMarker)
}
/**
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt b/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt
index d7fec3f..42b40c5 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("unused", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "UNUSED_PARAMETER")
package kotlinx.coroutines.flow
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt b/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt
index dfd08b8..55c7f13 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@file:Suppress("unused")
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Share.kt b/kotlinx-coroutines-core/common/src/flow/operators/Share.kt
index 2b690e3..a413c90 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Share.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Share.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@@ -24,17 +20,17 @@
* The starting of the sharing coroutine is controlled by the [started] parameter. The following options
* are supported.
*
- * * [Eagerly][SharingStarted.Eagerly] — the upstream flow is started even before the first subscriber appears. Note
+ * - [Eagerly][SharingStarted.Eagerly] — the upstream flow is started even before the first subscriber appears. Note
* that in this case all values emitted by the upstream beyond the most recent values as specified by
* [replay] parameter **will be immediately discarded**.
- * * [Lazily][SharingStarted.Lazily] — starts the upstream flow after the first subscriber appears, which guarantees
+ * - [Lazily][SharingStarted.Lazily] — starts the upstream flow after the first subscriber appears, which guarantees
* that this first subscriber gets all the emitted values, while subsequent subscribers are only guaranteed to
* get the most recent [replay] values. The upstream flow continues to be active even when all subscribers
* disappear, but only the most recent [replay] values are cached without subscribers.
- * * [WhileSubscribed()][SharingStarted.WhileSubscribed] — starts the upstream flow when the first subscriber
+ * - [WhileSubscribed()][SharingStarted.WhileSubscribed] — starts the upstream flow when the first subscriber
* appears, immediately stops when the last subscriber disappears, keeping the replay cache forever.
* It has additional optional configuration parameters as explained in its documentation.
- * * A custom strategy can be supplied by implementing the [SharingStarted] interface.
+ * - A custom strategy can be supplied by implementing the [SharingStarted] interface.
*
* The `shareIn` operator is useful in situations when there is a _cold_ flow that is expensive to create and/or
* to maintain, but there are multiple subscribers that need to collect its values. For example, consider a
@@ -111,12 +107,12 @@
* This default buffering can be overridden with an explicit buffer configuration by preceding the `shareIn` call
* with [buffer] or [conflate], for example:
*
- * * `buffer(0).shareIn(scope, started, 0)` — overrides the default buffer size and creates a [SharedFlow] without a buffer.
+ * - `buffer(0).shareIn(scope, started, 0)` — overrides the default buffer size and creates a [SharedFlow] without a buffer.
* Effectively, it configures sequential processing between the upstream emitter and subscribers,
* as the emitter is suspended until all subscribers process the value. Note, that the value is still immediately
* discarded when there are no subscribers.
- * * `buffer(b).shareIn(scope, started, r)` — creates a [SharedFlow] with `replay = r` and `extraBufferCapacity = b`.
- * * `conflate().shareIn(scope, started, r)` — creates a [SharedFlow] with `replay = r`, `onBufferOverflow = DROP_OLDEST`,
+ * - `buffer(b).shareIn(scope, started, r)` — creates a [SharedFlow] with `replay = r` and `extraBufferCapacity = b`.
+ * - `conflate().shareIn(scope, started, r)` — creates a [SharedFlow] with `replay = r`, `onBufferOverflow = DROP_OLDEST`,
* and `extraBufferCapacity = 1` when `replay == 0` to support this strategy.
*
* ### Operator fusion
@@ -201,9 +197,9 @@
/*
* Conditional start: in the case when sharing and subscribing happens in the same dispatcher, we want to
* have the following invariants preserved:
- * * Delayed sharing strategies have a chance to immediately observe consecutive subscriptions.
+ * - Delayed sharing strategies have a chance to immediately observe consecutive subscriptions.
* E.g. in the cases like `flow.shareIn(...); flow.take(1)` we want sharing strategy to see the initial subscription
- * * Eager sharing does not start immediately, so the subscribers have actual chance to subscribe _prior_ to sharing.
+ * - Eager sharing does not start immediately, so the subscribers have actual chance to subscribe _prior_ to sharing.
*/
val start = if (started == SharingStarted.Eagerly) CoroutineStart.DEFAULT else CoroutineStart.UNDISPATCHED
return launch(context, start = start) { // the single coroutine to rule the sharing
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt b/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt
index 4123aed..2f43cfa 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@file:Suppress("UNCHECKED_CAST")
diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt b/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt
index ed6f572..3b9237e 100644
--- a/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt
+++ b/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt
@@ -1,10 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
-@file:Suppress("UNCHECKED_CAST", "NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE") // KT-32203
+@file:Suppress("UNCHECKED_CAST")
package kotlinx.coroutines.flow
diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt
index 98852c5..5add0fd 100644
--- a/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt
+++ b/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt
index c973da8..3305712 100644
--- a/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt
+++ b/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt
index a15567e..cfa11bc 100644
--- a/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt
+++ b/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt
index 557c095..f241196 100644
--- a/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt
+++ b/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
@file:Suppress("UNCHECKED_CAST")
diff --git a/kotlinx-coroutines-core/common/src/internal/Atomic.kt b/kotlinx-coroutines-core/common/src/internal/Atomic.kt
index ff4320e..60e06ec 100644
--- a/kotlinx-coroutines-core/common/src/internal/Atomic.kt
+++ b/kotlinx-coroutines-core/common/src/internal/Atomic.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE")
package kotlinx.coroutines.internal
diff --git a/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt
index 848a42c..417e9a8 100644
--- a/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
internal expect class ReentrantLock() {
@@ -12,3 +8,33 @@
internal expect inline fun <T> ReentrantLock.withLock(action: () -> T): T
internal expect fun <E> identitySet(expectedSize: Int): MutableSet<E>
+
+/**
+ * Annotation indicating that the marked property is the subject of benign data race.
+ * LLVM does not support this notion, so on K/N platforms we alias it into `@Volatile` to prevent potential OoTA.
+ *
+ * The purpose of this annotation is not to save an extra-volatile on JVM platform, but rather to explicitly emphasize
+ * that data-race is benign.
+ */
+@OptionalExpectation
+@Target(AnnotationTarget.FIELD)
+internal expect annotation class BenignDataRace()
+
+// Used **only** as a workaround for #3820 in StateFlow. Do not use anywhere else
+internal expect class WorkaroundAtomicReference<T>(value: T) {
+ public fun get(): T
+ public fun set(value: T)
+ public fun getAndSet(value: T): T
+ public fun compareAndSet(expected: T, value: T): Boolean
+}
+
+@Suppress("UNUSED_PARAMETER", "EXTENSION_SHADOWED_BY_MEMBER")
+internal var <T> WorkaroundAtomicReference<T>.value: T
+ get() = this.get()
+ set(value) = this.set(value)
+
+internal inline fun <T> WorkaroundAtomicReference<T>.loop(action: WorkaroundAtomicReference<T>.(value: T) -> Unit) {
+ while (true) {
+ action(value)
+ }
+}
diff --git a/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt b/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt
index ecfafcf..8f9b13f 100644
--- a/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt
+++ b/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/common/src/internal/CoroutineExceptionHandlerImpl.common.kt b/kotlinx-coroutines-core/common/src/internal/CoroutineExceptionHandlerImpl.common.kt
index 3f5925a..25a3a26 100644
--- a/kotlinx-coroutines-core/common/src/internal/CoroutineExceptionHandlerImpl.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/CoroutineExceptionHandlerImpl.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt
index 0241c8d..e21f1ed 100644
--- a/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt
+++ b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt
index fc22e02..5a38d0d 100644
--- a/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt
+++ b/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -63,8 +59,8 @@
/**
* There are two implementations of `DispatchedTask`:
- * * [DispatchedContinuation] keeps only simple values as successfully results.
- * * [CancellableContinuationImpl] keeps additional data with values and overrides this method to unwrap it.
+ * - [DispatchedContinuation] keeps only simple values as successfully results.
+ * - [CancellableContinuationImpl] keeps additional data with values and overrides this method to unwrap it.
*/
@Suppress("UNCHECKED_CAST")
internal open fun <T> getSuccessfulResult(state: Any?): T =
@@ -72,9 +68,9 @@
/**
* There are two implementations of `DispatchedTask`:
- * * [DispatchedContinuation] is just an intermediate storage that stores the exception that has its stack-trace
+ * - [DispatchedContinuation] is just an intermediate storage that stores the exception that has its stack-trace
* properly recovered and is ready to pass to the [delegate] continuation directly.
- * * [CancellableContinuationImpl] stores raw cause of the failure in its state; when it needs to be dispatched
+ * - [CancellableContinuationImpl] stores raw cause of the failure in its state; when it needs to be dispatched
* its stack-trace has to be recovered, so it overrides this method for that purpose.
*/
internal open fun getExceptionalResult(state: Any?): Throwable? =
@@ -139,7 +135,7 @@
internal fun handleFatalException(exception: Throwable?, finallyException: Throwable?) {
if (exception === null && finallyException === null) return
if (exception !== null && finallyException !== null) {
- exception.addSuppressedThrowable(finallyException)
+ exception.addSuppressed(finallyException)
}
val cause = exception ?: finallyException
diff --git a/kotlinx-coroutines-core/common/src/internal/InlineList.kt b/kotlinx-coroutines-core/common/src/internal/InlineList.kt
index 61bf6d0..e2cae68 100644
--- a/kotlinx-coroutines-core/common/src/internal/InlineList.kt
+++ b/kotlinx-coroutines-core/common/src/internal/InlineList.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNCHECKED_CAST")
package kotlinx.coroutines.internal
diff --git a/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt b/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt
index 1df81c9..21eb1ec 100644
--- a/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt
@@ -1,10 +1,13 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
// Ignore JRE requirements for animal-sniffer, compileOnly dependency
-@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE)
+@Target(
+ AnnotationTarget.FUNCTION,
+ AnnotationTarget.PROPERTY_GETTER,
+ AnnotationTarget.PROPERTY_SETTER,
+ AnnotationTarget.CONSTRUCTOR,
+ AnnotationTarget.CLASS,
+ AnnotationTarget.FILE
+)
@OptionalExpectation
internal expect annotation class IgnoreJreRequirement()
diff --git a/kotlinx-coroutines-core/common/src/internal/LimitedDispatcher.kt b/kotlinx-coroutines-core/common/src/internal/LimitedDispatcher.kt
index 374e53b..0c8e077 100644
--- a/kotlinx-coroutines-core/common/src/internal/LimitedDispatcher.kt
+++ b/kotlinx-coroutines-core/common/src/internal/LimitedDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt b/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt
index 74848b2..7124f74 100644
--- a/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
/*
diff --git a/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt
index 121cded..456a3b7 100644
--- a/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE")
package kotlinx.coroutines.internal
diff --git a/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt
index 10c5c83..b056bfd 100644
--- a/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt
+++ b/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt b/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt
index 45872f1..c05b183 100644
--- a/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt
+++ b/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt b/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt
index 0701d68..11d7d0b 100644
--- a/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt
+++ b/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
@@ -19,7 +15,7 @@
// undeliveredElementException.cause !== ex is an optimization in case the same exception is thrown
// over and over again by on OnUndeliveredElement
if (undeliveredElementException != null && undeliveredElementException.cause !== ex) {
- undeliveredElementException.addSuppressedThrowable(ex)
+ undeliveredElementException.addSuppressed(ex)
} else {
return UndeliveredElementException("Exception in undelivered element handler for $element", ex)
}
diff --git a/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt b/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt
index a6d8136..463599b 100644
--- a/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/internal/Scopes.kt b/kotlinx-coroutines-core/common/src/internal/Scopes.kt
index e0a1830..7e561c8 100644
--- a/kotlinx-coroutines-core/common/src/internal/Scopes.kt
+++ b/kotlinx-coroutines-core/common/src/internal/Scopes.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt b/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt
index 2812b93..f5e0ab8 100644
--- a/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
@@ -40,7 +36,7 @@
* The opposite of [recoverStackTrace].
* It is guaranteed that `unwrap(recoverStackTrace(e)) === e`
*/
-@PublishedApi // published for the multiplatform implementation of kotlinx-coroutines-test
+@PublishedApi // Used from kotlinx-coroutines-test and reactor modules via suppress, not part of ABI
internal expect fun <E: Throwable> unwrap(exception: E): E
internal expect class StackTraceElement
diff --git a/kotlinx-coroutines-core/common/src/internal/Symbol.kt b/kotlinx-coroutines-core/common/src/internal/Symbol.kt
index b629951..96e3480 100644
--- a/kotlinx-coroutines-core/common/src/internal/Symbol.kt
+++ b/kotlinx-coroutines-core/common/src/internal/Symbol.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.jvm.*
diff --git a/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt b/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt
index 7107945..2c50f3c 100644
--- a/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt
index 281c075..61b7dc9 100644
--- a/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmName("SystemPropsKt")
@file:JvmMultifileClass
diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt
index 6d14e59..c52d35c 100644
--- a/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt
index 73ec93f..1562259 100644
--- a/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt
+++ b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
internal expect class CommonThreadLocal<T> {
diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt b/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt
index ad88103..c8d4cfe 100644
--- a/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt
+++ b/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
@@ -32,11 +28,6 @@
public val isEmpty: Boolean get() = size == 0
- public fun clear(): Unit = synchronized(this) {
- a?.fill(null)
- _size.value = 0
- }
-
public fun find(
predicate: (value: T) -> Boolean
): T? = synchronized(this) block@{
diff --git a/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt b/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt
index f5b96a8..1ba8a71 100644
--- a/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt
+++ b/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.intrinsics
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt
index 3fa53c4..3e086e3 100644
--- a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt
+++ b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.intrinsics
import kotlinx.coroutines.*
@@ -25,19 +21,6 @@
* immediately execute the coroutine in the current thread until the next suspension.
* It does not use [ContinuationInterceptor], but updates the context of the current thread for the new coroutine.
*/
-internal fun <T> (suspend () -> T).startCoroutineUndispatched(completion: Continuation<T>) {
- startDirect(completion) { actualCompletion ->
- withCoroutineContext(completion.context, null) {
- startCoroutineUninterceptedOrReturn(actualCompletion)
- }
- }
-}
-
-/**
- * Use this function to start a new coroutine in [CoroutineStart.UNDISPATCHED] mode —
- * immediately execute the coroutine in the current thread until the next suspension.
- * It does not use [ContinuationInterceptor], but updates the context of the current thread for the new coroutine.
- */
internal fun <R, T> (suspend (R) -> T).startCoroutineUndispatched(receiver: R, completion: Continuation<T>) {
startDirect(completion) { actualCompletion ->
withCoroutineContext(completion.context, null) {
diff --git a/kotlinx-coroutines-core/common/src/selects/OnTimeout.kt b/kotlinx-coroutines-core/common/src/selects/OnTimeout.kt
index ba39181..4499726 100644
--- a/kotlinx-coroutines-core/common/src/selects/OnTimeout.kt
+++ b/kotlinx-coroutines-core/common/src/selects/OnTimeout.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt
index 3ac3cb6..7e685af 100644
--- a/kotlinx-coroutines-core/common/src/selects/Select.kt
+++ b/kotlinx-coroutines-core/common/src/selects/Select.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
import kotlinx.atomicfu.*
@@ -42,10 +38,10 @@
* | [ReceiveChannel] | [receiveCatching][ReceiveChannel.receiveCatching] | [onReceiveCatching][ReceiveChannel.onReceiveCatching]
* | none | [delay] | [onTimeout][SelectBuilder.onTimeout]
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
- * function is suspended, this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*
* Note that this function does not check for cancellation when it is not suspended.
* Use [yield] or [CoroutineScope.isActive] to periodically check for cancellation in tight loops if needed.
@@ -243,7 +239,7 @@
@PublishedApi
internal open class SelectImplementation<R>(
override val context: CoroutineContext
-) : CancelHandler(), SelectBuilder<R>, SelectInstanceInternal<R> {
+) : CancelHandler, SelectBuilder<R>, SelectInstanceInternal<R> {
/**
* Essentially, the `select` operation is split into three phases: REGISTRATION, WAITING, and COMPLETION.
@@ -372,7 +368,12 @@
/**
* List of clauses waiting on this `select` instance.
+ *
+ * This property is the subject to bening data race: concurrent cancellation might null-out this property
+ * while [trySelect] operation reads it and iterates over its content.
+ * A logical race is resolved by the consensus on [state] property.
*/
+ @BenignDataRace
private var clauses: MutableList<ClauseData>? = ArrayList(2)
/**
@@ -407,7 +408,13 @@
* one that stores either result when the clause is successfully registered ([inRegistrationPhase] is `true`),
* or [DisposableHandle] instance when the clause is completed during registration ([inRegistrationPhase] is `false`).
* Yet, this optimization is omitted for code simplicity.
+ *
+ * This property is the subject to benign data race:
+ * [Cleanup][cleanup] procedure can be invoked both as part of the completion sequence
+ * and as a cancellation handler triggered by an external cancellation.
+ * In both scenarios, [NO_RESULT] is written to this property via race.
*/
+ @BenignDataRace
private var internalResult: Any? = NO_RESULT
/**
@@ -558,7 +565,7 @@
// Also, we MUST guarantee that this dispose handle is _visible_
// according to the memory model, and we CAN guarantee this when
// the state is updated.
- cont.invokeOnCancellation(this.asHandler)
+ cont.invokeOnCancellation(this)
return@sc
}
// This `select` is in REGISTRATION phase, but there are clauses that has to be registered again.
@@ -621,9 +628,8 @@
// try to resume the continuation.
this.internalResult = internalResult
if (cont.tryResume(onCancellation)) return TRY_SELECT_SUCCESSFUL
- // If the resumption failed, we need to clean
- // the [result] field to avoid memory leaks.
- this.internalResult = null
+ // If the resumption failed, we need to clean the [result] field to avoid memory leaks.
+ this.internalResult = NO_RESULT
return TRY_SELECT_CANCELLED
}
}
diff --git a/kotlinx-coroutines-core/common/src/selects/SelectOld.kt b/kotlinx-coroutines-core/common/src/selects/SelectOld.kt
index 85476d2..e636a63 100644
--- a/kotlinx-coroutines-core/common/src/selects/SelectOld.kt
+++ b/kotlinx-coroutines-core/common/src/selects/SelectOld.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt b/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt
index a4b1e04..e72c6ed 100644
--- a/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt
+++ b/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:OptIn(ExperimentalContracts::class)
package kotlinx.coroutines.selects
diff --git a/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt b/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt
index ccda656..43bb187 100644
--- a/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt
+++ b/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt
index 06aebcb..45bd383 100644
--- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt
+++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.sync
import kotlinx.atomicfu.*
@@ -42,12 +38,12 @@
public fun tryLock(owner: Any? = null): Boolean
/**
- * Locks this mutex, suspending caller while the mutex is locked.
+ * Locks this mutex, suspending caller until the lock is acquired (in other words, while the lock is held elsewhere).
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
- * function is suspended, this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
* This function releases the lock if it was already acquired by this function before the [CancellationException]
* was thrown.
*
@@ -121,10 +117,9 @@
contract {
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
}
-
lock(owner)
- try {
- return action()
+ return try {
+ action()
} finally {
unlock(owner)
}
diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt
index 9f30721..bf568f3 100644
--- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt
+++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.sync
import kotlinx.atomicfu.*
@@ -32,14 +28,14 @@
* Acquires a permit from this semaphore, suspending until one is available.
* All suspending acquirers are processed in first-in-first-out (FIFO) order.
*
- * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this
- * function is suspended, this function immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
* This function releases the semaphore if it was already acquired by this function before the [CancellationException]
* was thrown.
*
- * Note, that this function does not check for cancellation when it does not suspend.
+ * Note that this function does not check for cancellation when it does not suspend.
* Use [CoroutineScope.isActive] or [CoroutineScope.ensureActive] to periodically
* check for cancellation in tight loops if needed.
*
@@ -82,10 +78,9 @@
contract {
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
}
-
acquire()
- try {
- return action()
+ return try {
+ action()
} finally {
release()
}
diff --git a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt
index ebe88ce..ed33729 100644
--- a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt
+++ b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -59,7 +56,7 @@
}
override fun onCancelling(cause: Throwable?) {
- assertTrue(cause is TestException1)
+ assertIs<TestException1>(cause)
expect(5)
}
@@ -68,18 +65,18 @@
}
override fun onCancelled(cause: Throwable, handled: Boolean) {
- assertTrue(cause is TestException1)
+ assertIs<TestException1>(cause)
expect(8)
}
}
coroutine.invokeOnCompletion(onCancelling = true) {
- assertTrue(it is TestException1)
+ assertIs<TestException1>(it)
expect(6)
}
coroutine.invokeOnCompletion {
- assertTrue(it is TestException1)
+ assertIs<TestException1>(it)
expect(9)
}
diff --git a/kotlinx-coroutines-core/common/test/AsyncLazyTest.kt b/kotlinx-coroutines-core/common/test/AsyncLazyTest.kt
index cd24010..e87e461 100644
--- a/kotlinx-coroutines-core/common/test/AsyncLazyTest.kt
+++ b/kotlinx-coroutines-core/common/test/AsyncLazyTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class AsyncLazyTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/AsyncTest.kt b/kotlinx-coroutines-core/common/test/AsyncTest.kt
index 2096a4d..b9c4797 100644
--- a/kotlinx-coroutines-core/common/test/AsyncTest.kt
+++ b/kotlinx-coroutines-core/common/test/AsyncTest.kt
@@ -1,14 +1,10 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "UNREACHABLE_CODE", "USELESS_IS_CHECK") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
-@Suppress("DEPRECATION") // cancel(cause)
class AsyncTest : TestBase() {
@Test
@@ -241,11 +237,11 @@
@Test
fun testIncompleteAsyncState() = runTest {
val deferred = async {
- coroutineContext[Job]!!.invokeOnCompletion { }
+ coroutineContext[Job]!!.invokeOnCompletion { }
}
deferred.await().dispose()
- assertTrue(deferred.getCompleted() is DisposableHandle)
+ assertIs<DisposableHandle>(deferred.getCompleted())
assertNull(deferred.getCompletionExceptionOrNull())
assertTrue(deferred.isCompleted)
assertFalse(deferred.isActive)
@@ -255,11 +251,11 @@
@Test
fun testIncompleteAsyncFastPath() = runTest {
val deferred = async(Dispatchers.Unconfined) {
- coroutineContext[Job]!!.invokeOnCompletion { }
+ coroutineContext[Job]!!.invokeOnCompletion { }
}
deferred.await().dispose()
- assertTrue(deferred.getCompleted() is DisposableHandle)
+ assertIs<DisposableHandle>(deferred.getCompleted())
assertNull(deferred.getCompletionExceptionOrNull())
assertTrue(deferred.isCompleted)
assertFalse(deferred.isActive)
diff --git a/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt b/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt
index 3881eb2..52d3b8e 100644
--- a/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt
+++ b/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.selects.*
import kotlinx.coroutines.sync.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/AwaitCancellationTest.kt b/kotlinx-coroutines-core/common/test/AwaitCancellationTest.kt
index 2fe0c91..51376d5 100644
--- a/kotlinx-coroutines-core/common/test/AwaitCancellationTest.kt
+++ b/kotlinx-coroutines-core/common/test/AwaitCancellationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class AwaitCancellationTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/AwaitTest.kt b/kotlinx-coroutines-core/common/test/AwaitTest.kt
index 10d5b91..ca427df 100644
--- a/kotlinx-coroutines-core/common/test/AwaitTest.kt
+++ b/kotlinx-coroutines-core/common/test/AwaitTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class AwaitTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt b/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt
index 5a96c54..b732819 100644
--- a/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt
+++ b/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/CancellableContinuationHandlersTest.kt b/kotlinx-coroutines-core/common/test/CancellableContinuationHandlersTest.kt
index 54bc18c..f005c93 100644
--- a/kotlinx-coroutines-core/common/test/CancellableContinuationHandlersTest.kt
+++ b/kotlinx-coroutines-core/common/test/CancellableContinuationHandlersTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -50,7 +47,7 @@
suspendCancellableCoroutine<Unit> { c ->
c.cancel()
c.invokeOnCancellation {
- assertTrue(it is CancellationException)
+ assertIs<CancellationException>(it)
expect(1)
}
assertFailsWith<IllegalStateException> { c.invokeOnCancellation { expectUnreached() } }
@@ -90,7 +87,7 @@
cont = c
// Set IOC first -- not called (completed)
c.invokeOnCancellation {
- assertTrue(it is CancellationException)
+ assertIs<CancellationException>(it)
expect(4)
}
expect(1)
diff --git a/kotlinx-coroutines-core/common/test/CancellableContinuationTest.kt b/kotlinx-coroutines-core/common/test/CancellableContinuationTest.kt
index f9f610c..43ad996 100644
--- a/kotlinx-coroutines-core/common/test/CancellableContinuationTest.kt
+++ b/kotlinx-coroutines-core/common/test/CancellableContinuationTest.kt
@@ -1,10 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/CancellableResumeTest.kt b/kotlinx-coroutines-core/common/test/CancellableResumeTest.kt
index bff9719..517b0ce 100644
--- a/kotlinx-coroutines-core/common/test/CancellableResumeTest.kt
+++ b/kotlinx-coroutines-core/common/test/CancellableResumeTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
/**
@@ -37,7 +34,7 @@
expect(4)
cont.resume("OK") { cause ->
expect(5)
- assertTrue(cause is TestException)
+ assertIs<TestException>(cause)
}
finish(6)
}
@@ -63,7 +60,7 @@
expect(4)
cont.resume("OK") { cause ->
expect(5)
- assertTrue(cause is TestException)
+ assertIs<TestException>(cause)
throw TestException3("FAIL") // onCancellation block fails with exception
}
finish(6)
@@ -158,7 +155,7 @@
expect(6)
cc.resume("OK") { cause ->
expect(7)
- assertTrue(cause is TestCancellationException)
+ assertIs<TestCancellationException>(cause)
}
expect(8)
}
@@ -193,7 +190,7 @@
expect(6)
cc.resume("OK") { cause ->
expect(7)
- assertTrue(cause is TestCancellationException)
+ assertIs<TestCancellationException>(cause)
throw TestException3("FAIL") // onCancellation block fails with exception
}
expect(8)
@@ -212,7 +209,7 @@
cont.invokeOnCancellation { cause ->
// Note: invokeOnCancellation is called before cc.resume(value) { ... } handler
expect(7)
- assertTrue(cause is TestCancellationException)
+ assertIs<TestCancellationException>(cause)
}
cc = cont
}
@@ -225,7 +222,7 @@
cc.resume("OK") { cause ->
// Note: this handler is called after invokeOnCancellation handler
expect(8)
- assertTrue(cause is TestCancellationException)
+ assertIs<TestCancellationException>(cause)
}
expect(5)
job.cancel(TestCancellationException()) // cancel while execution is dispatched
@@ -252,7 +249,7 @@
cont.invokeOnCancellation { cause ->
// Note: invokeOnCancellation is called before cc.resume(value) { ... } handler
expect(7)
- assertTrue(cause is TestCancellationException)
+ assertIs<TestCancellationException>(cause)
throw TestException2("FAIL") // invokeOnCancellation handler fails with exception
}
cc = cont
@@ -266,7 +263,7 @@
cc.resume("OK") { cause ->
// Note: this handler is called after invokeOnCancellation handler
expect(8)
- assertTrue(cause is TestCancellationException)
+ assertIs<TestCancellationException>(cause)
throw TestException3("FAIL") // onCancellation block fails with exception
}
expect(5)
diff --git a/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt b/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt
index 9dd61b8..e981248 100644
--- a/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt
+++ b/kotlinx-coroutines-core/common/test/CancelledParentAttachTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.internal.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt b/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt
index 1f3978d..b2a3921 100644
--- a/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt
+++ b/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class CompletableDeferredTest : TestBase() {
@@ -29,11 +26,11 @@
@Test
fun testCompleteWithIncompleteResult() {
val c = CompletableDeferred<DisposableHandle>()
- assertEquals(true, c.complete(c.invokeOnCompletion { }))
+ assertEquals(true, c.complete(c.invokeOnCompletion { }))
checkCompleteOk(c)
- assertEquals(false, c.complete(c.invokeOnCompletion { }))
+ assertEquals(false, c.complete(c.invokeOnCompletion { }))
checkCompleteOk(c)
- assertTrue(c.getCompleted() is Incomplete)
+ assertIs<Incomplete>(c.getCompleted())
}
private fun checkFresh(c: CompletableDeferred<*>) {
@@ -49,7 +46,7 @@
assertEquals(false, c.isActive)
assertEquals(false, c.isCancelled)
assertEquals(true, c.isCompleted)
- assertTrue(c.getCancellationException() is JobCancellationException)
+ assertIs<JobCancellationException>(c.getCancellationException())
assertNull(c.getCompletionExceptionOrNull())
}
@@ -58,7 +55,7 @@
assertEquals(true, c.isCancelled)
assertEquals(true, c.isCompleted)
assertThrows<CancellationException> { c.getCompleted() }
- assertTrue(c.getCompletionExceptionOrNull() is CancellationException)
+ assertIs<CancellationException>(c.getCompletionExceptionOrNull())
}
@Test
@@ -74,9 +71,9 @@
assertEquals(false, c.isActive)
assertEquals(true, c.isCancelled)
assertEquals(true, c.isCompleted)
- assertTrue(c.getCancellationException() is JobCancellationException)
+ assertIs<JobCancellationException>(c.getCancellationException())
assertThrows<TestException> { c.getCompleted() }
- assertTrue(c.getCompletionExceptionOrNull() is TestException)
+ assertIs<TestException>(c.getCompletionExceptionOrNull())
}
@Test
@@ -111,7 +108,7 @@
assertEquals(true, c.isCancelled)
assertEquals(true, c.isCompleted)
assertThrows<CancellationException> { c.getCompleted() }
- assertTrue(c.getCompletionExceptionOrNull() is CancellationException)
+ assertIs<CancellationException>(c.getCompletionExceptionOrNull())
}
@Test
@@ -212,7 +209,7 @@
block()
fail("Should not complete normally")
} catch (e: Throwable) {
- assertTrue(e is T)
+ assertIs<T>(e)
}
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/common/test/CompletableJobTest.kt b/kotlinx-coroutines-core/common/test/CompletableJobTest.kt
index 8b17e23..697581a 100644
--- a/kotlinx-coroutines-core/common/test/CompletableJobTest.kt
+++ b/kotlinx-coroutines-core/common/test/CompletableJobTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class CompletableJobTest : TestBase() {
@@ -56,8 +53,8 @@
// KT-33840
hang {}
} catch (e: Throwable) {
- assertTrue(e is CancellationException)
- assertTrue((if (RECOVER_STACK_TRACES) e.cause?.cause else e.cause) is TestException)
+ assertIs<CancellationException>(e)
+ assertIs<TestException>(if (RECOVER_STACK_TRACES) e.cause?.cause else e.cause)
expect(4)
throw e
}
@@ -78,8 +75,8 @@
// KT-33840
hang {}
} catch (e: Throwable) {
- assertTrue(e is CancellationException)
- assertTrue((if (RECOVER_STACK_TRACES) e.cause?.cause else e.cause) is TestException)
+ assertIs<CancellationException>(e)
+ assertIs<TestException>(if (RECOVER_STACK_TRACES) e.cause?.cause else e.cause)
expect(4)
throw e
}
diff --git a/kotlinx-coroutines-core/common/test/CoroutineDispatcherOperatorFunInvokeTest.kt b/kotlinx-coroutines-core/common/test/CoroutineDispatcherOperatorFunInvokeTest.kt
index e6b340c..0a643cb 100644
--- a/kotlinx-coroutines-core/common/test/CoroutineDispatcherOperatorFunInvokeTest.kt
+++ b/kotlinx-coroutines-core/common/test/CoroutineDispatcherOperatorFunInvokeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.CoroutineContext
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/CoroutineExceptionHandlerTest.kt b/kotlinx-coroutines-core/common/test/CoroutineExceptionHandlerTest.kt
index 95e9366..5549b08 100644
--- a/kotlinx-coroutines-core/common/test/CoroutineExceptionHandlerTest.kt
+++ b/kotlinx-coroutines-core/common/test/CoroutineExceptionHandlerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class CoroutineExceptionHandlerTest : TestBase() {
@@ -23,7 +20,7 @@
expect(2)
job.join()
finish(4)
- assertTrue(coroutineException is TestException)
+ assertIs<TestException>(coroutineException)
assertTrue(parent.isCancelled)
}
@@ -42,6 +39,6 @@
job.join()
finish(3)
assertTrue(parent.isCancelled)
- assertTrue(parent.getCompletionExceptionOrNull() is TestException)
+ assertIs<TestException>(parent.getCompletionExceptionOrNull())
}
}
diff --git a/kotlinx-coroutines-core/common/test/CoroutineScopeTest.kt b/kotlinx-coroutines-core/common/test/CoroutineScopeTest.kt
index b678b03..87ab511 100644
--- a/kotlinx-coroutines-core/common/test/CoroutineScopeTest.kt
+++ b/kotlinx-coroutines-core/common/test/CoroutineScopeTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNREACHABLE_CODE")
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/CoroutinesTest.kt b/kotlinx-coroutines-core/common/test/CoroutinesTest.kt
index 534cfd6..8cd149e 100644
--- a/kotlinx-coroutines-core/common/test/CoroutinesTest.kt
+++ b/kotlinx-coroutines-core/common/test/CoroutinesTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class CoroutinesTest : TestBase() {
@@ -240,7 +237,7 @@
job.cancelAndJoin() // join should crash on child's exception but it will be wrapped into CancellationException
} catch (e: Throwable) {
e as CancellationException // type assertion
- assertTrue(e.cause is TestException)
+ assertIs<TestException>(e.cause)
throw e
}
expectUnreached()
@@ -332,4 +329,4 @@
}
private fun throwTestException() { throw TestException() }
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/common/test/DelayDurationTest.kt b/kotlinx-coroutines-core/common/test/DelayDurationTest.kt
index f054409..dad01eb 100644
--- a/kotlinx-coroutines-core/common/test/DelayDurationTest.kt
+++ b/kotlinx-coroutines-core/common/test/DelayDurationTest.kt
@@ -1,13 +1,10 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION")
// KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
import kotlin.time.*
import kotlin.time.Duration.Companion.seconds
diff --git a/kotlinx-coroutines-core/common/test/DelayTest.kt b/kotlinx-coroutines-core/common/test/DelayTest.kt
index 1b73146..007a272 100644
--- a/kotlinx-coroutines-core/common/test/DelayTest.kt
+++ b/kotlinx-coroutines-core/common/test/DelayTest.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class DelayTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/DispatchedContinuationTest.kt b/kotlinx-coroutines-core/common/test/DispatchedContinuationTest.kt
index b69eb22..2035ef5 100644
--- a/kotlinx-coroutines-core/common/test/DispatchedContinuationTest.kt
+++ b/kotlinx-coroutines-core/common/test/DispatchedContinuationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/DurationToMillisTest.kt b/kotlinx-coroutines-core/common/test/DurationToMillisTest.kt
new file mode 100644
index 0000000..4815419
--- /dev/null
+++ b/kotlinx-coroutines-core/common/test/DurationToMillisTest.kt
@@ -0,0 +1,66 @@
+package kotlinx.coroutines
+
+import kotlin.test.*
+import kotlin.time.*
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.nanoseconds
+import kotlin.time.Duration.Companion.seconds
+
+class DurationToMillisTest {
+
+ @Test
+ fun testNegativeDurationCoercedToZeroMillis() {
+ assertEquals(0L, (-1).seconds.toDelayMillis())
+ }
+
+ @Test
+ fun testZeroDurationCoercedToZeroMillis() {
+ assertEquals(0L, 0.seconds.toDelayMillis())
+ }
+
+ @Test
+ fun testOneNanosecondCoercedToOneMillisecond() {
+ assertEquals(1L, 1.nanoseconds.toDelayMillis())
+ }
+
+ @Test
+ fun testOneSecondCoercedTo1000Milliseconds() {
+ assertEquals(1_000L, 1.seconds.toDelayMillis())
+ }
+
+ @Test
+ fun testMixedComponentDurationRoundedUpToNextMillisecond() {
+ assertEquals(999L, (998.milliseconds + 75909.nanoseconds).toDelayMillis())
+ }
+
+ @Test
+ fun testOneExtraNanosecondRoundedUpToNextMillisecond() {
+ assertEquals(999L, (998.milliseconds + 1.nanoseconds).toDelayMillis())
+ }
+
+ @Test
+ fun testInfiniteDurationCoercedToLongMaxValue() {
+ assertEquals(Long.MAX_VALUE, Duration.INFINITE.toDelayMillis())
+ }
+
+ @Test
+ fun testNegativeInfiniteDurationCoercedToZero() {
+ assertEquals(0L, (-Duration.INFINITE).toDelayMillis())
+ }
+
+ @Test
+ fun testNanosecondOffByOneInfinityDoesNotOverflow() {
+ assertEquals(Long.MAX_VALUE / 1_000_000, (Long.MAX_VALUE - 1L).nanoseconds.toDelayMillis())
+ }
+
+ @Test
+ fun testMillisecondOffByOneInfinityDoesNotIncrement() {
+ assertEquals((Long.MAX_VALUE / 2) - 1, ((Long.MAX_VALUE / 2) - 1).milliseconds.toDelayMillis())
+ }
+
+ @Test
+ fun testOutOfBoundsNanosecondsButFiniteDoesNotIncrement() {
+ val milliseconds = Long.MAX_VALUE / 10
+ assertEquals(milliseconds, milliseconds.milliseconds.toDelayMillis())
+ }
+}
diff --git a/kotlinx-coroutines-core/common/test/EmptyContext.kt b/kotlinx-coroutines-core/common/test/EmptyContext.kt
index 97efec3..61e595c 100644
--- a/kotlinx-coroutines-core/common/test/EmptyContext.kt
+++ b/kotlinx-coroutines-core/common/test/EmptyContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.intrinsics.*
diff --git a/kotlinx-coroutines-core/common/test/ExperimentalDispatchModeTest.kt b/kotlinx-coroutines-core/common/test/ExperimentalDispatchModeTest.kt
index 37e6182..98c5e66 100644
--- a/kotlinx-coroutines-core/common/test/ExperimentalDispatchModeTest.kt
+++ b/kotlinx-coroutines-core/common/test/ExperimentalDispatchModeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class ExperimentalDispatchModeTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/FailedJobTest.kt b/kotlinx-coroutines-core/common/test/FailedJobTest.kt
index e4d0fad..77656ee 100644
--- a/kotlinx-coroutines-core/common/test/FailedJobTest.kt
+++ b/kotlinx-coroutines-core/common/test/FailedJobTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
// see https://github.com/Kotlin/kotlinx.coroutines/issues/585
diff --git a/kotlinx-coroutines-core/common/test/ImmediateYieldTest.kt b/kotlinx-coroutines-core/common/test/ImmediateYieldTest.kt
index 3801b8a..c2c2148 100644
--- a/kotlinx-coroutines-core/common/test/ImmediateYieldTest.kt
+++ b/kotlinx-coroutines-core/common/test/ImmediateYieldTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/JobExtensionsTest.kt b/kotlinx-coroutines-core/common/test/JobExtensionsTest.kt
index b335926..aacb022 100644
--- a/kotlinx-coroutines-core/common/test/JobExtensionsTest.kt
+++ b/kotlinx-coroutines-core/common/test/JobExtensionsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -79,8 +76,8 @@
private inline fun checkException(block: () -> Unit) {
val result = runCatching(block)
val exception = result.exceptionOrNull() ?: fail()
- assertTrue(exception is JobCancellationException)
- assertTrue(exception.cause is TestException)
+ assertIs<JobCancellationException>(exception)
+ assertIs<TestException>(exception.cause)
}
@Test
diff --git a/kotlinx-coroutines-core/common/test/JobStatesTest.kt b/kotlinx-coroutines-core/common/test/JobStatesTest.kt
index 739401f..6f18afd 100644
--- a/kotlinx-coroutines-core/common/test/JobStatesTest.kt
+++ b/kotlinx-coroutines-core/common/test/JobStatesTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
/**
diff --git a/kotlinx-coroutines-core/common/test/JobTest.kt b/kotlinx-coroutines-core/common/test/JobTest.kt
index 3889583..b86ac73 100644
--- a/kotlinx-coroutines-core/common/test/JobTest.kt
+++ b/kotlinx-coroutines-core/common/test/JobTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("DEPRECATION")
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class JobTest : TestBase() {
@@ -106,8 +103,8 @@
val cancelResult = runCatching { job.cancel() }
assertTrue(!job.isActive)
for (i in 0 until n) assertEquals(1, fireCount[i])
- assertTrue(cancelResult.exceptionOrNull() is CompletionHandlerException)
- assertTrue(cancelResult.exceptionOrNull()!!.cause is TestException)
+ assertIs<CompletionHandlerException>(cancelResult.exceptionOrNull())
+ assertIs<TestException>(cancelResult.exceptionOrNull()!!.cause)
}
@Test
diff --git a/kotlinx-coroutines-core/common/test/LaunchLazyTest.kt b/kotlinx-coroutines-core/common/test/LaunchLazyTest.kt
index 1ed466d..8f200fa 100644
--- a/kotlinx-coroutines-core/common/test/LaunchLazyTest.kt
+++ b/kotlinx-coroutines-core/common/test/LaunchLazyTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class LaunchLazyTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/LimitedParallelismSharedTest.kt b/kotlinx-coroutines-core/common/test/LimitedParallelismSharedTest.kt
index d01e857..d5b84ed 100644
--- a/kotlinx-coroutines-core/common/test/LimitedParallelismSharedTest.kt
+++ b/kotlinx-coroutines-core/common/test/LimitedParallelismSharedTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class LimitedParallelismSharedTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/NonCancellableTest.kt b/kotlinx-coroutines-core/common/test/NonCancellableTest.kt
index 07c3f9b..bede537 100644
--- a/kotlinx-coroutines-core/common/test/NonCancellableTest.kt
+++ b/kotlinx-coroutines-core/common/test/NonCancellableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class NonCancellableTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt
index 96c5cf3..fd07a06 100644
--- a/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt
+++ b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/SupervisorTest.kt b/kotlinx-coroutines-core/common/test/SupervisorTest.kt
index 535073e..1fb0ff9 100644
--- a/kotlinx-coroutines-core/common/test/SupervisorTest.kt
+++ b/kotlinx-coroutines-core/common/test/SupervisorTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class SupervisorTest : TestBase() {
@@ -86,10 +83,12 @@
@Test
fun testThrowingSupervisorScope() = runTest {
+ var childJob: Job? = null
+ var supervisorJob: Job? = null
try {
expect(1)
supervisorScope {
- async {
+ childJob = async {
try {
delay(Long.MAX_VALUE)
} finally {
@@ -99,9 +98,13 @@
expect(2)
yield()
+ supervisorJob = coroutineContext.job
throw TestException2()
}
} catch (e: Throwable) {
+ assertIs<TestException2>(e)
+ assertTrue(childJob!!.isCancelled)
+ assertTrue(supervisorJob!!.isCancelled)
finish(4)
}
}
@@ -158,6 +161,31 @@
}
}
+ /**
+ * Tests that [supervisorScope] cancels all its children when the current coroutine is cancelled.
+ */
+ @Test
+ fun testSupervisorScopeExternalCancellation() = runTest {
+ var childJob: Job? = null
+ val job = launch {
+ supervisorScope {
+ childJob = launch(start = CoroutineStart.UNDISPATCHED) {
+ try {
+ delay(Long.MAX_VALUE)
+ } finally {
+ expect(2)
+ }
+ }
+ }
+ }
+ while (childJob == null) yield()
+ expect(1)
+ job.cancel()
+ assertTrue(childJob!!.isCancelled)
+ job.join()
+ finish(3)
+ }
+
@Test
fun testAsyncCancellation() = runTest {
val parent = SupervisorJob()
@@ -173,7 +201,7 @@
expectUnreached()
} catch (e: CancellationException) {
val cause = if (RECOVER_STACK_TRACES) e.cause?.cause!! else e.cause
- assertTrue(cause is TestException1)
+ assertIs<TestException1>(cause)
finish(3)
}
}
diff --git a/kotlinx-coroutines-core/common/test/TestBase.common.kt b/kotlinx-coroutines-core/common/test/TestBase.common.kt
deleted file mode 100644
index 06e71b4..0000000
--- a/kotlinx-coroutines-core/common/test/TestBase.common.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("unused")
-
-package kotlinx.coroutines
-
-import kotlinx.coroutines.flow.*
-import kotlinx.coroutines.internal.*
-import kotlin.coroutines.*
-import kotlin.test.*
-
-public expect val isStressTest: Boolean
-public expect val stressTestMultiplier: Int
-public expect val stressTestMultiplierSqrt: Int
-
-/**
- * The result of a multiplatform asynchronous test.
- * Aliases into Unit on K/JVM and K/N, and into Promise on K/JS.
- */
-@Suppress("NO_ACTUAL_FOR_EXPECT")
-public expect class TestResult
-
-public expect val isNative: Boolean
-
-public expect open class TestBase constructor() {
- /*
- * In common tests we emulate parameterized tests
- * by iterating over parameters space in the single @Test method.
- * This kind of tests is too slow for JS and does not fit into
- * the default Mocha timeout, so we're using this flag to bail-out
- * and run such tests only on JVM and K/N.
- */
- public val isBoundByJsTestTimeout: Boolean
- public fun error(message: Any, cause: Throwable? = null): Nothing
- public fun expect(index: Int)
- public fun expectUnreached()
- public fun finish(index: Int)
- public fun ensureFinished() // Ensures that 'finish' was invoked
- public fun reset() // Resets counter and finish flag. Workaround for parametrized tests absence in common
-
- public fun runTest(
- expected: ((Throwable) -> Boolean)? = null,
- unhandled: List<(Throwable) -> Boolean> = emptyList(),
- block: suspend CoroutineScope.() -> Unit
- ): TestResult
-}
-
-public suspend inline fun hang(onCancellation: () -> Unit) {
- try {
- suspendCancellableCoroutine<Unit> { }
- } finally {
- onCancellation()
- }
-}
-
-public inline fun <reified T : Throwable> assertFailsWith(block: () -> Unit) {
- try {
- block()
- error("Should not be reached")
- } catch (e: Throwable) {
- assertTrue(e is T)
- }
-}
-
-public suspend inline fun <reified T : Throwable> assertFailsWith(flow: Flow<*>) {
- try {
- flow.collect()
- fail("Should be unreached")
- } catch (e: Throwable) {
- assertTrue(e is T, "Expected exception ${T::class}, but had $e instead")
- }
-}
-
-public suspend fun Flow<Int>.sum() = fold(0) { acc, value -> acc + value }
-public suspend fun Flow<Long>.longSum() = fold(0L) { acc, value -> acc + value }
-
-
-// data is added to avoid stacktrace recovery because CopyableThrowable is not accessible from common modules
-public class TestException(message: String? = null, private val data: Any? = null) : Throwable(message)
-public class TestException1(message: String? = null, private val data: Any? = null) : Throwable(message)
-public class TestException2(message: String? = null, private val data: Any? = null) : Throwable(message)
-public class TestException3(message: String? = null, private val data: Any? = null) : Throwable(message)
-public class TestCancellationException(message: String? = null, private val data: Any? = null) : CancellationException(message)
-public class TestRuntimeException(message: String? = null, private val data: Any? = null) : RuntimeException(message)
-public class RecoverableTestException(message: String? = null) : RuntimeException(message)
-public class RecoverableTestCancellationException(message: String? = null) : CancellationException(message)
-
-public fun wrapperDispatcher(context: CoroutineContext): CoroutineContext {
- val dispatcher = context[ContinuationInterceptor] as CoroutineDispatcher
- return object : CoroutineDispatcher() {
- override fun isDispatchNeeded(context: CoroutineContext): Boolean =
- dispatcher.isDispatchNeeded(context)
- override fun dispatch(context: CoroutineContext, block: Runnable) =
- dispatcher.dispatch(context, block)
- }
-}
-
-public suspend fun wrapperDispatcher(): CoroutineContext = wrapperDispatcher(coroutineContext)
-
-class BadClass {
- override fun equals(other: Any?): Boolean = error("equals")
- override fun hashCode(): Int = error("hashCode")
- override fun toString(): String = error("toString")
-}
-
-public expect val isJavaAndWindows: Boolean
diff --git a/kotlinx-coroutines-core/common/test/UnconfinedTest.kt b/kotlinx-coroutines-core/common/test/UnconfinedTest.kt
index 4f9cc9b..b22e4bf 100644
--- a/kotlinx-coroutines-core/common/test/UnconfinedTest.kt
+++ b/kotlinx-coroutines-core/common/test/UnconfinedTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class UnconfinedTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt b/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt
index 34b8164..cec00e7 100644
--- a/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt
+++ b/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/WithContextTest.kt b/kotlinx-coroutines-core/common/test/WithContextTest.kt
index 55127e5..9e9fd35 100644
--- a/kotlinx-coroutines-core/common/test/WithContextTest.kt
+++ b/kotlinx-coroutines-core/common/test/WithContextTest.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-22237
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class WithContextTest : TestBase() {
@@ -214,7 +211,7 @@
} catch (e: Throwable) {
expect(7)
// make sure TestException, not CancellationException is thrown
- assertTrue(e is TestException, "Caught $e")
+ assertIs<TestException>(e, "Caught $e")
}
}
expect(2)
@@ -244,7 +241,7 @@
} catch (e: Throwable) {
expect(7)
// make sure CancellationException is thrown
- assertTrue(e is CancellationException, "Caught $e")
+ assertIs<CancellationException>(e, "Caught $e")
}
}
diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt
index 60e64f5..855b00f 100644
--- a/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt
+++ b/kotlinx-coroutines-core/common/test/WithTimeoutDurationTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "UNREACHABLE_CODE") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt
index 1f9ad46..f92a4c2 100644
--- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt
+++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullDurationTest.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
import kotlin.time.*
diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt
index 5ab8ae7..51a6a38 100644
--- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt
+++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt
index 8462c96..5f2690c 100644
--- a/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt
+++ b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "UNREACHABLE_CODE") // KT-21913
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class WithTimeoutTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt b/kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt
index 1f9b6fa..fb9e0d9 100644
--- a/kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/BroadcastChannelFactoryTest.kt b/kotlinx-coroutines-core/common/test/channels/BroadcastChannelFactoryTest.kt
index e27edcf..652f307 100644
--- a/kotlinx-coroutines-core/common/test/channels/BroadcastChannelFactoryTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/BroadcastChannelFactoryTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/BroadcastTest.kt b/kotlinx-coroutines-core/common/test/channels/BroadcastTest.kt
index 34b1395..a308f7a 100644
--- a/kotlinx-coroutines-core/common/test/channels/BroadcastTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/BroadcastTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED")
+@file:Suppress("DEPRECATION")
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import kotlin.test.*
@@ -25,13 +22,14 @@
}
yield() // has no effect, because default is lazy
expect(2)
- b.consume {
- expect(3)
- assertEquals(1, receive()) // suspends
- expect(7)
- assertEquals(2, receive()) // suspends
- expect(8)
- }
+
+ val subscription = b.openSubscription()
+ expect(3)
+ assertEquals(1, subscription.receive()) // suspends
+ expect(7)
+ assertEquals(2, subscription.receive()) // suspends
+ expect(8)
+ subscription.cancel()
expect(9)
yield() // to broadcast
finish(11)
@@ -138,4 +136,4 @@
yield() // to cancel broadcast
finish(6)
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/common/test/channels/BufferedBroadcastChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/BufferedBroadcastChannelTest.kt
index fad6500..834d974 100644
--- a/kotlinx-coroutines-core/common/test/channels/BufferedBroadcastChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/BufferedBroadcastChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/BufferedChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/BufferedChannelTest.kt
index 0f70352..27ac005 100644
--- a/kotlinx-coroutines-core/common/test/channels/BufferedChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/BufferedChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelBufferOverflowTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelBufferOverflowTest.kt
index 0b9a0fd..a6ae885 100644
--- a/kotlinx-coroutines-core/common/test/channels/ChannelBufferOverflowTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ChannelBufferOverflowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelFactoryTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelFactoryTest.kt
index 706a2fd..9260c2d 100644
--- a/kotlinx-coroutines-core/common/test/channels/ChannelFactoryTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ChannelFactoryTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -11,28 +8,28 @@
class ChannelFactoryTest : TestBase() {
@Test
fun testRendezvousChannel() {
- assertTrue(Channel<Int>() is BufferedChannel)
- assertTrue(Channel<Int>(0) is BufferedChannel)
+ assertIs<BufferedChannel<*>>(Channel<Int>())
+ assertIs<BufferedChannel<*>>(Channel<Int>(0))
}
@Test
fun testUnlimitedChannel() {
- assertTrue(Channel<Int>(Channel.UNLIMITED) is BufferedChannel)
- assertTrue(Channel<Int>(Channel.UNLIMITED, BufferOverflow.DROP_OLDEST) is BufferedChannel)
- assertTrue(Channel<Int>(Channel.UNLIMITED, BufferOverflow.DROP_LATEST) is BufferedChannel)
+ assertIs<BufferedChannel<*>>(Channel<Int>(Channel.UNLIMITED))
+ assertIs<BufferedChannel<*>>(Channel<Int>(Channel.UNLIMITED, BufferOverflow.DROP_OLDEST))
+ assertIs<BufferedChannel<*>>(Channel<Int>(Channel.UNLIMITED, BufferOverflow.DROP_LATEST))
}
@Test
fun testConflatedChannel() {
- assertTrue(Channel<Int>(Channel.CONFLATED) is ConflatedBufferedChannel)
- assertTrue(Channel<Int>(1, BufferOverflow.DROP_OLDEST) is ConflatedBufferedChannel)
+ assertIs<ConflatedBufferedChannel<*>>(Channel<Int>(Channel.CONFLATED))
+ assertIs<ConflatedBufferedChannel<*>>(Channel<Int>(1, BufferOverflow.DROP_OLDEST))
}
@Test
fun testBufferedChannel() {
- assertTrue(Channel<Int>(1) is BufferedChannel)
- assertTrue(Channel<Int>(1, BufferOverflow.DROP_LATEST) is ConflatedBufferedChannel)
- assertTrue(Channel<Int>(10) is BufferedChannel)
+ assertIs<BufferedChannel<*>>(Channel<Int>(1))
+ assertIs<ConflatedBufferedChannel<*>>(Channel<Int>(1, BufferOverflow.DROP_LATEST))
+ assertIs<BufferedChannel<*>>(Channel<Int>(10))
}
@Test
diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelReceiveCatchingTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelReceiveCatchingTest.kt
index 2341c62..bb06a80 100644
--- a/kotlinx-coroutines-core/common/test/channels/ChannelReceiveCatchingTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ChannelReceiveCatchingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -17,13 +14,13 @@
}
val element = channel.receiveCatching()
- assertTrue(element.getOrThrow() is TestException1)
- assertTrue(element.getOrNull() is TestException1)
+ assertIs<TestException1>(element.getOrThrow())
+ assertIs<TestException1>(element.getOrNull())
val closed = channel.receiveCatching()
assertTrue(closed.isClosed)
assertTrue(closed.isFailure)
- assertTrue(closed.exceptionOrNull() is TestException2)
+ assertIs<TestException2>(closed.exceptionOrNull())
}
@Test
@@ -124,12 +121,12 @@
assertFalse(intResult.isClosed)
val closeCauseResult = channel.receiveCatching()
- assertTrue(closeCauseResult.getOrThrow().exceptionOrNull() is TestException1)
+ assertIs<TestException1>(closeCauseResult.getOrThrow().exceptionOrNull())
val closeCause = channel.receiveCatching()
assertTrue(closeCause.isClosed)
assertTrue(closeCause.isFailure)
- assertTrue(closeCause.exceptionOrNull() is TestException2)
+ assertIs<TestException2>(closeCause.exceptionOrNull())
}
@Test
diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementFailureTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementFailureTest.kt
index 0faa79b..c45ff29 100644
--- a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementFailureTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementFailureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import kotlinx.coroutines.selects.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt
index 3a99484..4be7c31 100644
--- a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt
index e40071b..d4d6887 100644
--- a/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("DEPRECATION")
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.math.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ConflatedBroadcastChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ConflatedBroadcastChannelTest.kt
index a8c2a29..72b5fde 100644
--- a/kotlinx-coroutines-core/common/test/channels/ConflatedBroadcastChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ConflatedBroadcastChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -36,7 +33,7 @@
fun testBasicScenario() = runTest {
expect(1)
val broadcast = ConflatedBroadcastChannel<String>()
- assertTrue(exceptionFrom { broadcast.value } is IllegalStateException)
+ assertIs<IllegalStateException>(exceptionFrom { broadcast.value })
assertNull(broadcast.valueOrNull)
launch(start = CoroutineStart.UNDISPATCHED) {
@@ -88,11 +85,11 @@
yield() // to second receiver
expect(18)
broadcast.close()
- assertTrue(exceptionFrom { broadcast.value } is IllegalStateException)
+ assertIs<IllegalStateException>(exceptionFrom { broadcast.value })
assertNull(broadcast.valueOrNull)
expect(19)
yield() // to second receiver
- assertTrue(exceptionFrom { broadcast.send("four") } is ClosedSendChannelException)
+ assertIs<ClosedSendChannelException>(exceptionFrom { broadcast.send("four") })
finish(22)
}
@@ -107,7 +104,7 @@
val sub = broadcast.openSubscription()
assertEquals(1, sub.receive())
expect(3)
- assertTrue(exceptionFrom { sub.receive() } is ClosedReceiveChannelException) // suspends
+ assertIs<ClosedReceiveChannelException>(exceptionFrom { sub.receive() }) // suspends
expect(6)
}
expect(4)
diff --git a/kotlinx-coroutines-core/common/test/channels/ConflatedChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ConflatedChannelTest.kt
index 370fd5b..e3e52df 100644
--- a/kotlinx-coroutines-core/common/test/channels/ConflatedChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ConflatedChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ConsumeTest.kt b/kotlinx-coroutines-core/common/test/channels/ConsumeTest.kt
new file mode 100644
index 0000000..f5df234
--- /dev/null
+++ b/kotlinx-coroutines-core/common/test/channels/ConsumeTest.kt
@@ -0,0 +1,107 @@
+@file:OptIn(DelicateCoroutinesApi::class)
+package kotlinx.coroutines.channels
+
+import kotlinx.coroutines.testing.*
+import kotlinx.coroutines.*
+import kotlin.test.*
+
+class ConsumeTest: TestBase() {
+
+ /** Check that [ReceiveChannel.consume] does not suffer from KT-58685 */
+ @Test
+ fun testConsumeJsMiscompilation() = runTest {
+ val channel = Channel<Int>()
+ assertFailsWith<IndexOutOfBoundsException> {
+ try {
+ channel.consume { null } ?: throw IndexOutOfBoundsException() // should throw…
+ } catch (e: Exception) {
+ throw e // …but instead fails here
+ }
+ }
+ }
+
+ /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */
+ @Test
+ fun testConsumeClosesOnSuccess() = runTest {
+ val channel = Channel<Int>()
+ channel.consume { }
+ assertTrue(channel.isClosedForReceive)
+ }
+
+ /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */
+ @Test
+ fun testConsumeClosesOnFailure() = runTest {
+ val channel = Channel<Int>()
+ try {
+ channel.consume { throw TestException() }
+ } catch (e: TestException) {
+ // Expected
+ }
+ assertTrue(channel.isClosedForReceive)
+ }
+
+ /** Checks that [ReceiveChannel.consume] closes the channel when the block does an early return. */
+ @Test
+ fun testConsumeClosesOnEarlyReturn() = runTest {
+ val channel = Channel<Int>()
+ fun f() {
+ try {
+ channel.consume { return }
+ } catch (e: TestException) {
+ // Expected
+ }
+ }
+ f()
+ assertTrue(channel.isClosedForReceive)
+ }
+
+ /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */
+ @Test
+ fun testConsumeEachClosesOnSuccess() = runTest {
+ val channel = Channel<Int>(Channel.UNLIMITED)
+ launch { channel.close() }
+ channel.consumeEach { fail("unreached") }
+ assertTrue(channel.isClosedForReceive)
+ }
+
+ /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */
+ @Test
+ fun testConsumeEachClosesOnFailure() = runTest {
+ val channel = Channel<Unit>(Channel.UNLIMITED)
+ channel.send(Unit)
+ try {
+ channel.consumeEach { throw TestException() }
+ } catch (e: TestException) {
+ // Expected
+ }
+ assertTrue(channel.isClosedForReceive)
+ }
+
+ /** Checks that [ReceiveChannel.consume] closes the channel when the block does an early return. */
+ @Test
+ fun testConsumeEachClosesOnEarlyReturn() = runTest {
+ val channel = Channel<Unit>(Channel.UNLIMITED)
+ channel.send(Unit)
+ suspend fun f() {
+ channel.consumeEach {
+ return@f
+ }
+ }
+ f()
+ assertTrue(channel.isClosedForReceive)
+ }
+
+ /** Check that [BroadcastChannel.consume] does not suffer from KT-58685 */
+ @Suppress("DEPRECATION", "DEPRECATION_ERROR")
+ @Test
+ fun testBroadcastChannelConsumeJsMiscompilation() = runTest {
+ val channel = BroadcastChannel<Int>(1)
+ assertFailsWith<IndexOutOfBoundsException> {
+ try {
+ channel.consume { null } ?: throw IndexOutOfBoundsException() // should throw…
+ } catch (e: Exception) {
+ throw e // …but instead fails here
+ }
+ }
+ }
+}
diff --git a/kotlinx-coroutines-core/common/test/channels/ProduceConsumeTest.kt b/kotlinx-coroutines-core/common/test/channels/ProduceConsumeTest.kt
index 5df0c7d..1ae5c8c 100644
--- a/kotlinx-coroutines-core/common/test/channels/ProduceConsumeTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ProduceConsumeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt
index 61ef072..1b68bac 100644
--- a/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt
index c83813e..8fd41b8 100644
--- a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/SendReceiveStressTest.kt b/kotlinx-coroutines-core/common/test/channels/SendReceiveStressTest.kt
index dcbb2d2..5fa22b5 100644
--- a/kotlinx-coroutines-core/common/test/channels/SendReceiveStressTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/SendReceiveStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/channels/TestBroadcastChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestBroadcastChannelKind.kt
index 94a4887..0d23238 100644
--- a/kotlinx-coroutines-core/common/test/channels/TestBroadcastChannelKind.kt
+++ b/kotlinx-coroutines-core/common/test/channels/TestBroadcastChannelKind.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
enum class TestBroadcastChannelKind {
diff --git a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt
index 305c0ee..97562d4 100644
--- a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt
+++ b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/test/channels/UnlimitedChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/UnlimitedChannelTest.kt
index 24b9d3d..08bcc20 100644
--- a/kotlinx-coroutines-core/common/test/channels/UnlimitedChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/UnlimitedChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/BuildersTest.kt b/kotlinx-coroutines-core/common/test/flow/BuildersTest.kt
new file mode 100644
index 0000000..6f2eda4
--- /dev/null
+++ b/kotlinx-coroutines-core/common/test/flow/BuildersTest.kt
@@ -0,0 +1,39 @@
+package kotlinx.coroutines.flow
+
+import kotlinx.coroutines.testing.*
+import kotlinx.coroutines.*
+import kotlin.test.*
+
+class BuildersTest : TestBase() {
+
+ @Test
+ fun testSuspendLambdaAsFlow() = runTest {
+ val lambda = suspend { 42 }
+ assertEquals(42, lambda.asFlow().single())
+ }
+
+ @Test
+ fun testRangeAsFlow() = runTest {
+ assertEquals((0..9).toList(), (0..9).asFlow().toList())
+ assertEquals(emptyList(), (0..-1).asFlow().toList())
+
+ assertEquals((0L..9L).toList(), (0L..9L).asFlow().toList())
+ assertEquals(emptyList(), (0L..-1L).asFlow().toList())
+ }
+
+ @Test
+ fun testArrayAsFlow() = runTest {
+ assertEquals((0..9).toList(), IntArray(10) { it }.asFlow().toList())
+ assertEquals(emptyList(), intArrayOf().asFlow().toList())
+
+ assertEquals((0L..9L).toList(), LongArray(10) { it.toLong() }.asFlow().toList())
+ assertEquals(emptyList(), longArrayOf().asFlow().toList())
+ }
+
+ @Test
+ fun testSequence() = runTest {
+ val expected = (0..9).toList()
+ assertEquals(expected, expected.iterator().asFlow().toList())
+ assertEquals(expected, expected.asIterable().asFlow().toList())
+ }
+}
diff --git a/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt b/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt
index 5f39d32..06eedb9 100644
--- a/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.testing.flow.*
import kotlin.coroutines.*
import kotlin.reflect.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/IdFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/IdFlowTest.kt
index a7299cc..be3be66 100644
--- a/kotlinx-coroutines-core/common/test/flow/IdFlowTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/IdFlowTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/NamedDispatchers.kt b/kotlinx-coroutines-core/common/test/flow/NamedDispatchers.kt
index 2459255..754b308 100644
--- a/kotlinx-coroutines-core/common/test/flow/NamedDispatchers.kt
+++ b/kotlinx-coroutines-core/common/test/flow/NamedDispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt
index eaba11b..26132ab 100644
--- a/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/VirtualTime.kt b/kotlinx-coroutines-core/common/test/flow/VirtualTime.kt
index bba5c6b..bd1fd6d 100644
--- a/kotlinx-coroutines-core/common/test/flow/VirtualTime.kt
+++ b/kotlinx-coroutines-core/common/test/flow/VirtualTime.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.jvm.*
@@ -83,6 +80,6 @@
// Create a platform-independent event loop
val dispatcher = VirtualTimeDispatcher(this)
withContext(dispatcher) { block() }
- ensureFinished()
+ checkFinishCall(allowNotUsingExpect = false)
}
}
diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt
index 410955c..7a51a8d 100644
--- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt
index f197a21..6e58461 100644
--- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt
index cfbf242..2b553a5 100644
--- a/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/internal/FlowScopeTest.kt b/kotlinx-coroutines-core/common/test/flow/internal/FlowScopeTest.kt
index e866647..aeaa3c1 100644
--- a/kotlinx-coroutines-core/common/test/flow/internal/FlowScopeTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/internal/FlowScopeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/BufferConflationTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/BufferConflationTest.kt
index 7b66977..789a713 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/BufferConflationTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/BufferConflationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/BufferTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/BufferTest.kt
index 6352aac..c840790 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/BufferTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/BufferTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.math.*
@@ -184,5 +181,14 @@
.toList()
assertEquals(listOf(1, 2), result)
}
+
+ @Test
+ fun testFailsOnIllegalArguments() {
+ val flow = emptyFlow<Int>()
+ assertFailsWith<IllegalArgumentException> { flow.buffer(capacity = -3) }
+ assertFailsWith<IllegalArgumentException> { flow.buffer(capacity = Int.MIN_VALUE) }
+ assertFailsWith<IllegalArgumentException> { flow.buffer(capacity = Channel.CONFLATED, onBufferOverflow = BufferOverflow.DROP_LATEST) }
+ assertFailsWith<IllegalArgumentException> { flow.buffer(capacity = Channel.CONFLATED, onBufferOverflow = BufferOverflow.DROP_OLDEST) }
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/CancellableTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/CancellableTest.kt
index b1b14c4..fff474e 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/CancellableTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/CancellableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt
index ad91e49..420470a 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/CatchTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -103,7 +100,7 @@
flow
.catch { e ->
expect(4)
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("A", kotlin.coroutines.coroutineContext[CoroutineName]?.name)
assertSame(d1, kotlin.coroutines.coroutineContext[ContinuationInterceptor] as CoroutineContext)
throw e // rethrow downstream
@@ -111,7 +108,7 @@
.flowOn(CoroutineName("A"))
.catch { e ->
expect(5)
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("B", kotlin.coroutines.coroutineContext[CoroutineName]?.name)
assertSame(d1, kotlin.coroutines.coroutineContext[ContinuationInterceptor] as CoroutineContext)
throw e // rethrow downstream
@@ -119,14 +116,14 @@
.flowOn(CoroutineName("B"))
.catch { e ->
expect(6)
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertSame(d1, kotlin.coroutines.coroutineContext[ContinuationInterceptor] as CoroutineContext)
throw e // rethrow downstream
}
.flowOn(d1)
.catch { e ->
expect(7)
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertSame(d2, kotlin.coroutines.coroutineContext[ContinuationInterceptor] as CoroutineContext)
throw e // rethrow downstream
}
@@ -138,7 +135,7 @@
}
.catch { e ->
expect(8)
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertSame(d0, kotlin.coroutines.coroutineContext[ContinuationInterceptor] as CoroutineContext)
}
.collect()
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/CombineParametersTestBase.kt b/kotlinx-coroutines-core/common/test/flow/operators/CombineParametersTest.kt
similarity index 94%
rename from kotlinx-coroutines-core/common/test/flow/operators/CombineParametersTestBase.kt
rename to kotlinx-coroutines-core/common/test/flow/operators/CombineParametersTest.kt
index 8c65ea4..f496dd7 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/CombineParametersTestBase.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/CombineParametersTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
@@ -113,8 +110,7 @@
@Test
fun testReified() = runTest {
val value = combine(flowOf(1), flowOf(2)) { args: Array<Int> ->
- @Suppress("USELESS_IS_CHECK")
- assertTrue(args is Array<Int>)
+ assertIs<Array<Int>>(args)
args[0] + args[1]
}.single()
assertEquals(3, value)
@@ -123,8 +119,7 @@
@Test
fun testReifiedTransform() = runTest {
val value = combineTransform(flowOf(1), flowOf(2)) { args: Array<Int> ->
- @Suppress("USELESS_IS_CHECK")
- assertTrue(args is Array<Int>)
+ assertIs<Array<Int>>(args)
emit(args[0] + args[1])
}.single()
assertEquals(3, value)
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/CombineTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/CombineTest.kt
index 5e2926d..6db9b84 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/CombineTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/CombineTest.kt
@@ -1,18 +1,13 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("UNCHECKED_CAST")
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
import kotlinx.coroutines.flow.combine as combineOriginal
import kotlinx.coroutines.flow.combineTransform as combineTransformOriginal
-/*
- * Replace: { i, j -> i + j } -> { i, j -> i + j } as soon as KT-30991 is fixed
- */
abstract class CombineTestBase : TestBase() {
abstract fun <T1, T2, R> Flow<T1>.combineLatest(other: Flow<T2>, transform: suspend (T1, T2) -> R): Flow<R>
@@ -21,7 +16,7 @@
fun testCombineLatest() = runTest {
val flow = flowOf("a", "b", "c")
val flow2 = flowOf(1, 2, 3)
- val list = flow.combineLatest(flow2) { i, j -> i + j }.toList()
+ val list = flow.combineLatest(flow2, String::plus).toList()
assertEquals(listOf("a1", "b2", "c3"), list)
}
@@ -29,7 +24,7 @@
fun testNulls() = runTest {
val flow = flowOf("a", null, null)
val flow2 = flowOf(1, 2, 3)
- val list = flow.combineLatest(flow2) { i, j -> i + j }.toList()
+ val list = flow.combineLatest(flow2, String?::plus).toList()
assertEquals(listOf("a1", "null2", "null3"), list)
}
@@ -37,13 +32,13 @@
fun testNullsOther() = runTest {
val flow = flowOf("a", "b", "c")
val flow2 = flowOf(null, 2, null)
- val list = flow.combineLatest(flow2) { i, j -> i + j }.toList()
+ val list = flow.combineLatest(flow2, String::plus).toList()
assertEquals(listOf("anull", "b2", "cnull"), list)
}
@Test
fun testEmptyFlow() = runTest {
- val flow = emptyFlow<String>().combineLatest(emptyFlow<Int>()) { i, j -> i + j }
+ val flow = emptyFlow<String>().combineLatest(emptyFlow<Int>(), String::plus)
assertNull(flow.singleOrNull())
}
@@ -51,14 +46,14 @@
fun testFirstIsEmpty() = runTest {
val f1 = emptyFlow<String>()
val f2 = flowOf(1)
- assertEquals(emptyList(), f1.combineLatest(f2) { i, j -> i + j }.toList())
+ assertEquals(emptyList(), f1.combineLatest(f2, String::plus).toList())
}
@Test
fun testSecondIsEmpty() = runTest {
val f1 = flowOf("a")
val f2 = emptyFlow<Int>()
- assertEquals(emptyList(), f1.combineLatest(f2) { i, j -> i + j }.toList())
+ assertEquals(emptyList(), f1.combineLatest(f2, String::plus).toList())
}
@Test
@@ -85,7 +80,7 @@
emit(3)
}
- val result = f1.combineLatest(f2) { i, j -> i + j }.toList()
+ val result = f1.combineLatest(f2, String::plus).toList()
assertEquals(listOf("a1", "b1", "c1", "c2", "c3"), result)
finish(8)
}
@@ -261,6 +256,10 @@
override fun <T1, T2, R> Flow<T1>.combineLatest(other: Flow<T2>, transform: suspend (T1, T2) -> R): Flow<R> = combineOriginal(other, transform)
}
+class CombineOverloadTest : CombineTestBase() {
+ override fun <T1, T2, R> Flow<T1>.combineLatest(other: Flow<T2>, transform: suspend (T1, T2) -> R): Flow<R> = combineOriginal(this, other, transform)
+}
+
class CombineTransformTest : CombineTestBase() {
override fun <T1, T2, R> Flow<T1>.combineLatest(other: Flow<T2>, transform: suspend (T1, T2) -> R): Flow<R> = combineTransformOriginal(other) { a, b ->
emit(transform(a, b))
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/ConflateTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/ConflateTest.kt
index 264aba0..b680b22 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/ConflateTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/ConflateTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt
index 0268a23..76270d0 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/DebounceTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
@@ -315,4 +312,10 @@
assertEquals(listOf("A", "C", "D", "E"), result)
finish(5)
}
+
+ @Test
+ fun testFailsWithIllegalArgument() {
+ val flow = emptyFlow<Int>()
+ assertFailsWith<IllegalArgumentException> { flow.debounce(-1) }
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/DistinctUntilChangedTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/DistinctUntilChangedTest.kt
index 68e7f66..874361b 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/DistinctUntilChangedTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/DistinctUntilChangedTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/DropTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/DropTest.kt
index dfa2827..50f70b9 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/DropTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/DropTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/DropWhileTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/DropWhileTest.kt
index 088954b..a811935 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/DropWhileTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/DropWhileTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FilterTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FilterTest.kt
index f52416d..a68cdf4 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FilterTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FilterTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FilterTrivialTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FilterTrivialTest.kt
index f41fe73..71a7a73 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FilterTrivialTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FilterTrivialTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapBaseTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapBaseTest.kt
index ca1fa25..6e51857 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapBaseTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapBaseTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapConcatTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapConcatTest.kt
index 8bb54fd..59ea47c 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapConcatTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapConcatTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapLatestTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapLatestTest.kt
index ad0bda9..b98e97d 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapLatestTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapLatestTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt
index f09db12..0cd1e0f 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt
@@ -1,13 +1,9 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-
package kotlinx.coroutines.flow
-import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
abstract class FlatMapMergeBaseTest : FlatMapBaseTest() {
@Test
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeFastPathTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeFastPathTest.kt
index f810221..c8a4124 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeFastPathTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeFastPathTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
class FlatMapMergeFastPathTest : FlatMapMergeBaseTest() {
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt
index c2ce346..e3b4ba2 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class FlatMapMergeTest : FlatMapMergeBaseTest() {
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlattenConcatTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlattenConcatTest.kt
index 4ec7cc3..31741b4 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlattenConcatTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlattenConcatTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class FlattenConcatTest : FlatMapBaseTest() {
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlattenMergeTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlattenMergeTest.kt
index c15f503..ee3804f 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlattenMergeTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlattenMergeTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt
index 7194a70..32022c4 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt
index 8fba845..bb0fabb 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.testing.flow.*
import kotlin.test.*
class FlowOnTest : TestBase() {
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/IndexedTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/IndexedTest.kt
index 53db88d..420bfc8 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/IndexedTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/IndexedTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/LintTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/LintTest.kt
index 9cf6cbb..6d0391f 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/LintTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/LintTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/MapNotNullTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/MapNotNullTest.kt
index d8bb480..f2aa3cc 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/MapNotNullTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/MapNotNullTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/MapTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/MapTest.kt
index 8c9398a..11d1d4d 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/MapTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/MapTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/MergeTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/MergeTest.kt
index f084798..694db25 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/MergeTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/MergeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
import kotlinx.coroutines.flow.merge as originalMerge
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/OnCompletionTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/OnCompletionTest.kt
index 0ff2e0b..14ee531 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/OnCompletionTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/OnCompletionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.internal.*
@@ -34,10 +31,10 @@
expect(1)
throw TestException()
}.onCompletion {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(2)
}.catch {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(3)
}.collect()
finish(4)
@@ -51,13 +48,13 @@
}.onEach {
expect(2)
}.onCompletion {
- assertTrue(it is TestException) // flow fails because of this exception
+ assertIs<TestException>(it) // flow fails because of this exception
expect(4)
}.onEach {
expect(3)
throw TestException()
}.catch {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(5)
}.collect()
finish(6)
@@ -66,16 +63,16 @@
@Test
fun testMultipleOnCompletions() = runTest {
flowOf(1).onCompletion {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(2)
}.onEach {
expect(1)
throw TestException()
}.onCompletion {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(3)
}.catch {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(4)
}.collect()
finish(5)
@@ -90,7 +87,7 @@
expect(2)
throw TestException2()
}.catch {
- assertTrue(it is TestException2)
+ assertIs<TestException2>(it)
expect(3)
}.collect()
finish(4)
@@ -109,7 +106,7 @@
throw TestException()
}
.catch {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(3)
}.collect()
finish(4)
@@ -145,7 +142,7 @@
}
.onCompletion { e ->
expect(8)
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
emit(TestData.Done(e)) // will fail
}.collect {
collected += it
@@ -172,7 +169,7 @@
}
.onCompletion { e ->
expect(8)
- assertTrue(e is CancellationException)
+ assertIs<CancellationException>(e)
try {
emit(TestData.Done(e))
expectUnreached()
@@ -311,4 +308,90 @@
.take(1)
.collect()
}
+
+ /**
+ * Tests that the operators that are used to limit the flow (like [take] and [zip]) faithfully propagate the
+ * cancellation exception to the original owner.
+ */
+ @Test
+ fun testOnCompletionBetweenLimitingOperators() = runTest {
+ // `zip` doesn't eat the exception thrown by `take`:
+ flowOf(1, 2, 3)
+ .zip(flowOf(4, 5)) { a, b -> a + b }
+ .onCompletion {
+ expect(2)
+ assertNotNull(it)
+ }
+ .take(1)
+ .collect {
+ expect(1)
+ }
+
+ // `take` doesn't eat the exception thrown by `zip`:
+ flowOf(1, 2, 3)
+ .take(2)
+ .onCompletion {
+ expect(4)
+ assertNotNull(it)
+ }
+ .zip(flowOf(4)) { a, b -> a + b }
+ .collect {
+ expect(3)
+ }
+
+ // `take` doesn't eat the exception thrown by `first`:
+ flowOf(1, 2, 3)
+ .take(2)
+ .onCompletion {
+ expect(5)
+ assertNotNull(it)
+ }
+ .first()
+
+ // `zip` doesn't eat the exception thrown by `first`:
+ flowOf(1, 2, 3)
+ .zip(flowOf(4, 5)) { a, b -> a + b }
+ .onCompletion {
+ expect(6)
+ assertNotNull(it)
+ }
+ .first()
+
+ // `take` doesn't eat the exception thrown by another `take`:
+ flowOf(1, 2, 3)
+ .take(2)
+ .onCompletion {
+ expect(8)
+ assertNotNull(it)
+ }
+ .take(1)
+ .collect {
+ expect(7)
+ }
+
+ // `zip` doesn't eat the exception thrown by another `zip`:
+ flowOf(1, 2, 3)
+ .zip(flowOf(4, 5)) { a, b -> a + b }
+ .onCompletion {
+ expect(10)
+ assertNotNull(it)
+ }
+ .zip(flowOf(6)) { a, b -> a + b }
+ .collect {
+ expect(9)
+ }
+
+ finish(11)
+ }
+
+ /**
+ * Tests that emitting new elements after completion doesn't overwrite the old elements.
+ */
+ @Test
+ fun testEmittingElementsAfterCancellation() = runTest {
+ assertEquals(1, flowOf(1, 2, 3)
+ .take(100)
+ .onCompletion { emit(4) }
+ .first())
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/OnEachTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/OnEachTest.kt
index 3c1ebfa..9698b28 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/OnEachTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/OnEachTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/OnEmptyTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/OnEmptyTest.kt
index 3da1666..cca7708 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/OnEmptyTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/OnEmptyTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/OnStartTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/OnStartTest.kt
index 0443e56..15fc4b5 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/OnStartTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/OnStartTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt
index e5dde1b..41377cb 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/RetryTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -16,12 +13,12 @@
throw TestException()
}
val sum = flow.retryWhen { cause, attempt ->
- assertTrue(cause is TestException)
+ assertIs<TestException>(cause)
expect(2 + attempt.toInt())
attempt < 3
}.catch { cause ->
expect(6)
- assertTrue(cause is TestException)
+ assertIs<TestException>(cause)
}.sum()
assertEquals(4, sum)
finish(7)
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/SampleTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/SampleTest.kt
index 3c04abd..781587d 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/SampleTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/SampleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
@@ -296,4 +293,10 @@
assertEquals(listOf("A", "B", "D"), result)
finish(5)
}
+
+ @Test
+ fun testFailsWithIllegalArgument() {
+ val flow = emptyFlow<Int>()
+ assertFailsWith<IllegalArgumentException> { flow.debounce(-1) }
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/ScanTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/ScanTest.kt
index c6be36d..7f19f97 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/ScanTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/ScanTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TakeTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TakeTest.kt
index ea8939f..3ecc2f4 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/TakeTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/TakeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TakeWhileTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TakeWhileTest.kt
index c198356..f097b77 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/TakeWhileTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/TakeWhileTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt
index c09882f..0162a21 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/TimeoutTest.kt
@@ -1,13 +1,14 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.operators
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.flow.internal.*
+import kotlin.coroutines.*
import kotlin.test.*
+import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
class TimeoutTest : TestBase() {
@Test
@@ -228,4 +229,31 @@
assertEquals((0 until 10).toList(), list)
finish(6)
}
+
+ @Test
+ fun testImmediateTimeout() {
+ testImmediateTimeout(Duration.ZERO)
+ reset()
+ testImmediateTimeout(-1.seconds)
+ }
+
+ @Test
+ fun testClosing() = runTest {
+ assertFailsWith<TestException> {
+ channelFlow<Int> { close(TestException()) }
+ .timeout(Duration.INFINITE)
+ .collect {
+ expectUnreached()
+ }
+ }
+ }
+
+ private fun testImmediateTimeout(timeout: Duration) {
+ expect(1)
+ val flow = emptyFlow<Int>().timeout(timeout)
+ flow::collect.startCoroutine(NopCollector, Continuation(EmptyCoroutineContext) {
+ assertIs<TimeoutCancellationException>(it.exceptionOrNull())
+ finish(2)
+ })
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TransformLatestTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TransformLatestTest.kt
index 8d3b40b..e072eab 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/TransformLatestTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/TransformLatestTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TransformTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TransformTest.kt
index feb3596..b70460a 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/TransformTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/TransformTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/TransformWhileTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/TransformWhileTest.kt
index df66010..4da0d26 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/TransformWhileTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/TransformWhileTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/operators/ZipTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/ZipTest.kt
index 02dbfc4..1f770df 100644
--- a/kotlinx-coroutines-core/common/test/flow/operators/ZipTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/operators/ZipTest.kt
@@ -1,29 +1,23 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
-/*
- * Replace: { i, j -> i + j } -> ::sum as soon as KT-30991 is fixed
- */
class ZipTest : TestBase() {
@Test
fun testZip() = runTest {
val f1 = flowOf("a", "b", "c")
val f2 = flowOf(1, 2, 3)
- assertEquals(listOf("a1", "b2", "c3"), f1.zip(f2, { i, j -> i + j }).toList())
+ assertEquals(listOf("a1", "b2", "c3"), f1.zip(f2, String::plus).toList())
}
@Test
fun testUnevenZip() = runTest {
val f1 = flowOf("a", "b", "c", "d", "e")
val f2 = flowOf(1, 2, 3)
- assertEquals(listOf("a1", "b2", "c3"), f1.zip(f2) { i, j -> i + j }.toList())
+ assertEquals(listOf("a1", "b2", "c3"), f1.zip(f2, String::plus).toList())
assertEquals(listOf("a1", "b2", "c3"), f2.zip(f1) { i, j -> j + i }.toList())
}
@@ -31,35 +25,35 @@
fun testEmptyFlows() = runTest {
val f1 = emptyFlow<String>()
val f2 = emptyFlow<Int>()
- assertEquals(emptyList(), f1.zip(f2, { i, j -> i + j }).toList())
+ assertEquals(emptyList(), f1.zip(f2, String::plus).toList())
}
@Test
fun testEmpty() = runTest {
val f1 = emptyFlow<String>()
val f2 = flowOf(1)
- assertEquals(emptyList(), f1.zip(f2, { i, j -> i + j }).toList())
+ assertEquals(emptyList(), f1.zip(f2, String::plus).toList())
}
@Test
fun testEmptyOther() = runTest {
val f1 = flowOf("a")
val f2 = emptyFlow<Int>()
- assertEquals(emptyList(), f1.zip(f2, { i, j -> i + j }).toList())
+ assertEquals(emptyList(), f1.zip(f2, String::plus).toList())
}
@Test
fun testNulls() = runTest {
val f1 = flowOf("a", null, null, "d")
val f2 = flowOf(1, 2, 3)
- assertEquals(listOf("a1", "null2", "null3"), f1.zip(f2, { i, j -> i + j }).toList())
+ assertEquals(listOf("a1", "null2", "null3"), f1.zip(f2, String?::plus).toList())
}
@Test
fun testNullsOther() = runTest {
val f1 = flowOf("a", "b", "c")
val f2 = flowOf(1, null, null, 2)
- assertEquals(listOf("a1", "bnull", "cnull"), f1.zip(f2, { i, j -> i + j }).toList())
+ assertEquals(listOf("a1", "bnull", "cnull"), f1.zip(f2, String::plus).toList())
}
@Test
@@ -74,7 +68,7 @@
emit("b")
expectUnreached()
}
- assertEquals(listOf("1a", "2b"), f1.zip(f2) { s1, s2 -> s1 + s2 }.toList())
+ assertEquals(listOf("1a", "2b"), f1.zip(f2, String::plus).toList())
finish(1)
}
@@ -92,7 +86,7 @@
}
val f2 = flowOf("a", "b")
- assertEquals(listOf("1a", "2b"), f1.zip(f2) { s1, s2 -> s1 + s2 }.toList())
+ assertEquals(listOf("1a", "2b"), f1.zip(f2, String::plus).toList())
finish(2)
}
@@ -112,7 +106,7 @@
yield()
}
- assertEquals(listOf("a1", "b2"), f2.zip(f1) { s1, s2 -> s1 + s2 }.toList())
+ assertEquals(listOf("a1", "b2"), f2.zip(f1, String::plus).toList())
finish(2)
}
@@ -252,6 +246,6 @@
yield()
}
- f1.zip(f2) { a, b -> a + b }.collect { }
+ f1.zip(f2, String::plus).collect { }
}
}
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInBufferTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInBufferTest.kt
index 9c6aed2..8871e31 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInBufferTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInBufferTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.math.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInConflationTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInConflationTest.kt
index c19d523..73d14ac 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInConflationTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInConflationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInFusionTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInFusionTest.kt
index 85a17ba..c7b4650 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInFusionTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInFusionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt
index cf83a50..1df59b9 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/ShareInTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
@@ -104,7 +101,7 @@
sharingJob.join() // should complete sharing
assertEquals(listOf("OK"), shared.replayCache) // cache is still there
if (failed) {
- assertTrue(sharingJob.getCompletionExceptionOrNull() is TestException)
+ assertIs<TestException>(sharingJob.getCompletionExceptionOrNull())
} else {
assertNull(sharingJob.getCompletionExceptionOrNull())
}
@@ -236,4 +233,9 @@
assertEquals(239, shared.first())
j.cancel()
}
+
+ @Test
+ fun testSubscriptionByFirstSuspensionInSharedFlow() = runTest {
+ testSubscriptionByFirstSuspensionInCollect(flowOf(1).stateIn(this@runTest), emit = { })
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowScenarioTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowScenarioTest.kt
index 794553b..f4417e1 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowScenarioTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowScenarioTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowTest.kt
index 98e04f0..eab4b79 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/SharedFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.random.*
@@ -614,7 +611,7 @@
throw TestException()
}
.catch { e ->
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
expect(3)
}
.collect {
@@ -818,4 +815,24 @@
j2.cancelAndJoin()
assertEquals(0, flow.subscriptionCount.first())
}
+
+ @Test
+ fun testSubscriptionByFirstSuspensionInSharedFlow() = runTest {
+ testSubscriptionByFirstSuspensionInCollect(MutableSharedFlow()) { emit(it) }
+ }
+}
+
+/**
+ * Check that, by the time [SharedFlow.collect] suspends for the first time, its subscription is already active.
+ */
+inline fun<T: Flow<Int>> CoroutineScope.testSubscriptionByFirstSuspensionInCollect(flow: T, emit: T.(Int) -> Unit) {
+ var received = 0
+ val job = launch(start = CoroutineStart.UNDISPATCHED) {
+ flow.collect {
+ received = it
+ }
+ }
+ flow.emit(1)
+ assertEquals(1, received)
+ job.cancel()
}
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedTest.kt
index 496fb7f..09450a1 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedWhileSubscribedTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedWhileSubscribedTest.kt
index da2f3e5..c8199f5 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedWhileSubscribedTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/SharingStartedWhileSubscribedTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
import kotlin.time.*
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/StateFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/StateFlowTest.kt
index be4f8c5..f8c1a83 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/StateFlowTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/StateFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
@@ -145,7 +142,7 @@
}
}
.catch { e ->
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
expect(6)
}
.launchIn(this)
@@ -181,4 +178,9 @@
state.update { it + 3 }
assertEquals(5, state.value)
}
+
+ @Test
+ fun testSubscriptionByFirstSuspensionInStateFlow() = runTest {
+ testSubscriptionByFirstSuspensionInCollect(MutableStateFlow(0)) { value = it; yield() }
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/sharing/StateInTest.kt b/kotlinx-coroutines-core/common/test/flow/sharing/StateInTest.kt
index d0e76c4..75a5e4b 100644
--- a/kotlinx-coroutines-core/common/test/flow/sharing/StateInTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/sharing/StateInTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
@@ -70,7 +67,7 @@
sharingJob.join() // should complete sharing
assertEquals("OK", shared.value) // value is still there
if (failed) {
- assertTrue(sharingJob.getCompletionExceptionOrNull() is TestException)
+ assertIs<TestException>(sharingJob.getCompletionExceptionOrNull())
} else {
assertNull(sharingJob.getCompletionExceptionOrNull())
}
@@ -86,4 +83,9 @@
assertFailsWith<TestException> { flow.stateIn(CoroutineScope(currentCoroutineContext() + Job() + ceh)) }
finish(3)
}
+
+ @Test
+ fun testSubscriptionByFirstSuspensionInStateFlow() = runTest {
+ testSubscriptionByFirstSuspensionInCollect(flowOf(1).stateIn(this@runTest)) { }
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/CollectLatestTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/CollectLatestTest.kt
index 122420c..2cecf8c 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/CollectLatestTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/CollectLatestTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/CountTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/CountTest.kt
index 4a6f5ae..167fdec 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/CountTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/CountTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt
index fa7fc9c..7433626 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.internal.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/FoldTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/FoldTest.kt
index 9a920f1..350d075 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/FoldTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/FoldTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/LastTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/LastTest.kt
index e7699cc..b424b2e 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/LastTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/LastTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/LaunchInTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/LaunchInTest.kt
index 6b04b02..e2b01f6 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/LaunchInTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/LaunchInTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -19,7 +16,7 @@
assertEquals(1, it)
expect(2)
}.onCompletion {
- assertTrue(it is TestException)
+ assertIs<TestException>(it)
expect(3)
}.catch {
assertTrue { it is TestException }
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/ReduceTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/ReduceTest.kt
index 8ba0b5e..ee70063 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/ReduceTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/ReduceTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt
index 2c1277b..b1741bb 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/SingleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/ToCollectionTest.kt b/kotlinx-coroutines-core/common/test/flow/terminal/ToCollectionTest.kt
index cfcbb52..a5c5fe6 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/ToCollectionTest.kt
+++ b/kotlinx-coroutines-core/common/test/flow/terminal/ToCollectionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectBiasTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectBiasTest.kt
index ec88fb5..42cdf94 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectBiasTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectBiasTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectBufferedChannelTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectBufferedChannelTest.kt
index 6bb8049..3abee42 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectBufferedChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectBufferedChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
@@ -318,7 +315,7 @@
channel.onReceiveCatching {
expect(5)
assertTrue(it.isClosed)
- assertTrue(it.exceptionOrNull() is TestException)
+ assertIs<TestException>(it.exceptionOrNull())
}
}
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectDeferredTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectDeferredTest.kt
index b1c07ba..5b977d9 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectDeferredTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectDeferredTest.kt
@@ -1,13 +1,11 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
+import kotlin.time.Duration.Companion.seconds
class SelectDeferredTest : TestBase() {
@Test
@@ -117,6 +115,23 @@
finish(9)
}
+ /**
+ * Tests that completing a [Deferred] with an exception will cause the [select] that uses [Deferred.onAwait]
+ * to throw the same exception.
+ */
+ @Test
+ fun testSelectFailure() = runTest {
+ val d = CompletableDeferred<Nothing>()
+ d.completeExceptionally(TestException())
+ val d2 = CompletableDeferred(42)
+ assertFailsWith<TestException> {
+ select {
+ d.onAwait { expectUnreached() }
+ d2.onAwait { 4 }
+ }
+ }
+ }
+
@Test
fun testSelectCancel() = runTest(
expected = { it is CancellationException }
@@ -170,4 +185,4 @@
override val list: NodeList?
get() = error("")
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectJobTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectJobTest.kt
index 099a874..6af517c 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectJobTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectJobTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectLoopTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectLoopTest.kt
index ba8f56a..dd83d4a 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectLoopTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectLoopTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectMutexTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectMutexTest.kt
index 6f4c9e1..db3361f 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectMutexTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectMutexTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectOldTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectOldTest.kt
index 34694fd..b500c9f 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectOldTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectOldTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectRendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectRendezvousChannelTest.kt
index f3c5b4f..36faaf4 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectRendezvousChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectRendezvousChannelTest.kt
@@ -1,10 +1,8 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
@@ -339,7 +337,7 @@
channel.onReceiveCatching {
expect(5)
assertTrue(it.isClosed)
- assertTrue(it.exceptionOrNull() is TestException)
+ assertIs<TestException>(it.exceptionOrNull())
}
}
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectTimeoutDurationTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectTimeoutDurationTest.kt
index 62e62e5..f78e1c3 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectTimeoutDurationTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectTimeoutDurationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
import kotlin.time.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectTimeoutTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectTimeoutTest.kt
index fbfb9c0..f3abfe4 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectTimeoutTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectTimeoutTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/selects/SelectUnlimitedChannelTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectUnlimitedChannelTest.kt
index 081c918..e460bd7 100644
--- a/kotlinx-coroutines-core/common/test/selects/SelectUnlimitedChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/selects/SelectUnlimitedChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt
index b4acd94..7c6b8ab 100644
--- a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt
+++ b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.sync
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import kotlin.test.*
@@ -60,6 +57,37 @@
}
@Test
+ fun testWithLockFailureUnlocksTheMutex() = runTest {
+ val mutex = Mutex()
+ assertFalse(mutex.isLocked)
+ try {
+ mutex.withLock {
+ expect(1)
+ assertTrue(mutex.isLocked)
+ throw TestException()
+ }
+ } catch (e: TestException) {
+ expect(2)
+ }
+ assertFalse(mutex.isLocked)
+ finish(3)
+ }
+
+ @Test
+ fun withLockOnEarlyReturnTest() = runTest {
+ val mutex = Mutex()
+ assertFalse(mutex.isLocked)
+ suspend fun f() {
+ mutex.withLock {
+ assertTrue(mutex.isLocked)
+ return@f
+ }
+ }
+ f()
+ assertFalse(mutex.isLocked)
+ }
+
+ @Test
fun testUnconfinedStackOverflow() {
val waiters = 10000
val mutex = Mutex(true)
@@ -148,4 +176,20 @@
assertFailsWith<IllegalStateException> { mutex.lock(owner) }
assertFailsWith<IllegalStateException> { select { mutex.onLock(owner) {} } }
}
+
+ @Test
+ fun testWithLockJsMiscompilation() = runTest {
+ // This is a reproducer for KT-58685
+ // On Kotlin/JS IR, the compiler miscompiles calls to 'unlock' in an inlined finally
+ // This is visible on the withLock function
+ // Until the compiler bug is fixed, this test case checks that we do not suffer from it
+ val mutex = Mutex()
+ assertFailsWith<IndexOutOfBoundsException> {
+ try {
+ mutex.withLock { null } ?: throw IndexOutOfBoundsException() // should throw…
+ } catch (e: Exception) {
+ throw e // …but instead fails here
+ }
+ }
+ }
}
diff --git a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt
index b4ff88b..89f066c 100644
--- a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt
+++ b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt
@@ -1,10 +1,8 @@
package kotlinx.coroutines.sync
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
+import kotlin.test.*
class SemaphoreTest : TestBase() {
@@ -70,6 +68,35 @@
}
@Test
+ fun withSemaphoreOnFailureTest() = runTest {
+ val semaphore = Semaphore(1)
+ assertEquals(1, semaphore.availablePermits)
+ try {
+ semaphore.withPermit {
+ assertEquals(0, semaphore.availablePermits)
+ throw TestException()
+ }
+ } catch (e: TestException) {
+ // Expected
+ }
+ assertEquals(1, semaphore.availablePermits)
+ }
+
+ @Test
+ fun withSemaphoreOnEarlyReturnTest() = runTest {
+ val semaphore = Semaphore(1)
+ assertEquals(1, semaphore.availablePermits)
+ suspend fun f() {
+ semaphore.withPermit {
+ assertEquals(0, semaphore.availablePermits)
+ return@f
+ }
+ }
+ f()
+ assertEquals(1, semaphore.availablePermits)
+ }
+
+ @Test
fun fairnessTest() = runTest {
val semaphore = Semaphore(1)
semaphore.acquire()
@@ -168,4 +195,20 @@
assertFailsWith<IllegalArgumentException> { Semaphore(1, -1) }
assertFailsWith<IllegalArgumentException> { Semaphore(1, 2) }
}
-}
\ No newline at end of file
+
+ @Test
+ fun testWithPermitJsMiscompilation() = runTest {
+ // This is a reproducer for KT-58685
+ // On Kotlin/JS IR, the compiler miscompiles calls to 'release' in an inlined finally
+ // This is visible on the withPermit function
+ // Until the compiler bug is fixed, this test case checks that we do not suffer from it
+ val semaphore = Semaphore(1)
+ assertFailsWith<IndexOutOfBoundsException> {
+ try {
+ semaphore.withPermit { null } ?: throw IndexOutOfBoundsException() // should throw…
+ } catch (e: Exception) {
+ throw e // …but instead fails here
+ }
+ }
+ }
+}
diff --git a/kotlinx-coroutines-core/concurrent/src/Builders.concurrent.kt b/kotlinx-coroutines-core/concurrent/src/Builders.concurrent.kt
index 8a6c092..7c0581b 100644
--- a/kotlinx-coroutines-core/concurrent/src/Builders.concurrent.kt
+++ b/kotlinx-coroutines-core/concurrent/src/Builders.concurrent.kt
@@ -1,14 +1,24 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
/**
* Runs a new coroutine and **blocks** the current thread until its completion.
- * This function should not be used from a coroutine. It is designed to bridge regular blocking code
- * to libraries that are written in suspending style, to be used in `main` functions and in tests.
+ *
+ * It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in
+ * `main` functions and in tests.
+ *
+ * Calling [runBlocking] from a suspend function is redundant.
+ * For example, the following code is incorrect:
+ * ```
+ * suspend fun loadConfiguration() {
+ * // DO NOT DO THIS:
+ * val data = runBlocking { // <- redundant and blocks the thread, do not do that
+ * fetchConfigurationData() // suspending function
+ * }
+ * ```
+ *
+ * Here, instead of releasing the thread on which `loadConfiguration` runs if `fetchConfigurationData` suspends, it will
+ * block, potentially leading to thread starvation issues.
*/
-public expect fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T
\ No newline at end of file
+public expect fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T
diff --git a/kotlinx-coroutines-core/concurrent/src/CompletionHandler.kt b/kotlinx-coroutines-core/concurrent/src/CompletionHandler.kt
deleted file mode 100644
index 4835f79..0000000
--- a/kotlinx-coroutines-core/concurrent/src/CompletionHandler.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlinx.coroutines.internal.*
-
-internal actual abstract class CompletionHandlerBase actual constructor() : LockFreeLinkedListNode(), CompletionHandler {
- actual abstract override fun invoke(cause: Throwable?)
-}
-
-internal actual inline val CompletionHandlerBase.asHandler: CompletionHandler get() = this
-
-internal actual abstract class CancelHandlerBase actual constructor() : CompletionHandler {
- actual abstract override fun invoke(cause: Throwable?)
-}
-
-internal actual inline val CancelHandlerBase.asHandler: CompletionHandler get() = this
-
-@Suppress("NOTHING_TO_INLINE")
-internal actual inline fun CompletionHandler.invokeIt(cause: Throwable?) = invoke(cause)
diff --git a/kotlinx-coroutines-core/concurrent/src/Dispatchers.kt b/kotlinx-coroutines-core/concurrent/src/Dispatchers.kt
index 8a937e3..aadca2f 100644
--- a/kotlinx-coroutines-core/concurrent/src/Dispatchers.kt
+++ b/kotlinx-coroutines-core/concurrent/src/Dispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/concurrent/src/MultithreadedDispatchers.common.kt b/kotlinx-coroutines-core/concurrent/src/MultithreadedDispatchers.common.kt
index cc2c16a..bda8d35 100644
--- a/kotlinx-coroutines-core/concurrent/src/MultithreadedDispatchers.common.kt
+++ b/kotlinx-coroutines-core/concurrent/src/MultithreadedDispatchers.common.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("ThreadPoolDispatcherKt")
package kotlinx.coroutines
@@ -15,17 +11,17 @@
*
* If the resulting dispatcher is [closed][CloseableCoroutineDispatcher.close] and
* attempt to submit a task is made, then:
- * * On the JVM, the [Job] of the affected task is [cancelled][Job.cancel] and the task is submitted to the
+ * - On the JVM, the [Job] of the affected task is [cancelled][Job.cancel] and the task is submitted to the
* [Dispatchers.IO], so that the affected coroutine can clean up its resources and promptly complete.
- * * On Native, the attempt to submit a task throws an exception.
+ * - On Native, the attempt to submit a task throws an exception.
*
* This is a **delicate** API. The result of this method is a closeable resource with the
* associated native resources (threads or native workers). It should not be allocated in place,
* should be closed at the end of its lifecycle, and has non-trivial memory and CPU footprint.
- * If you do not need a separate thread-pool, but only have to limit effective parallelism of the dispatcher,
+ * If you do not need a separate thread pool, but only have to limit effective parallelism of the dispatcher,
* it is recommended to use [CoroutineDispatcher.limitedParallelism] instead.
*
- * If you need a completely separate thread-pool with scheduling policy that is based on the standard
+ * If you need a completely separate thread pool with scheduling policy that is based on the standard
* JDK executors, use the following expression:
* `Executors.newSingleThreadExecutor().asCoroutineDispatcher()`.
* See `Executor.asCoroutineDispatcher` for details.
@@ -37,5 +33,30 @@
public fun newSingleThreadContext(name: String): CloseableCoroutineDispatcher =
newFixedThreadPoolContext(1, name)
+/**
+ * Creates a coroutine execution context with the fixed-size thread-pool and built-in [yield] support.
+ * **NOTE: The resulting [CoroutineDispatcher] owns native resources (its threads).
+ * Resources are reclaimed by [CloseableCoroutineDispatcher.close].**
+ *
+ * If the resulting dispatcher is [closed][CloseableCoroutineDispatcher.close] and
+ * attempt to submit a continuation task is made,
+ * - On the JVM, the [Job] of the affected task is [cancelled][Job.cancel] and the task is submitted to the
+ * [Dispatchers.IO], so that the affected coroutine can clean up its resources and promptly complete.
+ * - On Native, the attempt to submit a task throws an exception.
+ *
+ * This is a **delicate** API. The result of this method is a closeable resource with the
+ * associated native resources (threads or native workers). It should not be allocated in place,
+ * should be closed at the end of its lifecycle, and has non-trivial memory and CPU footprint.
+ * If you do not need a separate thread pool, but only have to limit effective parallelism of the dispatcher,
+ * it is recommended to use [CoroutineDispatcher.limitedParallelism] instead.
+ *
+ * If you need a completely separate thread pool with scheduling policy that is based on the standard
+ * JDK executors, use the following expression:
+ * `Executors.newFixedThreadPool().asCoroutineDispatcher()`.
+ * See `Executor.asCoroutineDispatcher` for details.
+ *
+ * @param nThreads the number of threads.
+ * @param name the base name of the created threads.
+ */
@ExperimentalCoroutinesApi
public expect fun newFixedThreadPoolContext(nThreads: Int, name: String): CloseableCoroutineDispatcher
diff --git a/kotlinx-coroutines-core/concurrent/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/concurrent/src/internal/LockFreeLinkedList.kt
index 0088849..970c01f 100644
--- a/kotlinx-coroutines-core/concurrent/src/internal/LockFreeLinkedList.kt
+++ b/kotlinx-coroutines-core/concurrent/src/internal/LockFreeLinkedList.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE")
package kotlinx.coroutines.internal
@@ -34,11 +31,11 @@
* the update of the next pointer. Removed nodes have their next pointer marked with [Removed] class.
*
* Important notes:
- * * There are no operations to add items to left side of the list, only to the end (right side), because we cannot
+ * - There are no operations to add items to left side of the list, only to the end (right side), because we cannot
* efficiently linearize them with atomic multi-step head-removal operations. In short,
* support for [describeRemoveFirst] operation precludes ability to add items at the beginning.
- * * Previous pointers are not marked for removal. We don't support linearizable backwards traversal.
- * * Remove-helping logic is simplified and consolidated in [correctPrev] method.
+ * - Previous pointers are not marked for removal. We don't support linearizable backwards traversal.
+ * - Remove-helping logic is simplified and consolidated in [correctPrev] method.
*
* @suppress **This is unstable API and it is subject to change.**
*/
@@ -85,7 +82,8 @@
}
// LINEARIZABLE. Returns next non-removed Node
- public actual val nextNode: Node get() = next.unwrap()
+ public actual val nextNode: Node get() =
+ next.let { (it as? Removed)?.ref ?: it as Node } // unwraps the `next` node
// LINEARIZABLE WHEN THIS NODE IS NOT REMOVED:
// Returns prev non-removed Node, makes sure prev is correct (prev.next === this)
@@ -263,7 +261,7 @@
*
* It returns `null` in two special cases:
*
- * * When this node is removed. In this case there is no need to waste time on corrections, because
+ * - When this node is removed. In this case there is no need to waste time on corrections, because
* remover of this node will ultimately call [correctPrev] on the next node and that will fix all
* the links from this node, too.
*/
@@ -323,9 +321,6 @@
override fun toString(): String = "Removed[$ref]"
}
-@PublishedApi
-internal fun Any.unwrap(): Node = (this as? Removed)?.ref ?: this as Node
-
/**
* Head (sentinel) item of the linked list that is never removed.
*
@@ -350,17 +345,6 @@
// optimization: because head is never removed, we don't have to read _next.value to check these:
override val isRemoved: Boolean get() = false
- override fun nextIfRemoved(): Node? = null
- internal fun validate() {
- var prev: Node = this
- var cur: Node = next as Node
- while (cur != this) {
- val next = cur.nextNode
- cur.validateNode(prev, next)
- prev = cur
- cur = next
- }
- validateNode(prev, next as Node)
- }
+ override fun nextIfRemoved(): Node? = null
}
diff --git a/kotlinx-coroutines-core/concurrent/src/internal/OnDemandAllocatingPool.kt b/kotlinx-coroutines-core/concurrent/src/internal/OnDemandAllocatingPool.kt
index 1c2beff..8c21159 100644
--- a/kotlinx-coroutines-core/concurrent/src/internal/OnDemandAllocatingPool.kt
+++ b/kotlinx-coroutines-core/concurrent/src/internal/OnDemandAllocatingPool.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/concurrent/test/AbstractDispatcherConcurrencyTest.kt b/kotlinx-coroutines-core/concurrent/test/AbstractDispatcherConcurrencyTest.kt
index 7dc500f..b7648eb 100644
--- a/kotlinx-coroutines-core/concurrent/test/AbstractDispatcherConcurrencyTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/AbstractDispatcherConcurrencyTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/AtomicCancellationTest.kt b/kotlinx-coroutines-core/concurrent/test/AtomicCancellationTest.kt
index 7bbd7eb..d43c307 100644
--- a/kotlinx-coroutines-core/concurrent/test/AtomicCancellationTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/AtomicCancellationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/CommonThreadLocalTest.kt b/kotlinx-coroutines-core/concurrent/test/CommonThreadLocalTest.kt
index 598a96c..b692e2d 100644
--- a/kotlinx-coroutines-core/concurrent/test/CommonThreadLocalTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/CommonThreadLocalTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.exceptions.*
import kotlinx.coroutines.internal.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/ConcurrentExceptionsStressTest.kt b/kotlinx-coroutines-core/concurrent/test/ConcurrentExceptionsStressTest.kt
index cbfa332..a3fa590 100644
--- a/kotlinx-coroutines-core/concurrent/test/ConcurrentExceptionsStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/ConcurrentExceptionsStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.exceptions.*
import kotlinx.coroutines.internal.*
import kotlin.test.*
@@ -48,7 +45,7 @@
val completionException = deferred.getCompletionExceptionOrNull()
val cause = completionException as? StressException
?: unexpectedException("completion", completionException)
- val suppressed = cause.suppressed
+ val suppressed = cause.suppressedExceptions
val indices = listOf(cause.index) + suppressed.mapIndexed { index, e ->
(e as? StressException)?.index ?: unexpectedException("suppressed $index", e)
}
@@ -62,6 +59,6 @@
throw IllegalStateException("Unexpected $msg exception", e)
}
- private class StressException(val index: Int) : SuppressSupportingThrowable()
+ private class StressException(val index: Int) : Throwable()
}
diff --git a/kotlinx-coroutines-core/concurrent/test/ConcurrentTestUtilities.common.kt b/kotlinx-coroutines-core/concurrent/test/ConcurrentTestUtilities.common.kt
index d40f118..8cc7f93 100644
--- a/kotlinx-coroutines-core/concurrent/test/ConcurrentTestUtilities.common.kt
+++ b/kotlinx-coroutines-core/concurrent/test/ConcurrentTestUtilities.common.kt
@@ -1,17 +1,26 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
import kotlinx.coroutines.*
+import kotlin.concurrent.Volatile
+import kotlin.random.*
-internal expect open class SuppressSupportingThrowable() : Throwable
-expect val Throwable.suppressed: Array<Throwable>
-// Unused on purpose, used manually during debugging sessions
-expect fun Throwable.printStackTrace()
+fun randomWait() {
+ val n = Random.nextInt(1000)
+ if (n < 500) return // no wait 50% of time
+ repeat(n) {
+ BlackHole.sink *= 3
+ }
+ // use the BlackHole value somehow, so even if the compiler gets smarter, it won't remove the object
+ val sinkValue = if (BlackHole.sink > 16) 1 else 0
+ if (n + sinkValue > 900) yieldThread()
+}
-expect fun randomWait()
+private object BlackHole {
+ @Volatile
+ var sink = 1
+}
+
+expect inline fun yieldThread()
expect fun currentThreadName(): String
diff --git a/kotlinx-coroutines-core/concurrent/test/DefaultDispatchersConcurrencyTest.kt b/kotlinx-coroutines-core/concurrent/test/DefaultDispatchersConcurrencyTest.kt
index 66dfd07..c231bb1 100644
--- a/kotlinx-coroutines-core/concurrent/test/DefaultDispatchersConcurrencyTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/DefaultDispatchersConcurrencyTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
class DefaultDispatcherConcurrencyTest : AbstractDispatcherConcurrencyTest() {
diff --git a/kotlinx-coroutines-core/concurrent/test/JobStructuredJoinStressTest.kt b/kotlinx-coroutines-core/concurrent/test/JobStructuredJoinStressTest.kt
index 4b5c952..4abb495 100644
--- a/kotlinx-coroutines-core/concurrent/test/JobStructuredJoinStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/JobStructuredJoinStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/LimitedParallelismConcurrentTest.kt b/kotlinx-coroutines-core/concurrent/test/LimitedParallelismConcurrentTest.kt
index 49fe93f..5985aaa 100644
--- a/kotlinx-coroutines-core/concurrent/test/LimitedParallelismConcurrentTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/LimitedParallelismConcurrentTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.exceptions.*
@@ -68,7 +65,7 @@
@Test
fun testNotDoingDispatchesWhenNoTasksArePresent() = runTest {
class NaggingDispatcher: CoroutineDispatcher() {
- val closed = atomic(false)
+ private val closed = atomic(false)
override fun dispatch(context: CoroutineContext, block: Runnable) {
if (closed.value)
fail("Dispatcher was closed, but still dispatched a task")
diff --git a/kotlinx-coroutines-core/concurrent/test/MultithreadedDispatcherStressTest.kt b/kotlinx-coroutines-core/concurrent/test/MultithreadedDispatcherStressTest.kt
index 4e4583f..9445637 100644
--- a/kotlinx-coroutines-core/concurrent/test/MultithreadedDispatcherStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/MultithreadedDispatcherStressTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
@@ -9,7 +5,7 @@
import kotlin.test.*
class MultithreadedDispatcherStressTest {
- val shared = atomic(0)
+ private val shared = atomic(0)
/**
* Tests that [newFixedThreadPoolContext] will not drop tasks when closed.
diff --git a/kotlinx-coroutines-core/concurrent/test/RunBlockingTest.kt b/kotlinx-coroutines-core/concurrent/test/RunBlockingTest.kt
index f484476..f04b491 100644
--- a/kotlinx-coroutines-core/concurrent/test/RunBlockingTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/RunBlockingTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.exceptions.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -26,7 +24,7 @@
expect(1)
runBlocking {
expect(2)
- assertTrue(coroutineContext[ContinuationInterceptor] is EventLoop)
+ assertIs<EventLoop>(coroutineContext[ContinuationInterceptor])
yield() // is supported!
expect(3)
}
diff --git a/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt b/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt
index 245a80c..8db6d8b 100644
--- a/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/channels/BroadcastChannelSubStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -15,13 +12,13 @@
*/
class BroadcastChannelSubStressTest: TestBase() {
- private val nSeconds = 5 * stressTestMultiplier
+ private val nSeconds = maxOf(5, stressTestMultiplier)
private val sentTotal = atomic(0L)
private val receivedTotal = atomic(0L)
@Test
fun testStress() = runTest {
- TestBroadcastChannelKind.values().forEach { kind ->
+ TestBroadcastChannelKind.entries.forEach { kind ->
println("--- BroadcastChannelSubStressTest $kind")
val broadcast = kind.create<Long>()
val sender =
diff --git a/kotlinx-coroutines-core/concurrent/test/channels/ChannelCancelUndeliveredElementStressTest.kt b/kotlinx-coroutines-core/concurrent/test/channels/ChannelCancelUndeliveredElementStressTest.kt
index 1cf7d8a..292d5bd 100644
--- a/kotlinx-coroutines-core/concurrent/test/channels/ChannelCancelUndeliveredElementStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/channels/ChannelCancelUndeliveredElementStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
@@ -81,7 +78,7 @@
}
}
} catch (e: Throwable) {
- assertTrue(e is CancellationException) // the only exception possible in this test
+ assertIs<CancellationException>(e) // the only exception possible in this test
dSendExceptionCnt++
throw e
}
diff --git a/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt b/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt
index d9ec7ad..a9e8756 100644
--- a/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/channels/TrySendBlockingTest.kt b/kotlinx-coroutines-core/concurrent/test/channels/TrySendBlockingTest.kt
index 77c6518..4a48550 100644
--- a/kotlinx-coroutines-core/concurrent/test/channels/TrySendBlockingTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/channels/TrySendBlockingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
@@ -30,7 +27,7 @@
val channel = Channel<Unit>().also { it.close() }
channel.trySendBlocking(Unit)
.onSuccess { expectUnreached() }
- .onFailure { assertTrue(it is ClosedSendChannelException) }
+ .onFailure { assertIs<ClosedSendChannelException>(it) }
.also { assertTrue { it.isClosed } }
}
@@ -38,7 +35,7 @@
val channel = Channel<Unit>().also { it.close(TestException()) }
channel.trySendBlocking(Unit)
.onSuccess { expectUnreached() }
- .onFailure { assertTrue(it is TestException) }
+ .onFailure { assertIs<TestException>(it) }
.also { assertTrue { it.isClosed } }
}
@@ -46,7 +43,7 @@
val channel = Channel<Unit>().also { it.cancel(TestCancellationException()) }
channel.trySendBlocking(Unit)
.onSuccess { expectUnreached() }
- .onFailure { assertTrue(it is TestCancellationException) }
+ .onFailure { assertIs<TestCancellationException>(it) }
.also { assertTrue { it.isClosed } }
}
}
diff --git a/kotlinx-coroutines-core/concurrent/test/flow/CombineStressTest.kt b/kotlinx-coroutines-core/concurrent/test/flow/CombineStressTest.kt
index ea6f96b..102d7d2 100644
--- a/kotlinx-coroutines-core/concurrent/test/flow/CombineStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/flow/CombineStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/flow/FlowCancellationTest.kt b/kotlinx-coroutines-core/concurrent/test/flow/FlowCancellationTest.kt
index 8680ff7..4e36563 100644
--- a/kotlinx-coroutines-core/concurrent/test/flow/FlowCancellationTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/flow/FlowCancellationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
diff --git a/kotlinx-coroutines-core/concurrent/test/flow/StateFlowCommonStressTest.kt b/kotlinx-coroutines-core/concurrent/test/flow/StateFlowCommonStressTest.kt
index abd191e..e066052 100644
--- a/kotlinx-coroutines-core/concurrent/test/flow/StateFlowCommonStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/flow/StateFlowCommonStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.random.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/flow/StateFlowUpdateCommonTest.kt b/kotlinx-coroutines-core/concurrent/test/flow/StateFlowUpdateCommonTest.kt
index 8c75b46..a4a5118 100644
--- a/kotlinx-coroutines-core/concurrent/test/flow/StateFlowUpdateCommonTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/flow/StateFlowUpdateCommonTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/selects/SelectChannelStressTest.kt b/kotlinx-coroutines-core/concurrent/test/selects/SelectChannelStressTest.kt
index a5bf90a..32098b2 100644
--- a/kotlinx-coroutines-core/concurrent/test/selects/SelectChannelStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/selects/SelectChannelStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/selects/SelectMutexStressTest.kt b/kotlinx-coroutines-core/concurrent/test/selects/SelectMutexStressTest.kt
index 9395a98..e8c2c82 100644
--- a/kotlinx-coroutines-core/concurrent/test/selects/SelectMutexStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/selects/SelectMutexStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/concurrent/test/sync/MutexStressTest.kt b/kotlinx-coroutines-core/concurrent/test/sync/MutexStressTest.kt
index 77fa7bf..67ff03b 100644
--- a/kotlinx-coroutines-core/concurrent/test/sync/MutexStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/sync/MutexStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.sync
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.exceptions.*
import kotlinx.coroutines.selects.*
@@ -11,7 +8,7 @@
class MutexStressTest : TestBase() {
- private val n = (if (isNative) 1_000 else 10_000) * stressTestMultiplier
+ private val n = 1000 * stressTestMultiplier // It mostly stresses K/N as JVM Mutex is tested by lincheck
@Test
fun testDefaultDispatcher() = runTest { testBody(Dispatchers.Default) }
diff --git a/kotlinx-coroutines-core/concurrent/test/sync/SemaphoreStressTest.kt b/kotlinx-coroutines-core/concurrent/test/sync/SemaphoreStressTest.kt
index 9a3d25b..4be485d 100644
--- a/kotlinx-coroutines-core/concurrent/test/sync/SemaphoreStressTest.kt
+++ b/kotlinx-coroutines-core/concurrent/test/sync/SemaphoreStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.sync
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.exceptions.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jdk8/src/future/Future.kt b/kotlinx-coroutines-core/jdk8/src/future/Future.kt
index f7b4fdc..ac61b1e 100644
--- a/kotlinx-coroutines-core/jdk8/src/future/Future.kt
+++ b/kotlinx-coroutines-core/jdk8/src/future/Future.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.future
import kotlinx.coroutines.*
@@ -150,7 +146,7 @@
* Awaits for completion of [CompletionStage] without blocking a thread.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* stops waiting for the completion stage and immediately resumes with [CancellationException][kotlinx.coroutines.CancellationException].
*
* This method is intended to be used with one-shot futures, so on coroutine cancellation the [CompletableFuture] that
diff --git a/kotlinx-coroutines-core/jdk8/src/stream/Stream.kt b/kotlinx-coroutines-core/jdk8/src/stream/Stream.kt
index b0d72de..bbbac1f 100644
--- a/kotlinx-coroutines-core/jdk8/src/stream/Stream.kt
+++ b/kotlinx-coroutines-core/jdk8/src/stream/Stream.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.stream
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/jdk8/src/time/Time.kt b/kotlinx-coroutines-core/jdk8/src/time/Time.kt
index 78cf6e5..3bb1d05 100644
--- a/kotlinx-coroutines-core/jdk8/src/time/Time.kt
+++ b/kotlinx-coroutines-core/jdk8/src/time/Time.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 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
diff --git a/kotlinx-coroutines-core/js/src/CompletionHandler.kt b/kotlinx-coroutines-core/js/src/CompletionHandler.kt
deleted file mode 100644
index 2ff1070..0000000
--- a/kotlinx-coroutines-core/js/src/CompletionHandler.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlinx.coroutines.internal.*
-
-internal actual abstract class CompletionHandlerBase : LinkedListNode() {
- @JsName("invoke")
- actual abstract fun invoke(cause: Throwable?)
-}
-
-@Suppress("UnsafeCastFromDynamic")
-internal actual inline val CompletionHandlerBase.asHandler: CompletionHandler get() = asDynamic()
-
-internal actual abstract class CancelHandlerBase {
- @JsName("invoke")
- actual abstract fun invoke(cause: Throwable?)
-}
-
-@Suppress("UnsafeCastFromDynamic")
-internal actual inline val CancelHandlerBase.asHandler: CompletionHandler get() = asDynamic()
-
-internal actual fun CompletionHandler.invokeIt(cause: Throwable?) {
- when(jsTypeOf(this)) {
- "function" -> invoke(cause)
- else -> asDynamic().invoke(cause)
- }
-}
diff --git a/kotlinx-coroutines-core/js/src/CoroutineContext.kt b/kotlinx-coroutines-core/js/src/CoroutineContext.kt
index 8036c88..3156dca 100644
--- a/kotlinx-coroutines-core/js/src/CoroutineContext.kt
+++ b/kotlinx-coroutines-core/js/src/CoroutineContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.browser.*
@@ -12,7 +8,7 @@
private const val UNDEFINED = "undefined"
internal external val process: dynamic
-internal fun createDefaultDispatcher(): CoroutineDispatcher = when {
+internal actual fun createDefaultDispatcher(): CoroutineDispatcher = when {
// Check if we are running under jsdom. WindowDispatcher doesn't work under jsdom because it accesses MessageEvent#source.
// It is not implemented in jsdom, see https://github.com/jsdom/jsdom/blob/master/Changelog.md
// "It's missing a few semantics, especially around origins, as well as MessageEvent source."
@@ -33,6 +29,7 @@
jsTypeOf(navigator.userAgent.match) != UNDEFINED &&
navigator.userAgent.match("\\bjsdom\\b")
+@PublishedApi // Used from kotlinx-coroutines-test via suppress, not part of ABI
internal actual val DefaultDelay: Delay
get() = Dispatchers.Default as Delay
diff --git a/kotlinx-coroutines-core/js/src/Debug.kt b/kotlinx-coroutines-core/js/src/Debug.kt
index 7655b54..d36d673 100644
--- a/kotlinx-coroutines-core/js/src/Debug.kt
+++ b/kotlinx-coroutines-core/js/src/Debug.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
private var counter = 0
diff --git a/kotlinx-coroutines-core/js/src/JSDispatcher.kt b/kotlinx-coroutines-core/js/src/JSDispatcher.kt
index 8ddb903..f547c15 100644
--- a/kotlinx-coroutines-core/js/src/JSDispatcher.kt
+++ b/kotlinx-coroutines-core/js/src/JSDispatcher.kt
@@ -1,53 +1,35 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
-import kotlinx.coroutines.internal.*
import org.w3c.dom.*
-import kotlin.coroutines.*
import kotlin.js.Promise
-private const val MAX_DELAY = Int.MAX_VALUE.toLong()
+public actual typealias W3CWindow = Window
-private fun delayToInt(timeMillis: Long): Int =
- timeMillis.coerceIn(0, MAX_DELAY).toInt()
+internal actual fun w3cSetTimeout(window: W3CWindow, handler: () -> Unit, timeout: Int): Int =
+ setTimeout(window, handler, timeout)
-internal sealed class SetTimeoutBasedDispatcher: CoroutineDispatcher(), Delay {
- inner class ScheduledMessageQueue : MessageQueue() {
- internal val processQueue: dynamic = { process() }
+internal actual fun w3cSetTimeout(handler: () -> Unit, timeout: Int): Int =
+ setTimeout(handler, timeout)
- override fun schedule() {
- scheduleQueueProcessing()
- }
+internal actual fun w3cClearTimeout(window: W3CWindow, handle: Int) =
+ window.clearTimeout(handle)
- override fun reschedule() {
- setTimeout(processQueue, 0)
- }
+internal actual fun w3cClearTimeout(handle: Int) =
+ clearTimeout(handle)
+
+internal actual class ScheduledMessageQueue actual constructor(private val dispatcher: SetTimeoutBasedDispatcher) : MessageQueue() {
+ internal val processQueue: dynamic = { process() }
+
+ actual override fun schedule() {
+ dispatcher.scheduleQueueProcessing()
}
- internal val messageQueue = ScheduledMessageQueue()
-
- abstract fun scheduleQueueProcessing()
-
- override fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
- parallelism.checkParallelism()
- return this
+ actual override fun reschedule() {
+ setTimeout(processQueue, 0)
}
- override fun dispatch(context: CoroutineContext, block: Runnable) {
- messageQueue.enqueue(block)
- }
-
- override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
- val handle = setTimeout({ block.run() }, delayToInt(timeMillis))
- return ClearTimeout(handle)
- }
-
- override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
- val handle = setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, delayToInt(timeMillis))
- continuation.invokeOnCancellation(handler = ClearTimeout(handle).asHandler)
+ internal actual fun setTimeout(timeout: Int) {
+ setTimeout(processQueue, timeout)
}
}
@@ -57,48 +39,7 @@
}
}
-internal object SetTimeoutDispatcher : SetTimeoutBasedDispatcher() {
- override fun scheduleQueueProcessing() {
- setTimeout(messageQueue.processQueue, 0)
- }
-}
-
-private open class ClearTimeout(protected val handle: Int) : CancelHandler(), DisposableHandle {
-
- override fun dispose() {
- clearTimeout(handle)
- }
-
- override fun invoke(cause: Throwable?) {
- dispose()
- }
-
- override fun toString(): String = "ClearTimeout[$handle]"
-}
-
-internal class WindowDispatcher(private val window: Window) : CoroutineDispatcher(), Delay {
- private val queue = WindowMessageQueue(window)
-
- override fun dispatch(context: CoroutineContext, block: Runnable) = queue.enqueue(block)
-
- override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
- val handle = window.setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, delayToInt(timeMillis))
- continuation.invokeOnCancellation(handler = WindowClearTimeout(handle).asHandler)
- }
-
- override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
- val handle = window.setTimeout({ block.run() }, delayToInt(timeMillis))
- return WindowClearTimeout(handle)
- }
-
- private inner class WindowClearTimeout(handle: Int) : ClearTimeout(handle) {
- override fun dispose() {
- window.clearTimeout(handle)
- }
- }
-}
-
-private class WindowMessageQueue(private val window: Window) : MessageQueue() {
+internal actual class WindowMessageQueue actual constructor(private val window: W3CWindow) : MessageQueue() {
private val messageName = "dispatchCoroutine"
init {
@@ -110,61 +51,20 @@
}, true)
}
- override fun schedule() {
+ actual override fun schedule() {
Promise.resolve(Unit).then({ process() })
}
- override fun reschedule() {
+ actual override fun reschedule() {
window.postMessage(messageName, "*")
}
}
-/**
- * An abstraction over JS scheduling mechanism that leverages micro-batching of dispatched blocks without
- * paying the cost of JS callbacks scheduling on every dispatch.
- *
- * Queue uses two scheduling mechanisms:
- * 1) [schedule] is used to schedule the initial processing of the message queue.
- * JS engine-specific microtask mechanism is used in order to boost performance on short runs and a dispatch batch
- * 2) [reschedule] is used to schedule processing of the queue after yield to the JS event loop.
- * JS engine-specific macrotask mechanism is used not to starve animations and non-coroutines macrotasks.
- *
- * Yet there could be a long tail of "slow" reschedules, but it should be amortized by the queue size.
- */
-internal abstract class MessageQueue : MutableList<Runnable> by ArrayDeque() {
- val yieldEvery = 16 // yield to JS macrotask event loop after this many processed messages
- private var scheduled = false
-
- abstract fun schedule()
-
- abstract fun reschedule()
-
- fun enqueue(element: Runnable) {
- add(element)
- if (!scheduled) {
- scheduled = true
- schedule()
- }
- }
-
- fun process() {
- try {
- // limit number of processed messages
- repeat(yieldEvery) {
- val element = removeFirstOrNull() ?: return@process
- element.run()
- }
- } finally {
- if (isEmpty()) {
- scheduled = false
- } else {
- reschedule()
- }
- }
- }
-}
-
// We need to reference global setTimeout and clearTimeout so that it works on Node.JS as opposed to
// using them via "window" (which only works in browser)
private external fun setTimeout(handler: dynamic, timeout: Int = definedExternally): Int
+
private external fun clearTimeout(handle: Int = definedExternally)
+
+private fun setTimeout(window: Window, handler: () -> Unit, timeout: Int): Int =
+ window.setTimeout(handler, timeout)
diff --git a/kotlinx-coroutines-core/js/src/Promise.kt b/kotlinx-coroutines-core/js/src/Promise.kt
index 336a388..f84338a 100644
--- a/kotlinx-coroutines-core/js/src/Promise.kt
+++ b/kotlinx-coroutines-core/js/src/Promise.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
@@ -59,11 +55,10 @@
/**
* Awaits for completion of the promise without blocking.
*
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * stops waiting for the promise and immediately resumes with [CancellationException].
- * There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
- * suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting on the promise, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
*/
public suspend fun <T> Promise<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
[email protected](
diff --git a/kotlinx-coroutines-core/js/src/SchedulerTask.kt b/kotlinx-coroutines-core/js/src/SchedulerTask.kt
deleted file mode 100644
index c0ecc4f..0000000
--- a/kotlinx-coroutines-core/js/src/SchedulerTask.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-internal actual abstract class SchedulerTask : Runnable
-
-@Suppress("ACTUAL_WITHOUT_EXPECT")
-internal actual typealias SchedulerTaskContext = Unit
-
-internal actual val SchedulerTask.taskContext: SchedulerTaskContext get() = Unit
-
-@Suppress("NOTHING_TO_INLINE")
-internal actual inline fun SchedulerTaskContext.afterTask() {}
-
diff --git a/kotlinx-coroutines-core/js/src/Window.kt b/kotlinx-coroutines-core/js/src/Window.kt
index 7e99328..7fea6f3 100644
--- a/kotlinx-coroutines-core/js/src/Window.kt
+++ b/kotlinx-coroutines-core/js/src/Window.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import org.w3c.dom.Window
diff --git a/kotlinx-coroutines-core/js/src/internal/Concurrent.kt b/kotlinx-coroutines-core/js/src/internal/Concurrent.kt
deleted file mode 100644
index 6272679..0000000
--- a/kotlinx-coroutines-core/js/src/internal/Concurrent.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.internal
-
-internal actual typealias ReentrantLock = NoOpLock
-
-internal actual inline fun <T> ReentrantLock.withLock(action: () -> T) = action()
-
-internal class NoOpLock {
- fun tryLock() = true
- fun unlock(): Unit {}
-}
-
-internal actual fun <E> identitySet(expectedSize: Int): MutableSet<E> = HashSet(expectedSize)
-
diff --git a/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt
index 335e35d..26ad530 100644
--- a/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt
+++ b/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
/**
diff --git a/kotlinx-coroutines-core/js/src/internal/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/js/src/internal/CoroutineExceptionHandlerImpl.kt
index 675cc4a..b3c09e7 100644
--- a/kotlinx-coroutines-core/js/src/internal/CoroutineExceptionHandlerImpl.kt
+++ b/kotlinx-coroutines-core/js/src/internal/CoroutineExceptionHandlerImpl.kt
@@ -1,26 +1,8 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
-import kotlin.coroutines.*
-
-private val platformExceptionHandlers_ = mutableSetOf<CoroutineExceptionHandler>()
-
-internal actual val platformExceptionHandlers: Collection<CoroutineExceptionHandler>
- get() = platformExceptionHandlers_
-
-internal actual fun ensurePlatformExceptionHandlerLoaded(callback: CoroutineExceptionHandler) {
- platformExceptionHandlers_ += callback
-}
internal actual fun propagateExceptionFinalResort(exception: Throwable) {
// log exception
- console.error(exception)
-}
-
-internal actual class DiagnosticCoroutineContextException actual constructor(context: CoroutineContext) :
- RuntimeException(context.toString())
-
+ console.error(exception.toString())
+}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt
deleted file mode 100644
index 4fb334e..0000000
--- a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.internal
-
-internal actual fun systemProp(propertyName: String): String? = null
diff --git a/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt
deleted file mode 100644
index 2370e42..0000000
--- a/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.internal
-
-import kotlin.coroutines.*
-
-internal actual fun threadContextElements(context: CoroutineContext): Any = 0
diff --git a/kotlinx-coroutines-core/js/test/ImmediateDispatcherTest.kt b/kotlinx-coroutines-core/js/test/ImmediateDispatcherTest.kt
deleted file mode 100644
index 7ca6a24..0000000
--- a/kotlinx-coroutines-core/js/test/ImmediateDispatcherTest.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlin.test.*
-
-class ImmediateDispatcherTest : TestBase() {
-
- @Test
- fun testImmediate() = runTest {
- expect(1)
- val job = launch { expect(3) }
- withContext(Dispatchers.Main.immediate) {
- expect(2)
- }
- job.join()
- finish(4)
- }
-
- @Test
- fun testMain() = runTest {
- expect(1)
- val job = launch { expect(2) }
- withContext(Dispatchers.Main) {
- expect(3)
- }
- job.join()
- finish(4)
- }
-}
diff --git a/kotlinx-coroutines-core/js/test/PromiseTest.kt b/kotlinx-coroutines-core/js/test/PromiseTest.kt
index 6049a90..319778d 100644
--- a/kotlinx-coroutines-core/js/test/PromiseTest.kt
+++ b/kotlinx-coroutines-core/js/test/PromiseTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.js.*
import kotlin.test.*
@@ -30,7 +27,7 @@
deferred.await()
expectUnreached()
} catch (e: Throwable) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("Rejected", e.message)
}
}
diff --git a/kotlinx-coroutines-core/js/test/TestBase.kt b/kotlinx-coroutines-core/js/test/TestBase.kt
deleted file mode 100644
index f0e3a2d..0000000
--- a/kotlinx-coroutines-core/js/test/TestBase.kt
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlin.js.*
-
-public actual val isStressTest: Boolean = false
-public actual val stressTestMultiplier: Int = 1
-public actual val stressTestMultiplierSqrt: Int = 1
-
-@Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE")
-public actual typealias TestResult = Promise<Unit>
-
-public actual val isNative = false
-
-public actual open class TestBase actual constructor() {
- public actual val isBoundByJsTestTimeout = true
- private var actionIndex = 0
- private var finished = false
- private var error: Throwable? = null
- private var lastTestPromise: Promise<*>? = null
-
- /**
- * Throws [IllegalStateException] like `error` in stdlib, but also ensures that the test will not
- * complete successfully even if this exception is consumed somewhere in the test.
- */
- @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
- public actual fun error(message: Any, cause: Throwable? = null): Nothing {
- if (cause != null) console.log(cause)
- val exception = IllegalStateException(
- if (cause == null) message.toString() else "$message; caused by $cause")
- if (error == null) error = exception
- throw exception
- }
-
- private fun printError(message: String, cause: Throwable) {
- if (error == null) error = cause
- println("$message: $cause")
- console.log(cause)
- }
-
- /**
- * Asserts that this invocation is `index`-th in the execution sequence (counting from one).
- */
- public actual fun expect(index: Int) {
- val wasIndex = ++actionIndex
- check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" }
- }
-
- /**
- * Asserts that this line is never executed.
- */
- public actual fun expectUnreached() {
- error("Should not be reached")
- }
-
- /**
- * Asserts that this it the last action in the test. It must be invoked by any test that used [expect].
- */
- public actual fun finish(index: Int) {
- expect(index)
- check(!finished) { "Should call 'finish(...)' at most once" }
- finished = true
- }
-
- /**
- * Asserts that [finish] was invoked
- */
- public actual fun ensureFinished() {
- require(finished) { "finish(...) should be caller prior to this check" }
- }
-
- public actual fun reset() {
- check(actionIndex == 0 || finished) { "Expecting that 'finish(...)' was invoked, but it was not" }
- actionIndex = 0
- finished = false
- }
-
- @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
- public actual fun runTest(
- expected: ((Throwable) -> Boolean)? = null,
- unhandled: List<(Throwable) -> Boolean> = emptyList(),
- block: suspend CoroutineScope.() -> Unit
- ): TestResult {
- var exCount = 0
- var ex: Throwable? = null
- /*
- * This is an additional sanity check against `runTest` mis-usage on JS.
- * The only way to write an async test on JS is to return Promise from the test function.
- * _Just_ launching promise and returning `Unit` won't suffice as the underlying test framework
- * won't be able to detect an asynchronous failure in a timely manner.
- * We cannot detect such situations, but we can detect the most common erroneous pattern
- * in our code base, an attempt to use multiple `runTest` in the same `@Test` method,
- * which typically is a premise to the same error:
- * ```
- * @Test
- * fun incorrectTestForJs() { // <- promise is not returned
- * for (parameter in parameters) {
- * runTest {
- * runTestForParameter(parameter)
- * }
- * }
- * }
- * ```
- */
- if (lastTestPromise != null) {
- error("Attempt to run multiple asynchronous test within one @Test method")
- }
- val result = GlobalScope.promise(block = block, context = CoroutineExceptionHandler { _, e ->
- if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
- exCount++
- when {
- exCount > unhandled.size ->
- printError("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
- !unhandled[exCount - 1](e) ->
- printError("Unhandled exception was unexpected: $e", e)
- }
- }).catch { e ->
- ex = e
- if (expected != null) {
- if (!expected(e))
- error("Unexpected exception", e)
- } else
- throw e
- }.finally {
- if (ex == null && expected != null) error("Exception was expected but none produced")
- if (exCount < unhandled.size)
- error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
- error?.let { throw it }
- check(actionIndex == 0 || finished) { "Expecting that 'finish(...)' was invoked, but it was not" }
- }
- lastTestPromise = result
- return result
- }
-}
-
-private fun <T> Promise<T>.finally(block: () -> Unit): Promise<T> =
- then(onFulfilled = { value -> block(); value }, onRejected = { ex -> block(); throw ex })
-
-public actual val isJavaAndWindows: Boolean get() = false
diff --git a/kotlinx-coroutines-core/js/src/CloseableCoroutineDispatcher.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/CloseableCoroutineDispatcher.kt
similarity index 61%
rename from kotlinx-coroutines-core/js/src/CloseableCoroutineDispatcher.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/CloseableCoroutineDispatcher.kt
index 0e239a4..81e0c5d 100644
--- a/kotlinx-coroutines-core/js/src/CloseableCoroutineDispatcher.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/CloseableCoroutineDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
public actual abstract class CloseableCoroutineDispatcher actual constructor() : CoroutineDispatcher() {
diff --git a/kotlinx-coroutines-core/js/src/Dispatchers.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/Dispatchers.kt
similarity index 92%
rename from kotlinx-coroutines-core/js/src/Dispatchers.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/Dispatchers.kt
index 1304c5a..ca74fba 100644
--- a/kotlinx-coroutines-core/js/src/Dispatchers.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/Dispatchers.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
+internal expect fun createDefaultDispatcher(): CoroutineDispatcher
+
public actual object Dispatchers {
public actual val Default: CoroutineDispatcher = createDefaultDispatcher()
public actual val Main: MainCoroutineDispatcher
diff --git a/kotlinx-coroutines-core/js/src/EventLoop.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/EventLoop.kt
similarity index 88%
rename from kotlinx-coroutines-core/js/src/EventLoop.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/EventLoop.kt
index 13c3369..90549ee 100644
--- a/kotlinx-coroutines-core/js/src/EventLoop.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/EventLoop.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/js/src/Exceptions.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/Exceptions.kt
similarity index 84%
rename from kotlinx-coroutines-core/js/src/Exceptions.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/Exceptions.kt
index da9979b..c6173af 100644
--- a/kotlinx-coroutines-core/js/src/Exceptions.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/Exceptions.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
@@ -12,6 +8,11 @@
*/
public actual typealias CancellationException = kotlin.coroutines.cancellation.CancellationException
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
[email protected]
+public actual fun CancellationException(message: String?, cause: Throwable?): CancellationException =
+ CancellationException(message, cause)
+
/**
* Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled or completed
* without cause, or with a cause or exception that is not [CancellationException]
@@ -30,8 +31,5 @@
(message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0)
}
-@Suppress("NOTHING_TO_INLINE")
-internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) { /* empty */ }
-
// For use in tests
internal actual val RECOVER_STACK_TRACES: Boolean = false
diff --git a/kotlinx-coroutines-core/js/src/Runnable.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/Runnable.kt
similarity index 79%
rename from kotlinx-coroutines-core/js/src/Runnable.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/Runnable.kt
index b8e6980..1a9e0ae 100644
--- a/kotlinx-coroutines-core/js/src/Runnable.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/Runnable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/src/SchedulerTask.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/SchedulerTask.kt
new file mode 100644
index 0000000..111a9fc
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/SchedulerTask.kt
@@ -0,0 +1,13 @@
+package kotlinx.coroutines
+
+internal actual abstract class SchedulerTask : Runnable
+
+internal actual interface SchedulerTaskContext { }
+
+private object TaskContext: SchedulerTaskContext { }
+
+internal actual val SchedulerTask.taskContext: SchedulerTaskContext get() = TaskContext
+
+@Suppress("NOTHING_TO_INLINE")
+internal actual inline fun SchedulerTaskContext.afterTask() {}
+
diff --git a/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/flow/internal/FlowExceptions.kt
similarity index 69%
rename from kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/flow/internal/FlowExceptions.kt
index 000395e..0e780f5 100644
--- a/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/flow/internal/FlowExceptions.kt
@@ -1,13 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
internal actual class AbortFlowException actual constructor(
- actual val owner: FlowCollector<*>
+ actual val owner: Any
) : CancellationException("Flow was aborted, no more elements needed")
internal actual class ChildCancelledException : CancellationException("Child of the scoped flow was cancelled")
diff --git a/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/flow/internal/SafeCollector.kt
similarity index 85%
rename from kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/flow/internal/SafeCollector.kt
index b74b547..ded11e2 100644
--- a/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/flow/internal/SafeCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
@@ -17,7 +13,7 @@
internal actual val collectContextSize = collectContext.fold(0) { count, _ -> count + 1 }
private var lastEmissionContext: CoroutineContext? = null
- override suspend fun emit(value: T) {
+ actual override suspend fun emit(value: T) {
val currentContext = currentCoroutineContext()
currentContext.ensureActive()
if (lastEmissionContext !== currentContext) {
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/src/internal/Concurrent.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/Concurrent.kt
new file mode 100644
index 0000000..652d60c
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/Concurrent.kt
@@ -0,0 +1,35 @@
+package kotlinx.coroutines.internal
+
+internal actual typealias ReentrantLock = NoOpLock
+
+internal actual inline fun <T> ReentrantLock.withLock(action: () -> T) = action()
+
+internal class NoOpLock {
+ fun tryLock() = true
+ fun unlock(): Unit {}
+}
+
+internal actual fun <E> identitySet(expectedSize: Int): MutableSet<E> = HashSet(expectedSize)
+
+internal actual class WorkaroundAtomicReference<T> actual constructor(private var value: T) {
+
+ public actual fun get(): T = value
+
+ public actual fun set(value: T) {
+ this.value = value
+ }
+
+ public actual fun getAndSet(value: T): T {
+ val prev = this.value
+ this.value = value
+ return prev
+ }
+
+ public actual fun compareAndSet(expected: T, value: T): Boolean {
+ if (this.value === expected) {
+ this.value = value
+ return true
+ }
+ return false
+ }
+}
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/src/internal/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/CoroutineExceptionHandlerImpl.kt
new file mode 100644
index 0000000..d664ce6
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/CoroutineExceptionHandlerImpl.kt
@@ -0,0 +1,17 @@
+package kotlinx.coroutines.internal
+
+import kotlinx.coroutines.*
+import kotlin.coroutines.*
+
+private val platformExceptionHandlers_ = mutableSetOf<CoroutineExceptionHandler>()
+
+internal actual val platformExceptionHandlers: Collection<CoroutineExceptionHandler>
+ get() = platformExceptionHandlers_
+
+internal actual fun ensurePlatformExceptionHandlerLoaded(callback: CoroutineExceptionHandler) {
+ platformExceptionHandlers_ += callback
+}
+
+internal actual class DiagnosticCoroutineContextException actual constructor(context: CoroutineContext) :
+ RuntimeException(context.toString())
+
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/src/internal/JSDispatcher.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/JSDispatcher.kt
new file mode 100644
index 0000000..b002ea7
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/JSDispatcher.kt
@@ -0,0 +1,137 @@
+package kotlinx.coroutines
+
+import kotlinx.coroutines.internal.*
+import kotlin.coroutines.*
+
+public expect abstract class W3CWindow
+internal expect fun w3cSetTimeout(window: W3CWindow, handler: () -> Unit, timeout: Int): Int
+internal expect fun w3cSetTimeout(handler: () -> Unit, timeout: Int): Int
+internal expect fun w3cClearTimeout(handle: Int)
+internal expect fun w3cClearTimeout(window: W3CWindow, handle: Int)
+
+internal expect class ScheduledMessageQueue(dispatcher: SetTimeoutBasedDispatcher) : MessageQueue {
+ override fun schedule()
+ override fun reschedule()
+ internal fun setTimeout(timeout: Int)
+}
+
+internal expect class WindowMessageQueue(window: W3CWindow) : MessageQueue {
+ override fun schedule()
+ override fun reschedule()
+}
+
+private const val MAX_DELAY = Int.MAX_VALUE.toLong()
+
+private fun delayToInt(timeMillis: Long): Int =
+ timeMillis.coerceIn(0, MAX_DELAY).toInt()
+
+internal abstract class SetTimeoutBasedDispatcher: CoroutineDispatcher(), Delay {
+ internal val messageQueue = ScheduledMessageQueue(this)
+
+ abstract fun scheduleQueueProcessing()
+
+ override fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
+ parallelism.checkParallelism()
+ return this
+ }
+
+ override fun dispatch(context: CoroutineContext, block: Runnable) {
+ messageQueue.enqueue(block)
+ }
+
+ override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
+ val handle = w3cSetTimeout({ block.run() }, delayToInt(timeMillis))
+ return ClearTimeout(handle)
+ }
+
+ override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
+ val handle = w3cSetTimeout({ with(continuation) { resumeUndispatched(Unit) } }, delayToInt(timeMillis))
+ continuation.invokeOnCancellation(handler = ClearTimeout(handle))
+ }
+}
+
+internal class WindowDispatcher(private val window: W3CWindow) : CoroutineDispatcher(), Delay {
+ private val queue = WindowMessageQueue(window)
+
+ override fun dispatch(context: CoroutineContext, block: Runnable) = queue.enqueue(block)
+
+ override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
+ val handle = w3cSetTimeout(window, { with(continuation) { resumeUndispatched(Unit) } }, delayToInt(timeMillis))
+ continuation.invokeOnCancellation(handler = WindowClearTimeout(handle))
+ }
+
+ override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
+ val handle = w3cSetTimeout(window, block::run, delayToInt(timeMillis))
+ return WindowClearTimeout(handle)
+ }
+
+ private inner class WindowClearTimeout(handle: Int) : ClearTimeout(handle) {
+ override fun dispose() {
+ w3cClearTimeout(window, handle)
+ }
+ }
+}
+
+internal object SetTimeoutDispatcher : SetTimeoutBasedDispatcher() {
+ override fun scheduleQueueProcessing() {
+ messageQueue.setTimeout(0)
+ }
+}
+
+private open class ClearTimeout(protected val handle: Int) : CancelHandler, DisposableHandle {
+ override fun dispose() {
+ w3cClearTimeout(handle)
+ }
+
+ override fun invoke(cause: Throwable?) {
+ dispose()
+ }
+
+ override fun toString(): String = "ClearTimeout[$handle]"
+}
+
+
+/**
+ * An abstraction over JS scheduling mechanism that leverages micro-batching of dispatched blocks without
+ * paying the cost of JS callbacks scheduling on every dispatch.
+ *
+ * Queue uses two scheduling mechanisms:
+ * 1) [schedule] is used to schedule the initial processing of the message queue.
+ * JS engine-specific microtask mechanism is used in order to boost performance on short runs and a dispatch batch
+ * 2) [reschedule] is used to schedule processing of the queue after yield to the JS event loop.
+ * JS engine-specific macrotask mechanism is used not to starve animations and non-coroutines macrotasks.
+ *
+ * Yet there could be a long tail of "slow" reschedules, but it should be amortized by the queue size.
+ */
+internal abstract class MessageQueue : MutableList<Runnable> by ArrayDeque() {
+ val yieldEvery = 16 // yield to JS macrotask event loop after this many processed messages
+ private var scheduled = false
+
+ abstract fun schedule()
+
+ abstract fun reschedule()
+
+ fun enqueue(element: Runnable) {
+ add(element)
+ if (!scheduled) {
+ scheduled = true
+ schedule()
+ }
+ }
+
+ fun process() {
+ try {
+ // limit number of processed messages
+ repeat(yieldEvery) {
+ val element = removeFirstOrNull() ?: return@process
+ element.run()
+ }
+ } finally {
+ if (isEmpty()) {
+ scheduled = false
+ } else {
+ reschedule()
+ }
+ }
+ }
+}
diff --git a/kotlinx-coroutines-core/js/src/internal/LinkedList.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/LinkedList.kt
similarity index 93%
rename from kotlinx-coroutines-core/js/src/internal/LinkedList.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/internal/LinkedList.kt
index de5d491..8d68f8b 100644
--- a/kotlinx-coroutines-core/js/src/internal/LinkedList.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/LinkedList.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("unused", "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE", "NO_EXPLICIT_VISIBILITY_IN_API_MODE")
package kotlinx.coroutines.internal
@@ -9,8 +5,8 @@
import kotlinx.coroutines.*
private typealias Node = LinkedListNode
+
/** @suppress **This is unstable API and it is subject to change.** */
-@Suppress("NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS") // :TODO: Remove when fixed: https://youtrack.jetbrains.com/issue/KT-23703
public actual typealias LockFreeLinkedListNode = LinkedListNode
/** @suppress **This is unstable API and it is subject to change.** */
diff --git a/kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/LocalAtomics.kt
similarity index 70%
rename from kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/internal/LocalAtomics.kt
index 643fe85..e0e1bee 100644
--- a/kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/LocalAtomics.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
internal actual class LocalAtomicInt actual constructor(private var value: Int) {
diff --git a/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ProbesSupport.kt
similarity index 65%
rename from kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/internal/ProbesSupport.kt
index 47d3fdb..00581f1 100644
--- a/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ProbesSupport.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/StackTraceRecovery.kt
similarity index 87%
rename from kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/internal/StackTraceRecovery.kt
index 06107b8..7003a24 100644
--- a/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/StackTraceRecovery.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
@@ -10,6 +6,7 @@
internal actual fun <E: Throwable> recoverStackTrace(exception: E): E = exception
internal actual suspend inline fun recoverAndThrow(exception: Throwable): Nothing = throw exception
+@PublishedApi
internal actual fun <E : Throwable> unwrap(exception: E): E = exception
@Suppress("UNUSED")
diff --git a/kotlinx-coroutines-core/js/src/internal/Synchronized.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/Synchronized.kt
similarity index 70%
rename from kotlinx-coroutines-core/js/src/internal/Synchronized.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/internal/Synchronized.kt
index 05db528..e828f67 100644
--- a/kotlinx-coroutines-core/js/src/internal/Synchronized.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/Synchronized.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
@@ -10,7 +6,7 @@
* @suppress **This an internal API and should not be used from general code.**
*/
@InternalCoroutinesApi
-public actual typealias SynchronizedObject = Any
+public actual open class SynchronizedObject
/**
* @suppress **This an internal API and should not be used from general code.**
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/src/internal/SystemProps.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/SystemProps.kt
new file mode 100644
index 0000000..accc247
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/SystemProps.kt
@@ -0,0 +1,3 @@
+package kotlinx.coroutines.internal
+
+internal actual fun systemProp(propertyName: String): String? = null
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ThreadContext.kt
new file mode 100644
index 0000000..3f56f99
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ThreadContext.kt
@@ -0,0 +1,5 @@
+package kotlinx.coroutines.internal
+
+import kotlin.coroutines.*
+
+internal actual fun threadContextElements(context: CoroutineContext): Any = 0
diff --git a/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ThreadLocal.kt
similarity index 74%
rename from kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/src/internal/ThreadLocal.kt
index c8dd096..94eecfa 100644
--- a/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/src/internal/ThreadLocal.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
internal actual class CommonThreadLocal<T> {
@@ -11,4 +7,4 @@
actual fun set(value: T) { this.value = value }
}
-internal actual fun<T> commonThreadLocal(name: Symbol): CommonThreadLocal<T> = CommonThreadLocal()
+internal actual fun<T> commonThreadLocal(name: Symbol): CommonThreadLocal<T> = CommonThreadLocal()
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jsAndWasmShared/test/ImmediateDispatcherTest.kt b/kotlinx-coroutines-core/jsAndWasmShared/test/ImmediateDispatcherTest.kt
new file mode 100644
index 0000000..936713b
--- /dev/null
+++ b/kotlinx-coroutines-core/jsAndWasmShared/test/ImmediateDispatcherTest.kt
@@ -0,0 +1,39 @@
+package kotlinx.coroutines
+
+import kotlinx.coroutines.testing.*
+import kotlinx.coroutines.testing.*
+import kotlin.coroutines.*
+import kotlin.test.*
+
+class ImmediateDispatcherTest : MainDispatcherTestBase.WithRealTimeDelay() {
+
+ /** Tests that [MainCoroutineDispatcher.immediate] doesn't require dispatches from the test context. */
+ @Test
+ fun testImmediate() = runTest {
+ expect(1)
+ val job = launch { expect(3) }
+ assertFalse(Dispatchers.Main.immediate.isDispatchNeeded(currentCoroutineContext()))
+ withContext(Dispatchers.Main.immediate) {
+ expect(2)
+ }
+ job.join()
+ finish(4)
+ }
+
+ @Test
+ fun testMain() = runTest {
+ expect(1)
+ val job = launch { expect(2) }
+ withContext(Dispatchers.Main) {
+ expect(3)
+ }
+ job.join()
+ finish(4)
+ }
+
+ override fun isMainThread(): Boolean? = null
+
+ override fun scheduleOnMainQueue(block: () -> Unit) {
+ Dispatchers.Default.dispatch(EmptyCoroutineContext, Runnable { block() })
+ }
+}
diff --git a/kotlinx-coroutines-core/js/test/MessageQueueTest.kt b/kotlinx-coroutines-core/jsAndWasmShared/test/MessageQueueTest.kt
similarity index 94%
rename from kotlinx-coroutines-core/js/test/MessageQueueTest.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/test/MessageQueueTest.kt
index 7ce7380..5bf4d2d 100644
--- a/kotlinx-coroutines-core/js/test/MessageQueueTest.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/test/MessageQueueTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/js/test/SetTimeoutDispatcherTest.kt b/kotlinx-coroutines-core/jsAndWasmShared/test/SetTimeoutDispatcherTest.kt
similarity index 90%
rename from kotlinx-coroutines-core/js/test/SetTimeoutDispatcherTest.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/test/SetTimeoutDispatcherTest.kt
index 7870077..3b4e422 100644
--- a/kotlinx-coroutines-core/js/test/SetTimeoutDispatcherTest.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/test/SetTimeoutDispatcherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class SetTimeoutDispatcherTest : TestBase() {
diff --git a/kotlinx-coroutines-core/js/test/internal/LinkedListTest.kt b/kotlinx-coroutines-core/jsAndWasmShared/test/internal/LinkedListTest.kt
similarity index 92%
rename from kotlinx-coroutines-core/js/test/internal/LinkedListTest.kt
rename to kotlinx-coroutines-core/jsAndWasmShared/test/internal/LinkedListTest.kt
index 6c1fddf..04b7006 100644
--- a/kotlinx-coroutines-core/js/test/internal/LinkedListTest.kt
+++ b/kotlinx-coroutines-core/jsAndWasmShared/test/internal/LinkedListTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.test.Test
diff --git a/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin b/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin
index 9d171f3..ce82c79 100644
--- a/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin
+++ b/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin
Binary files differ
diff --git a/kotlinx-coroutines-core/jvm/src/AbstractTimeSource.kt b/kotlinx-coroutines-core/jvm/src/AbstractTimeSource.kt
index 3f7ac67..f497dc8 100644
--- a/kotlinx-coroutines-core/jvm/src/AbstractTimeSource.kt
+++ b/kotlinx-coroutines-core/jvm/src/AbstractTimeSource.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// Need InlineOnly for efficient bytecode on Android
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "NOTHING_TO_INLINE")
@@ -24,7 +20,12 @@
// For tests only
// @JvmField: Don't use JvmField here to enable R8 optimizations via "assumenosideeffects"
-internal var timeSource: AbstractTimeSource? = null
+private var timeSource: AbstractTimeSource? = null
+
+// TODO: without this, there's a compilation error. Why?
+internal inline fun mockTimeSource(source: AbstractTimeSource?) {
+ timeSource = source
+}
@InlineOnly
internal inline fun currentTimeMillis(): Long =
diff --git a/kotlinx-coroutines-core/jvm/src/Builders.kt b/kotlinx-coroutines-core/jvm/src/Builders.kt
index 8c4b62b..d2249bf 100644
--- a/kotlinx-coroutines-core/jvm/src/Builders.kt
+++ b/kotlinx-coroutines-core/jvm/src/Builders.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("BuildersKt")
@file:OptIn(ExperimentalContracts::class)
@@ -14,8 +10,22 @@
/**
* Runs a new coroutine and **blocks** the current thread _interruptibly_ until its completion.
- * This function should not be used from a coroutine. It is designed to bridge regular blocking code
- * to libraries that are written in suspending style, to be used in `main` functions and in tests.
+ *
+ * It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in
+ * `main` functions and in tests.
+ *
+ * Calling [runBlocking] from a suspend function is redundant.
+ * For example, the following code is incorrect:
+ * ```
+ * suspend fun loadConfiguration() {
+ * // DO NOT DO THIS:
+ * val data = runBlocking { // <- redundant and blocks the thread, do not do that
+ * fetchConfigurationData() // suspending function
+ * }
+ * ```
+ *
+ * Here, instead of releasing the thread on which `loadConfiguration` runs if `fetchConfigurationData` suspends, it will
+ * block, potentially leading to thread starvation issues.
*
* The default [CoroutineDispatcher] for this builder is an internal implementation of event loop that processes continuations
* in this blocked thread until the completion of this coroutine.
diff --git a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt
index b736125..ae8275f 100644
--- a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt
+++ b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -42,12 +38,12 @@
/**
* Folds two contexts properly applying [CopyableThreadContextElement] rules when necessary.
* The rules are the following:
- * * If neither context has CTCE, the sum of two contexts is returned
- * * Every CTCE from the left-hand side context that does not have a matching (by key) element from right-hand side context
+ * - If neither context has CTCE, the sum of two contexts is returned
+ * - Every CTCE from the left-hand side context that does not have a matching (by key) element from right-hand side context
* is [copied][CopyableThreadContextElement.copyForChild] if [isNewCoroutine] is `true`.
- * * Every CTCE from the left-hand side context that has a matching element in the right-hand side context is [merged][CopyableThreadContextElement.mergeForChild]
- * * Every CTCE from the right-hand side context that hasn't been merged is copied
- * * Everything else is added to the resulting context as is.
+ * - Every CTCE from the left-hand side context that has a matching element in the right-hand side context is [merged][CopyableThreadContextElement.mergeForChild]
+ * - Every CTCE from the right-hand side context that hasn't been merged is copied
+ * - Everything else is added to the resulting context as is.
*/
private fun foldCopies(originalContext: CoroutineContext, appendContext: CoroutineContext, isNewCoroutine: Boolean): CoroutineContext {
// Do we have something to copy left-hand side?
@@ -195,8 +191,8 @@
* (You can read more about this effect as "GC nepotism").
*
* To avoid that, we attempt to narrow down the lifetime of this thread local as much as possible:
- * * It's never accessed when we are sure there are no thread context elements
- * * It's cleaned up via [ThreadLocal.remove] as soon as the coroutine is suspended or finished.
+ * - It's never accessed when we are sure there are no thread context elements
+ * - It's cleaned up via [ThreadLocal.remove] as soon as the coroutine is suspended or finished.
*/
private val threadStateToRecover = ThreadLocal<Pair<CoroutineContext, Any?>>()
diff --git a/kotlinx-coroutines-core/jvm/src/Debug.kt b/kotlinx-coroutines-core/jvm/src/Debug.kt
index 4a821a1..96166d1 100644
--- a/kotlinx-coroutines-core/jvm/src/Debug.kt
+++ b/kotlinx-coroutines-core/jvm/src/Debug.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// Need InlineOnly for efficient bytecode on Android
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@@ -23,9 +19,9 @@
* Enable debugging facilities with "`kotlinx.coroutines.debug`" ([DEBUG_PROPERTY_NAME]) system property,
* use the following values:
*
- * * "`auto`" (default mode, [DEBUG_PROPERTY_VALUE_AUTO]) -- enabled when assertions are enabled with "`-ea`" JVM option.
- * * "`on`" ([DEBUG_PROPERTY_VALUE_ON]) or empty string -- enabled.
- * * "`off`" ([DEBUG_PROPERTY_VALUE_OFF]) -- disabled.
+ * - "`auto`" (default mode, [DEBUG_PROPERTY_VALUE_AUTO]) -- enabled when assertions are enabled with "`-ea`" JVM option.
+ * - "`on`" ([DEBUG_PROPERTY_VALUE_ON]) or empty string -- enabled.
+ * - "`off`" ([DEBUG_PROPERTY_VALUE_OFF]) -- disabled.
*
* Coroutine name can be explicitly assigned using [CoroutineName] context element.
* The string "coroutine" is used as a default name.
@@ -78,7 +74,8 @@
// Note: stack-trace recovery is enabled only in debug mode
// @JvmField: Don't use JvmField here to enable R8 optimizations via "assumenosideeffects"
-internal actual val RECOVER_STACK_TRACES =
+@PublishedApi
+internal actual val RECOVER_STACK_TRACES: Boolean =
DEBUG && systemProp(STACKTRACE_RECOVERY_PROPERTY_NAME, true)
// It is used only in debug mode
diff --git a/kotlinx-coroutines-core/jvm/src/DebugStrings.kt b/kotlinx-coroutines-core/jvm/src/DebugStrings.kt
index 32bd07a..ce5adc5 100644
--- a/kotlinx-coroutines-core/jvm/src/DebugStrings.kt
+++ b/kotlinx-coroutines-core/jvm/src/DebugStrings.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt b/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt
index c993bc2..b467cd1 100644
--- a/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt
+++ b/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -10,6 +6,7 @@
private val defaultMainDelayOptIn = systemProp("kotlinx.coroutines.main.delay", false)
+@PublishedApi
internal actual val DefaultDelay: Delay = initializeDefaultDelay()
private fun initializeDefaultDelay(): Delay {
@@ -134,6 +131,13 @@
private fun createThreadSync(): Thread {
return _thread ?: Thread(this, THREAD_NAME).apply {
_thread = this
+ /*
+ * `DefaultExecutor` is a global singleton that creates its thread lazily.
+ * To isolate the classloaders properly, we are inherting the context classloader from
+ * the singleton itself instead of using parent' thread one
+ * in order not to accidentally capture temporary application classloader.
+ */
+ contextClassLoader = [email protected]
isDaemon = true
start()
}
diff --git a/kotlinx-coroutines-core/jvm/src/Dispatchers.kt b/kotlinx-coroutines-core/jvm/src/Dispatchers.kt
index 2222f0d..6b3fa5e 100644
--- a/kotlinx-coroutines-core/jvm/src/Dispatchers.kt
+++ b/kotlinx-coroutines-core/jvm/src/Dispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/jvm/src/EventLoop.kt b/kotlinx-coroutines-core/jvm/src/EventLoop.kt
index 7d1078c..d7388ce 100644
--- a/kotlinx-coroutines-core/jvm/src/EventLoop.kt
+++ b/kotlinx-coroutines-core/jvm/src/EventLoop.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.Runnable
@@ -9,6 +5,7 @@
import kotlinx.coroutines.scheduling.CoroutineScheduler
internal actual abstract class EventLoopImplPlatform: EventLoop() {
+
protected abstract val thread: Thread
protected actual fun unpark() {
@@ -32,9 +29,9 @@
* Processes next event in the current thread's event loop.
*
* The result of this function is to be interpreted like this:
- * * `<= 0` -- there are potentially more events for immediate processing;
- * * `> 0` -- a number of nanoseconds to wait for the next scheduled event;
- * * [Long.MAX_VALUE] -- no more events or no thread-local event loop.
+ * - `<= 0` -- there are potentially more events for immediate processing;
+ * - `> 0` -- a number of nanoseconds to wait for the next scheduled event;
+ * - [Long.MAX_VALUE] -- no more events or no thread-local event loop.
*
* Sample usage of this function:
*
diff --git a/kotlinx-coroutines-core/jvm/src/Exceptions.kt b/kotlinx-coroutines-core/jvm/src/Exceptions.kt
index 48b4788..6175595 100644
--- a/kotlinx-coroutines-core/jvm/src/Exceptions.kt
+++ b/kotlinx-coroutines-core/jvm/src/Exceptions.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("FunctionName")
package kotlinx.coroutines
@@ -17,7 +13,6 @@
/**
* Creates a cancellation exception with a specified message and [cause].
*/
-@Suppress("FunctionName")
public actual fun CancellationException(message: String?, cause: Throwable?) : CancellationException =
CancellationException(message).apply { initCause(cause) }
@@ -69,7 +64,3 @@
override fun hashCode(): Int =
(message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0)
}
-
-@Suppress("NOTHING_TO_INLINE")
-internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) =
- addSuppressed(other)
diff --git a/kotlinx-coroutines-core/jvm/src/Executors.kt b/kotlinx-coroutines-core/jvm/src/Executors.kt
index 121ba3f..53ef77d 100644
--- a/kotlinx-coroutines-core/jvm/src/Executors.kt
+++ b/kotlinx-coroutines-core/jvm/src/Executors.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.flow.*
diff --git a/kotlinx-coroutines-core/jvm/src/Future.kt b/kotlinx-coroutines-core/jvm/src/Future.kt
index b27a970..2e217cc 100644
--- a/kotlinx-coroutines-core/jvm/src/Future.kt
+++ b/kotlinx-coroutines-core/jvm/src/Future.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("JobKt")
@@ -42,7 +38,7 @@
}
}
-private class CancelFutureOnCancel(private val future: Future<*>) : CancelHandler() {
+private class CancelFutureOnCancel(private val future: Future<*>) : CancelHandler {
override fun invoke(cause: Throwable?) {
// Don't interrupt when cancelling future on completion, because no one is going to reset this
// interruption flag and it will cause spurious failures elsewhere
diff --git a/kotlinx-coroutines-core/jvm/src/Interruptible.kt b/kotlinx-coroutines-core/jvm/src/Interruptible.kt
index 8129be7..b25a289 100644
--- a/kotlinx-coroutines-core/jvm/src/Interruptible.kt
+++ b/kotlinx-coroutines-core/jvm/src/Interruptible.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
@@ -63,7 +59,7 @@
private const val INTERRUPTING = 2
private const val INTERRUPTED = 3
-private class ThreadState(private val job: Job) : CompletionHandler {
+private class ThreadState(private val job: Job) : InternalCompletionHandler {
/*
=== States ===
diff --git a/kotlinx-coroutines-core/jvm/src/Runnable.kt b/kotlinx-coroutines-core/jvm/src/Runnable.kt
index 844f9fc..73440ee 100644
--- a/kotlinx-coroutines-core/jvm/src/Runnable.kt
+++ b/kotlinx-coroutines-core/jvm/src/Runnable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt b/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt
index 6a00f45..5f81dd3 100644
--- a/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt
+++ b/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.scheduling.*
diff --git a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt
index bfe9995..15b2780 100644
--- a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt
+++ b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt b/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt
index 0828c0b..c385b70 100644
--- a/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt
+++ b/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("ThreadPoolDispatcherKt")
package kotlinx.coroutines
@@ -9,30 +5,6 @@
import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicInteger
-/**
- * Creates a coroutine execution context with the fixed-size thread-pool and built-in [yield] support.
- * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its threads).
- * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
- *
- * If the resulting dispatcher is [closed][ExecutorCoroutineDispatcher.close] and
- * attempt to submit a continuation task is made,
- * then the [Job] of the affected task is [cancelled][Job.cancel] and the task is submitted to the
- * [Dispatchers.IO], so that the affected coroutine can cleanup its resources and promptly complete.
- *
- * This is a **delicate** API. The result of this method is a closeable resource with the
- * associated native resources (threads). It should not be allocated in place,
- * should be closed at the end of its lifecycle, and has non-trivial memory and CPU footprint.
- * If you do not need a separate thread-pool, but only have to limit effective parallelism of the dispatcher,
- * it is recommended to use [CoroutineDispatcher.limitedParallelism] instead.
- *
- * If you need a completely separate thread-pool with scheduling policy that is based on the standard
- * JDK executors, use the following expression:
- * `Executors.newFixedThreadPool().asCoroutineDispatcher()`.
- * See [Executor.asCoroutineDispatcher] for details.
- *
- * @param nThreads the number of threads.
- * @param name the base name of the created threads.
- */
@DelicateCoroutinesApi
public actual fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher {
require(nThreads >= 1) { "Expected at least one thread, but $nThreads specified" }
diff --git a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt
index e8a9152..62eb19e 100644
--- a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt
+++ b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
import kotlinx.coroutines.*
@@ -178,6 +174,7 @@
return super.trySend(element)
}
+ @Suppress("MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION_WARNING") // do not remove the MULTIPLE_DEFAULTS suppression: required in K2
override fun close(cause: Throwable?): Boolean {
// close the channel _first_
val closed = super.close(cause)
diff --git a/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt b/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt
index 6c23982..c07e68d 100644
--- a/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt
+++ b/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt b/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt
index fb5c5b1..4f8abb8 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
import android.annotation.*
diff --git a/kotlinx-coroutines-core/jvm/src/debug/CoroutineDebugging.kt b/kotlinx-coroutines-core/jvm/src/debug/CoroutineDebugging.kt
index 49a794e..7029994 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/CoroutineDebugging.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/CoroutineDebugging.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
/* This package name is like this so that
1) the artificial stack frames look pretty, and
2) the IDE reliably navigates to this file. */
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/AgentInstallationType.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/AgentInstallationType.kt
index 0e9b26c..15eead7 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/AgentInstallationType.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/AgentInstallationType.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.internal
/**
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt
index b02eac6..f28d9a6 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt
index 56ca6c5..91a4cad 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.internal
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt
index 261d247..66bb904 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.internal
import java.lang.ref.*
@@ -53,9 +49,9 @@
* How many consecutive unmatched 'updateState(RESUMED)' this object has received.
* It can be `> 1` in two cases:
*
- * * The coroutine is finishing and its state is being unrolled in BaseContinuationImpl, see comment to DebugProbesImpl#callerInfoCache
+ * - The coroutine is finishing and its state is being unrolled in BaseContinuationImpl, see comment to DebugProbesImpl#callerInfoCache
* Such resumes are not expected to be matched and are ignored.
- * * We encountered suspend-resume race explained above, and we do wait for a match.
+ * - We encountered suspend-resume race explained above, and we do wait for a match.
*/
private var unmatchedResume = 0
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbes.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbes.kt
index 8dc5b7c..672990e 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbes.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbes.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("unused")
package kotlinx.coroutines.debug.internal
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt
index c11028c..2ab03a7 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.internal
import kotlinx.atomicfu.*
@@ -35,13 +31,16 @@
* This internal method is used by the IDEA debugger under the JVM name
* "isInstalled$kotlinx_coroutines_debug" and must be kept binary-compatible, see KTIJ-24102
*/
- val isInstalled: Boolean get() = installations.value > 0
+ val isInstalled: Boolean
+ // IDEA depended on "internal val isInstalled", thus the mangling. Public + JvmName in order to make this getter part of the ABI
+ @JvmName("isInstalled\$kotlinx_coroutines_debug")
+ get() = installations.value > 0
// To sort coroutines by creation order, used as a unique id
private val sequenceNumber = atomic(0L)
internal var sanitizeStackTraces: Boolean = true
- internal var enableCreationStackTraces: Boolean = true
+ internal var enableCreationStackTraces: Boolean = false
public var ignoreCoroutinesWithEmptyContext: Boolean = true
/*
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt
index 0b63cd2..342c123 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNUSED")
package kotlinx.coroutines.debug.internal
diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt
index 6cdd5f2..d780545 100644
--- a/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt
+++ b/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.internal
import kotlin.coroutines.jvm.internal.*
diff --git a/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt
index cfe5b69..e6f3453 100644
--- a/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt
+++ b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt
@@ -1,14 +1,10 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
internal actual class AbortFlowException actual constructor(
- @JvmField @Transient actual val owner: FlowCollector<*>
+ @JvmField @Transient actual val owner: Any
) : CancellationException("Flow was aborted, no more elements needed") {
override fun fillInStackTrace(): Throwable {
diff --git a/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt
index cad3f1a..a02feee 100644
--- a/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt
+++ b/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
@@ -13,9 +9,25 @@
@Suppress("UNCHECKED_CAST")
private val emitFun =
FlowCollector<Any?>::emit as Function3<FlowCollector<Any?>, Any?, Continuation<Unit>, Any?>
-/*
- * Implementor of ContinuationImpl (that will be preserved as ABI nearly forever)
- * in order to properly control 'intercepted()' lifecycle.
+
+/**
+ * A safe collector is an instance of [FlowCollector] that ensures that neither context preservation
+ * nor exception transparency invariants are broken. Instances of [SafeCollector] are used in flow
+ * operators that provide raw access to the [FlowCollector] e.g. [Flow.transform].
+ * Mechanically, each [emit] call captures [currentCoroutineContext], ensures it is not different from the
+ * previously caught one and proceeds further. If an exception is thrown from the downstream,
+ * it is caught, and any further attempts to [emit] lead to the [IllegalStateException].
+ *
+ * ### Performance hacks
+ *
+ * Implementor of [ContinuationImpl] (that will be preserved as ABI nearly forever)
+ * in order to properly control `intercepted()` lifecycle.
+ * The safe collector implements [ContinuationImpl] to pretend it *is* a state-machine of its own `emit` method.
+ * It is [ContinuationImpl] and not any other [Continuation] subclass because only [ContinuationImpl] supports `intercepted()` caching.
+ * This is the most performance-sensitive place in the overall flow pipeline, because otherwise safe collector is forced to allocate
+ * a state machine on each element being emitted for each intermediate stage where the safe collector is present.
+ *
+ * See a comment to [emit] for the explanation of what and how is being optimized.
*/
@Suppress("CANNOT_OVERRIDE_INVISIBLE_MEMBER", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNCHECKED_CAST")
internal actual class SafeCollector<T> actual constructor(
@@ -23,7 +35,7 @@
@JvmField internal actual val collectContext: CoroutineContext
) : FlowCollector<T>, ContinuationImpl(NoOpContinuation, EmptyCoroutineContext), CoroutineStackFrame {
- override val callerFrame: CoroutineStackFrame? get() = completion as? CoroutineStackFrame
+ override val callerFrame: CoroutineStackFrame? get() = completion_ as? CoroutineStackFrame
override fun getStackTraceElement(): StackTraceElement? = null
@@ -32,20 +44,20 @@
// Either context of the last emission or wrapper 'DownstreamExceptionContext'
private var lastEmissionContext: CoroutineContext? = null
- // Completion if we are currently suspended or within completion body or null otherwise
- private var completion: Continuation<Unit>? = null
+ // Completion if we are currently suspended or within completion_ body or null otherwise
+ private var completion_: Continuation<Unit>? = null
/*
* This property is accessed in two places:
- * * ContinuationImpl invokes this in its `releaseIntercepted` as `context[ContinuationInterceptor]!!`
- * * When we are within a callee, it is used to create its continuation object with this collector as completion
+ * - ContinuationImpl invokes this in its `releaseIntercepted` as `context[ContinuationInterceptor]!!`
+ * - When we are within a callee, it is used to create its continuation object with this collector as completion_
*/
override val context: CoroutineContext
get() = lastEmissionContext ?: EmptyCoroutineContext
override fun invokeSuspend(result: Result<Any?>): Any {
result.onFailure { lastEmissionContext = DownstreamExceptionContext(it, context) }
- completion?.resumeWith(result as Result<Unit>)
+ completion_?.resumeWith(result as Result<Unit>)
return COROUTINE_SUSPENDED
}
@@ -56,11 +68,15 @@
/**
* This is a crafty implementation of state-machine reusing.
- * First it checks that it is not used concurrently (which we explicitly prohibit) and
- * then just cache an instance of the completion in order to avoid extra allocation on each emit,
+ *
+ * First it checks that it is not used concurrently (which we explicitly prohibit), and
+ * then just caches an instance of the completion_ in order to avoid extra allocation on each emit,
* making it effectively garbage-free on its hot-path.
+ *
+ * See `emit` overload.
*/
- override suspend fun emit(value: T) {
+ actual override suspend fun emit(value: T) {
+ // NB: it is a tail-call, so we are sure `uCont` is the completion of the emit's **caller**.
return suspendCoroutineUninterceptedOrReturn sc@{ uCont ->
try {
emit(uCont, value)
@@ -74,23 +90,33 @@
}
}
+ /**
+ * Here we use the following trick:
+ * - Perform all the required checks
+ * - Having a non-intercepted, non-cancellable caller's `uCont`, we leverage our implementation knowledge
+ * and invoke `collector.emit(T)` as `collector.emit(value: T, completion: Continuation), passing `this`
+ * as the completion. We also setup `this` state, so if the `completion.resume` is invoked, we are
+ * invoking `uCont.resume` properly in accordance with `ContinuationImpl`/`BaseContinuationImpl` internal invariants.
+ *
+ * Note that in such scenarios, `collector.emit` completion is the current instance of SafeCollector and thus is reused.
+ */
private fun emit(uCont: Continuation<Unit>, value: T): Any? {
val currentContext = uCont.context
currentContext.ensureActive()
- // This check is triggered once per flow on happy path.
+ // This check is triggered once per flow on a happy path.
val previousContext = lastEmissionContext
if (previousContext !== currentContext) {
checkContext(currentContext, previousContext, value)
lastEmissionContext = currentContext
}
- completion = uCont
+ completion_ = uCont
val result = emitFun(collector as FlowCollector<Any?>, value, this as Continuation<Unit>)
/*
* If the callee hasn't suspended, that means that it won't (it's forbidden) call 'resumeWith` (-> `invokeSuspend`)
* and we don't have to retain a strong reference to it to avoid memory leaks.
*/
if (result != COROUTINE_SUSPENDED) {
- completion = null
+ completion_ = null
}
return result
}
diff --git a/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt
index 5df79b8..4e8eaf2 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import java.lang.reflect.*
@@ -14,6 +10,9 @@
internal actual inline fun <T> ReentrantLock.withLock(action: () -> T) = this.withLockJvm(action)
+@Suppress("ACTUAL_WITHOUT_EXPECT") // Visibility
+internal actual typealias WorkaroundAtomicReference<T> = java.util.concurrent.atomic.AtomicReference<T>
+
@Suppress("NOTHING_TO_INLINE") // So that R8 can completely remove ConcurrentKt class
internal actual inline fun <E> identitySet(expectedSize: Int): MutableSet<E> =
Collections.newSetFromMap(IdentityHashMap(expectedSize))
diff --git a/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt
index 7f11898..0014e17 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import java.util.*
diff --git a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstructor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstructor.kt
index 4f425a3..581af4b 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstructor.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstructor.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import android.annotation.SuppressLint
diff --git a/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt b/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt
index e93de2a..6267581 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import java.io.*
diff --git a/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt b/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt
index 41707f7..16b4a48 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
@Suppress("ACTUAL_WITHOUT_EXPECT") // Not the same name to WA the bug in the compiler
diff --git a/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt b/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt
index 9dda30b..febc5b9 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
@Suppress("ACTUAL_WITHOUT_EXPECT")
diff --git a/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt
index 0c55d92..3eaf723 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt
index 48e01fb..53713be 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package kotlinx.coroutines.internal
diff --git a/kotlinx-coroutines-core/jvm/src/internal/ResizableAtomicArray.kt b/kotlinx-coroutines-core/jvm/src/internal/ResizableAtomicArray.kt
index 6c98a9d..9cc2983 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/ResizableAtomicArray.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/ResizableAtomicArray.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import java.util.concurrent.atomic.*
diff --git a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
index afc9989..619c61a 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNCHECKED_CAST")
package kotlinx.coroutines.internal
@@ -157,10 +153,12 @@
}
}
+@PublishedApi
@Suppress("NOTHING_TO_INLINE") // Inline for better R8 optimizations
internal actual inline fun <E : Throwable> unwrap(exception: E): E =
if (!RECOVER_STACK_TRACES) exception else unwrapImpl(exception)
+@PublishedApi
internal fun <E : Throwable> unwrapImpl(exception: E): E {
val cause = exception.cause
// Fast-path to avoid array cloning
diff --git a/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt b/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt
index 5b12faa..47273d6 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt
index 7385372..837c2ff 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmName("SystemPropsKt")
@file:JvmMultifileClass
diff --git a/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt
index 8536cef..8f21b13 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt
index 0924a5b..d5f7156 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import java.lang.ThreadLocal
diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt
index 5ca3de5..4d6dce3 100644
--- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt
+++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
import kotlinx.atomicfu.*
@@ -12,15 +8,14 @@
import java.util.concurrent.locks.*
import kotlin.jvm.internal.Ref.ObjectRef
import kotlin.math.*
-import kotlin.random.*
/**
* Coroutine scheduler (pool of shared threads) which primary target is to distribute dispatched coroutines
* over worker threads, including both CPU-intensive and blocking tasks, in the most efficient manner.
*
* Current scheduler implementation has two optimization targets:
- * * Efficiency in the face of communication patterns (e.g. actors communicating via channel)
- * * Dynamic resizing to support blocking calls without re-dispatching coroutine to separate "blocking" thread pool.
+ * - Efficiency in the face of communication patterns (e.g. actors communicating via channel)
+ * - Dynamic resizing to support blocking calls without re-dispatching coroutine to separate "blocking" thread pool.
*
* ### Structural overview
*
@@ -112,6 +107,7 @@
@JvmField
val globalCpuQueue = GlobalQueue()
+
@JvmField
val globalBlockingQueue = GlobalQueue()
@@ -349,12 +345,13 @@
for (i in 1..created) {
val worker = workers[i]!!
if (worker !== currentWorker) {
- while (worker.isAlive) {
+ // Note: this is java.lang.Thread.getState() of type java.lang.Thread.State
+ while (worker.getState() != Thread.State.TERMINATED) {
LockSupport.unpark(worker)
worker.join(timeout)
}
- val state = worker.state
- assert { state === WorkerState.TERMINATED } // Expected TERMINATED state
+ // Note: this is CoroutineScheduler.Worker.state of type CoroutineScheduler.WorkerState
+ assert { worker.state === WorkerState.TERMINATED } // Expected TERMINATED state
worker.localQueue.offloadAllWorkTo(globalBlockingQueue) // Doesn't actually matter which queue to use
}
}
@@ -386,8 +383,8 @@
* If `true`, then the task will be dispatched in a FIFO manner and no additional workers will be requested,
* but only if the current thread is a corresponding worker thread.
* Note that caller cannot be ensured that it is being executed on worker thread for the following reasons:
- * * [CoroutineStart.UNDISPATCHED]
- * * Concurrent [close] that effectively shutdowns the worker thread
+ * - [CoroutineStart.UNDISPATCHED]
+ * - Concurrent [close] that effectively shutdowns the worker thread
*/
fun dispatch(block: Runnable, taskContext: TaskContext = NonBlockingContext, tailDispatch: Boolean = false) {
trackTask() // this is needed for virtual time support
@@ -547,36 +544,39 @@
++blockingWorkers
queueSizes += queueSize.toString() + "b" // Blocking
}
+
WorkerState.CPU_ACQUIRED -> {
++cpuWorkers
queueSizes += queueSize.toString() + "c" // CPU
}
+
WorkerState.DORMANT -> {
++dormant
if (queueSize > 0) queueSizes += queueSize.toString() + "d" // Retiring
}
+
WorkerState.TERMINATED -> ++terminated
}
}
val state = controlState.value
return "$schedulerName@$hexAddress[" +
- "Pool Size {" +
- "core = $corePoolSize, " +
- "max = $maxPoolSize}, " +
- "Worker States {" +
- "CPU = $cpuWorkers, " +
- "blocking = $blockingWorkers, " +
- "parked = $parkedWorkers, " +
- "dormant = $dormant, " +
- "terminated = $terminated}, " +
- "running workers queues = $queueSizes, "+
- "global CPU queue size = ${globalCpuQueue.size}, " +
- "global blocking queue size = ${globalBlockingQueue.size}, " +
- "Control State {" +
- "created workers= ${createdWorkers(state)}, " +
- "blocking tasks = ${blockingTasks(state)}, " +
- "CPUs acquired = ${corePoolSize - availableCpuPermits(state)}" +
- "}]"
+ "Pool Size {" +
+ "core = $corePoolSize, " +
+ "max = $maxPoolSize}, " +
+ "Worker States {" +
+ "CPU = $cpuWorkers, " +
+ "blocking = $blockingWorkers, " +
+ "parked = $parkedWorkers, " +
+ "dormant = $dormant, " +
+ "terminated = $terminated}, " +
+ "running workers queues = $queueSizes, " +
+ "global CPU queue size = ${globalCpuQueue.size}, " +
+ "global blocking queue size = ${globalBlockingQueue.size}, " +
+ "Control State {" +
+ "created workers= ${createdWorkers(state)}, " +
+ "blocking tasks = ${blockingTasks(state)}, " +
+ "CPUs acquired = ${corePoolSize - availableCpuPermits(state)}" +
+ "}]"
}
fun runSafely(task: Task) {
@@ -593,6 +593,13 @@
internal inner class Worker private constructor() : Thread() {
init {
isDaemon = true
+ /*
+ * `Dispatchers.Default` is used as *the* dispatcher in the containerized environments,
+ * isolated by their own classloaders. Workers are populated lazily, thus we are inheriting
+ * `Dispatchers.Default` context class loader here instead of using parent' thread one
+ * in order not to accidentally capture temporary application classloader.
+ */
+ contextClassLoader = [email protected]
}
// guarded by scheduler lock, index in workers array, 0 when not in array (terminated)
@@ -650,11 +657,21 @@
var nextParkedWorker: Any? = NOT_IN_STACK
/*
- * The delay until at least one task in other worker queues will become stealable.
+ * The delay until at least one task in other worker queues will become stealable.
*/
private var minDelayUntilStealableTaskNs = 0L
- private var rngState = Random.nextInt()
+ /**
+ * The state of embedded Marsaglia xorshift random number generator, used for work-stealing purposes.
+ * It is initialized with a seed.
+ */
+ private var rngState: Int = run {
+ // This could've been Random.nextInt(), but we are shaving an extra initialization cost, see #4051
+ val seed = System.nanoTime().toInt()
+ // rngState shouldn't be zero, as required for the xorshift algorithm
+ if (seed != 0) return@run seed
+ 42
+ }
/**
* Tries to acquire CPU token if worker doesn't have one
@@ -666,6 +683,7 @@
state = WorkerState.CPU_ACQUIRED
true
}
+
else -> false
}
@@ -673,7 +691,7 @@
* Releases CPU token if worker has any and changes state to [newState].
* Returns `true` if CPU permit was returned to the pool
*/
- fun tryReleaseCpu(newState: WorkerState): Boolean {
+ fun tryReleaseCpu(newState: WorkerState): Boolean {
val previousState = state
val hadCpu = previousState == WorkerState.CPU_ACQUIRED
if (hadCpu) releaseCpuPermit()
@@ -739,7 +757,7 @@
*/
fun runSingleTask(): Long {
val stateSnapshot = state
- val isCpuThread = state == WorkerState.CPU_ACQUIRED
+ val isCpuThread = state == WorkerState.CPU_ACQUIRED
val task = if (isCpuThread) {
findCpuTask()
} else {
@@ -751,7 +769,7 @@
}
runSafely(task)
if (!isCpuThread) decrementBlockingTasks()
- assert { state == stateSnapshot}
+ assert { state == stateSnapshot }
return 0L
}
@@ -913,8 +931,8 @@
if (tryAcquireCpuPermit()) return findAnyTask(mayHaveLocalTasks)
/*
* If we can't acquire a CPU permit, attempt to find blocking task:
- * * Check if our queue has one (maybe mixed in with CPU tasks)
- * * Poll global and try steal
+ * - Check if our queue has one (maybe mixed in with CPU tasks)
+ * - Poll global and try steal
*/
return findBlockingTask()
}
diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Deprecated.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Deprecated.kt
index e5defba..2fd3173 100644
--- a/kotlinx-coroutines-core/jvm/src/scheduling/Deprecated.kt
+++ b/kotlinx-coroutines-core/jvm/src/scheduling/Deprecated.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("unused")
package kotlinx.coroutines.scheduling
diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt
index f91125a..f3d66cd 100644
--- a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt
+++ b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt
index 5249edf..eefccd5 100644
--- a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt
+++ b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt b/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt
index a185410..a048d75 100644
--- a/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt
+++ b/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
import kotlinx.atomicfu.*
@@ -117,9 +113,9 @@
* or positive value of how many nanoseconds should pass until the head of this queue will be available to steal.
*
* [StealingMode] controls what tasks to steal:
- * * [STEAL_ANY] is default mode for scheduler, task from the head (in FIFO order) is stolen
- * * [STEAL_BLOCKING_ONLY] is mode for stealing *an arbitrary* blocking task, which is used by the scheduler when helping in Dispatchers.IO mode
- * * [STEAL_CPU_ONLY] is a kludge for `runSingleTaskFromCurrentSystemDispatcher`
+ * - [STEAL_ANY] is default mode for scheduler, task from the head (in FIFO order) is stolen
+ * - [STEAL_BLOCKING_ONLY] is mode for stealing *an arbitrary* blocking task, which is used by the scheduler when helping in Dispatchers.IO mode
+ * - [STEAL_CPU_ONLY] is a kludge for `runSingleTaskFromCurrentSystemDispatcher`
*/
fun trySteal(stealingMode: StealingMode, stolenTaskRef: ObjectRef<Task?>): Long {
val task = when (stealingMode) {
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferFromScope.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferFromScope.txt
index aa5a6a1..de14e9d 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferFromScope.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferFromScope.txt
@@ -1,10 +1,10 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:109)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:167)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:162)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendFromScope$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:172)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:112)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:109)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithContextWrapped.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithContextWrapped.txt
index 4908d3b..1a153d3 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithContextWrapped.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithContextWrapped.txt
@@ -1,9 +1,9 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithContextWrapped$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:98)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:199)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:194)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithContextWrapped$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:100)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithContextWrapped$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:98)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithCurrentContext.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithCurrentContext.txt
index 1eb464c..5bc7124 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithCurrentContext.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithCurrentContext.txt
@@ -1,9 +1,9 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithCurrentContext$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:86)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:210)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:205)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithCurrentContext$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:89)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithCurrentContext$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:86)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromChannel.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromChannel.txt
index da3558b..e02f709 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromChannel.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromChannel.txt
@@ -1,9 +1,9 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.channels.BufferedChannel.receive$suspendImpl(BufferedChannel.kt)
at kotlinx.coroutines.channels.BufferedChannel.receive(BufferedChannel.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelReceive(StackTraceRecoveryChannelsTest.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.access$channelReceive(StackTraceRecoveryChannelsTest.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$channelReceive$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromChannel$1$job$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromClosedChannel.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromClosedChannel.txt
index 3f392cd..d486300 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromClosedChannel.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testReceiveFromClosedChannel.txt
@@ -1,8 +1,8 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:110)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelReceive(StackTraceRecoveryChannelsTest.kt:116)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:111)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:110)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendFromScope.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendFromScope.txt
index 49c3628..bc0f9cd 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendFromScope.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendFromScope.txt
@@ -1,10 +1,10 @@
-kotlinx.coroutines.RecoverableTestCancellationException
+kotlinx.coroutines.testing.RecoverableTestCancellationException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:136)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:167)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:162)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendFromScope$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:172)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendFromScope$1$deferred$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:126)
-Caused by: kotlinx.coroutines.RecoverableTestCancellationException
+Caused by: kotlinx.coroutines.testing.RecoverableTestCancellationException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:136)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToChannel.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToChannel.txt
index e40cc74..af6e564 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToChannel.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToChannel.txt
@@ -17,4 +17,4 @@
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
- at kotlinx.coroutines.TestBase.runTest(TestBase.kt)
+ at kotlinx.coroutines.testing.TestBase.runTest(TestBase.kt)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToClosedChannel.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToClosedChannel.txt
index f260959..cd20092 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToClosedChannel.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToClosedChannel.txt
@@ -1,8 +1,8 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:43)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelSend(StackTraceRecoveryChannelsTest.kt:74)
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:44)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:43)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcher.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcher.txt
index 0e75e64..3c7ee94 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcher.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcher.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:40)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
@@ -6,7 +6,7 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.doFastPath(StackTraceRecoveryResumeModeTest.kt:71)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:62)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:40)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:40)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcherSuspending.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcherSuspending.txt
index 0792646..100c8f0 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcherSuspending.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testEventLoopDispatcherSuspending.txt
@@ -1,10 +1,10 @@
-otlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:99)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$4.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:116)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.doSuspendingPath(StackTraceRecoveryResumeModeTest.kt:110)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeSuspending(StackTraceRecoveryResumeModeTest.kt:101)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcherSuspending$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:89)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:99)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContext.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContext.txt
index f3ca1fc..18d2293 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContext.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContext.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopChangedContext$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:54)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
@@ -7,7 +7,7 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:62)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopChangedContext$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:54)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopChangedContext$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:53)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopChangedContext$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:54)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContextSuspending.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContextSuspending.txt
index dbb574f..fb44df4 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContextSuspending.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopChangedContextSuspending.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:113)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$4.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:130)
@@ -6,6 +6,6 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeSuspending(StackTraceRecoveryResumeModeTest.kt:115)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopChangedContextSuspending$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:103)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopChangedContextSuspending$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:102)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:113)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcher.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcher.txt
index e17e2db..13b12c1 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcher.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcher.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopDispatcher$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:47)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
@@ -7,7 +7,7 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:62)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopDispatcher$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:47)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:46)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopDispatcher$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:47)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcherSuspending.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcherSuspending.txt
index 26e0359..2b30264 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcherSuspending.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedEventLoopDispatcherSuspending.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:113)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$4.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:130)
@@ -6,6 +6,6 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeSuspending(StackTraceRecoveryResumeModeTest.kt:115)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopDispatcherSuspending$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:96)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedEventLoopDispatcherSuspending$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:95)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:113)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfined.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfined.txt
index f247920..5740f12 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfined.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfined.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfined$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:27)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
@@ -7,7 +7,7 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:62)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfined$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:27)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfined$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:26)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfined$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:27)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContext.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContext.txt
index b7ae52c..a3bc4ed 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContext.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContext.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedChangedContext$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:34)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
@@ -7,7 +7,7 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:62)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedChangedContext$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:34)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedChangedContext$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:33)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedChangedContext$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:34)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContextSuspending.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContextSuspending.txt
index 241a3b2..ffbcd58 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContextSuspending.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedChangedContextSuspending.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:128)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$4.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:148)
@@ -6,6 +6,6 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeSuspending(StackTraceRecoveryResumeModeTest.kt:130)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedChangedContextSuspending$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:95)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedChangedContextSuspending$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:94)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:128)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedSuspending.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedSuspending.txt
index 4484c66..e115a69 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedSuspending.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testNestedUnconfinedSuspending.txt
@@ -1,4 +1,4 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:128)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$4.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:148)
@@ -6,6 +6,6 @@
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeSuspending(StackTraceRecoveryResumeModeTest.kt:130)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedSuspending$1$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:88)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testNestedUnconfinedSuspending$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:87)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:128)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfined.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfined.txt
index 9fc7167..2125245 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfined.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfined.txt
@@ -1,8 +1,8 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.channels.BufferedChannel.receive$suspendImpl(BufferedChannel.kt)
at kotlinx.coroutines.channels.BufferedChannel.receive(BufferedChannel.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.access$testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testUnconfined$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfinedSuspending.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfinedSuspending.txt
index fb742a3..1199fe6 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfinedSuspending.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/resume-mode/testUnconfinedSuspending.txt
@@ -1,9 +1,9 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:128)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.doSuspendingPath(StackTraceRecoveryResumeModeTest.kt:140)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeSuspending(StackTraceRecoveryResumeModeTest.kt:130)
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testUnconfinedSuspending$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:82)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testResumeModeSuspending$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:128)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectCompletedAwait.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectCompletedAwait.txt
index 2e86a7a..900cb6c 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectCompletedAwait.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectCompletedAwait.txt
@@ -1,7 +1,7 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoverySelectTest$testSelectCompletedAwait$1.invokeSuspend(StackTraceRecoverySelectTest.kt:40)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoverySelectTest$testSelectCompletedAwait$1.invokeSuspend(StackTraceRecoverySelectTest.kt:41)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoverySelectTest$testSelectCompletedAwait$1.invokeSuspend(StackTraceRecoverySelectTest.kt:40)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
diff --git a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectJoin.txt b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectJoin.txt
index 420aa7e..15a689b 100644
--- a/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectJoin.txt
+++ b/kotlinx-coroutines-core/jvm/test-resources/stacktraces/select/testSelectJoin.txt
@@ -1,8 +1,8 @@
-kotlinx.coroutines.RecoverableTestException
+kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoverySelectTest$doSelect$2$1.invokeSuspend(StackTraceRecoverySelectTest.kt)
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.selects.SelectImplementation.processResultAndInvokeBlockRecoveringException(Select.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoverySelectTest$testSelectJoin$1.invokeSuspend(StackTraceRecoverySelectTest.kt)
-Caused by: kotlinx.coroutines.RecoverableTestException
+Caused by: kotlinx.coroutines.testing.RecoverableTestException
at kotlinx.coroutines.exceptions.StackTraceRecoverySelectTest$doSelect$2$1.invokeSuspend(StackTraceRecoverySelectTest.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)
diff --git a/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt
index da73ca6..6287be0 100644
--- a/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.jetbrains.kotlinx.lincheck.*
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
import org.jetbrains.kotlinx.lincheck.strategy.stress.*
-import org.jetbrains.kotlinx.lincheck.verifier.*
import org.junit.*
abstract class AbstractLincheckTest {
@@ -16,16 +13,16 @@
@Test
fun modelCheckingTest() = ModelCheckingOptions()
- .iterations(if (isStressTest) 200 else 20)
- .invocationsPerIteration(if (isStressTest) 10_000 else 1_000)
+ .iterations(20 * stressTestMultiplierSqrt)
+ .invocationsPerIteration(1_000 * stressTestMultiplierSqrt)
.commonConfiguration()
.customize(isStressTest)
.check(this::class)
@Test
fun stressTest() = StressOptions()
- .iterations(if (isStressTest) 200 else 20)
- .invocationsPerIteration(if (isStressTest) 10_000 else 1_000)
+ .iterations(20 * stressTestMultiplierSqrt)
+ .invocationsPerIteration(1_000 * stressTestMultiplierSqrt)
.commonConfiguration()
.customize(isStressTest)
.check(this::class)
diff --git a/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt
index 59ff76a..05bc505 100644
--- a/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/AwaitJvmTest.kt b/kotlinx-coroutines-core/jvm/test/AwaitJvmTest.kt
index c6b57c8..e43611e 100644
--- a/kotlinx-coroutines-core/jvm/test/AwaitJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/AwaitJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
class AwaitJvmTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt b/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt
index 6b711db..8c84e7d 100644
--- a/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/CancellableContinuationJvmTest.kt b/kotlinx-coroutines-core/jvm/test/CancellableContinuationJvmTest.kt
index f1a957a..e53cd0c 100644
--- a/kotlinx-coroutines-core/jvm/test/CancellableContinuationJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/CancellableContinuationJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt
index b8bc3f0..fa6030d 100644
--- a/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import org.junit.*
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/CancelledAwaitStressTest.kt b/kotlinx-coroutines-core/jvm/test/CancelledAwaitStressTest.kt
index c7c2c04..5a85aeb 100644
--- a/kotlinx-coroutines-core/jvm/test/CancelledAwaitStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/CancelledAwaitStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
class CancelledAwaitStressTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/ConcurrentTestUtilities.kt b/kotlinx-coroutines-core/jvm/test/ConcurrentTestUtilities.kt
index 4ccb74b..6d6bc21 100644
--- a/kotlinx-coroutines-core/jvm/test/ConcurrentTestUtilities.kt
+++ b/kotlinx-coroutines-core/jvm/test/ConcurrentTestUtilities.kt
@@ -1,29 +1,5 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
-import kotlin.random.*
-
-actual fun randomWait() {
- val n = Random.nextInt(1000)
- if (n < 500) return // no wait 50% of time
- repeat(n) {
- BlackHole.sink *= 3
- }
- if (n > 900) Thread.yield()
-}
-
-private object BlackHole {
- @Volatile
- var sink = 1
-}
-
-@Suppress("ACTUAL_WITHOUT_EXPECT")
-internal actual typealias SuppressSupportingThrowable = Throwable
-
-@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "unused")
-actual fun Throwable.printStackTrace() = printStackTrace()
+actual inline fun yieldThread() { Thread.yield() }
actual fun currentThreadName(): String = Thread.currentThread().name
diff --git a/kotlinx-coroutines-core/jvm/test/CoroutinesJvmTest.kt b/kotlinx-coroutines-core/jvm/test/CoroutinesJvmTest.kt
index e890ea2..416226c 100644
--- a/kotlinx-coroutines-core/jvm/test/CoroutinesJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/CoroutinesJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class CoroutinesJvmTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/DebugThreadNameTest.kt b/kotlinx-coroutines-core/jvm/test/DebugThreadNameTest.kt
index 9d68396..4505f39 100644
--- a/kotlinx-coroutines-core/jvm/test/DebugThreadNameTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/DebugThreadNameTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class DebugThreadNameTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/DefaultExecutorStressTest.kt b/kotlinx-coroutines-core/jvm/test/DefaultExecutorStressTest.kt
index bc2de8c..58b8024 100644
--- a/kotlinx-coroutines-core/jvm/test/DefaultExecutorStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/DefaultExecutorStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt b/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt
index 2906c31..710f773 100644
--- a/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import java.util.concurrent.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt b/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt
index 303e8cc..8b6c219 100644
--- a/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/DispatchersToStringTest.kt b/kotlinx-coroutines-core/jvm/test/DispatchersToStringTest.kt
index 7adaa2a..9bd7e8c 100644
--- a/kotlinx-coroutines-core/jvm/test/DispatchersToStringTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/DispatchersToStringTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/EventLoopsTest.kt b/kotlinx-coroutines-core/jvm/test/EventLoopsTest.kt
index 835e6b4..9ab52fd 100644
--- a/kotlinx-coroutines-core/jvm/test/EventLoopsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/EventLoopsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.channels.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/ExecutorAsCoroutineDispatcherDelayTest.kt b/kotlinx-coroutines-core/jvm/test/ExecutorAsCoroutineDispatcherDelayTest.kt
index dbe9cb3..072ae28 100644
--- a/kotlinx-coroutines-core/jvm/test/ExecutorAsCoroutineDispatcherDelayTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ExecutorAsCoroutineDispatcherDelayTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import java.lang.Runnable
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
index 6e5b18f..1ad2f8a 100644
--- a/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import java.util.concurrent.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/FailFastOnStartTest.kt b/kotlinx-coroutines-core/jvm/test/FailFastOnStartTest.kt
index 8a7878c..ae3c503 100644
--- a/kotlinx-coroutines-core/jvm/test/FailFastOnStartTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/FailFastOnStartTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("DeferredResultUnused")
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt b/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt
index 04b0ba5..144e4e9 100644
--- a/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/IODispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/IODispatcherTest.kt
index fe3c71a..db81f12 100644
--- a/kotlinx-coroutines-core/jvm/test/IODispatcherTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/IODispatcherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/IntellijIdeaDebuggerEvaluatorCompatibilityTest.kt b/kotlinx-coroutines-core/jvm/test/IntellijIdeaDebuggerEvaluatorCompatibilityTest.kt
index 6bbfdd1..56f2f3b 100644
--- a/kotlinx-coroutines-core/jvm/test/IntellijIdeaDebuggerEvaluatorCompatibilityTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/IntellijIdeaDebuggerEvaluatorCompatibilityTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/JobActivationStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobActivationStressTest.kt
index 8341df9..c8bfbf0 100644
--- a/kotlinx-coroutines-core/jvm/test/JobActivationStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JobActivationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.*
@@ -59,13 +56,13 @@
joinAll(d, canceller, starter)
if (wasStarted) {
val exception = d.getCompletionExceptionOrNull()
- assertTrue(exception is TestException, "exception=$exception")
+ assertIs<TestException>(exception, "exception=$exception")
val cause = synchronized(causeHolder) {
while (causeHolder.cause == null) (causeHolder as Object).wait()
causeHolder.cause
}
- assertTrue(cause is TestException, "cause=$cause")
+ assertIs<TestException>(cause, "cause=$cause")
}
}
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/jvm/test/JobCancellationExceptionSerializerTest.kt b/kotlinx-coroutines-core/jvm/test/JobCancellationExceptionSerializerTest.kt
index c909f27..c063e94 100644
--- a/kotlinx-coroutines-core/jvm/test/JobCancellationExceptionSerializerTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JobCancellationExceptionSerializerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import java.io.*
diff --git a/kotlinx-coroutines-core/jvm/test/JobChildStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobChildStressTest.kt
index 107cc52..3ac1967 100644
--- a/kotlinx-coroutines-core/jvm/test/JobChildStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JobChildStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.*
@@ -53,8 +50,8 @@
assertNull(unhandledException)
if (wasLaunched) {
val exception = parent.getCompletionExceptionOrNull()
- assertTrue(exception is TestException, "exception=$exception")
+ assertIs<TestException>(exception, "exception=$exception")
}
}
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/jvm/test/JobDisposeStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobDisposeStressTest.kt
index 3a074f1..22b5d59 100644
--- a/kotlinx-coroutines-core/jvm/test/JobDisposeStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JobDisposeStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.concurrent.thread
diff --git a/kotlinx-coroutines-core/jvm/test/JobHandlersUpgradeStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobHandlersUpgradeStressTest.kt
index 852aa2a..dc2314b 100644
--- a/kotlinx-coroutines-core/jvm/test/JobHandlersUpgradeStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JobHandlersUpgradeStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import java.util.*
import java.util.concurrent.*
@@ -29,7 +26,7 @@
@Volatile
private var job: Job? = null
- class State {
+ internal class State {
val state = atomic(0)
}
diff --git a/kotlinx-coroutines-core/jvm/test/JobStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobStressTest.kt
index 2decb3d..cb0274e 100644
--- a/kotlinx-coroutines-core/jvm/test/JobStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JobStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class JobStressTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/JoinStressTest.kt b/kotlinx-coroutines-core/jvm/test/JoinStressTest.kt
index 6d47418..6c3190d 100644
--- a/kotlinx-coroutines-core/jvm/test/JoinStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/JoinStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/LimitedParallelismStressTest.kt b/kotlinx-coroutines-core/jvm/test/LimitedParallelismStressTest.kt
index 58f2b6b..211ff04 100644
--- a/kotlinx-coroutines-core/jvm/test/LimitedParallelismStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/LimitedParallelismStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/LimitedParallelismUnhandledExceptionTest.kt b/kotlinx-coroutines-core/jvm/test/LimitedParallelismUnhandledExceptionTest.kt
index 8d48aa4..e952554 100644
--- a/kotlinx-coroutines-core/jvm/test/LimitedParallelismUnhandledExceptionTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/LimitedParallelismUnhandledExceptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import java.util.concurrent.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/MemoryFootprintTest.kt b/kotlinx-coroutines-core/jvm/test/MemoryFootprintTest.kt
index be467cc..8f78a92 100644
--- a/kotlinx-coroutines-core/jvm/test/MemoryFootprintTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/MemoryFootprintTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import org.openjdk.jol.info.ClassLayout
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/MutexCancellationStressTest.kt b/kotlinx-coroutines-core/jvm/test/MutexCancellationStressTest.kt
index 20798b8..dc096fe 100644
--- a/kotlinx-coroutines-core/jvm/test/MutexCancellationStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/MutexCancellationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.internal.*
import kotlinx.coroutines.selects.*
import kotlinx.coroutines.sync.*
diff --git a/kotlinx-coroutines-core/jvm/test/NoParamAssertionsTest.kt b/kotlinx-coroutines-core/jvm/test/NoParamAssertionsTest.kt
index 5e1c462..40b6144 100644
--- a/kotlinx-coroutines-core/jvm/test/NoParamAssertionsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/NoParamAssertionsTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt b/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt
index 7f6d6b6..770a854 100644
--- a/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/RejectedExecutionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.internal.*
import kotlinx.coroutines.scheduling.*
diff --git a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationInvariantStressTest.kt b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationInvariantStressTest.kt
index 4d8116c..ef0d146 100644
--- a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationInvariantStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationInvariantStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicReference
diff --git a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationLeakStressTest.kt b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationLeakStressTest.kt
index 8a20e08..b2ed34c 100644
--- a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationLeakStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationLeakStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt
index 06839f4..d9f455a 100644
--- a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/ReusableContinuationStressTest.kt b/kotlinx-coroutines-core/jvm/test/ReusableContinuationStressTest.kt
index a256815..489ecc3 100644
--- a/kotlinx-coroutines-core/jvm/test/ReusableContinuationStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ReusableContinuationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.flow.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/RunBlockingJvmTest.kt b/kotlinx-coroutines-core/jvm/test/RunBlockingJvmTest.kt
index 057a8bb..cc2291e 100644
--- a/kotlinx-coroutines-core/jvm/test/RunBlockingJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/RunBlockingJvmTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
class RunBlockingJvmTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt b/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt
index 701b958..b42bdad 100644
--- a/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.atomic.*
diff --git a/kotlinx-coroutines-core/jvm/test/RunInterruptibleTest.kt b/kotlinx-coroutines-core/jvm/test/RunInterruptibleTest.kt
index 49c93c7..bf194c0 100644
--- a/kotlinx-coroutines-core/jvm/test/RunInterruptibleTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/RunInterruptibleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import java.io.*
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt
deleted file mode 100644
index f9e5466..0000000
--- a/kotlinx-coroutines-core/jvm/test/TestBase.kt
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlinx.coroutines.internal.*
-import kotlinx.coroutines.scheduling.*
-import org.junit.*
-import java.io.*
-import java.util.*
-import java.util.concurrent.atomic.*
-import kotlin.coroutines.*
-import kotlin.test.*
-
-private val VERBOSE = systemProp("test.verbose", false)
-
-/**
- * Is `true` when running in a nightly stress test mode.
- */
-public actual val isStressTest = System.getProperty("stressTest")?.toBoolean() ?: false
-
-public actual val stressTestMultiplierSqrt = if (isStressTest) 5 else 1
-
-private const val SHUTDOWN_TIMEOUT = 1_000L // 1s at most to wait per thread
-
-public actual val isNative = false
-
-/**
- * Multiply various constants in stress tests by this factor, so that they run longer during nightly stress test.
- */
-public actual val stressTestMultiplier = stressTestMultiplierSqrt * stressTestMultiplierSqrt
-
-
-@Suppress("ACTUAL_WITHOUT_EXPECT")
-public actual typealias TestResult = Unit
-
-/**
- * Base class for tests, so that tests for predictable scheduling of actions in multiple coroutines sharing a single
- * thread can be written. Use it like this:
- *
- * ```
- * class MyTest : TestBase() {
- * @Test
- * fun testSomething() = runBlocking { // run in the context of the main thread
- * expect(1) // initiate action counter
- * launch { // use the context of the main thread
- * expect(3) // the body of this coroutine in going to be executed in the 3rd step
- * }
- * expect(2) // launch just scheduled coroutine for execution later, so this line is executed second
- * yield() // yield main thread to the launched job
- * finish(4) // fourth step is the last one. `finish` must be invoked or test fails
- * }
- * }
- * ```
- */
-public actual open class TestBase(private var disableOutCheck: Boolean) {
-
- actual constructor(): this(false)
-
- public actual val isBoundByJsTestTimeout = false
- private var actionIndex = AtomicInteger()
- private var finished = AtomicBoolean()
- private var error = AtomicReference<Throwable>()
-
- // Shutdown sequence
- private lateinit var threadsBefore: Set<Thread>
- private val uncaughtExceptions = Collections.synchronizedList(ArrayList<Throwable>())
- private var originalUncaughtExceptionHandler: Thread.UncaughtExceptionHandler? = null
- /*
- * System.out that we redefine in order to catch any debugging/diagnostics
- * 'println' from main source set.
- * NB: We do rely on the name 'previousOut' in the FieldWalker in order to skip its
- * processing
- */
- private lateinit var previousOut: PrintStream
-
- /**
- * Throws [IllegalStateException] like `error` in stdlib, but also ensures that the test will not
- * complete successfully even if this exception is consumed somewhere in the test.
- */
- @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
- public actual fun error(message: Any, cause: Throwable? = null): Nothing {
- throw makeError(message, cause)
- }
-
- public fun hasError() = error.get() != null
-
- private fun makeError(message: Any, cause: Throwable? = null): IllegalStateException =
- IllegalStateException(message.toString(), cause).also {
- setError(it)
- }
-
- private fun setError(exception: Throwable) {
- error.compareAndSet(null, exception)
- }
-
- private fun printError(message: String, cause: Throwable) {
- setError(cause)
- System.err.println("$message: $cause")
- cause.printStackTrace(System.err)
- System.err.println("--- Detected at ---")
- Throwable().printStackTrace(System.err)
- }
-
- /**
- * Throws [IllegalStateException] when `value` is false like `check` in stdlib, but also ensures that the
- * test will not complete successfully even if this exception is consumed somewhere in the test.
- */
- public inline fun check(value: Boolean, lazyMessage: () -> Any) {
- if (!value) error(lazyMessage())
- }
-
- /**
- * Asserts that this invocation is `index`-th in the execution sequence (counting from one).
- */
- public actual fun expect(index: Int) {
- val wasIndex = actionIndex.incrementAndGet()
- if (VERBOSE) println("expect($index), wasIndex=$wasIndex")
- check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" }
- }
-
- /**
- * Asserts that this line is never executed.
- */
- public actual fun expectUnreached() {
- error("Should not be reached, current action index is ${actionIndex.get()}")
- }
-
- /**
- * Asserts that this is the last action in the test. It must be invoked by any test that used [expect].
- */
- public actual fun finish(index: Int) {
- expect(index)
- check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" }
- }
-
- /**
- * Asserts that [finish] was invoked
- */
- public actual fun ensureFinished() {
- require(finished.get()) { "finish(...) should be caller prior to this check" }
- }
-
- public actual fun reset() {
- check(actionIndex.get() == 0 || finished.get()) { "Expecting that 'finish(...)' was invoked, but it was not" }
- actionIndex.set(0)
- finished.set(false)
- }
-
- private object TestOutputStream : PrintStream(object : OutputStream() {
- override fun write(b: Int) {
- error("Detected unexpected call to 'println' from source code")
- }
- })
-
- fun println(message: Any?) {
- if (disableOutCheck) kotlin.io.println(message)
- else previousOut.println(message)
- }
-
- @Before
- fun before() {
- initPoolsBeforeTest()
- threadsBefore = currentThreads()
- originalUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
- Thread.setDefaultUncaughtExceptionHandler { t, e ->
- println("Exception in thread $t: $e") // The same message as in default handler
- e.printStackTrace()
- uncaughtExceptions.add(e)
- }
- if (!disableOutCheck) {
- previousOut = System.out
- System.setOut(TestOutputStream)
- }
- }
-
- @After
- fun onCompletion() {
- // onCompletion should not throw exceptions before it finishes all cleanup, so that other tests always
- // start in a clear, restored state
- if (actionIndex.get() != 0 && !finished.get()) {
- makeError("Expecting that 'finish(${actionIndex.get() + 1})' was invoked, but it was not")
- }
- // Shutdown all thread pools
- shutdownPoolsAfterTest()
- // Check that are now leftover threads
- runCatching {
- checkTestThreads(threadsBefore)
- }.onFailure {
- setError(it)
- }
- // Restore original uncaught exception handler
- Thread.setDefaultUncaughtExceptionHandler(originalUncaughtExceptionHandler)
- if (!disableOutCheck) {
- System.setOut(previousOut)
- }
- if (uncaughtExceptions.isNotEmpty()) {
- makeError("Expected no uncaught exceptions, but got $uncaughtExceptions")
- }
- // The very last action -- throw error if any was detected
- error.get()?.let { throw it }
- }
-
- fun initPoolsBeforeTest() {
- DefaultScheduler.usePrivateScheduler()
- }
-
- fun shutdownPoolsAfterTest() {
- DefaultScheduler.shutdown(SHUTDOWN_TIMEOUT)
- DefaultExecutor.shutdownForTests(SHUTDOWN_TIMEOUT)
- DefaultScheduler.restore()
- }
-
- @Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
- public actual fun runTest(
- expected: ((Throwable) -> Boolean)? = null,
- unhandled: List<(Throwable) -> Boolean> = emptyList(),
- block: suspend CoroutineScope.() -> Unit
- ): TestResult {
- var exCount = 0
- var ex: Throwable? = null
- try {
- runBlocking(block = block, context = CoroutineExceptionHandler { _, e ->
- if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
- exCount++
- when {
- exCount > unhandled.size ->
- printError("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
- !unhandled[exCount - 1](e) ->
- printError("Unhandled exception was unexpected: $e", e)
- }
- })
- } catch (e: Throwable) {
- ex = e
- if (expected != null) {
- if (!expected(e))
- error("Unexpected exception: $e", e)
- } else {
- throw e
- }
- } finally {
- if (ex == null && expected != null) error("Exception was expected but none produced")
- }
- if (exCount < unhandled.size)
- error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
- }
-
- protected inline fun <reified T: Throwable> assertFailsWith(block: () -> Unit): T {
- val result = runCatching(block)
- assertTrue(result.exceptionOrNull() is T, "Expected ${T::class}, but had $result")
- return result.exceptionOrNull()!! as T
- }
-
- protected suspend fun currentDispatcher() = coroutineContext[ContinuationInterceptor]!!
-}
-
-/*
- * We ignore tests that test **real** non-virtualized tests with time on Windows, because
- * our CI Windows is virtualized itself (oh, the irony) and its clock resolution is dozens of ms,
- * which makes such tests flaky.
- */
-public actual val isJavaAndWindows: Boolean = System.getProperty("os.name")!!.contains("Windows")
diff --git a/kotlinx-coroutines-core/jvm/test/TestBaseTest.kt b/kotlinx-coroutines-core/jvm/test/TestBaseTest.kt
index b198102..49b26ab 100644
--- a/kotlinx-coroutines-core/jvm/test/TestBaseTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/TestBaseTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
class TestBaseTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/TestSecurityManager.kt b/kotlinx-coroutines-core/jvm/test/TestSecurityManager.kt
index e7b039c..781d5d0 100644
--- a/kotlinx-coroutines-core/jvm/test/TestSecurityManager.kt
+++ b/kotlinx-coroutines-core/jvm/test/TestSecurityManager.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import java.security.Permission
diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt
index e2ab4d7..cd34196 100644
--- a/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt
index 3bb79b4..3b106c4 100644
--- a/kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextMutableCopiesTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextMutableCopiesTest.kt
index 73d4ee6..0b174ec 100644
--- a/kotlinx-coroutines-core/jvm/test/ThreadContextMutableCopiesTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ThreadContextMutableCopiesTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.flow.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt
index 49f4a12..877a4ca 100644
--- a/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.internal.*
import org.junit.Test
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/ThreadLocalStressTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadLocalStressTest.kt
index 20621d1..63ed3f2 100644
--- a/kotlinx-coroutines-core/jvm/test/ThreadLocalStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ThreadLocalStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.sync.*
import java.util.concurrent.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt
index 5d8c3d5..79a2490 100644
--- a/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.lang.IllegalStateException
diff --git a/kotlinx-coroutines-core/jvm/test/UnconfinedConcurrentStressTest.kt b/kotlinx-coroutines-core/jvm/test/UnconfinedConcurrentStressTest.kt
index 0308800..61aa7da 100644
--- a/kotlinx-coroutines-core/jvm/test/UnconfinedConcurrentStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/UnconfinedConcurrentStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/VirtualTimeSource.kt b/kotlinx-coroutines-core/jvm/test/VirtualTimeSource.kt
index b4bc96e..8a46108 100644
--- a/kotlinx-coroutines-core/jvm/test/VirtualTimeSource.kt
+++ b/kotlinx-coroutines-core/jvm/test/VirtualTimeSource.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import java.io.*
@@ -13,14 +9,14 @@
internal inline fun withVirtualTimeSource(log: PrintStream? = null, block: () -> Unit) {
DefaultExecutor.shutdownForTests(SHUTDOWN_TIMEOUT) // shutdown execution with old time source (in case it was working)
val testTimeSource = VirtualTimeSource(log)
- timeSource = testTimeSource
+ mockTimeSource(testTimeSource)
DefaultExecutor.ensureStarted() // should start with new time source
try {
block()
} finally {
DefaultExecutor.shutdownForTests(SHUTDOWN_TIMEOUT)
testTimeSource.shutdown()
- timeSource = null // restore time source
+ mockTimeSource(null) // restore time source
}
}
diff --git a/kotlinx-coroutines-core/jvm/test/WithDefaultContextTest.kt b/kotlinx-coroutines-core/jvm/test/WithDefaultContextTest.kt
index 0cad285..44b3127 100644
--- a/kotlinx-coroutines-core/jvm/test/WithDefaultContextTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/WithDefaultContextTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class WithDefaultContextTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt
index 4d440a7..cc5e1d8 100644
--- a/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt
index cce77bb..a0a29f0 100644
--- a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class WithTimeoutOrNullJvmTest : TestBase() {
diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt
index ea1ba1a..a5aeefd 100644
--- a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt
index 82f5e92..58c7336 100644
--- a/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.test.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt
index d3b2ff1..7ed5d4e 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt
index 5a2778d..8898158 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelLeakTest.kt b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelLeakTest.kt
index df94465..7102636 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelLeakTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelLeakTest.kt
@@ -1,6 +1,6 @@
package kotlinx.coroutines.channels
-import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.test.*
@@ -31,4 +31,4 @@
FieldWalker.assertReachableCount(0, broadcast) { it === sub }
}
}
-}
\ 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 8c9777b..5b21180 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import org.junit.*
@@ -18,15 +15,17 @@
class BroadcastChannelMultiReceiveStressTest(
private val kind: TestBroadcastChannelKind
) : TestBase() {
+
+ // Stressed by lincheck
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun params(): Collection<Array<Any>> =
- TestBroadcastChannelKind.values().map { arrayOf<Any>(it) }
+ TestBroadcastChannelKind.entries.map { arrayOf<Any>(it) }
}
private val nReceivers = if (isStressTest) 10 else 5
- private val nSeconds = 3 * stressTestMultiplier
+ private val nSeconds = 3 * stressTestMultiplierSqrt
private val broadcast = kind.create<Long>()
private val pool = newFixedThreadPoolContext(nReceivers + 1, "BroadcastChannelMultiReceiveStressTest")
@@ -65,13 +64,13 @@
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()
@@ -96,7 +95,7 @@
} 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
@@ -119,8 +118,9 @@
try {
val stop = doReceived(receiverIndex, channel.receive())
if (stop) break
+ } catch (ex: ClosedReceiveChannelException) {
+ break
}
- catch (ex: ClosedReceiveChannelException) { break }
}
}
@@ -144,7 +144,9 @@
val event = select<Long> { channel.onReceive { it } }
val stop = doReceived(receiverIndex, event)
if (stop) break
- } catch (ex: ClosedReceiveChannelException) { break }
+ } catch (ex: ClosedReceiveChannelException) {
+ break
+ }
}
}
@@ -155,4 +157,10 @@
if (stop) break
}
}
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun println(debugMessage: String) {
+ // Uncomment for local debugging
+ //println(debugMessage as Any?)
+ }
}
diff --git a/kotlinx-coroutines-core/jvm/test/channels/BufferedChannelStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/BufferedChannelStressTest.kt
index a646426..87754b3 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/BufferedChannelStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/BufferedChannelStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelMemoryLeakStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelMemoryLeakStressTest.kt
index ebc2bee..67170c2 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ChannelMemoryLeakStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelMemoryLeakStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt
index a44ff6c..f7a12c6 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt
index 8a60ce5..e9c087a 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementSelectOldStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementSelectOldStressTest.kt
index 25cccf9..fc5c384 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementSelectOldStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementSelectOldStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementStressTest.kt
index f8a5644..ec123f1 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelUndeliveredElementStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ConflatedChannelCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ConflatedChannelCloseStressTest.kt
index 793d7e4..e36cafe 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ConflatedChannelCloseStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ConflatedChannelCloseStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.atomic.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/DoubleChannelCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/DoubleChannelCloseStressTest.kt
index 01cace7..247b077 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/DoubleChannelCloseStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/DoubleChannelCloseStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/InvokeOnCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/InvokeOnCloseStressTest.kt
index 8ac8591..19aa040 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/InvokeOnCloseStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/InvokeOnCloseStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt
index 61c6635..6b5f2bf 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/SendReceiveJvmStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/SendReceiveJvmStressTest.kt
index 60d1adb..865f2ab 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/SendReceiveJvmStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/SendReceiveJvmStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.runner.*
import org.junit.runners.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt
index eeddfb5..3708251 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/channels/TickerChannelCommonTest.kt b/kotlinx-coroutines-core/jvm/test/channels/TickerChannelCommonTest.kt
index fbc28a1..6510209 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/TickerChannelCommonTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/TickerChannelCommonTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/channels/TickerChannelTest.kt b/kotlinx-coroutines-core/jvm/test/channels/TickerChannelTest.kt
index fcdc6bb..051d670 100644
--- a/kotlinx-coroutines-core/jvm/test/channels/TickerChannelTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/channels/TickerChannelTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.channels
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-delay-01.kt b/kotlinx-coroutines-core/jvm/test/examples/example-delay-01.kt
index 1bc3791..63dcc08 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-delay-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-delay-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleDelay01
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-delay-02.kt b/kotlinx-coroutines-core/jvm/test/examples/example-delay-02.kt
index ac48af9..498ce33 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-delay-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-delay-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleDelay02
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-delay-03.kt b/kotlinx-coroutines-core/jvm/test/examples/example-delay-03.kt
index 1fa9dc4..f9c44c3 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-delay-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-delay-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleDelay03
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-01.kt b/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-01.kt
index 954af06..00c613f 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleDelayDuration01
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-02.kt b/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-02.kt
index 45935a0..a75f251 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleDelayDuration02
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-03.kt b/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-03.kt
index fc389c2..dbd4842 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-delay-duration-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleDelayDuration03
diff --git a/kotlinx-coroutines-core/jvm/test/examples/example-timeout-duration-01.kt b/kotlinx-coroutines-core/jvm/test/examples/example-timeout-duration-01.kt
index 5db6e6a..c336528 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/example-timeout-duration-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/example-timeout-duration-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.exampleTimeoutDuration01
@@ -19,8 +15,15 @@
emit(3)
delay(1000)
emit(4)
-}.timeout(100.milliseconds).catch {
- emit(-1) // Item to emit on timeout
+}.timeout(100.milliseconds).catch { exception ->
+ if (exception is TimeoutCancellationException) {
+ // Catch the TimeoutCancellationException emitted above.
+ // Emit desired item on timeout.
+ emit(-1)
+ } else {
+ // Throw other exceptions.
+ throw exception
+ }
}.onEach {
delay(300) // This will not cause a timeout
}
diff --git a/kotlinx-coroutines-core/jvm/test/examples/test/FlowDelayTest.kt b/kotlinx-coroutines-core/jvm/test/examples/test/FlowDelayTest.kt
index f7e93b3..b0bc05f 100644
--- a/kotlinx-coroutines-core/jvm/test/examples/test/FlowDelayTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/examples/test/FlowDelayTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from Delay.kt by Knit tool. Do not edit.
package kotlinx.coroutines.examples.test
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/CoroutineExceptionHandlerJvmTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/CoroutineExceptionHandlerJvmTest.kt
index 2095f14..2e35199 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/CoroutineExceptionHandlerJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/CoroutineExceptionHandlerJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
@@ -33,9 +30,9 @@
}
job.join()
- assertTrue(caughtException is RuntimeException)
- assertTrue(caughtException.cause is AssertionError)
- assertTrue(caughtException.suppressed[0] is TestException)
+ assertIs<RuntimeException>(caughtException)
+ assertIs<AssertionError>(caughtException.cause)
+ assertIs<TestException>(caughtException.suppressed[0])
finish(3)
}
@@ -47,7 +44,7 @@
expect(2)
throw TestException()
}.join()
- assertTrue(caughtException is TestException)
+ assertIs<TestException>(caughtException)
assertContains(caughtException.suppressed[0].toString(), "last-ditch")
finish(3)
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/Exceptions.kt b/kotlinx-coroutines-core/jvm/test/exceptions/Exceptions.kt
deleted file mode 100644
index 4849f52..0000000
--- a/kotlinx-coroutines-core/jvm/test/exceptions/Exceptions.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.exceptions
-
-import kotlinx.coroutines.*
-import java.io.*
-import java.util.*
-import kotlin.coroutines.*
-import kotlin.test.*
-
-/**
- * Proxy for [Throwable.getSuppressed] for tests, which are compiled for both JDK 1.6 and JDK 1.8,
- * but run only under JDK 1.8
- */
-@Suppress("ConflictingExtensionProperty")
-actual val Throwable.suppressed: Array<Throwable> get() {
- val method = this::class.java.getMethod("getSuppressed") ?: error("This test can only be run using JDK 1.7")
- @Suppress("UNCHECKED_CAST")
- return method.invoke(this) as Array<Throwable>
-}
-
-internal inline fun <reified T : Throwable> checkException(exception: Throwable): Boolean {
- assertTrue(exception is T)
- assertTrue(exception.suppressed.isEmpty())
- assertNull(exception.cause)
- return true
-}
-
-internal fun checkCycles(t: Throwable) {
- val sw = StringWriter()
- t.printStackTrace(PrintWriter(sw))
- assertFalse(sw.toString().contains("CIRCULAR REFERENCE"))
-}
-
-class CapturingHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler),
- CoroutineExceptionHandler
-{
- private var unhandled: ArrayList<Throwable>? = ArrayList()
-
- override fun handleException(context: CoroutineContext, exception: Throwable) = synchronized<Unit>(this) {
- unhandled!!.add(exception)
- }
-
- fun getExceptions(): List<Throwable> = synchronized(this) {
- return unhandled!!.also { unhandled = null }
- }
-
- fun getException(): Throwable = synchronized(this) {
- val size = unhandled!!.size
- assert(size == 1) { "Expected one unhandled exception, but have $size: $unhandled" }
- return unhandled!![0].also { unhandled = null }
- }
-}
-
-internal fun captureExceptionsRun(
- context: CoroutineContext = EmptyCoroutineContext,
- block: suspend CoroutineScope.() -> Unit
-): Throwable {
- val handler = CapturingHandler()
- runBlocking(context + handler, block = block)
- return handler.getException()
-}
-
-internal fun captureMultipleExceptionsRun(
- context: CoroutineContext = EmptyCoroutineContext,
- block: suspend CoroutineScope.() -> Unit
-): List<Throwable> {
- val handler = CapturingHandler()
- runBlocking(context + handler, block = block)
- return handler.getExceptions()
-}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/FlowSuppressionTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/FlowSuppressionTest.kt
index 41fe090..8af4937 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/FlowSuppressionTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/FlowSuppressionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/JobBasicCancellationTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobBasicCancellationTest.kt
index 28d85fe..7ea6c4a 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/JobBasicCancellationTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/JobBasicCancellationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.io.*
@@ -152,7 +149,7 @@
assertTrue(deferred.completeExceptionally(IndexOutOfBoundsException()))
assertFalse(deferred.completeExceptionally(AssertionError())) // second is too late
val cause = deferred.getCancellationException().cause!!
- assertTrue(cause is IndexOutOfBoundsException)
+ assertIs<IndexOutOfBoundsException>(cause)
assertNull(cause.cause)
assertTrue(cause.suppressed.isEmpty())
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionHandlingTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionHandlingTest.kt
index eaa73bd..d031020 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionHandlingTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionHandlingTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineStart.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.Test
import java.io.*
import kotlin.test.*
@@ -192,9 +190,7 @@
finish(5)
}
- assertTrue(exception is ArithmeticException)
- assertNull(exception.cause)
- assertTrue(exception.suppressed.isEmpty())
+ checkException<ArithmeticException>(exception)
}
@Test
@@ -232,11 +228,12 @@
finish(6)
}
- assertTrue(exception is ArithmeticException)
+ assertIs<ArithmeticException>(exception)
+ assertNull(exception.cause)
val suppressed = exception.suppressed
assertEquals(2, suppressed.size)
- assertTrue(suppressed[0] is IOException)
- assertTrue(suppressed[1] is IllegalArgumentException)
+ assertIs<IOException>(suppressed[0])
+ assertIs<IllegalArgumentException>(suppressed[1])
}
@Test
@@ -269,11 +266,11 @@
finish(5)
}
- assertTrue(exception is AssertionError)
+ assertIs<AssertionError>(exception)
val suppressed = exception.suppressed
assertEquals(2, suppressed.size)
- assertTrue(suppressed[0] is IOException)
- assertTrue(suppressed[1] is IllegalArgumentException)
+ assertIs<IOException>(suppressed[0])
+ assertIs<IllegalArgumentException>(suppressed[1])
}
@Test
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionsStressTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionsStressTest.kt
index 4c977e8..4634c4f 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionsStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionsStressTest.kt
@@ -1,10 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/JobNestedExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobNestedExceptionsTest.kt
index 4a5fa74..8b0a32b 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/JobNestedExceptionsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/JobNestedExceptionsTest.kt
@@ -1,10 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.Test
import java.io.*
import kotlin.test.*
@@ -61,7 +59,7 @@
finish(3)
}
- assertTrue(exception is IOException)
+ assertIs<IOException>(exception)
}
@Test
@@ -80,13 +78,13 @@
job.join()
finish(5)
}
- assertTrue(exception is ArithmeticException, "Found $exception")
+ assertIs<ArithmeticException>(exception, "Found $exception")
checkException<IOException>(exception.suppressed[0])
}
@Test
fun testChildThrowsDuringCompletion() {
- val exceptions = captureMultipleExceptionsRun {
+ val exception = captureExceptionsRun {
expect(1)
val job = launch(NonCancellable + CoroutineName("outer"), start = CoroutineStart.ATOMIC) {
expect(2)
@@ -108,12 +106,10 @@
finish(7)
}
- assertEquals(1, exceptions.size, "Found $exceptions")
- val exception = exceptions[0]
- assertTrue(exception is ArithmeticException, "Exception is $exception")
+ assertIs<ArithmeticException>(exception, "Exception is $exception")
val suppressed = exception.suppressed
val ioe = suppressed[0]
- assertTrue(ioe is IOException)
+ assertIs<IOException>(ioe)
checkException<NullPointerException>(ioe.suppressed[0])
checkCycles(exception)
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt
index 33585f4..98f080e 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.Test
@@ -65,7 +62,7 @@
produce.receive()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -162,7 +159,7 @@
channel.receive()
} catch (e: CancellationException) {
// RECOVER_STACK_TRACES
- assertTrue(e.cause?.cause is TestException2)
+ assertIs<TestException2>(e.cause?.cause)
finish(4)
}
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryChannelsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryChannelsTest.kt
index 2d8c0eb..f6d1986 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryChannelsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryChannelsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt
index 0f987e5..ea0a868 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.Test
@@ -51,7 +48,7 @@
} catch (e: Copyable) {
assertEquals(239, e.customData)
val cause = e.cause
- assertTrue(cause is Copyable)
+ assertIs<Copyable>(cause)
assertEquals(239, cause.customData)
}
}
@@ -68,7 +65,7 @@
} catch (e: WithDefault) {
assertEquals("custom", e.message)
val cause = e.cause
- assertTrue(cause is WithDefault)
+ assertIs<WithDefault>(cause)
assertEquals("custom", cause.message)
}
}
@@ -83,7 +80,7 @@
}
}
val ex = result.exceptionOrNull() ?: error("Expected to fail")
- assertTrue(ex is WrongMessageException)
+ assertIs<WrongMessageException>(ex)
assertEquals("Token OK", ex.message)
}
@@ -118,7 +115,7 @@
// Iterator has a special code path
}
}.exceptionOrNull() ?: error("Expected to fail")
- assertTrue(ex is WrongMessageException)
+ assertIs<WrongMessageException>(ex)
assertEquals("Token OK", ex.message)
}
@@ -141,7 +138,7 @@
}
}
val ex = result.exceptionOrNull() ?: error("Expected to fail")
- assertTrue(ex is CopyableWithCustomMessage)
+ assertIs<CopyableWithCustomMessage>(ex)
assertEquals("Recovered: [OK]", ex.message)
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt
index dbb1ead..0422df9 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt
@@ -1,5 +1,6 @@
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import kotlin.coroutines.*
@@ -8,7 +9,7 @@
private val TEST_MACROS = "TEST_NAME"
- private val expectedTrace = "kotlinx.coroutines.RecoverableTestException\n" +
+ private val expectedTrace = "kotlinx.coroutines.testing.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" +
@@ -16,7 +17,7 @@
"\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" +
+ "Caused by: kotlinx.coroutines.testing.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" +
@@ -78,7 +79,7 @@
deferred.await()
} catch (e: Exception) {
verifyStackTrace(e,
- "kotlinx.coroutines.RecoverableTestException\n" +
+ "kotlinx.coroutines.testing.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" +
@@ -88,7 +89,7 @@
"\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.testing.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" +
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedTest.kt
index 02607c0..28875c9 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("DeferredResultUnused")
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryResumeModeTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryResumeModeTest.kt
index 36f6052..1039d29 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryResumeModeTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryResumeModeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoverySelectTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoverySelectTest.kt
index 0efa252..0ac8084 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoverySelectTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoverySelectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt
index 1db7c1d..169654d 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt
@@ -1,12 +1,10 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.intrinsics.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.Test
import java.lang.RuntimeException
import java.util.concurrent.*
@@ -89,14 +87,14 @@
}
outerMethod(deferred,
- "kotlinx.coroutines.RecoverableTestException\n" +
+ "kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testWithContext\$1\$deferred\$1.invokeSuspend(StackTraceRecoveryTest.kt:143)\n" +
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.innerMethod(StackTraceRecoveryTest.kt:158)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$outerMethod\$2.invokeSuspend(StackTraceRecoveryTest.kt:151)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.outerMethod(StackTraceRecoveryTest.kt:150)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testWithContext\$1.invokeSuspend(StackTraceRecoveryTest.kt:141)\n",
- "Caused by: kotlinx.coroutines.RecoverableTestException\n" +
+ "Caused by: kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testWithContext\$1\$deferred\$1.invokeSuspend(StackTraceRecoveryTest.kt:143)\n" +
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n")
deferred.join()
@@ -126,14 +124,14 @@
}
outerScopedMethod(deferred,
- "kotlinx.coroutines.RecoverableTestException\n" +
+ "kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCoroutineScope\$1\$deferred\$1.invokeSuspend(StackTraceRecoveryTest.kt:143)\n" +
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.innerMethod(StackTraceRecoveryTest.kt:158)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$outerScopedMethod\$2\$1.invokeSuspend(StackTraceRecoveryTest.kt:193)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$outerScopedMethod\$2.invokeSuspend(StackTraceRecoveryTest.kt:151)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCoroutineScope\$1.invokeSuspend(StackTraceRecoveryTest.kt:141)\n",
- "Caused by: kotlinx.coroutines.RecoverableTestException\n" +
+ "Caused by: kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCoroutineScope\$1\$deferred\$1.invokeSuspend(StackTraceRecoveryTest.kt:143)\n" +
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n")
deferred.join()
@@ -223,14 +221,14 @@
barrier.await()
val e = exception
assertNotNull(e)
- verifyStackTrace(e, "kotlinx.coroutines.RecoverableTestException\n" +
+ verifyStackTrace(e, "kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.throws(StackTraceRecoveryTest.kt:280)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.access\$throws(StackTraceRecoveryTest.kt:20)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$throws\$1.invokeSuspend(StackTraceRecoveryTest.kt)\n" +
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.awaiter(StackTraceRecoveryTest.kt:285)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testNonDispatchedRecovery\$await\$1.invokeSuspend(StackTraceRecoveryTest.kt:291)\n" +
- "Caused by: kotlinx.coroutines.RecoverableTestException")
+ "Caused by: kotlinx.coroutines.testing.RecoverableTestException")
}
private class Callback(val cont: CancellableContinuation<*>)
@@ -242,12 +240,12 @@
try {
awaitCallback(channel)
} catch (e: Throwable) {
- verifyStackTrace(e, "kotlinx.coroutines.RecoverableTestException\n" +
+ verifyStackTrace(e, "kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCancellableContinuation\$1.invokeSuspend(StackTraceRecoveryTest.kt:329)\n" +
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.awaitCallback(StackTraceRecoveryTest.kt:348)\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCancellableContinuation\$1\$1.invokeSuspend(StackTraceRecoveryTest.kt:322)\n" +
- "Caused by: kotlinx.coroutines.RecoverableTestException\n" +
+ "Caused by: kotlinx.coroutines.testing.RecoverableTestException\n" +
"\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCancellableContinuation\$1.invokeSuspend(StackTraceRecoveryTest.kt:329)")
}
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt
index 8e628db..6d57366 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryWithTimeoutTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.rules.*
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt
index edce175..3346957 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.testing.exceptions.*
import java.io.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -22,7 +20,7 @@
}
override fun onCancelling(cause: Throwable?) {
- assertTrue(cause is ArithmeticException)
+ assertIs<ArithmeticException>(cause)
assertTrue(cause.suppressed.isEmpty())
expect(5)
}
@@ -32,20 +30,20 @@
}
override fun onCancelled(cause: Throwable, handled: Boolean) {
- assertTrue(cause is ArithmeticException)
+ assertIs<ArithmeticException>(cause)
checkException<IOException>(cause.suppressed[0])
expect(8)
}
}
coroutine.invokeOnCompletion(onCancelling = true) {
- assertTrue(it is ArithmeticException)
+ assertIs<ArithmeticException>(it)
assertTrue(it.suppressed.isEmpty())
expect(6)
}
coroutine.invokeOnCompletion {
- assertTrue(it is ArithmeticException)
+ assertIs<ArithmeticException>(it)
checkException<IOException>(it.suppressed[0])
expect(9)
}
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt
index f148a3a..ad35334 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/WithContextExceptionHandlingTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextExceptionHandlingTest.kt
index a95a3da..11809ce 100644
--- a/kotlinx-coroutines-core/jvm/test/exceptions/WithContextExceptionHandlingTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextExceptionHandlingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.runner.*
@@ -29,7 +26,7 @@
* Result: TE2
*/
runCancellation(null, TestException2()) { e ->
- assertTrue(e is TestException2)
+ assertIs<TestException2>(e)
assertNull(e.cause)
val suppressed = e.suppressed
assertTrue(suppressed.isEmpty())
@@ -45,7 +42,7 @@
*/
val cancellationCause = TestCancellationException()
runCancellation(cancellationCause, TestException2()) { e ->
- assertTrue(e is TestException2)
+ assertIs<TestException2>(e)
assertNull(e.cause)
val suppressed = e.suppressed
assertTrue(suppressed.isEmpty())
@@ -61,7 +58,7 @@
*/
val cancellationCause = TestCancellationException()
runCancellation(cancellationCause, cancellationCause) { e ->
- assertTrue(e is TestCancellationException)
+ assertIs<TestCancellationException>(e)
assertNull(e.cause)
val suppressed = e.suppressed
assertTrue(suppressed.isEmpty())
@@ -278,4 +275,4 @@
}
fail()
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt b/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt
index f1be284..f59bc1b 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.testing.flow.*
import org.junit.Test
import kotlin.concurrent.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt b/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt
index aca9eb9..6387508 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/FirstJvmTest.kt b/kotlinx-coroutines-core/jvm/test/flow/FirstJvmTest.kt
index 77ad083..1ac9bd2 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/FirstJvmTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/FirstJvmTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/FlatMapStressTest.kt b/kotlinx-coroutines-core/jvm/test/flow/FlatMapStressTest.kt
index 699d9c6..01201e0 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/FlatMapStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/FlatMapStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.internal.*
import kotlinx.coroutines.scheduling.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/OnCompletionInterceptedReleaseTest.kt b/kotlinx-coroutines-core/jvm/test/flow/OnCompletionInterceptedReleaseTest.kt
index a6268b5..5d332bf 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/OnCompletionInterceptedReleaseTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/OnCompletionInterceptedReleaseTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/SafeCollectorMemoryLeakTest.kt b/kotlinx-coroutines-core/jvm/test/flow/SafeCollectorMemoryLeakTest.kt
index b75ec60..094f8cc 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/SafeCollectorMemoryLeakTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/SafeCollectorMemoryLeakTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/SharedFlowStressTest.kt b/kotlinx-coroutines-core/jvm/test/flow/SharedFlowStressTest.kt
index 58e3ef4..712f2bd 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/SharedFlowStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/SharedFlowStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/SharingReferenceTest.kt b/kotlinx-coroutines-core/jvm/test/flow/SharingReferenceTest.kt
index aba95ed..f1e15be 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/SharingReferenceTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/SharingReferenceTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import org.junit.*
@@ -12,7 +9,6 @@
* Tests that shared flows keep strong reference to their source flows.
* See https://github.com/Kotlin/kotlinx.coroutines/issues/2557
*/
-@OptIn(DelicateCoroutinesApi::class)
class SharingReferenceTest : TestBase() {
private val token = object {}
diff --git a/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt b/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt
index 25c0c98..0d160e6 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/SharingStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
@@ -14,7 +11,6 @@
import kotlin.time.*
import kotlin.time.TimeSource
-@OptIn(ExperimentalTime::class)
class SharingStressTest : TestBase() {
private val testDuration = 1000L * stressTestMultiplier
private val nSubscribers = 5
diff --git a/kotlinx-coroutines-core/jvm/test/flow/StateFlowCancellabilityTest.kt b/kotlinx-coroutines-core/jvm/test/flow/StateFlowCancellabilityTest.kt
index fc4996c..cb91dd6 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/StateFlowCancellabilityTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/StateFlowCancellabilityTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import java.util.concurrent.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/StateFlowStressTest.kt b/kotlinx-coroutines-core/jvm/test/flow/StateFlowStressTest.kt
index e55eaad..3739aef 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/StateFlowStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/StateFlowStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import kotlin.random.*
diff --git a/kotlinx-coroutines-core/jvm/test/flow/StateFlowUpdateStressTest.kt b/kotlinx-coroutines-core/jvm/test/flow/StateFlowUpdateStressTest.kt
index 660ed0a..adc6610 100644
--- a/kotlinx-coroutines-core/jvm/test/flow/StateFlowUpdateStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/flow/StateFlowUpdateStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt
index 529f881..725beac 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleBasic01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt
index 6bf2af4..b010206 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleBasic02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt
index 67b6894..37ad624 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleBasic03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt
index efac708..bee0331 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleBasic04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt
index 193f2cc..d9a29ac 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleBasic05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt
index 3c503ac..c621cfb 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleBasic06
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt
index a1b036d..5a0d5a8 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt
index f6dec6e..3704051 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt
index 2cf0770..a950f80 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt
index 7d7f3bd..195c2ea 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt
index 97ea956..c82fb4a 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt
index ef66f5d..844db98 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel06
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 ea4a103..73d2574 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel07
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt
index 79d0809..29f3e10 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel08
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 ecd5a94..5baa99f 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel09
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 03dd852..6cbc2e5 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCancel10
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt
index 0af1ebd..8c9845a 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel01
@@ -11,7 +7,8 @@
fun main() = runBlocking {
val channel = Channel<Int>()
launch {
- // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
+ // this might be heavy CPU-consuming computation or async logic,
+ // we'll just send five squares
for (x in 1..5) channel.send(x * x)
}
// here we print five received integers:
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt
index 33eb7b3..5a5a754 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt
index 4a2613b..9c69c62 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt
index 73e8b6c..da61e14 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt
index 2143df5..f8b2f36 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt
index b78fcc9..1d61cea 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel06
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt
index 84de403..f21274f 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel07
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt
index eedf1c7..f5549ca 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel08
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt
index 259f52e..d93bc0e 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel09
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt
index 1f48b02..8867e94 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleChannel10
@@ -9,25 +5,25 @@
import kotlinx.coroutines.channels.*
fun main() = runBlocking<Unit> {
- val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
+ val tickerChannel = ticker(delayMillis = 200, initialDelayMillis = 0) // create a ticker channel
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
println("Initial element is available immediately: $nextElement") // no initial delay
- nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
- println("Next element is not ready in 50 ms: $nextElement")
+ nextElement = withTimeoutOrNull(100) { tickerChannel.receive() } // all subsequent elements have 200ms delay
+ println("Next element is not ready in 100 ms: $nextElement")
- nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
- println("Next element is ready in 100 ms: $nextElement")
+ nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
+ println("Next element is ready in 200 ms: $nextElement")
// Emulate large consumption delays
- println("Consumer pauses for 150ms")
- delay(150)
+ println("Consumer pauses for 300ms")
+ delay(300)
// Next element is available immediately
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
println("Next element is available immediately after large consumer delay: $nextElement")
// Note that the pause between `receive` calls is taken into account and next element arrives faster
- nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
- println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
+ nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
+ println("Next element is ready in 100ms after consumer pause in 300ms: $nextElement")
tickerChannel.cancel() // indicate that no more elements are needed
}
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt
index ec20f1e..7194b64 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCompose01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt
index 9531b5c..126004c 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCompose02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt
index a61afea..04801c6 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCompose03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt
index 35536a7..0d77045 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCompose04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt
index 37c4f99..d32b5ef 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCompose05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt
index 5ee9e45..1dbbc80 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleCompose06
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt
index 0a95460..1c6a362 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt
index 49bfe7e..3aa64e9 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt
index 3aaf0b3..696852c 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt
index c5ce5eb..9609df8 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt
index 3017b04..e459561 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt
index 6796532..a90e521 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext06
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt
index 8037a55..8470096 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext07
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt
index a34e1ae..bb87166 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext08
@@ -15,12 +11,12 @@
val v1 = async(CoroutineName("v1coroutine")) {
delay(500)
log("Computing v1")
- 252
+ 6
}
val v2 = async(CoroutineName("v2coroutine")) {
delay(1000)
log("Computing v2")
- 6
+ 7
}
- log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
+ log("The answer for v1 * v2 = ${v1.await() * v2.await()}")
}
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt
index 6c1121b..a4f730b 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext09
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt
index 73ecbd2..d1385a9 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext10
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt
index e356317..2b0a521 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleContext11
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt
index 24cbabe..a6ae6ca 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleExceptions01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt
index c3ab68a..c619d79 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleExceptions02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt
index 1ad5aef..02bd6b8 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleExceptions03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt
index b966c1e..cb8b4ff 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleExceptions04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt
index 5f1f3d8..c7e543d 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleExceptions05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt
index bc9f77b..5d88a1e 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleExceptions06
@@ -14,7 +10,7 @@
println("CoroutineExceptionHandler got $exception")
}
val job = GlobalScope.launch(handler) {
- val inner = launch { // all this stack of coroutines will get cancelled
+ val innerJob = launch { // all this stack of coroutines will get cancelled
launch {
launch {
throw IOException() // the original exception
@@ -22,7 +18,7 @@
}
}
try {
- inner.join()
+ innerJob.join()
} catch (e: CancellationException) {
println("Rethrowing CancellationException with original cause")
throw e // cancellation exception is rethrown, yet the original IOException gets to the handler
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt
index 7c6c157..8db2596 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt
index e3fabe3..1162b1e 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt
index 61601dd..57e466f 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt
index c91f704..9efed63 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt
index 788d941..93fcb19 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt
index bd4058e..8abc161 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow06
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt
index 73b1734..03e2d2e 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow07
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt
index 1e8580c..c834439 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow08
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt
index 7e2113c..a151946 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow09
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt
index 61e74a1..03981b6 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow10
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt
index 513057d..7435920 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow11
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt
index 54ddf65..806d2b8 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow12
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt
index 945ce89..2ff0d08 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow13
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt
index b5fc35e..26d2b49 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow14
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt
index 0218e99..1a6e0fd 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow15
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt
index 7f3414f..35ec7a2 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow16
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt
index ed71617..4048f43 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow17
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt
index fc7bdef..61779b3 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow18
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt
index f4ee219..82b0269 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow19
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt
index bb829d1..f0d6801 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow20
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt
index e0adea6..9c3c22d 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow21
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt
index 9450ce5..9cf2734 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow22
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt
index 973f363..4ff4488 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow23
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt
index 7da20e0..f4132be 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow24
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt
index e3c2b81..a09def0 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow25
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt
index 95f9a11..1297f3f 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow26
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt
index 3f34a76..29ed17c 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow27
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt
index 02b231e..6514f15 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow28
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt
index 5ec37af..536660a 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow29
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt
index e787ca3..0cff2ab 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow30
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt
index 19fcb1c..4f833f5 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow31
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt
index 9848957..d007993 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow32
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt
index 9f86765..0d4f7f0 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow33
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt
index b2cee7f..f27545d 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow34
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt
index 928c8bf..a2b15e8 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow35
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt
index 3138464..c58035b 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow36
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-37.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-37.kt
index 229e55b..6d35f6f 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-37.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-37.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow37
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-38.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-38.kt
index fcbbb24..169a3fd 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-38.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-38.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow38
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-39.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-39.kt
index 86275c7..a79e8a5 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-39.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-39.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleFlow39
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt
index bf15b65..5bc6710 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from select-expression.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSelect01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt
index 22380d3..3aa101a 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from select-expression.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSelect02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt
index 36597dd..c9f3d37 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from select-expression.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSelect03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt
index 4cd9f6d..4837957 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from select-expression.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSelect04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt
index 68b4456..c8b2e99 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from select-expression.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSelect05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt
index db819e4..a5cd1fd 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSupervision01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt
index 50deff3..3c82527 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSupervision02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt
index 943c64f..e23fe7f 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSupervision03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt
index 32d4ac4..69c01b7 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync01
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt
index fb551f8..971c6e5 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync02
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt
index 8153c02..e3b3b94 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync03
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt
index f94c4a0..382a834 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync04
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt
index a6a1cdd..597674a 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync05
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt
index e6c5f1b..4fc7767 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync06
diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt
index a84e02c..14c452c 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.exampleSync07
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt
index 550f8e7..8452f43 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-basics.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt
index 871e491..f09b762 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt
index d15a550..97aa1da 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from channels.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
@@ -117,11 +113,11 @@
fun testExampleChannel10() {
test("ExampleChannel10") { kotlinx.coroutines.guide.exampleChannel10.main() }.verifyLines(
"Initial element is available immediately: kotlin.Unit",
- "Next element is not ready in 50 ms: null",
- "Next element is ready in 100 ms: kotlin.Unit",
- "Consumer pauses for 150ms",
+ "Next element is not ready in 100 ms: null",
+ "Next element is ready in 200 ms: kotlin.Unit",
+ "Consumer pauses for 300ms",
"Next element is available immediately after large consumer delay: kotlin.Unit",
- "Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit"
+ "Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit"
)
}
}
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt
index 1f9692d..2668276 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt
index e18741e..1cf6c2b 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
@@ -81,7 +77,7 @@
"[main @main#1] Started main coroutine",
"[main @v1coroutine#2] Computing v1",
"[main @v2coroutine#3] Computing v2",
- "[main @main#1] The answer for v1 / v2 = 42"
+ "[main @main#1] The answer for v1 * v2 = 42"
)
}
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt
index f34fd3f..dc60061 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from exception-handling.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
@@ -13,7 +9,7 @@
fun testExampleExceptions01() {
test("ExampleExceptions01") { kotlinx.coroutines.guide.exampleExceptions01.main() }.verifyExceptions(
"Throwing exception from launch",
- "Exception in thread \"DefaultDispatcher-worker-2 @coroutine#2\" java.lang.IndexOutOfBoundsException",
+ "Exception in thread \"DefaultDispatcher-worker-1 @coroutine#2\" java.lang.IndexOutOfBoundsException",
"Joined failed job",
"Throwing exception from async",
"Caught ArithmeticException"
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt
index c7d4a72..4735a9c 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from flow.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt
index 8bc8191..d0e879e 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from select-expression.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt
index 034b82e..7e43650 100644
--- a/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit.
package kotlinx.coroutines.guide.test
diff --git a/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapCollectionStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapCollectionStressTest.kt
index d9a2a96..a85b396 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapCollectionStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapCollectionStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import junit.framework.Assert.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
diff --git a/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapOperationStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapOperationStressTest.kt
index 63b5838..934dbbc 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapOperationStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapOperationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
diff --git a/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapTest.kt
index e4fa5e9..2394e90 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/ConcurrentWeakMapTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import junit.framework.Assert.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
diff --git a/kotlinx-coroutines-core/jvm/test/internal/FastServiceLoaderTest.kt b/kotlinx-coroutines-core/jvm/test/internal/FastServiceLoaderTest.kt
index a070f63..b47cd7d 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/FastServiceLoaderTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/FastServiceLoaderTest.kt
@@ -1,5 +1,6 @@
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListLongStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListLongStressTest.kt
index 7e1b0c6..577e73d 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListLongStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListLongStressTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
-import kotlinx.coroutines.TestBase
+import kotlinx.coroutines.testing.*
+import kotlinx.coroutines.testing.TestBase
import org.junit.Test
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
@@ -70,4 +67,16 @@
}
require(!expected.hasNext())
}
+
+ private fun LockFreeLinkedListHead.validate() {
+ var prev: LockFreeLinkedListNode = this
+ var cur: LockFreeLinkedListNode = next as LockFreeLinkedListNode
+ while (cur != this) {
+ val next = cur.nextNode
+ cur.validateNode(prev, next)
+ prev = cur
+ cur = next
+ }
+ validateNode(prev, next as LockFreeLinkedListNode)
+ }
}
diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueStressTest.kt
index 16e436e..625df76 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import org.junit.runner.*
diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueTest.kt
index 29f019b..de4dff8 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.runner.*
import org.junit.runners.*
diff --git a/kotlinx-coroutines-core/jvm/test/internal/OnDemandAllocatingPoolLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/internal/OnDemandAllocatingPoolLincheckTest.kt
index 9655890..77d8179 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/OnDemandAllocatingPoolLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/OnDemandAllocatingPoolLincheckTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
@@ -11,10 +7,10 @@
/**
* Test that:
- * * All elements allocated in [OnDemandAllocatingPool] get returned when [close] is invoked.
- * * After reaching the maximum capacity, new elements are not added.
- * * After [close] is invoked, [OnDemandAllocatingPool.allocate] returns `false`.
- * * [OnDemandAllocatingPool.close] will return an empty list after the first invocation.
+ * - All elements allocated in [OnDemandAllocatingPool] get returned when [close] is invoked.
+ * - After reaching the maximum capacity, new elements are not added.
+ * - After [close] is invoked, [OnDemandAllocatingPool.allocate] returns `false`.
+ * - [OnDemandAllocatingPool.close] will return an empty list after the first invocation.
*/
abstract class OnDemandAllocatingPoolLincheckTest(maxCapacity: Int) : AbstractLincheckTest() {
private val counter = atomic(0)
diff --git a/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapStressTest.kt
index 5bc0952..20ae9f3 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import java.util.concurrent.*
import java.util.concurrent.CancellationException
diff --git a/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt
index ee0960c..c7f2548 100644
--- a/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
import java.util.*
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/future/AsFutureTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/future/AsFutureTest.kt
index 743816f..3296072 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/future/AsFutureTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/future/AsFutureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.future
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.util.concurrent.*
@@ -65,7 +62,7 @@
expectUnreached()
} catch (e: ExecutionException) {
assertTrue(future.isCompletedExceptionally)
- assertTrue(e.cause is OutOfMemoryError)
+ assertIs<OutOfMemoryError>(e.cause)
finish(2)
}
}
@@ -81,7 +78,7 @@
expectUnreached()
} catch (e: ExecutionException) {
assertTrue(future.isCompletedExceptionally)
- assertTrue(e.cause is OutOfMemoryError)
+ assertIs<OutOfMemoryError>(e.cause)
finish(2)
}
}
@@ -119,6 +116,6 @@
assertTrue(deferred.isCancelled)
assertTrue(deferred.isCompleted)
assertFalse(deferred.isActive)
- assertTrue(deferred.getCompletionExceptionOrNull() is CancellationException)
+ assertIs<CancellationException>(deferred.getCompletionExceptionOrNull())
}
}
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureAsDeferredUnhandledCompletionExceptionTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureAsDeferredUnhandledCompletionExceptionTest.kt
index 9c9c97e..97d5484 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureAsDeferredUnhandledCompletionExceptionTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureAsDeferredUnhandledCompletionExceptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.future
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.future.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureExceptionsTest.kt
index 0c919b1..0fc1290 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureExceptionsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureExceptionsTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.future
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.io.*
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt
index eda3816..0b9f83b 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/future/FutureTest.kt
@@ -1,13 +1,11 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.future
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.CancellationException
import org.junit.*
import org.junit.Test
+import java.lang.IllegalArgumentException
import java.util.concurrent.*
import java.util.concurrent.atomic.*
import java.util.concurrent.locks.*
@@ -157,7 +155,7 @@
future.get()
fail("'get' should've throw an exception")
} catch (e: ExecutionException) {
- assertTrue(e.cause is IllegalStateException)
+ assertIs<IllegalStateException>(e.cause)
assertEquals("OK", e.cause!!.message)
}
}
@@ -239,14 +237,14 @@
assertTrue(deferred.isCancelled)
val completionException = deferred.getCompletionExceptionOrNull()!!
- assertTrue(completionException is TestException)
+ assertIs<TestException>(completionException)
assertEquals("something went wrong", completionException.message)
try {
deferred.await()
fail("deferred.await() should throw an exception")
} catch (e: Throwable) {
- assertTrue(e is TestException)
+ assertIs<TestException>(e)
assertEquals("something went wrong", e.message)
}
}
@@ -473,7 +471,7 @@
private inline fun <reified T: Throwable> CompletableFuture<*>.checkFutureException(vararg suppressed: KClass<out Throwable>) {
val e = assertFailsWith<ExecutionException> { get() }
val cause = e.cause!!
- assertTrue(cause is T)
+ assertIs<T>(cause)
for ((index, clazz) in suppressed.withIndex()) {
assertTrue(clazz.isInstance(cause.suppressed[index]))
}
@@ -590,4 +588,11 @@
assertEquals(count, completed.get())
}
}
+
+ @Test
+ fun testFailsIfLazy() {
+ assertFailsWith<IllegalArgumentException> {
+ GlobalScope.future<Unit>(start = CoroutineStart.LAZY) { }
+ }
+ }
}
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/stream/ConsumeAsFlowTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/stream/ConsumeAsFlowTest.kt
index 96ff963..49e8f34 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/stream/ConsumeAsFlowTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/stream/ConsumeAsFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.stream
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt
index 9ab0ccf..d13e4e0 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/time/DurationOverflowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.time
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowDebounceTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowDebounceTest.kt
index d6b2b8c..7313b1a 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowDebounceTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowDebounceTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.time
-import kotlinx.coroutines.TestBase
+import kotlinx.coroutines.testing.*
+import kotlinx.coroutines.testing.TestBase
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.withVirtualTime
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowSampleTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowSampleTest.kt
index d35ee72..a19c4b7 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowSampleTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/time/FlowSampleTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.time
-import kotlinx.coroutines.TestBase
+import kotlinx.coroutines.testing.*
+import kotlinx.coroutines.testing.TestBase
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.withVirtualTime
diff --git a/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt b/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt
index d33eaac..c34a6b1 100644
--- a/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/jdk8/time/WithTimeoutTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.time
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.time.*
diff --git a/kotlinx-coroutines-core/jvm/test/knit/ClosedAfterGuideTestExecutor.kt b/kotlinx-coroutines-core/jvm/test/knit/ClosedAfterGuideTestExecutor.kt
index 30fbfee..bbe4dc1 100644
--- a/kotlinx-coroutines-core/jvm/test/knit/ClosedAfterGuideTestExecutor.kt
+++ b/kotlinx-coroutines-core/jvm/test/knit/ClosedAfterGuideTestExecutor.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines // Trick to make guide tests use these declarations with executors that can be closed on our side implicitly
+import kotlinx.coroutines.testing.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*
import kotlin.coroutines.*
@@ -13,15 +10,6 @@
internal fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher =
ClosedAfterGuideTestDispatcher(nThreads, name)
-internal class PoolThread(
- @JvmField val dispatcher: ExecutorCoroutineDispatcher, // for debugging & tests
- target: Runnable, name: String
-) : Thread(target, name) {
- init {
- isDaemon = true
- }
-}
-
private class ClosedAfterGuideTestDispatcher(
private val nThreads: Int,
private val name: String
diff --git a/kotlinx-coroutines-core/jvm/test/knit/TestUtil.kt b/kotlinx-coroutines-core/jvm/test/knit/TestUtil.kt
index 80c9803..d0a5551 100644
--- a/kotlinx-coroutines-core/jvm/test/knit/TestUtil.kt
+++ b/kotlinx-coroutines-core/jvm/test/knit/TestUtil.kt
@@ -1,12 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.knit
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import kotlinx.coroutines.scheduling.*
+import kotlinx.coroutines.testing.*
import kotlinx.knit.test.*
import java.util.concurrent.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt
index 092ef6f..26a58c3 100644
--- a/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt
@@ -1,10 +1,8 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package kotlinx.coroutines.lincheck
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.channels.Channel.Factory.CONFLATED
diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt
index 11f5535..9a44891 100644
--- a/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("unused")
package kotlinx.coroutines.lincheck
diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt
index 983a64a..3705179 100644
--- a/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("unused")
package kotlinx.coroutines.lincheck
diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/ResizableAtomicArrayLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/ResizableAtomicArrayLincheckTest.kt
index e937b37..5561a7d 100644
--- a/kotlinx-coroutines-core/jvm/test/lincheck/ResizableAtomicArrayLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/ResizableAtomicArrayLincheckTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt
index d093e80..12b44d5 100644
--- a/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt
@@ -1,9 +1,7 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("unused")
package kotlinx.coroutines.lincheck
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
import org.jetbrains.kotlinx.lincheck.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherLivenessStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherLivenessStressTest.kt
index 7fc212f..20748a2 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherLivenessStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherLivenessStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt
index 3a55f8c..fe0fa4a 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTerminationStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTerminationStressTest.kt
index 864ecdc..2b00eb7 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTerminationStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTerminationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.scheduling.*
import org.junit.*
import java.util.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt
index f8830fe..49510cd 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.rules.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt
index c1fda44..8029db6 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Ignore
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherWorkSignallingStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherWorkSignallingStressTest.kt
index 3b3e085..81a1421 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherWorkSignallingStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherWorkSignallingStressTest.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("DeferredResultUnused")
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt
index c95415a..ee21be2 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt
index a50867d..d6719aa 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerInternalApiStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerInternalApiStressTest.kt
index 2ec714f..dbc6609 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerInternalApiStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerInternalApiStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.AVAILABLE_PROCESSORS
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerLivenessStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerLivenessStressTest.kt
index b7677be..07b549f 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerLivenessStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerLivenessStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.scheduling.CoroutineScheduler.Companion.MAX_SUPPORTED_POOL_SIZE
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerOversubscriptionTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerOversubscriptionTest.kt
index 0fd6159..c891878 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerOversubscriptionTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerOversubscriptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerStressTest.kt
index 7aefd4f..615cdee 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt
index 9d41c05..edb3799 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.lang.Runnable
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/DefaultDispatchersTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/DefaultDispatchersTest.kt
index 56c6695..f06f7cb 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/DefaultDispatchersTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/DefaultDispatchersTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/LimitingCoroutineDispatcherStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/LimitingCoroutineDispatcherStressTest.kt
index 0123ac5..6a11444 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/LimitingCoroutineDispatcherStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/LimitingCoroutineDispatcherStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/LimitingDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/LimitingDispatcherTest.kt
index e570580..1ba1120 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/LimitingDispatcherTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/LimitingDispatcherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt b/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt
index fc4436f..f6e0f70 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt
@@ -1,11 +1,8 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNUSED_VARIABLE")
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt
index 743b4a6..87103d7 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt b/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt
index 233e442..39df9a6 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueStressTest.kt
index e2562b5..1bf2434 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueTest.kt
index f690d38..e9fbc6b 100644
--- a/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.scheduling
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
diff --git a/kotlinx-coroutines-core/jvm/test/selects/SelectDeadlockStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectDeadlockStressTest.kt
index d8d4b22..466aecf 100644
--- a/kotlinx-coroutines-core/jvm/test/selects/SelectDeadlockStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/selects/SelectDeadlockStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.*
diff --git a/kotlinx-coroutines-core/jvm/test/selects/SelectMemoryLeakStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectMemoryLeakStressTest.kt
index 2ddf133..4b0ce46 100644
--- a/kotlinx-coroutines-core/jvm/test/selects/SelectMemoryLeakStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/selects/SelectMemoryLeakStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt
index 22179f3..423c1a8 100644
--- a/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt
@@ -1,16 +1,13 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.selects
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
import org.junit.Test
import kotlin.test.*
class SelectPhilosophersStressTest : TestBase() {
- private val TEST_DURATION = 3000L * stressTestMultiplier
+ private val TEST_DURATION = 3000L * stressTestMultiplierSqrt
val n = 10 // number of philosophers
private val forks = Array(n) { Mutex() }
@@ -62,4 +59,4 @@
assertTrue(eats > 0, "$id shall not starve")
}
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-core/jvmBenchmark/README.md b/kotlinx-coroutines-core/jvmBenchmark/README.md
new file mode 100644
index 0000000..a89761a
--- /dev/null
+++ b/kotlinx-coroutines-core/jvmBenchmark/README.md
@@ -0,0 +1,15 @@
+## kotlinx-coroutines-core benchmarks
+
+This source-set contains benchmarks that leverage `internal` API (e.g. `suspendCancellableCoroutineReusable`)
+and thus cannot be written in `benchmarks` module.
+
+This is an interim solution unless we introduce clear separation of responsibilities in benchmark modules
+and decide on their usability.
+
+
+### Usage
+
+```
+./gradlew :kotlinx-coroutines-core:jvmBenchmarkBenchmarkJar
+java -jar kotlinx-coroutines-core/build/benchmarks/jvmBenchmark/jars/kotlinx-coroutines-core-jvmBenchmark-jmh-*-JMH.jar
+```
diff --git a/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/BenchmarkUtils.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/BenchmarkUtils.kt
new file mode 100644
index 0000000..f0fdd82
--- /dev/null
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/BenchmarkUtils.kt
@@ -0,0 +1,13 @@
+package kotlinx.coroutines
+
+import java.util.concurrent.*
+
+public fun doGeomDistrWork(work: Int) {
+ // We use geometric distribution here. We also checked on macbook pro 13" (2017) that the resulting work times
+ // are distributed geometrically, see https://github.com/Kotlin/kotlinx.coroutines/pull/1464#discussion_r355705325
+ val p = 1.0 / work
+ val r = ThreadLocalRandom.current()
+ while (true) {
+ if (r.nextDouble() < p) break
+ }
+}
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/SemaphoreBenchmark.kt
similarity index 89%
rename from benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt
rename to kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/SemaphoreBenchmark.kt
index 6826b7a..9fe895e 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/SemaphoreBenchmark.kt
@@ -1,10 +1,5 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+package kotlinx.coroutines
-package benchmarks
-
-import benchmarks.common.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.scheduling.*
@@ -80,8 +75,7 @@
}
enum class SemaphoreBenchDispatcherCreator(val create: (parallelism: Int) -> CoroutineDispatcher) {
- // FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
- @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+ FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
DEFAULT({ parallelism -> ExperimentalCoroutineDispatcher(corePoolSize = parallelism, maxPoolSize = parallelism) })
}
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/ChannelProducerConsumerBenchmark.kt
similarity index 93%
rename from benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt
rename to kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/ChannelProducerConsumerBenchmark.kt
index 0aa218e..e7d01bc 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/ChannelProducerConsumerBenchmark.kt
@@ -1,16 +1,12 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+package kotlinx.coroutines.channels
-package benchmarks
-
-import benchmarks.common.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.scheduling.*
import kotlinx.coroutines.selects.select
import org.openjdk.jmh.annotations.*
import java.lang.Integer.max
+import java.util.concurrent.ForkJoinPool
import java.util.concurrent.Phaser
import java.util.concurrent.TimeUnit
@@ -136,8 +132,7 @@
}
enum class DispatcherCreator(val create: (parallelism: Int) -> CoroutineDispatcher) {
- //FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
- @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+ FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
DEFAULT({ parallelism -> ExperimentalCoroutineDispatcher(corePoolSize = parallelism, maxPoolSize = parallelism) })
}
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SelectBenchmark.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SelectBenchmark.kt
similarity index 86%
rename from benchmarks/src/jmh/kotlin/benchmarks/tailcall/SelectBenchmark.kt
rename to kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SelectBenchmark.kt
index cb4d39e..0df0c59 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SelectBenchmark.kt
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SelectBenchmark.kt
@@ -1,8 +1,4 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package benchmarks.tailcall
+package kotlinx.coroutines.channels
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SimpleChannel.kt
similarity index 89%
rename from benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt
rename to kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SimpleChannel.kt
index 1f71d8d..e198ea6 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SimpleChannel.kt
@@ -1,14 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package benchmarks.tailcall
+package kotlinx.coroutines.channels
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
-@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public abstract class SimpleChannel {
companion object {
const val NULL_SURROGATE: Int = -1
@@ -83,13 +78,11 @@
}
class CancellableReusableChannel : SimpleChannel() {
- @Suppress("INVISIBLE_MEMBER")
override suspend fun suspendReceive(): Int = suspendCancellableCoroutineReusable {
consumer = it.intercepted()
COROUTINE_SUSPENDED
}
- @Suppress("INVISIBLE_MEMBER")
override suspend fun suspendSend(element: Int) = suspendCancellableCoroutineReusable<Unit> {
enqueuedValue = element
producer = it.intercepted()
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SimpleChannelBenchmark.kt
similarity index 89%
rename from benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt
rename to kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SimpleChannelBenchmark.kt
index 9654b6d..3228687 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/channels/SimpleChannelBenchmark.kt
@@ -1,8 +1,4 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package benchmarks.tailcall
+package kotlinx.coroutines.channels
import kotlinx.coroutines.*
import org.openjdk.jmh.annotations.*
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/flow/TakeWhileBenchmark.kt
similarity index 87%
rename from benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt
rename to kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/flow/TakeWhileBenchmark.kt
index 7501e2c..bdaabc3 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt
+++ b/kotlinx-coroutines-core/jvmBenchmark/kotlin/kotlinx/coroutines/flow/TakeWhileBenchmark.kt
@@ -1,16 +1,11 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
-
-package benchmarks.flow
+package kotlinx.coroutines.flow
import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.internal.*
+import kotlinx.coroutines.flow.internal.AbortFlowException
+import kotlinx.coroutines.flow.internal.unsafeFlow
import org.openjdk.jmh.annotations.*
-import java.util.concurrent.TimeUnit
+import java.util.concurrent.*
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
diff --git a/kotlinx-coroutines-core/knit.properties b/kotlinx-coroutines-core/knit.properties
index 5b57398..f27241a 100644
--- a/kotlinx-coroutines-core/knit.properties
+++ b/kotlinx-coroutines-core/knit.properties
@@ -1,7 +1,3 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
knit.package=kotlinx.coroutines.examples
knit.dir=jvm/test/examples/
diff --git a/kotlinx-coroutines-core/native/src/Builders.kt b/kotlinx-coroutines-core/native/src/Builders.kt
index 1f1d352..0464747 100644
--- a/kotlinx-coroutines-core/native/src/Builders.kt
+++ b/kotlinx-coroutines-core/native/src/Builders.kt
@@ -1,20 +1,29 @@
-/*
- * 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:OptIn(ExperimentalContracts::class, ObsoleteWorkersApi::class)
package kotlinx.coroutines
import kotlinx.cinterop.*
-import platform.posix.*
import kotlin.contracts.*
import kotlin.coroutines.*
import kotlin.native.concurrent.*
/**
* Runs new coroutine and **blocks** current thread _interruptibly_ until its completion.
- * This function should not be used from coroutine. It is designed to bridge regular blocking code
- * to libraries that are written in suspending style, to be used in `main` functions and in tests.
+ *
+ * It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in
+ * `main` functions and in tests.
+ *
+ * Calling [runBlocking] from a suspend function is redundant.
+ * For example, the following code is incorrect:
+ * ```
+ * suspend fun loadConfiguration() {
+ * // DO NOT DO THIS:
+ * val data = runBlocking { // <- redundant and blocks the thread, do not do that
+ * fetchConfigurationData() // suspending function
+ * }
+ * ```
+ *
+ * Here, instead of releasing the thread on which `loadConfiguration` runs if `fetchConfigurationData` suspends, it will
+ * block, potentially leading to thread starvation issues.
*
* The default [CoroutineDispatcher] for this builder in an implementation of [EventLoop] that processes continuations
* in this blocked thread until the completion of this coroutine.
diff --git a/kotlinx-coroutines-core/native/src/CloseableCoroutineDispatcher.kt b/kotlinx-coroutines-core/native/src/CloseableCoroutineDispatcher.kt
index 0e239a4..81e0c5d 100644
--- a/kotlinx-coroutines-core/native/src/CloseableCoroutineDispatcher.kt
+++ b/kotlinx-coroutines-core/native/src/CloseableCoroutineDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
public actual abstract class CloseableCoroutineDispatcher actual constructor() : CoroutineDispatcher() {
diff --git a/kotlinx-coroutines-core/native/src/CoroutineContext.kt b/kotlinx-coroutines-core/native/src/CoroutineContext.kt
index 51ffd73..70064e2 100644
--- a/kotlinx-coroutines-core/native/src/CoroutineContext.kt
+++ b/kotlinx-coroutines-core/native/src/CoroutineContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
@@ -30,6 +26,7 @@
internal expect fun createDefaultDispatcher(): CoroutineDispatcher
+@PublishedApi
internal actual val DefaultDelay: Delay = DefaultExecutor
public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
diff --git a/kotlinx-coroutines-core/native/src/Debug.kt b/kotlinx-coroutines-core/native/src/Debug.kt
index f17c2ed..3cf2488 100644
--- a/kotlinx-coroutines-core/native/src/Debug.kt
+++ b/kotlinx-coroutines-core/native/src/Debug.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.math.*
diff --git a/kotlinx-coroutines-core/native/src/Dispatchers.kt b/kotlinx-coroutines-core/native/src/Dispatchers.kt
index 2576ba5..9965186 100644
--- a/kotlinx-coroutines-core/native/src/Dispatchers.kt
+++ b/kotlinx-coroutines-core/native/src/Dispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.coroutines.internal.*
diff --git a/kotlinx-coroutines-core/native/src/EventLoop.kt b/kotlinx-coroutines-core/native/src/EventLoop.kt
index 25c3c12..e457842 100644
--- a/kotlinx-coroutines-core/native/src/EventLoop.kt
+++ b/kotlinx-coroutines-core/native/src/EventLoop.kt
@@ -1,6 +1,4 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+@file:OptIn(ObsoleteWorkersApi::class)
package kotlinx.coroutines
@@ -28,4 +26,5 @@
internal actual fun createEventLoop(): EventLoop = EventLoopImpl()
+@Suppress("DEPRECATION")
internal actual fun nanoTime(): Long = getTimeNanos()
diff --git a/kotlinx-coroutines-core/native/src/Exceptions.kt b/kotlinx-coroutines-core/native/src/Exceptions.kt
index 1a923c4..c6173af 100644
--- a/kotlinx-coroutines-core/native/src/Exceptions.kt
+++ b/kotlinx-coroutines-core/native/src/Exceptions.kt
@@ -1,12 +1,5 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
-import kotlinx.coroutines.internal.*
-import kotlinx.coroutines.internal.SuppressSupportingThrowableImpl
-
/**
* Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
* It indicates _normal_ cancellation of a coroutine.
@@ -15,6 +8,11 @@
*/
public actual typealias CancellationException = kotlin.coroutines.cancellation.CancellationException
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
[email protected]
+public actual fun CancellationException(message: String?, cause: Throwable?): CancellationException =
+ CancellationException(message, cause)
+
/**
* Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled or completed
* without cause, or with a cause or exception that is not [CancellationException]
@@ -33,10 +31,5 @@
(message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0)
}
-@Suppress("NOTHING_TO_INLINE")
-internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) {
- if (this is SuppressSupportingThrowableImpl) addSuppressed(other)
-}
-
// For use in tests
internal actual val RECOVER_STACK_TRACES: Boolean = false
diff --git a/kotlinx-coroutines-core/native/src/MultithreadedDispatchers.kt b/kotlinx-coroutines-core/native/src/MultithreadedDispatchers.kt
index 007d079..283fce0 100644
--- a/kotlinx-coroutines-core/native/src/MultithreadedDispatchers.kt
+++ b/kotlinx-coroutines-core/native/src/MultithreadedDispatchers.kt
@@ -1,6 +1,4 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+@file:OptIn(ObsoleteWorkersApi::class)
package kotlinx.coroutines
@@ -8,6 +6,7 @@
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
+import kotlin.concurrent.AtomicReference
import kotlin.native.concurrent.*
import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
@@ -17,7 +16,6 @@
return MultiWorkerDispatcher(name, nThreads)
}
-@OptIn(ExperimentalTime::class)
internal class WorkerDispatcher(name: String) : CloseableCoroutineDispatcher(), Delay {
private val worker = Worker.start(name = name)
diff --git a/kotlinx-coroutines-core/native/src/Runnable.kt b/kotlinx-coroutines-core/native/src/Runnable.kt
index b8e6980..1a9e0ae 100644
--- a/kotlinx-coroutines-core/native/src/Runnable.kt
+++ b/kotlinx-coroutines-core/native/src/Runnable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
/**
diff --git a/kotlinx-coroutines-core/native/src/SchedulerTask.kt b/kotlinx-coroutines-core/native/src/SchedulerTask.kt
index 781e322..229302b 100644
--- a/kotlinx-coroutines-core/native/src/SchedulerTask.kt
+++ b/kotlinx-coroutines-core/native/src/SchedulerTask.kt
@@ -1,15 +1,12 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
internal actual abstract class SchedulerTask : Runnable
-@Suppress("ACTUAL_WITHOUT_EXPECT")
-internal actual typealias SchedulerTaskContext = Unit
+internal actual interface SchedulerTaskContext { }
-internal actual val SchedulerTask.taskContext: SchedulerTaskContext get() = kotlin.Unit
+private object TaskContext: SchedulerTaskContext { }
+
+internal actual val SchedulerTask.taskContext: SchedulerTaskContext get() = TaskContext
@Suppress("NOTHING_TO_INLINE")
internal actual inline fun SchedulerTaskContext.afterTask() {}
diff --git a/kotlinx-coroutines-core/native/src/WorkerMain.native.kt b/kotlinx-coroutines-core/native/src/WorkerMain.native.kt
deleted file mode 100644
index bf8fe6a..0000000
--- a/kotlinx-coroutines-core/native/src/WorkerMain.native.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-// It is used in the main sources of native-mt branch
-internal expect inline fun workerMain(block: () -> Unit)
diff --git a/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt
index bc7a1ff..1109b15 100644
--- a/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt
+++ b/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt
@@ -1,14 +1,10 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
internal actual class AbortFlowException actual constructor(
- actual val owner: FlowCollector<*>
+ actual val owner: Any
) : CancellationException("Flow was aborted, no more elements needed")
internal actual class ChildCancelledException : CancellationException("Child of the scoped flow was cancelled")
diff --git a/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt
index b74b547..ded11e2 100644
--- a/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt
+++ b/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.flow.internal
import kotlinx.coroutines.*
@@ -17,7 +13,7 @@
internal actual val collectContextSize = collectContext.fold(0) { count, _ -> count + 1 }
private var lastEmissionContext: CoroutineContext? = null
- override suspend fun emit(value: T) {
+ actual override suspend fun emit(value: T) {
val currentContext = currentCoroutineContext()
currentContext.ensureActive()
if (lastEmissionContext !== currentContext) {
diff --git a/kotlinx-coroutines-core/native/src/internal/Concurrent.kt b/kotlinx-coroutines-core/native/src/internal/Concurrent.kt
index 17975e2..8423c61 100644
--- a/kotlinx-coroutines-core/native/src/internal/Concurrent.kt
+++ b/kotlinx-coroutines-core/native/src/internal/Concurrent.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
+import kotlinx.cinterop.*
import kotlinx.atomicfu.locks.withLock as withLock2
@Suppress("ACTUAL_WITHOUT_EXPECT")
@@ -14,18 +11,20 @@
internal actual fun <E> identitySet(expectedSize: Int): MutableSet<E> = HashSet()
+@Suppress("ACTUAL_WITHOUT_EXPECT") // This suppress can be removed in 2.0: KT-59355
+internal actual typealias BenignDataRace = kotlin.concurrent.Volatile
-// "Suppress-supporting throwable" is currently used for tests only
-internal open class SuppressSupportingThrowableImpl : Throwable() {
- private val _suppressed = atomic<Array<Throwable>>(emptyArray())
+internal actual class WorkaroundAtomicReference<T> actual constructor(value: T) {
- val suppressed: Array<Throwable>
- get() = _suppressed.value
+ private val nativeAtomic = kotlin.concurrent.AtomicReference<T>(value)
- fun addSuppressed(other: Throwable) {
- _suppressed.update { current ->
- current + other
- }
+ public actual fun get(): T = nativeAtomic.value
+
+ public actual fun set(value: T) {
+ nativeAtomic.value = value
}
-}
+ public actual fun getAndSet(value: T): T = nativeAtomic.getAndSet(value)
+
+ public actual fun compareAndSet(expected: T, value: T): Boolean = nativeAtomic.compareAndSet(expected, value)
+}
diff --git a/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
index 2896c2e..32e1c4a 100644
--- a/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
+++ b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/native/src/internal/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/native/src/internal/CoroutineExceptionHandlerImpl.kt
index 43d776c..621b8a9 100644
--- a/kotlinx-coroutines-core/native/src/internal/CoroutineExceptionHandlerImpl.kt
+++ b/kotlinx-coroutines-core/native/src/internal/CoroutineExceptionHandlerImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt b/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt
index c8c6fff..cbbeec1 100644
--- a/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt
+++ b/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt
index 47d3fdb..00581f1 100644
--- a/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt
+++ b/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt
index d93af9f..9c6df6b 100644
--- a/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt
+++ b/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt
@@ -1,13 +1,11 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
internal actual fun <E: Throwable> recoverStackTrace(exception: E, continuation: Continuation<*>): E = exception
internal actual fun <E: Throwable> recoverStackTrace(exception: E): E = exception
+
+@PublishedApi
internal actual fun <E : Throwable> unwrap(exception: E): E = exception
internal actual suspend inline fun recoverAndThrow(exception: Throwable): Nothing = throw exception
diff --git a/kotlinx-coroutines-core/native/src/internal/Synchronized.kt b/kotlinx-coroutines-core/native/src/internal/Synchronized.kt
index 8a8ecfe..43ff8bd 100644
--- a/kotlinx-coroutines-core/native/src/internal/Synchronized.kt
+++ b/kotlinx-coroutines-core/native/src/internal/Synchronized.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlinx.cinterop.*
import kotlinx.coroutines.*
import kotlinx.atomicfu.locks.withLock as withLock2
diff --git a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt
index 4fb334e..accc247 100644
--- a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt
+++ b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
internal actual fun systemProp(propertyName: String): String? = null
diff --git a/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt
index 2370e42..3f56f99 100644
--- a/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt
+++ b/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt
index 405cbfb..0c803a7 100644
--- a/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt
+++ b/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt
@@ -1,9 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.internal
+import kotlin.native.concurrent.ThreadLocal
+
internal actual class CommonThreadLocal<T>(private val name: Symbol) {
@Suppress("UNCHECKED_CAST")
actual fun get(): T = Storage[name] as T
diff --git a/kotlinx-coroutines-core/native/test/ConcurrentTestUtilities.kt b/kotlinx-coroutines-core/native/test/ConcurrentTestUtilities.kt
index 6690972..ff1638f 100644
--- a/kotlinx-coroutines-core/native/test/ConcurrentTestUtilities.kt
+++ b/kotlinx-coroutines-core/native/test/ConcurrentTestUtilities.kt
@@ -1,36 +1,8 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.exceptions
-import kotlinx.coroutines.internal.*
import platform.posix.*
import kotlin.native.concurrent.*
-import kotlin.random.*
-actual fun randomWait() {
- val n = Random.nextInt(1000)
- if (n < 500) return // no wait 50% of time
- repeat(n) {
- BlackHole.sink *= 3
- }
- // use the BlackHole value somehow, so even if the compiler gets smarter, it won't remove the object
- val sinkValue = if (BlackHole.sink > 16) 1 else 0
- if (n + sinkValue > 900) sched_yield()
-}
-
-@ThreadLocal
-private object BlackHole {
- var sink = 1
-}
-
-internal actual typealias SuppressSupportingThrowable = SuppressSupportingThrowableImpl
-
-actual val Throwable.suppressed: Array<Throwable>
- get() = (this as? SuppressSupportingThrowableImpl)?.suppressed ?: emptyArray()
-
-@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "unused")
-actual fun Throwable.printStackTrace() = printStackTrace()
+actual inline fun yieldThread() { sched_yield() }
actual fun currentThreadName(): String = Worker.current.name
diff --git a/kotlinx-coroutines-core/native/test/DelayExceptionTest.kt b/kotlinx-coroutines-core/native/test/DelayExceptionTest.kt
index b040993..8ffa0e2 100644
--- a/kotlinx-coroutines-core/native/test/DelayExceptionTest.kt
+++ b/kotlinx-coroutines-core/native/test/DelayExceptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-core/native/test/MultithreadedDispatchersTest.kt b/kotlinx-coroutines-core/native/test/MultithreadedDispatchersTest.kt
index 501b7b5..beaace2 100644
--- a/kotlinx-coroutines-core/native/test/MultithreadedDispatchersTest.kt
+++ b/kotlinx-coroutines-core/native/test/MultithreadedDispatchersTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlinx.atomicfu.*
diff --git a/kotlinx-coroutines-core/native/test/TestBase.kt b/kotlinx-coroutines-core/native/test/TestBase.kt
deleted file mode 100644
index d7dfeea..0000000
--- a/kotlinx-coroutines-core/native/test/TestBase.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlinx.atomicfu.*
-
-public actual val isStressTest: Boolean = false
-public actual val stressTestMultiplier: Int = 1
-public actual val stressTestMultiplierSqrt: Int = 1
-
-public actual val isNative = true
-
-@Suppress("ACTUAL_WITHOUT_EXPECT")
-public actual typealias TestResult = Unit
-
-public actual open class TestBase actual constructor() {
- public actual val isBoundByJsTestTimeout = false
- private var actionIndex = atomic(0)
- private var finished = atomic(false)
- private var error: Throwable? = null
-
- /**
- * Throws [IllegalStateException] like `error` in stdlib, but also ensures that the test will not
- * complete successfully even if this exception is consumed somewhere in the test.
- */
- @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
- public actual fun error(message: Any, cause: Throwable? = null): Nothing {
- val exception = IllegalStateException(message.toString(), cause)
- if (error == null) error = exception
- throw exception
- }
-
- private fun printError(message: String, cause: Throwable) {
- if (error == null) error = cause
- println("$message: $cause")
- }
-
- /**
- * Asserts that this invocation is `index`-th in the execution sequence (counting from one).
- */
- public actual fun expect(index: Int) {
- val wasIndex = actionIndex.incrementAndGet()
- check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" }
- }
-
- /**
- * Asserts that this line is never executed.
- */
- public actual fun expectUnreached() {
- error("Should not be reached")
- }
-
- /**
- * Asserts that this it the last action in the test. It must be invoked by any test that used [expect].
- */
- public actual fun finish(index: Int) {
- expect(index)
- check(!finished.value) { "Should call 'finish(...)' at most once" }
- finished.value = true
- }
-
- /**
- * Asserts that [finish] was invoked
- */
- actual fun ensureFinished() {
- require(finished.value) { "finish(...) should be caller prior to this check" }
- }
-
- actual fun reset() {
- check(actionIndex.value == 0 || finished.value) { "Expecting that 'finish(...)' was invoked, but it was not" }
- actionIndex.value = 0
- finished.value = false
- }
-
- @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
- public actual fun runTest(
- expected: ((Throwable) -> Boolean)? = null,
- unhandled: List<(Throwable) -> Boolean> = emptyList(),
- block: suspend CoroutineScope.() -> Unit
- ): TestResult {
- var exCount = 0
- var ex: Throwable? = null
- try {
- runBlocking(block = block, context = CoroutineExceptionHandler { _, e ->
- if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
- exCount++
- when {
- exCount > unhandled.size ->
- printError("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
- !unhandled[exCount - 1](e) ->
- printError("Unhandled exception was unexpected: $e", e)
- }
- })
- } catch (e: Throwable) {
- ex = e
- if (expected != null) {
- if (!expected(e))
- error("Unexpected exception: $e", e)
- } else
- throw e
- } finally {
- if (ex == null && expected != null) error("Exception was expected but none produced")
- }
- if (exCount < unhandled.size)
- error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
- }
-}
-
-public actual val isJavaAndWindows: Boolean get() = false
diff --git a/kotlinx-coroutines-core/native/test/WorkerTest.kt b/kotlinx-coroutines-core/native/test/WorkerTest.kt
index 7ae31b2..1eb9d92 100644
--- a/kotlinx-coroutines-core/native/test/WorkerTest.kt
+++ b/kotlinx-coroutines-core/native/test/WorkerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.channels.*
import kotlin.coroutines.*
import kotlin.native.concurrent.*
diff --git a/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt b/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt
index edc0a13..786f0f2 100644
--- a/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt
+++ b/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt
@@ -1,6 +1,4 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+@file:OptIn(BetaInteropApi::class)
package kotlinx.coroutines
@@ -8,7 +6,7 @@
import platform.CoreFoundation.*
import platform.darwin.*
import kotlin.coroutines.*
-import kotlin.native.concurrent.*
+import kotlin.concurrent.*
import kotlin.native.internal.NativePtr
internal fun isMainThread(): Boolean = CFRunLoopGetCurrent() == CFRunLoopGetMain()
@@ -65,7 +63,7 @@
}
override fun toString(): String =
- "MainDispatcher${ if(invokeImmediately) "[immediate]" else "" }"
+ if (invokeImmediately) "Dispatchers.Main.immediate" else "Dispatchers.Main"
}
private typealias TimerBlock = (CFRunLoopTimerRef?) -> Unit
diff --git a/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt b/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt
deleted file mode 100644
index 010bd03..0000000
--- a/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-import kotlinx.cinterop.*
-
-internal actual inline fun workerMain(block: () -> Unit) {
- autoreleasepool {
- block()
- }
-}
diff --git a/kotlinx-coroutines-core/nativeDarwin/test/Launcher.kt b/kotlinx-coroutines-core/nativeDarwin/test/Launcher.kt
index 3a2820e..4f63946 100644
--- a/kotlinx-coroutines-core/nativeDarwin/test/Launcher.kt
+++ b/kotlinx-coroutines-core/nativeDarwin/test/Launcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import platform.CoreFoundation.*
@@ -20,9 +16,3 @@
error("CFRunLoopRun should never return")
}
-// This is a separate entry point for tests with leak checker
-fun mainNoExit(args: Array<String>) {
- workerMain { // autoreleasepool to make sure interop objects are properly freed
- testLauncherEntryPoint(args)
- }
-}
diff --git a/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt b/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt
index 9904f06..0094bcd 100644
--- a/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt
+++ b/kotlinx-coroutines-core/nativeDarwin/test/MainDispatcherTest.kt
@@ -1,129 +1,25 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
+import kotlinx.coroutines.testing.*
+import kotlinx.cinterop.*
+import kotlinx.coroutines.testing.*
import platform.CoreFoundation.*
import platform.darwin.*
import kotlin.coroutines.*
import kotlin.test.*
-class MainDispatcherTest : TestBase() {
+class MainDispatcherTest : MainDispatcherTestBase.WithRealTimeDelay() {
- private fun isMainThread(): Boolean = CFRunLoopGetCurrent() == CFRunLoopGetMain()
- private fun canTestMainDispatcher() = !isMainThread()
+ override fun isMainThread(): Boolean = CFRunLoopGetCurrent() == CFRunLoopGetMain()
- private fun runTestNotOnMainDispatcher(block: suspend CoroutineScope.() -> Unit) {
- // skip if already on the main thread, run blocking doesn't really work well with that
- if (!canTestMainDispatcher()) return
- runTest(block = block)
- }
+ // skip if already on the main thread, run blocking doesn't really work well with that
+ override fun shouldSkipTesting(): Boolean = isMainThread()
- @Test
- fun testDispatchNecessityCheckWithMainImmediateDispatcher() = runTestNotOnMainDispatcher {
- val main = Dispatchers.Main.immediate
- assertTrue(main.isDispatchNeeded(EmptyCoroutineContext))
- withContext(Dispatchers.Default) {
- assertTrue(main.isDispatchNeeded(EmptyCoroutineContext))
- withContext(Dispatchers.Main) {
- assertFalse(main.isDispatchNeeded(EmptyCoroutineContext))
- }
- assertTrue(main.isDispatchNeeded(EmptyCoroutineContext))
- }
- }
-
- @Test
- fun testWithContext() = runTestNotOnMainDispatcher {
- expect(1)
- assertFalse(isMainThread())
- withContext(Dispatchers.Main) {
- assertTrue(isMainThread())
- expect(2)
- }
- assertFalse(isMainThread())
- finish(3)
- }
-
- @Test
- fun testWithContextDelay() = runTestNotOnMainDispatcher {
- expect(1)
- withContext(Dispatchers.Main) {
- assertTrue(isMainThread())
- expect(2)
- delay(100)
- assertTrue(isMainThread())
- expect(3)
- }
- assertFalse(isMainThread())
- finish(4)
- }
-
- @Test
- fun testWithTimeoutContextDelayNoTimeout() = runTestNotOnMainDispatcher {
- expect(1)
- withTimeout(1000) {
- withContext(Dispatchers.Main) {
- assertTrue(isMainThread())
- expect(2)
- delay(100)
- assertTrue(isMainThread())
- expect(3)
+ override fun scheduleOnMainQueue(block: () -> Unit) {
+ autoreleasepool {
+ dispatch_async(dispatch_get_main_queue()) {
+ block()
}
}
- assertFalse(isMainThread())
- finish(4)
- }
-
- @Test
- fun testWithTimeoutContextDelayTimeout() = runTestNotOnMainDispatcher {
- expect(1)
- assertFailsWith<TimeoutCancellationException> {
- withTimeout(100) {
- withContext(Dispatchers.Main) {
- assertTrue(isMainThread())
- expect(2)
- delay(1000)
- expectUnreached()
- }
- }
- expectUnreached()
- }
- assertFalse(isMainThread())
- finish(3)
- }
-
- @Test
- fun testWithContextTimeoutDelayNoTimeout() = runTestNotOnMainDispatcher {
- expect(1)
- withContext(Dispatchers.Main) {
- withTimeout(1000) {
- assertTrue(isMainThread())
- expect(2)
- delay(100)
- assertTrue(isMainThread())
- expect(3)
- }
- }
- assertFalse(isMainThread())
- finish(4)
- }
-
- @Test
- fun testWithContextTimeoutDelayTimeout() = runTestNotOnMainDispatcher {
- expect(1)
- assertFailsWith<TimeoutCancellationException> {
- withContext(Dispatchers.Main) {
- withTimeout(100) {
- assertTrue(isMainThread())
- expect(2)
- delay(1000)
- expectUnreached()
- }
- }
- expectUnreached()
- }
- assertFalse(isMainThread())
- finish(3)
}
}
diff --git a/kotlinx-coroutines-core/nativeOther/src/Dispatchers.kt b/kotlinx-coroutines-core/nativeOther/src/Dispatchers.kt
index 17278b0..5d200d3 100644
--- a/kotlinx-coroutines-core/nativeOther/src/Dispatchers.kt
+++ b/kotlinx-coroutines-core/nativeOther/src/Dispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt b/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt
deleted file mode 100644
index f3bd99a..0000000
--- a/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
-
-internal actual inline fun workerMain(block: () -> Unit) = block()
diff --git a/kotlinx-coroutines-core/nativeOther/test/Launcher.kt b/kotlinx-coroutines-core/nativeOther/test/Launcher.kt
index 58dbefc..a957a51 100644
--- a/kotlinx-coroutines-core/nativeOther/test/Launcher.kt
+++ b/kotlinx-coroutines-core/nativeOther/test/Launcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines
import kotlin.native.concurrent.*
@@ -16,8 +12,3 @@
exitProcess(result)
}.result // block main thread
}
-
-// This is a separate entry point for tests with leak checker
-fun mainNoExit(args: Array<String>) {
- testLauncherEntryPoint(args)
-}
diff --git a/kotlinx-coroutines-core/wasmJs/src/CoroutineContext.kt b/kotlinx-coroutines-core/wasmJs/src/CoroutineContext.kt
new file mode 100644
index 0000000..f4db72a
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/src/CoroutineContext.kt
@@ -0,0 +1,47 @@
+package kotlinx.coroutines
+
+import kotlinx.coroutines.internal.*
+import org.w3c.dom.*
+import kotlin.coroutines.*
+
+internal external interface JsProcess : JsAny {
+ fun nextTick(handler: () -> Unit)
+}
+
+internal fun tryGetProcess(): JsProcess? =
+ js("(typeof(process) !== 'undefined' && typeof(process.nextTick) === 'function') ? process : null")
+
+internal fun tryGetWindow(): Window? =
+ js("(typeof(window) !== 'undefined' && window != null && typeof(window.addEventListener) === 'function') ? window : null")
+
+internal actual fun createDefaultDispatcher(): CoroutineDispatcher =
+ tryGetProcess()?.let(::NodeDispatcher)
+ ?: tryGetWindow()?.let(::WindowDispatcher)
+ ?: SetTimeoutDispatcher
+
+@PublishedApi // Used from kotlinx-coroutines-test via suppress, not part of ABI
+internal actual val DefaultDelay: Delay
+ get() = Dispatchers.Default as Delay
+
+public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
+ val combined = coroutineContext + context
+ return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)
+ combined + Dispatchers.Default else combined
+}
+
+public actual fun CoroutineContext.newCoroutineContext(addedContext: CoroutineContext): CoroutineContext {
+ return this + addedContext
+}
+
+// No debugging facilities on Wasm
+internal actual inline fun <T> withCoroutineContext(context: CoroutineContext, countOrElement: Any?, block: () -> T): T = block()
+internal actual inline fun <T> withContinuationContext(continuation: Continuation<*>, countOrElement: Any?, block: () -> T): T = block()
+internal actual fun Continuation<*>.toDebugString(): String = toString()
+internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on Wasm
+
+internal actual class UndispatchedCoroutine<in T> actual constructor(
+ context: CoroutineContext,
+ uCont: Continuation<T>
+) : ScopeCoroutine<T>(context, uCont) {
+ override fun afterResume(state: Any?) = uCont.resumeWith(recoverResult(state, uCont))
+}
diff --git a/kotlinx-coroutines-core/wasmJs/src/Debug.kt b/kotlinx-coroutines-core/wasmJs/src/Debug.kt
new file mode 100644
index 0000000..00fa5bd
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/src/Debug.kt
@@ -0,0 +1,16 @@
+package kotlinx.coroutines
+
+internal actual val DEBUG: Boolean = false
+
+internal actual val Any.hexAddress: String
+ get() = this.hashCode().toString()
+
+internal actual val Any.classSimpleName: String get() = this::class.simpleName ?: "Unknown"
+
+internal actual inline fun assert(value: () -> Boolean) {}
+
+internal external interface Console {
+ fun error(s: String)
+}
+
+internal external val console: Console
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/wasmJs/src/JSDispatcher.kt b/kotlinx-coroutines-core/wasmJs/src/JSDispatcher.kt
new file mode 100644
index 0000000..9481e2f
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/src/JSDispatcher.kt
@@ -0,0 +1,88 @@
+package kotlinx.coroutines
+
+import org.w3c.dom.Window
+import kotlin.js.*
+
+public actual typealias W3CWindow = Window
+
+internal actual fun w3cSetTimeout(window: W3CWindow, handler: () -> Unit, timeout: Int): Int =
+ setTimeout(window, handler, timeout)
+
+internal actual fun w3cSetTimeout(handler: () -> Unit, timeout: Int): Int =
+ setTimeout(handler, timeout)
+
+internal actual fun w3cClearTimeout(window: W3CWindow, handle: Int) =
+ window.clearTimeout(handle)
+
+internal actual fun w3cClearTimeout(handle: Int) =
+ clearTimeout(handle)
+
+internal actual class ScheduledMessageQueue actual constructor(private val dispatcher: SetTimeoutBasedDispatcher) : MessageQueue() {
+ internal val processQueue: () -> Unit = ::process
+
+ actual override fun schedule() {
+ dispatcher.scheduleQueueProcessing()
+ }
+
+ actual override fun reschedule() {
+ setTimeout(processQueue, 0)
+ }
+
+ internal actual fun setTimeout(timeout: Int) {
+ setTimeout(processQueue, timeout)
+ }
+}
+
+internal class NodeDispatcher(private val process: JsProcess) : SetTimeoutBasedDispatcher() {
+ override fun scheduleQueueProcessing() {
+ process.nextTick(messageQueue.processQueue)
+ }
+}
+
+@Suppress("UNUSED_PARAMETER")
+private fun subscribeToWindowMessages(window: Window, process: () -> Unit): Unit = js("""{
+ const handler = (event) => {
+ if (event.source == window && event.data == 'dispatchCoroutine') {
+ event.stopPropagation();
+ process();
+ }
+ }
+ window.addEventListener('message', handler, true);
+}""")
+
+@Suppress("UNUSED_PARAMETER")
+private fun createRescheduleMessagePoster(window: Window): () -> Unit =
+ js("() => window.postMessage('dispatchCoroutine', '*')")
+
+@Suppress("UNUSED_PARAMETER")
+private fun createScheduleMessagePoster(process: () -> Unit): () -> Unit =
+ js("() => Promise.resolve(0).then(process)")
+
+internal actual class WindowMessageQueue actual constructor(window: W3CWindow) : MessageQueue() {
+ private val scheduleMessagePoster = createScheduleMessagePoster(::process)
+ private val rescheduleMessagePoster = createRescheduleMessagePoster(window)
+ init {
+ subscribeToWindowMessages(window, ::process)
+ }
+
+ actual override fun schedule() {
+ scheduleMessagePoster()
+ }
+
+ actual override fun reschedule() {
+ rescheduleMessagePoster()
+ }
+}
+
+// We need to reference global setTimeout and clearTimeout so that it works on Node.JS as opposed to
+// using them via "window" (which only works in browser)
+private external fun setTimeout(handler: () -> Unit, timeout: Int): Int
+
+// d8 doesn't have clearTimeout
+@Suppress("UNUSED_PARAMETER")
+private fun clearTimeout(handle: Int): Unit =
+ js("{ if (typeof clearTimeout !== 'undefined') clearTimeout(handle); }")
+
+@Suppress("UNUSED_PARAMETER")
+private fun setTimeout(window: Window, handler: () -> Unit, timeout: Int): Int =
+ js("window.setTimeout(handler, timeout)")
diff --git a/kotlinx-coroutines-core/wasmJs/src/Promise.kt b/kotlinx-coroutines-core/wasmJs/src/Promise.kt
new file mode 100644
index 0000000..9099a7c
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/src/Promise.kt
@@ -0,0 +1,80 @@
+package kotlinx.coroutines
+
+import kotlin.coroutines.*
+import kotlin.js.*
+
+@Suppress("UNUSED_PARAMETER")
+internal fun promiseSetDeferred(promise: Promise<JsAny?>, deferred: JsAny): Unit =
+ js("promise.deferred = deferred")
+
+@Suppress("UNUSED_PARAMETER")
+internal fun promiseGetDeferred(promise: Promise<JsAny?>): JsAny? = js("""{
+ console.assert(promise instanceof Promise, "promiseGetDeferred must receive a promise, but got ", promise);
+ return promise.deferred == null ? null : promise.deferred;
+}""")
+
+
+/**
+ * Starts new coroutine and returns its result as an implementation of [Promise].
+ *
+ * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [context] argument.
+ * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used.
+ * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
+ * with corresponding [context] element.
+ *
+ * By default, the coroutine is immediately scheduled for execution.
+ * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
+ *
+ * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
+ * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
+ * @param block the coroutine code.
+ */
+public fun <T> CoroutineScope.promise(
+ context: CoroutineContext = EmptyCoroutineContext,
+ start: CoroutineStart = CoroutineStart.DEFAULT,
+ block: suspend CoroutineScope.() -> T
+): Promise<JsAny?> =
+ async(context, start, block).asPromise()
+
+/**
+ * Converts this deferred value to the instance of [Promise<JsAny?>].
+ */
+public fun <T> Deferred<T>.asPromise(): Promise<JsAny?> {
+ val promise = Promise<JsAny?> { resolve, reject ->
+ invokeOnCompletion {
+ val e = getCompletionExceptionOrNull()
+ if (e != null) {
+ reject(e.toJsReference())
+ } else {
+ resolve(getCompleted()?.toJsReference())
+ }
+ }
+ }
+ promiseSetDeferred(promise, this.toJsReference())
+ return promise
+}
+
+/**
+ * Converts this promise value to the instance of [Deferred].
+ */
+@Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE", "UNCHECKED_CAST")
+public fun <T> Promise<JsAny?>.asDeferred(): Deferred<T> {
+ val deferred = promiseGetDeferred(this) as? JsReference<Deferred<T>>
+ return deferred?.get() ?: GlobalScope.async(start = CoroutineStart.UNDISPATCHED) { await() }
+}
+
+/**
+ * Awaits for completion of the promise without blocking.
+ *
+ * This suspending function is cancellable: if the [Job] of the current coroutine is cancelled while this
+ * suspending function is waiting on the promise, this function immediately resumes with [CancellationException].
+ * There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
+ * while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
+ */
+@Suppress("UNCHECKED_CAST")
+public suspend fun <T> Promise<JsAny?>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
+ [email protected](
+ onFulfilled = { cont.resume(it as T); null },
+ onRejected = { cont.resumeWithException(it.toThrowableOrNull() ?: error("Unexpected non-Kotlin exception $it")); null }
+ )
+}
diff --git a/kotlinx-coroutines-core/wasmJs/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/wasmJs/src/internal/CopyOnWriteList.kt
new file mode 100644
index 0000000..43496a5
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/src/internal/CopyOnWriteList.kt
@@ -0,0 +1,69 @@
+package kotlinx.coroutines.internal
+
+@Suppress("UNCHECKED_CAST")
+internal class CopyOnWriteList<E> : AbstractMutableList<E>() {
+ private var array: Array<Any?> = arrayOfNulls<Any?>(0)
+
+ override val size: Int
+ get() = array.size
+
+ override fun add(element: E): Boolean {
+ val n = size
+ val update = array.copyOf(n + 1)
+ update[n] = element
+ array = update
+ return true
+ }
+
+ override fun add(index: Int, element: E) {
+ rangeCheck(index)
+ val n = size
+ val update = arrayOfNulls<Any?>(n + 1)
+ array.copyInto(destination = update, endIndex = index)
+ update[index] = element
+ array.copyInto(destination = update, destinationOffset = index + 1, startIndex = index, endIndex = n + 1)
+ array = update
+ }
+
+ override fun remove(element: E): Boolean {
+ val index = array.indexOf(element as Any)
+ if (index == -1) return false
+ removeAt(index)
+ return true
+ }
+
+ override fun removeAt(index: Int): E {
+ rangeCheck(index)
+ val n = size
+ val element = array[index]
+ val update = arrayOfNulls<Any>(n - 1)
+ array.copyInto(destination = update, endIndex = index)
+ array.copyInto(destination = update, destinationOffset = index, startIndex = index + 1, endIndex = n)
+ array = update
+ return element as E
+ }
+
+ override fun iterator(): MutableIterator<E> = IteratorImpl(array as Array<E>)
+ override fun listIterator(): MutableListIterator<E> = throw UnsupportedOperationException("Operation is not supported")
+ override fun listIterator(index: Int): MutableListIterator<E> = throw UnsupportedOperationException("Operation is not supported")
+ override fun isEmpty(): Boolean = size == 0
+ override fun set(index: Int, element: E): E = throw UnsupportedOperationException("Operation is not supported")
+ override fun get(index: Int): E = array[rangeCheck(index)] as E
+
+ private class IteratorImpl<E>(private val array: Array<E>) : MutableIterator<E> {
+ private var current = 0
+
+ override fun hasNext(): Boolean = current != array.size
+
+ override fun next(): E {
+ if (!hasNext()) throw NoSuchElementException()
+ return array[current++]
+ }
+
+ override fun remove() = throw UnsupportedOperationException("Operation is not supported")
+ }
+
+ private fun rangeCheck(index: Int) = index.apply {
+ if (index < 0 || index >= size) throw IndexOutOfBoundsException("index: $index, size: $size")
+ }
+}
diff --git a/kotlinx-coroutines-core/wasmJs/src/internal/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/wasmJs/src/internal/CoroutineExceptionHandlerImpl.kt
new file mode 100644
index 0000000..b3c09e7
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/src/internal/CoroutineExceptionHandlerImpl.kt
@@ -0,0 +1,8 @@
+package kotlinx.coroutines.internal
+
+import kotlinx.coroutines.*
+
+internal actual fun propagateExceptionFinalResort(exception: Throwable) {
+ // log exception
+ console.error(exception.toString())
+}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt b/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt
new file mode 100644
index 0000000..6355043
--- /dev/null
+++ b/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt
@@ -0,0 +1,87 @@
+package kotlinx.coroutines
+
+import kotlinx.coroutines.testing.*
+import kotlin.js.*
+import kotlin.test.*
+
+class PromiseTest : TestBase() {
+ @Test
+ fun testPromiseResolvedAsDeferred() = GlobalScope.promise {
+ val promise = Promise<JsReference<String>> { resolve, _ ->
+ resolve("OK".toJsReference())
+ }
+ val deferred = promise.asDeferred<JsReference<String>>()
+ assertEquals("OK", deferred.await().get())
+ }
+
+ @Test
+ fun testPromiseRejectedAsDeferred() = GlobalScope.promise {
+ lateinit var promiseReject: (JsAny) -> Unit
+ val promise = Promise<JsAny?> { _, reject ->
+ promiseReject = reject
+ }
+ val deferred = promise.asDeferred<JsReference<String>>()
+ // reject after converting to deferred to avoid "Unhandled promise rejection" warnings
+ promiseReject(TestException("Rejected").toJsReference())
+ try {
+ deferred.await()
+ expectUnreached()
+ } catch (e: Throwable) {
+ assertIs<TestException>(e)
+ assertEquals("Rejected", e.message)
+ }
+ }
+
+ @Test
+ fun testCompletedDeferredAsPromise() = GlobalScope.promise {
+ val deferred = async(start = CoroutineStart.UNDISPATCHED) {
+ // completed right away
+ "OK"
+ }
+ val promise = deferred.asPromise()
+ assertEquals("OK", promise.await())
+ }
+
+ @Test
+ fun testWaitForDeferredAsPromise() = GlobalScope.promise {
+ val deferred = async {
+ // will complete later
+ "OK"
+ }
+ val promise = deferred.asPromise()
+ assertEquals("OK", promise.await()) // await yields main thread to deferred coroutine
+ }
+
+ @Test
+ fun testCancellableAwaitPromise() = GlobalScope.promise {
+ lateinit var r: (JsAny) -> Unit
+ val toAwait = Promise<JsAny?> { resolve, _ -> r = resolve }
+ val job = launch(start = CoroutineStart.UNDISPATCHED) {
+ toAwait.await() // suspends
+ }
+ job.cancel() // cancel the job
+ r("fail".toJsString()) // too late, the waiting job was already cancelled
+ }
+
+ @Test
+ fun testAsPromiseAsDeferred() = GlobalScope.promise {
+ val deferred = async { "OK" }
+ val promise = deferred.asPromise()
+ val d2 = promise.asDeferred<String>()
+ assertSame(d2, deferred)
+ assertEquals("OK", d2.await())
+ }
+
+ @Test
+ fun testLeverageTestResult(): TestResult {
+ // Cannot use expect(..) here
+ var seq = 0
+ val result = runTest {
+ ++seq
+ }
+ return result.then {
+ if (seq != 1) error("Unexpected result: $seq")
+ null
+ }
+ }
+}
diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md
index 104dde3..24a2fa8 100644
--- a/kotlinx-coroutines-debug/README.md
+++ b/kotlinx-coroutines-debug/README.md
@@ -61,7 +61,7 @@
### Using as JVM agent
Debug module can also be used as a standalone JVM agent to enable debug probes on the application startup.
-You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.7.2.jar`.
+You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.8.1.jar`.
Additionally, on Linux and Mac OS X you can use `kill -5 $pid` command in order to force your application to print all alive coroutines.
When used as Java agent, `"kotlinx.coroutines.debug.enable.creation.stack.trace"` system property can be used to control
[DebugProbes.enableCreationStackTraces] along with agent startup.
@@ -70,8 +70,8 @@
It is possible to run an application in production environments with debug probes in order to monitor its
state and improve its observability.
-For that, it is strongly recommended to switch off [DebugProbes.enableCreationStackTraces] property to significantly
-reduce the overhead of debug probes and make it insignificant.
+For that, it is strongly recommended not to enable [DebugProbes.enableCreationStackTraces], as enabling it makes
+the performance overhead of the debug probes non-negligible.
With creation stack-traces disabled, the typical overhead of enabled debug probes is a single-digit percentage of the total
application throughput.
@@ -123,16 +123,6 @@
at ExampleKt.combineResults(Example.kt:11)
at ExampleKt$computeValue$2.invokeSuspend(Example.kt:7)
at ExampleKt$main$1$deferred$1.invokeSuspend(Example.kt:25)
- at _COROUTINE._CREATION._(CoroutineDebugging.kt)
- at kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)
- at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)
- at kotlinx.coroutines.BuildersKt.async$default(Unknown Source)
- at ExampleKt$main$1.invokeSuspend(Example.kt:25)
- at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
- at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
- at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
- at ExampleKt.main(Example.kt:23)
- at ExampleKt.main(Example.kt)
... More coroutines here ...
diff --git a/kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api b/kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api
index b671b1a..11131fa 100644
--- a/kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api
+++ b/kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api
@@ -39,6 +39,7 @@
public static final field CREATED Lkotlinx/coroutines/debug/State;
public static final field RUNNING Lkotlinx/coroutines/debug/State;
public static final field SUSPENDED Lkotlinx/coroutines/debug/State;
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lkotlinx/coroutines/debug/State;
public static fun values ()[Lkotlinx/coroutines/debug/State;
}
diff --git a/kotlinx-coroutines-debug/build.gradle b/kotlinx-coroutines-debug/build.gradle
deleted file mode 100644
index 42d0b8d..0000000
--- a/kotlinx-coroutines-debug/build.gradle
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-apply plugin: "com.github.johnrengelman.shadow"
-
-// apply plugin to use autocomplete for Kover DSL
-apply plugin: 'org.jetbrains.kotlinx.kover'
-
-configurations {
- shadowDeps // shaded dependencies, not included into the resulting .pom file
- compileOnly.extendsFrom(shadowDeps)
- runtimeOnly.extendsFrom(shadowDeps)
-}
-
-dependencies {
- compileOnly "junit:junit:$junit_version"
- compileOnly "org.junit.jupiter:junit-jupiter-api:$junit5_version"
- testImplementation "org.junit.jupiter:junit-jupiter-engine:$junit5_version"
- testImplementation "org.junit.platform:junit-platform-testkit:1.7.0"
- shadowDeps "net.bytebuddy:byte-buddy:$byte_buddy_version"
- shadowDeps "net.bytebuddy:byte-buddy-agent:$byte_buddy_version"
- compileOnly "io.projectreactor.tools:blockhound:$blockhound_version"
- testImplementation "io.projectreactor.tools:blockhound:$blockhound_version"
- testImplementation "com.google.code.gson:gson:2.8.6"
- api "net.java.dev.jna:jna:$jna_version"
- api "net.java.dev.jna:jna-platform:$jna_version"
-}
-
-java {
- /* This is needed to be able to run JUnit5 tests. Otherwise, Gradle complains that it can't find the
- JVM1.6-compatible version of the `junit-jupiter-api` artifact. */
- disableAutoTargetJvm()
-}
-
-// This is required for BlockHound tests to work, see https://github.com/Kotlin/kotlinx.coroutines/issues/3701
-tasks.withType(Test).configureEach {
- if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_13)) {
- jvmArgs += ["-XX:+AllowRedefinitionToAddDeleteMethods"]
- }
-}
-
-jar {
- setEnabled(false)
-}
-
-def shadowJarTask = shadowJar {
- classifier null
- // Shadow only byte buddy, do not package kotlin stdlib
- configurations = [project.configurations.shadowDeps]
- relocate('net.bytebuddy', 'kotlinx.coroutines.repackaged.net.bytebuddy')
-
- manifest {
- attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain"
- attributes "Can-Redefine-Classes": "true"
- }
-}
-
-configurations {
- artifacts {
- add("apiElements", shadowJarTask)
- add("runtimeElements", shadowJarTask)
- }
-}
-
-koverReport {
- filters {
- excludes {
- // Never used, safety mechanism
- classes("kotlinx.coroutines.debug.internal.NoOpProbesKt")
- }
- }
-}
diff --git a/kotlinx-coroutines-debug/build.gradle.kts b/kotlinx-coroutines-debug/build.gradle.kts
new file mode 100644
index 0000000..a9b2d67
--- /dev/null
+++ b/kotlinx-coroutines-debug/build.gradle.kts
@@ -0,0 +1,111 @@
+import com.github.jengelman.gradle.plugins.shadow.tasks.*
+import java.net.*
+import java.nio.file.*
+
+plugins {
+ id("com.github.johnrengelman.shadow")
+ id("org.jetbrains.kotlinx.kover") // apply plugin to use autocomplete for Kover DSL
+}
+
+configurations {
+ val shadowDeps by creating
+ compileOnly.configure {
+ extendsFrom(shadowDeps)
+ }
+ runtimeOnly.configure {
+ extendsFrom(shadowDeps)
+ }
+}
+
+val junit_version by properties
+val junit5_version by properties
+val byte_buddy_version by properties
+val blockhound_version by properties
+val jna_version by properties
+
+dependencies {
+ compileOnly("junit:junit:$junit_version")
+ compileOnly("org.junit.jupiter:junit-jupiter-api:$junit5_version")
+ testImplementation("org.junit.jupiter:junit-jupiter-engine:$junit5_version")
+ testImplementation("org.junit.platform:junit-platform-testkit:1.7.0")
+ add("shadowDeps", "net.bytebuddy:byte-buddy:$byte_buddy_version")
+ add("shadowDeps", "net.bytebuddy:byte-buddy-agent:$byte_buddy_version")
+ compileOnly("io.projectreactor.tools:blockhound:$blockhound_version")
+ testImplementation("io.projectreactor.tools:blockhound:$blockhound_version")
+ testImplementation("com.google.code.gson:gson:2.8.6")
+ api("net.java.dev.jna:jna:$jna_version")
+ api("net.java.dev.jna:jna-platform:$jna_version")
+}
+
+java {
+ /* This is needed to be able to run JUnit5 tests. Otherwise, Gradle complains that it can't find the
+ JVM1.6-compatible version of the `junit-jupiter-api` artifact. */
+ disableAutoTargetJvm()
+}
+
+// This is required for BlockHound tests to work, see https://github.com/Kotlin/kotlinx.coroutines/issues/3701
+tasks.withType<Test>().configureEach {
+ if (JavaVersion.toVersion(jdkToolchainVersion).isCompatibleWith(JavaVersion.VERSION_13)) {
+ jvmArgs("-XX:+AllowRedefinitionToAddDeleteMethods")
+ }
+}
+
+val jar by tasks.existing(Jar::class) {
+ enabled = false
+}
+
+val shadowJar by tasks.existing(ShadowJar::class) {
+ // Shadow only byte buddy, do not package kotlin stdlib
+ configurations = listOf(project.configurations["shadowDeps"])
+ relocate("net.bytebuddy", "kotlinx.coroutines.repackaged.net.bytebuddy")
+ /* These classifiers are both set to `null` to trick Gradle into thinking that this jar file is both the
+ artifact from the `jar` task and the one from `shadowJar`. Without this, Gradle complains that the artifact
+ from the `jar` task is not present when the compilaton finishes, even if the file with this name exists. */
+ archiveClassifier.convention(null as String?)
+ archiveClassifier = null
+ archiveBaseName = jar.flatMap { it.archiveBaseName }
+ archiveVersion = jar.flatMap { it.archiveVersion }
+ manifest {
+ attributes(
+ mapOf(
+ "Premain-Class" to "kotlinx.coroutines.debug.AgentPremain",
+ "Can-Redefine-Classes" to "true",
+ "Multi-Release" to "true"
+ )
+ )
+ }
+ // add module-info.class to the META-INF/versions/9/ directory.
+ dependsOn(tasks.compileModuleInfoJava)
+ doLast {
+ // We can't do that directly with the shadowJar task because it doesn't support replacing existing files.
+ val zipPath = [email protected]()
+ val zipUri = URI.create("jar:${zipPath.toUri()}")
+ val moduleInfoFilePath = tasks.compileModuleInfoJava.get().outputs.files.asFileTree.matching {
+ include("module-info.class")
+ }.singleFile.toPath()
+ FileSystems.newFileSystem(zipUri, emptyMap<String, String>()).use { fs ->
+ val moduleInfoFile = fs.getPath("META-INF/versions/9/module-info.class")
+ Files.copy(moduleInfoFilePath, moduleInfoFile, StandardCopyOption.REPLACE_EXISTING)
+ }
+ }
+}
+
+configurations {
+ // shadowJar is already part of the `shadowRuntimeElements` and `shadowApiElements`, but the other subprojects
+ // that depend on `kotlinx-coroutines-debug` look at `runtimeElements` and `apiElements`.
+ artifacts {
+ add("apiElements", shadowJar)
+ add("runtimeElements", shadowJar)
+ }
+}
+
+kover {
+ reports {
+ filters {
+ excludes {
+ // Never used, safety mechanism
+ classes("kotlinx.coroutines.debug.internal.NoOpProbesKt")
+ }
+ }
+ }
+}
diff --git a/kotlinx-coroutines-debug/src/CoroutineInfo.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt
index 62728ad..cb89405 100644
--- a/kotlinx-coroutines-debug/src/CoroutineInfo.kt
+++ b/kotlinx-coroutines-debug/src/CoroutineInfo.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNUSED")
package kotlinx.coroutines.debug
diff --git a/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt b/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt
index 99f2b19..f8213ea 100644
--- a/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt
+++ b/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package kotlinx.coroutines.debug
diff --git a/kotlinx-coroutines-debug/src/DebugProbes.kt b/kotlinx-coroutines-debug/src/DebugProbes.kt
index 493b85e..104212b 100644
--- a/kotlinx-coroutines-debug/src/DebugProbes.kt
+++ b/kotlinx-coroutines-debug/src/DebugProbes.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNUSED", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package kotlinx.coroutines.debug
@@ -13,11 +9,12 @@
import kotlin.coroutines.*
/**
- * Debug probes support.
+ * Kotlin debug probes support.
*
* Debug probes is a dynamic attach mechanism which installs multiple hooks into coroutines machinery.
- * It slows down all coroutine-related code, but in return provides a lot of diagnostic information, including
- * asynchronous stack-traces and coroutine dumps (similar to [ThreadMXBean.dumpAllThreads] and `jstack` via [DebugProbes.dumpCoroutines].
+ * It slows down all coroutine-related code, but in return provides diagnostic information, including
+ * asynchronous stacktraces, coroutine dumps (similar to [ThreadMXBean.dumpAllThreads] and `jstack`) via [DebugProbes.dumpCoroutines],
+ * and programmatic introspection of all alive coroutines.
* All introspecting methods throw [IllegalStateException] if debug probes were not installed.
*
* ### Consistency guarantees
@@ -28,16 +25,26 @@
* In practice, it means that for snapshotting operations in progress, for each concurrent coroutine either
* the state prior to the operation or the state that was reached during the current operation is observed.
*
- * ### Installed hooks
- * * `probeCoroutineResumed` is invoked on every [Continuation.resume].
- * * `probeCoroutineSuspended` is invoked on every continuation suspension.
- * * `probeCoroutineCreated` is invoked on every coroutine creation.
- *
* ### Overhead
- * * Every created coroutine is stored in a concurrent hash map and hash map is looked up and
+ *
+ * - Every created coroutine is stored in a concurrent hash map, and the hash map is looked up in and
* updated on each suspension and resumption.
- * * If [DebugProbes.enableCreationStackTraces] is enabled, stack trace of the current thread is captured on
+ * - If [DebugProbes.enableCreationStackTraces] is enabled, stack trace of the current thread is captured on
* each created coroutine that is a rough equivalent of throwing an exception per each created coroutine.
+ *
+ * ### Internal machinery and classloading.
+ *
+ * Under the hood, debug probes replace internal `kotlin.coroutines.jvm.internal.DebugProbesKt` class that has the following
+ * empty static methods:
+ *
+ * - `probeCoroutineResumed` that is invoked on every [Continuation.resume].
+ * - `probeCoroutineSuspended` that is invoked on every continuation suspension.
+ * - `probeCoroutineCreated` that is invoked on every coroutine creation.
+ *
+ * with a `kotlinx-coroutines`-specific class to keep track of all the coroutines machinery.
+ *
+ * The new class is located in the `kotlinx-coroutines-core` module, meaning that all target application classes that use
+ * coroutines and `suspend` functions have to be loaded by the classloader in which `kotlinx-coroutines-core` classes are available.
*/
@ExperimentalCoroutinesApi
public object DebugProbes {
@@ -51,21 +58,22 @@
*/
public var sanitizeStackTraces: Boolean
get() = DebugProbesImpl.sanitizeStackTraces
+ @Suppress("INVISIBLE_SETTER") // do not remove the INVISIBLE_SETTER suppression: required in k2
set(value) {
DebugProbesImpl.sanitizeStackTraces = value
}
/**
* Whether coroutine creation stack traces should be captured.
- * When enabled, for each created coroutine a stack trace of the current
- * thread is captured and attached to the coroutine.
+ * When enabled, for each created coroutine a stack trace of the current thread is captured and attached to the coroutine.
* This option can be useful during local debug sessions, but is recommended
- * to be disabled in production environments to avoid stack trace dumping overhead.
+ * to be disabled in production environments to avoid performance overhead of capturing real stacktraces.
*
- * `true` by default.
+ * `false` by default.
*/
public var enableCreationStackTraces: Boolean
get() = DebugProbesImpl.enableCreationStackTraces
+ @Suppress("INVISIBLE_SETTER") // do not remove the INVISIBLE_SETTER suppression: required in k2
set(value) {
DebugProbesImpl.enableCreationStackTraces = value
}
@@ -82,6 +90,7 @@
*/
public var ignoreCoroutinesWithEmptyContext: Boolean
get() = DebugProbesImpl.ignoreCoroutinesWithEmptyContext
+ @Suppress("INVISIBLE_SETTER") // do not remove the INVISIBLE_SETTER suppression: required in k2
set(value) {
DebugProbesImpl.ignoreCoroutinesWithEmptyContext = value
}
diff --git a/kotlinx-coroutines-debug/src/internal/Attach.kt b/kotlinx-coroutines-debug/src/internal/Attach.kt
index f1cc96e..63bfe8e 100644
--- a/kotlinx-coroutines-debug/src/internal/Attach.kt
+++ b/kotlinx-coroutines-debug/src/internal/Attach.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("unused")
package kotlinx.coroutines.debug.internal
diff --git a/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt b/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt
index 34f1afe..b7b8bf5 100644
--- a/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt
+++ b/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("unused", "UNUSED_PARAMETER")
package kotlinx.coroutines.debug.internal
diff --git a/kotlinx-coroutines-debug/src/junit/CoroutinesTimeoutImpl.kt b/kotlinx-coroutines-debug/src/junit/CoroutinesTimeoutImpl.kt
index 06a84a5..ba5804d 100644
--- a/kotlinx-coroutines-debug/src/junit/CoroutinesTimeoutImpl.kt
+++ b/kotlinx-coroutines-debug/src/junit/CoroutinesTimeoutImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
import java.util.concurrent.*
diff --git a/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeout.kt b/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeout.kt
index 12bc947..f9f2a74 100644
--- a/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeout.kt
+++ b/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeout.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit4
import kotlinx.coroutines.debug.*
@@ -18,7 +14,7 @@
* Additionally, this rule installs [DebugProbes] and dumps all coroutines at the moment of the timeout.
* It may cancel coroutines on timeout if [cancelOnTimeout] set to `true`.
* [enableCoroutineCreationStackTraces] controls the corresponding [DebugProbes.enableCreationStackTraces] property
- * and can be optionally disabled to speed-up tests if creation stack traces are not needed.
+ * and can be optionally enabled if the creation stack traces are necessary.
*
* Example of usage:
* ```
@@ -38,7 +34,7 @@
public class CoroutinesTimeout(
private val testTimeoutMs: Long,
private val cancelOnTimeout: Boolean = false,
- private val enableCoroutineCreationStackTraces: Boolean = true
+ private val enableCoroutineCreationStackTraces: Boolean = false
) : TestRule {
@Suppress("UNUSED") // Binary compatibility
diff --git a/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeoutStatement.kt b/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeoutStatement.kt
index aa6b8df..a51ea6a 100644
--- a/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeoutStatement.kt
+++ b/kotlinx-coroutines-debug/src/junit/junit4/CoroutinesTimeoutStatement.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit4
import kotlinx.coroutines.debug.*
diff --git a/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeout.kt b/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeout.kt
index 9a8263f..c2ac059 100644
--- a/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeout.kt
+++ b/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeout.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.debug.*
import org.junit.jupiter.api.*
diff --git a/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt b/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt
index 442fdf8..3179dc1 100644
--- a/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt
+++ b/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.debug.*
@@ -21,7 +17,7 @@
* Additionally, it installs [DebugProbes] and dumps all coroutines at the moment of the timeout. It also cancels
* coroutines on timeout if [cancelOnTimeout] set to `true`.
* [enableCoroutineCreationStackTraces] controls the corresponding [DebugProbes.enableCreationStackTraces] property
- * and can be optionally disabled to speed-up tests if creation stack traces are not needed.
+ * and can be optionally enabled if the creation stack traces are necessary.
*
* Beware that if several tests that use this extension set [enableCoroutineCreationStackTraces] to different values and
* execute in parallel, the behavior is ill-defined. In order to avoid conflicts between different instances of this
@@ -55,7 +51,7 @@
* */
// NB: the constructor is not private so that JUnit is able to call it via reflection.
internal class CoroutinesTimeoutExtension internal constructor(
- private val enableCoroutineCreationStackTraces: Boolean = true,
+ private val enableCoroutineCreationStackTraces: Boolean = false,
private val timeoutMs: Long? = null,
private val cancelOnTimeout: Boolean? = null): InvocationInterceptor
{
@@ -112,14 +108,14 @@
* However, extension instances can be reused with different value stores, and value stores can be reused across
* extension instances. This leads to a tricky scheme of performing [DebugProbes.uninstall]:
*
- * * If neither the ownership of this instance's [DebugProbes] was yet passed nor there is any cleanup procedure
+ * - If neither the ownership of this instance's [DebugProbes] was yet passed nor there is any cleanup procedure
* stored, it means that we can just store our cleanup procedure, passing the ownership.
- * * If the ownership was not yet passed, but a cleanup procedure is already stored, we can't just replace it with
+ * - If the ownership was not yet passed, but a cleanup procedure is already stored, we can't just replace it with
* another one, as this would lead to imbalance between [DebugProbes.install] and [DebugProbes.uninstall].
* Instead, we know that this extension context will at least outlive this use of this instance, so some debug
* probes other than the ones from our constructor are already installed and won't be uninstalled during our
* operation. We simply uninstall the debug probes that were installed in our constructor.
- * * If the ownership was passed, but the store is empty, it means that this test instance is reused and, possibly,
+ * - If the ownership was passed, but the store is empty, it means that this test instance is reused and, possibly,
* the debug probes installed in its constructor were already uninstalled. This means that we have to install them
* anew and store an uninstaller.
*/
@@ -276,4 +272,4 @@
): T =
runWithTimeoutDumpingCoroutines(methodName, testTimeoutMs, cancelOnTimeout,
{ CoroutinesTimeoutException(testTimeoutMs) }, { invocation.proceed() })
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-debug/test/BlockHoundTest.kt b/kotlinx-coroutines-debug/test/BlockHoundTest.kt
index 5ec767c..8faa3e8 100644
--- a/kotlinx-coroutines-debug/test/BlockHoundTest.kt
+++ b/kotlinx-coroutines-debug/test/BlockHoundTest.kt
@@ -1,5 +1,6 @@
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.*
diff --git a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt
index 12573cf..aba27e7 100644
--- a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt
+++ b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt
@@ -1,10 +1,8 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
+import org.junit.*
import org.junit.Test
import kotlin.coroutines.*
import kotlin.test.*
@@ -13,6 +11,12 @@
private val monitor = Any()
private var coroutineThread: Thread? = null // guarded by monitor
+ @Before
+ override fun setUp() {
+ super.setUp()
+ DebugProbes.enableCreationStackTraces = true
+ }
+
@Test
fun testSuspendedCoroutine() = runBlocking {
val deferred = async(Dispatchers.Default) {
diff --git a/kotlinx-coroutines-debug/test/DebugLeaksTest.kt b/kotlinx-coroutines-debug/test/DebugLeaksTest.kt
index a43b33b..7a59783 100644
--- a/kotlinx-coroutines-debug/test/DebugLeaksTest.kt
+++ b/kotlinx-coroutines-debug/test/DebugLeaksTest.kt
@@ -1,7 +1,4 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.*
import kotlinx.coroutines.debug.internal.*
@@ -54,4 +51,4 @@
private fun assertNoCapturedReference() {
FieldWalker.assertReachableCount(0, DebugProbesImpl, rootStatics = true) { it is Captured }
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-debug/test/DebugProbesTest.kt b/kotlinx-coroutines-debug/test/DebugProbesTest.kt
index cbeeb31..3994bb4 100644
--- a/kotlinx-coroutines-debug/test/DebugProbesTest.kt
+++ b/kotlinx-coroutines-debug/test/DebugProbesTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import java.util.concurrent.*
@@ -20,14 +18,14 @@
val deferred = createDeferred()
val traces = listOf(
"java.util.concurrent.ExecutionException\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
- "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:49)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:44)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsync\$1.invokeSuspend(DebugProbesTest.kt:17)\n",
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
+ "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:49)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:44)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsync\$1.invokeSuspend(DebugProbesTest.kt:17)\n",
"Caused by: java.util.concurrent.ExecutionException\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
- "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)"
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
+ "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)"
)
nestedMethod(deferred, traces)
deferred.join()
@@ -40,25 +38,15 @@
val deferred = createDeferred()
val traces = listOf(
"java.util.concurrent.ExecutionException\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
- "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:62)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)\n" +
- "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt)\n" +
- "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable\$default(Cancellable.kt)\n" +
- "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt)\n" +
- "\tat kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt)\n" +
- "\tat kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt)\n" +
- "\tat kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)\n" +
- "\tat kotlinx.coroutines.TestBase.runTest(TestBase.kt)\n" +
- "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.testAsyncWithProbes(DebugProbesTest.kt)",
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
+ "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:62)",
"Caused by: java.util.concurrent.ExecutionException\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
- "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)\n")
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
+ "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)\n"
+ )
nestedMethod(deferred, traces)
deferred.join()
}
@@ -71,18 +59,15 @@
val deferred = createDeferred()
val traces = listOf(
"java.util.concurrent.ExecutionException\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
- "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:71)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:66)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithSanitizedProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:87)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
- "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest.testAsyncWithSanitizedProbes(DebugProbesTest.kt:38)",
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
+ "\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:71)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:66)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithSanitizedProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:87)",
"Caused by: java.util.concurrent.ExecutionException\n" +
- "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
- "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n")
+ "\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
+ "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n"
+ )
nestedMethod(deferred, traces)
deferred.join()
}
diff --git a/kotlinx-coroutines-debug/test/DebugTestBase.kt b/kotlinx-coroutines-debug/test/DebugTestBase.kt
index 2a37f58..97c2906 100644
--- a/kotlinx-coroutines-debug/test/DebugTestBase.kt
+++ b/kotlinx-coroutines-debug/test/DebugTestBase.kt
@@ -1,9 +1,7 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit4.*
import org.junit.*
@@ -18,7 +16,7 @@
open fun setUp() {
before()
DebugProbes.sanitizeStackTraces = false
- DebugProbes.enableCreationStackTraces = true
+ DebugProbes.enableCreationStackTraces = false
DebugProbes.install()
}
diff --git a/kotlinx-coroutines-debug/test/DumpCoroutineInfoAsJsonAndReferencesTest.kt b/kotlinx-coroutines-debug/test/DumpCoroutineInfoAsJsonAndReferencesTest.kt
index 7d25219..afd7a50 100644
--- a/kotlinx-coroutines-debug/test/DumpCoroutineInfoAsJsonAndReferencesTest.kt
+++ b/kotlinx-coroutines-debug/test/DumpCoroutineInfoAsJsonAndReferencesTest.kt
@@ -1,9 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import com.google.gson.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
@@ -70,12 +68,13 @@
val lastObservedFrames = dumpResult[2]
val coroutinesInfo = dumpResult[3]
- assertTrue(coroutinesInfoAsJsonString is String)
- assertTrue(lastObservedThreads is Array<*>)
- assertTrue(lastObservedFrames is Array<*>)
- assertTrue(coroutinesInfo is Array<*>)
+ assertIs<String>(coroutinesInfoAsJsonString)
+ assertIs<Array<*>>(lastObservedThreads)
+ assertIs<Array<*>>(lastObservedFrames)
+ assertIs<Array<*>>(coroutinesInfo)
- val coroutinesInfoFromJson = Gson().fromJson(coroutinesInfoAsJsonString, Array<CoroutineInfoFromJson>::class.java)
+ val coroutinesInfoFromJson =
+ Gson().fromJson(coroutinesInfoAsJsonString, Array<CoroutineInfoFromJson>::class.java)
val size = coroutinesInfo.size
assertTrue(size != 0)
@@ -86,7 +85,7 @@
for (i in 0 until size) {
val info = coroutinesInfo[i]
val infoFromJson = coroutinesInfoFromJson[i]
- assertTrue(info is DebugCoroutineInfo)
+ assertIs<DebugCoroutineInfo>(info)
assertEquals(info.lastObservedThread, lastObservedThreads[i])
assertEquals(info.lastObservedFrame, lastObservedFrames[i])
assertEquals(info.sequenceNumber, infoFromJson.sequenceNumber)
diff --git a/kotlinx-coroutines-debug/test/DumpWithCreationStackTraceTest.kt b/kotlinx-coroutines-debug/test/DumpWithCreationStackTraceTest.kt
new file mode 100644
index 0000000..cb0ae38
--- /dev/null
+++ b/kotlinx-coroutines-debug/test/DumpWithCreationStackTraceTest.kt
@@ -0,0 +1,47 @@
+package kotlinx.coroutines.debug
+
+import kotlinx.coroutines.*
+import org.junit.*
+import org.junit.Test
+import kotlin.test.*
+
+class DumpWithCreationStackTraceTest : DebugTestBase() {
+ @Before
+ override fun setUp() {
+ super.setUp()
+ DebugProbes.enableCreationStackTraces = true
+ }
+
+ @Test
+ fun testCoroutinesDump() = runTest {
+ val deferred = createActiveDeferred()
+ yield()
+ verifyDump(
+ "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@70d1cb56, state: RUNNING\n" +
+ "\tat java.lang.Thread.getStackTrace(Thread.java)\n" +
+ "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.enhanceStackTraceWithThreadDumpImpl(DebugProbesImpl.kt)\n" +
+ "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutinesSynchronized(DebugProbesImpl.kt)\n" +
+ "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutines(DebugProbesImpl.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DebugProbes.dumpCoroutines(DebugProbes.kt:182)\n" +
+ "\tat kotlinx.coroutines.debug.StacktraceUtilsKt.verifyDump(StacktraceUtils.kt)\n" +
+ "\tat kotlinx.coroutines.debug.StacktraceUtilsKt.verifyDump\$default(StacktraceUtils.kt)\n" +
+ "\tat kotlinx.coroutines.debug.DumpWithCreationStackTraceTest\$testCoroutinesDump\$1.invokeSuspend(DumpWithCreationStackTraceTest.kt)\n" +
+ "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
+ "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)",
+
+ "Coroutine \"coroutine#2\":DeferredCoroutine{Active}@383fa309, state: SUSPENDED\n" +
+ "\tat kotlinx.coroutines.debug.DumpWithCreationStackTraceTest\$createActiveDeferred\$1.invokeSuspend(DumpWithCreationStackTraceTest.kt)"
+ )
+ deferred.cancelAndJoin()
+ }
+
+
+ private fun CoroutineScope.createActiveDeferred(): Deferred<*> = async {
+ suspendingMethod()
+ assertTrue(true)
+ }
+
+ private suspend fun suspendingMethod() {
+ delay(Long.MAX_VALUE)
+ }
+}
diff --git a/kotlinx-coroutines-debug/test/DumpWithoutCreationStackTraceTest.kt b/kotlinx-coroutines-debug/test/DumpWithoutCreationStackTraceTest.kt
deleted file mode 100644
index 6e405ca..0000000
--- a/kotlinx-coroutines-debug/test/DumpWithoutCreationStackTraceTest.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-package kotlinx.coroutines.debug
-
-import kotlinx.coroutines.*
-import org.junit.*
-import org.junit.Test
-import kotlin.test.*
-
-class DumpWithoutCreationStackTraceTest : DebugTestBase() {
- @Before
- override fun setUp() {
- super.setUp()
- DebugProbes.enableCreationStackTraces = false
- }
-
- @Test
- fun testCoroutinesDump() = runTest {
- val deferred = createActiveDeferred()
- yield()
- verifyDump(
- "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@70d1cb56, state: RUNNING\n" +
- "\tat java.lang.Thread.getStackTrace(Thread.java)\n" +
- "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.enhanceStackTraceWithThreadDumpImpl(DebugProbesImpl.kt)\n" +
- "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutinesSynchronized(DebugProbesImpl.kt)\n" +
- "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutines(DebugProbesImpl.kt)",
-
- "Coroutine \"coroutine#2\":DeferredCoroutine{Active}@383fa309, state: SUSPENDED\n" +
- "\tat kotlinx.coroutines.debug.DumpWithoutCreationStackTraceTest\$createActiveDeferred\$1.invokeSuspend(DumpWithoutCreationStackTraceTest.kt)"
- )
- deferred.cancelAndJoin()
- }
-
-
- private fun CoroutineScope.createActiveDeferred(): Deferred<*> = async {
- suspendingMethod()
- assertTrue(true)
- }
-
- private suspend fun suspendingMethod() {
- delay(Long.MAX_VALUE)
- }
-}
diff --git a/kotlinx-coroutines-debug/test/EnhanceStackTraceWithTreadDumpAsJsonTest.kt b/kotlinx-coroutines-debug/test/EnhanceStackTraceWithTreadDumpAsJsonTest.kt
index fcf9f1a..72e61d6 100644
--- a/kotlinx-coroutines-debug/test/EnhanceStackTraceWithTreadDumpAsJsonTest.kt
+++ b/kotlinx-coroutines-debug/test/EnhanceStackTraceWithTreadDumpAsJsonTest.kt
@@ -1,9 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import com.google.gson.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
diff --git a/kotlinx-coroutines-debug/test/LazyCoroutineTest.kt b/kotlinx-coroutines-debug/test/LazyCoroutineTest.kt
index c872b6a..8cf1f86 100644
--- a/kotlinx-coroutines-debug/test/LazyCoroutineTest.kt
+++ b/kotlinx-coroutines-debug/test/LazyCoroutineTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-debug/test/RecoveryExample.kt b/kotlinx-coroutines-debug/test/RecoveryExample.kt
index 2280dd1..eeadcf5 100644
--- a/kotlinx-coroutines-debug/test/RecoveryExample.kt
+++ b/kotlinx-coroutines-debug/test/RecoveryExample.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("PackageDirectoryMismatch")
package example
diff --git a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt
index 89dd914..bafea1f 100644
--- a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt
+++ b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
import org.junit.Test
@@ -20,18 +18,16 @@
awaitCoroutineStarted()
verifyDump(
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@50284dc4, state: RUNNING\n" +
- "\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
- "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
- "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
- "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
- "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:86)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.access\$nonSuspendingFun(RunningThreadStackMergeTest.kt:12)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$suspendingFunction\$2.invokeSuspend(RunningThreadStackMergeTest.kt:77)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunction(RunningThreadStackMergeTest.kt:75)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchCoroutine\$1.invokeSuspend(RunningThreadStackMergeTest.kt:68)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)",
+ "\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
+ "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
+ "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
+ "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
+ "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:86)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.access\$nonSuspendingFun(RunningThreadStackMergeTest.kt:12)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$suspendingFunction\$2.invokeSuspend(RunningThreadStackMergeTest.kt:77)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunction(RunningThreadStackMergeTest.kt:75)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchCoroutine\$1.invokeSuspend(RunningThreadStackMergeTest.kt:68)",
ignoredCoroutine = "BlockingCoroutine"
) {
coroutineBlocker.await()
@@ -74,18 +70,16 @@
Thread.sleep(10)
verifyDump(
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@3aea3c67, state: RUNNING\n" +
- "\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
- "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
- "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
- "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
- "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:83)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.access\$nonSuspendingFun(RunningThreadStackMergeTest.kt:12)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$suspendingFunctionWithContext\$2.invokeSuspend(RunningThreadStackMergeTest.kt:124)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunctionWithContext(RunningThreadStackMergeTest.kt:122)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchEscapingCoroutine\$1.invokeSuspend(RunningThreadStackMergeTest.kt:116)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)",
+ "\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
+ "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
+ "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
+ "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
+ "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:83)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.access\$nonSuspendingFun(RunningThreadStackMergeTest.kt:12)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$suspendingFunctionWithContext\$2.invokeSuspend(RunningThreadStackMergeTest.kt:124)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunctionWithContext(RunningThreadStackMergeTest.kt:122)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchEscapingCoroutine\$1.invokeSuspend(RunningThreadStackMergeTest.kt:116)",
ignoredCoroutine = "BlockingCoroutine"
) {
coroutineBlocker.await()
@@ -114,16 +108,14 @@
awaitCoroutineStarted()
verifyDump(
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@3aea3c67, state: RUNNING\n" +
- "\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
- "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
- "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
- "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
- "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:83)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunctionWithoutContext(RunningThreadStackMergeTest.kt:160)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchEscapingCoroutineWithoutContext\$1.invokeSuspend(RunningThreadStackMergeTest.kt:153)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)",
+ "\tat jdk.internal.misc.Unsafe.park(Native Method)\n" +
+ "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" +
+ "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" +
+ "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" +
+ "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:83)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunctionWithoutContext(RunningThreadStackMergeTest.kt:160)\n" +
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchEscapingCoroutineWithoutContext\$1.invokeSuspend(RunningThreadStackMergeTest.kt:153)",
ignoredCoroutine = "BlockingCoroutine"
) {
coroutineBlocker.await()
@@ -145,7 +137,8 @@
@Test
fun testRunBlocking() = runBlocking {
- verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@4bcd176c, state: RUNNING\n" +
+ verifyDump(
+ "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@4bcd176c, state: RUNNING\n" +
"\tat java.lang.Thread.getStackTrace(Thread.java)\n" +
"\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.enhanceStackTraceWithThreadDumpImpl(DebugProbesImpl.kt)\n" +
"\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutinesSynchronized(DebugProbesImpl.kt)\n" +
@@ -153,9 +146,8 @@
"\tat kotlinx.coroutines.debug.DebugProbes.dumpCoroutines(DebugProbes.kt)\n" +
"\tat kotlinx.coroutines.debug.StacktraceUtilsKt.verifyDump(StacktraceUtils.kt)\n" +
"\tat kotlinx.coroutines.debug.StacktraceUtilsKt.verifyDump\$default(StacktraceUtils.kt)\n" +
- "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$testRunBlocking\$1.invokeSuspend(RunningThreadStackMergeTest.kt)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)\n")
+ "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$testRunBlocking\$1.invokeSuspend(RunningThreadStackMergeTest.kt)"
+ )
}
diff --git a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt
index 6afda16..b14ac7c 100644
--- a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt
+++ b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("PackageDirectoryMismatch")
package definitely.not.kotlinx.coroutines
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.*
import kotlinx.coroutines.selects.*
@@ -18,6 +15,7 @@
override fun setUp() {
super.setUp()
DebugProbes.sanitizeStackTraces = true
+ DebugProbes.enableCreationStackTraces = true
}
@Test
@@ -33,7 +31,7 @@
"\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" +
- "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt:141)\n" +
+ "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:141)\n" +
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testRecoveredStackTrace(SanitizedProbesTest.kt:33)",
"Caused by: java.util.concurrent.ExecutionException\n" +
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$createDeferredNested\$1.invokeSuspend(SanitizedProbesTest.kt:57)\n" +
@@ -53,7 +51,7 @@
"\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" +
- "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt:141)\n" +
+ "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:141)\n" +
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testCoroutinesDump(SanitizedProbesTest.kt:56)",
"Coroutine \"coroutine#4\":DeferredCoroutine{Active}@75c072cb, state: SUSPENDED\n" +
@@ -68,7 +66,7 @@
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testCoroutinesDump\$1.invokeSuspend(SanitizedProbesTest.kt:57)\n" +
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" +
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:237)\n" +
- "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt:141)\n" +
+ "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:141)\n" +
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testCoroutinesDump(SanitizedProbesTest.kt:56)"
)
deferred.cancelAndJoin()
@@ -97,7 +95,7 @@
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testSelectBuilder\$1.invokeSuspend(SanitizedProbesTest.kt:89)\n" +
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" +
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:233)\n" +
- "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt:154)\n" +
+ "\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt:154)\n" +
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testSelectBuilder(SanitizedProbesTest.kt:88)")
finish(4)
selector.cancelAndJoin()
diff --git a/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt b/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt
index 801b74b..a1eb331 100644
--- a/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt
+++ b/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import kotlin.coroutines.*
@@ -16,17 +13,14 @@
yield()
yield()
verifyDump(
- "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@16612a51, state: RUNNING\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n",
+ "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@16612a51, state: RUNNING",
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@6b53e23f, state: SUSPENDED\n" +
"\tat kotlinx.coroutines.debug.ScopedBuildersTest\$doWithContext\$2.invokeSuspend(ScopedBuildersTest.kt:49)\n" +
"\tat kotlinx.coroutines.debug.ScopedBuildersTest.doWithContext(ScopedBuildersTest.kt:47)\n" +
"\tat kotlinx.coroutines.debug.ScopedBuildersTest\$doInScope\$2.invokeSuspend(ScopedBuildersTest.kt:41)\n" +
- "\tat kotlinx.coroutines.debug.ScopedBuildersTest\$testNestedScopes\$1\$job\$1.invokeSuspend(ScopedBuildersTest.kt:30)\n" +
- "\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
- "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)")
+ "\tat kotlinx.coroutines.debug.ScopedBuildersTest\$testNestedScopes\$1\$job\$1.invokeSuspend(ScopedBuildersTest.kt:30)"
+ )
job.cancelAndJoin()
finish(4)
}
diff --git a/kotlinx-coroutines-debug/test/StacktraceUtils.kt b/kotlinx-coroutines-debug/test/StacktraceUtils.kt
index 869e297..90ce389 100644
--- a/kotlinx-coroutines-debug/test/StacktraceUtils.kt
+++ b/kotlinx-coroutines-debug/test/StacktraceUtils.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
import java.io.*
diff --git a/kotlinx-coroutines-debug/test/StandardBuildersDebugTest.kt b/kotlinx-coroutines-debug/test/StandardBuildersDebugTest.kt
index 7ca8f14..1a3076e 100644
--- a/kotlinx-coroutines-debug/test/StandardBuildersDebugTest.kt
+++ b/kotlinx-coroutines-debug/test/StandardBuildersDebugTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import org.junit.Test
import kotlin.test.*
diff --git a/kotlinx-coroutines-debug/test/StartModeProbesTest.kt b/kotlinx-coroutines-debug/test/StartModeProbesTest.kt
index c2656d3..035873a 100644
--- a/kotlinx-coroutines-debug/test/StartModeProbesTest.kt
+++ b/kotlinx-coroutines-debug/test/StartModeProbesTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.Test
diff --git a/kotlinx-coroutines-debug/test/TestRuleExample.kt b/kotlinx-coroutines-debug/test/TestRuleExample.kt
index b5d1c26..df5473e 100644
--- a/kotlinx-coroutines-debug/test/TestRuleExample.kt
+++ b/kotlinx-coroutines-debug/test/TestRuleExample.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import kotlinx.coroutines.*
import kotlinx.coroutines.debug.junit4.*
import org.junit.*
diff --git a/kotlinx-coroutines-debug/test/ToStringTest.kt b/kotlinx-coroutines-debug/test/ToStringTest.kt
index 0ea412b..e4330b7 100644
--- a/kotlinx-coroutines-debug/test/ToStringTest.kt
+++ b/kotlinx-coroutines-debug/test/ToStringTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.*
diff --git a/kotlinx-coroutines-debug/test/WithContextUndispatchedTest.kt b/kotlinx-coroutines-debug/test/WithContextUndispatchedTest.kt
index e803c98..47274d8 100644
--- a/kotlinx-coroutines-debug/test/WithContextUndispatchedTest.kt
+++ b/kotlinx-coroutines-debug/test/WithContextUndispatchedTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.debug
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.*
diff --git a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutDisabledTracesTest.kt b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutDisabledTracesTest.kt
index 4352140..8a24313 100644
--- a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutDisabledTracesTest.kt
+++ b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutDisabledTracesTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit4
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.runners.model.*
diff --git a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutEagerTest.kt b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutEagerTest.kt
index 7a686ff..458d0ee 100644
--- a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutEagerTest.kt
+++ b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutEagerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit4
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.runners.model.*
diff --git a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt
index 53447ac..9a429d5 100644
--- a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt
+++ b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit4
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.runners.model.*
diff --git a/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt b/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt
index 6d25a6d..5bbb84c 100644
--- a/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt
+++ b/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit4
import kotlinx.coroutines.debug.*
diff --git a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutExtensionTest.kt b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutExtensionTest.kt
index 752c6c3..1229815 100644
--- a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutExtensionTest.kt
+++ b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutExtensionTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutInheritanceTest.kt b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutInheritanceTest.kt
index 7c8de53..4aa90bb 100644
--- a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutInheritanceTest.kt
+++ b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutInheritanceTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.jupiter.api.*
diff --git a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutMethodTest.kt b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutMethodTest.kt
index 64611b3..02bcafc 100644
--- a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutMethodTest.kt
+++ b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutMethodTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutNestedTest.kt b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutNestedTest.kt
index 04c933d..afb5169 100644
--- a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutNestedTest.kt
+++ b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutNestedTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutSimpleTest.kt b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutSimpleTest.kt
index 513a884..01487b7 100644
--- a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutSimpleTest.kt
+++ b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutSimpleTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutTest.kt b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutTest.kt
index 1f7b208..e504a3c 100644
--- a/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutTest.kt
+++ b/kotlinx-coroutines-debug/test/junit5/CoroutinesTimeoutTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import org.assertj.core.api.*
diff --git a/kotlinx-coroutines-debug/test/junit5/RegisterExtensionExample.kt b/kotlinx-coroutines-debug/test/junit5/RegisterExtensionExample.kt
index 2de6b5b..10411b7 100644
--- a/kotlinx-coroutines-debug/test/junit5/RegisterExtensionExample.kt
+++ b/kotlinx-coroutines-debug/test/junit5/RegisterExtensionExample.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.debug.junit5
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/README.md b/kotlinx-coroutines-test/README.md
index aa0606d..fbadf57 100644
--- a/kotlinx-coroutines-test/README.md
+++ b/kotlinx-coroutines-test/README.md
@@ -26,7 +26,7 @@
Add `kotlinx-coroutines-test` to your project test dependencies:
```
dependencies {
- testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.2'
+ testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1'
}
```
diff --git a/kotlinx-coroutines-test/build.gradle.kts b/kotlinx-coroutines-test/build.gradle.kts
index c968fc4..2c1d043 100644
--- a/kotlinx-coroutines-test/build.gradle.kts
+++ b/kotlinx-coroutines-test/build.gradle.kts
@@ -1,22 +1,10 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import org.jetbrains.kotlin.gradle.plugin.mpp.*
-
-val experimentalAnnotations = listOf(
- "kotlin.Experimental",
- "kotlinx.coroutines.ExperimentalCoroutinesApi",
- "kotlinx.coroutines.InternalCoroutinesApi"
-)
+import org.jetbrains.kotlin.gradle.targets.js.dsl.*
kotlin {
- sourceSets.all { configureMultiplatform() }
-
targets.withType(KotlinNativeTargetWithTests::class.java).configureEach {
binaries.getTest("DEBUG").apply {
optimized = true
- binaryOptions["memoryModel"] = "experimental"
}
}
@@ -27,4 +15,16 @@
}
}
}
+
+ @OptIn(ExperimentalWasmDsl::class)
+ wasmJs {
+ nodejs {
+ testTask {
+ filter.apply {
+ // https://youtrack.jetbrains.com/issue/KT-61888
+ excludeTest("TestDispatchersTest", "testMainMocking")
+ }
+ }
+ }
+ }
}
diff --git a/kotlinx-coroutines-test/common/src/TestBuilders.kt b/kotlinx-coroutines-test/common/src/TestBuilders.kt
index f95dabc..4fa8685 100644
--- a/kotlinx-coroutines-test/common/src/TestBuilders.kt
+++ b/kotlinx-coroutines-test/common/src/TestBuilders.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:JvmName("TestBuildersKt")
@file:JvmMultifileClass
@@ -14,22 +11,21 @@
import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.internal.*
/**
* A test result.
*
- * * On JVM and Native, this resolves to [Unit], representing the fact that tests are run in a blocking manner on these
+ * - On JVM and Native, this resolves to [Unit], representing the fact that tests are run in a blocking manner on these
* platforms: a call to a function returning a [TestResult] will simply execute the test inside it.
- * * On JS, this is a `Promise`, which reflects the fact that the test-running function does not wait for a test to
+ * - On JS, this is a `Promise`, which reflects the fact that the test-running function does not wait for a test to
* finish. The JS test frameworks typically support returning `Promise` from a test and will correctly handle it.
*
* Because of the behavior on JS, extra care must be taken when writing multiplatform tests to avoid losing test errors:
- * * Don't do anything after running the functions returning a [TestResult]. On JS, this code will execute *before* the
+ * - Don't do anything after running the functions returning a [TestResult]. On JS, this code will execute *before* the
* test finishes.
- * * As a corollary, don't run functions returning a [TestResult] more than once per test. The only valid thing to do
+ * - As a corollary, don't run functions returning a [TestResult] more than once per test. The only valid thing to do
* with a [TestResult] is to immediately `return` it from a test.
- * * Don't nest functions returning a [TestResult].
+ * - Don't nest functions returning a [TestResult].
*/
@Suppress("NO_ACTUAL_FOR_EXPECT")
public expect class TestResult
@@ -122,8 +118,14 @@
*
* #### Timing out
*
- * There's a built-in timeout of 10 seconds for the test body. If the test body doesn't complete within this time,
- * then the test fails with an [AssertionError]. The timeout can be changed by setting the [timeout] parameter.
+ * There's a built-in timeout of 60 seconds for the test body. If the test body doesn't complete within this time,
+ * then the test fails with an [AssertionError]. The timeout can be changed for each test separately by setting the
+ * [timeout] parameter.
+ *
+ * Additionally, setting the `kotlinx.coroutines.test.default_timeout` system property on the
+ * JVM to any string that can be parsed using [Duration.parse] (like `1m`, `30s` or `1500ms`) will change the default
+ * timeout to that value for all tests whose [timeout] is not set explicitly; setting it to anything else will throw an
+ * exception every time [runTest] is invoked.
*
* On timeout, the test body is cancelled so that the test finishes. If the code inside the test body does not
* respond to cancellation, the timeout will not be able to make the test execution stop.
@@ -157,7 +159,7 @@
*/
public fun runTest(
context: CoroutineContext = EmptyCoroutineContext,
- timeout: Duration = DEFAULT_TIMEOUT,
+ timeout: Duration = DEFAULT_TIMEOUT.getOrThrow(),
testBody: suspend TestScope.() -> Unit
): TestResult {
check(context[RunningInRunTest] == null) {
@@ -301,7 +303,7 @@
* Performs [runTest] on an existing [TestScope]. See the documentation for [runTest] for details.
*/
public fun TestScope.runTest(
- timeout: Duration = DEFAULT_TIMEOUT,
+ timeout: Duration = DEFAULT_TIMEOUT.getOrThrow(),
testBody: suspend TestScope.() -> Unit
): TestResult = asSpecificImplementation().let { scope ->
scope.enter()
@@ -421,8 +423,15 @@
/**
* The default timeout to use when running a test.
+ *
+ * It's not just a [Duration] but a [Result] so that every access to [runTest]
+ * throws the same clear exception if parsing the environment variable failed.
+ * Otherwise, the parsing error would only be thrown in one tests, while the
+ * other ones would get an incomprehensible `NoClassDefFoundError`.
*/
-internal val DEFAULT_TIMEOUT = 10.seconds
+private val DEFAULT_TIMEOUT: Result<Duration> = runCatching {
+ systemProperty("kotlinx.coroutines.test.default_timeout", Duration::parse, 60.seconds)
+}
/**
* Run the [body][testBody] of the [test coroutine][coroutine], waiting for asynchronous completions for at most
@@ -453,11 +462,11 @@
* 1. Try running the work that the scheduler knows about, both background and foreground.
*
* 2. Wait until we run out of foreground work to do. This could mean one of the following:
- * * The main coroutine is already completed. This is checked separately; then we leave the procedure.
- * * It's switched to another dispatcher that doesn't know about the [TestCoroutineScheduler].
- * * Generally, it's waiting for something external (like a network request, or just an arbitrary callback).
- * * The test simply hanged.
- * * The main coroutine is waiting for some background work.
+ * - The main coroutine is already completed. This is checked separately; then we leave the procedure.
+ * - It's switched to another dispatcher that doesn't know about the [TestCoroutineScheduler].
+ * - Generally, it's waiting for something external (like a network request, or just an arbitrary callback).
+ * - The test simply hanged.
+ * - The main coroutine is waiting for some background work.
*
* 3. We await progress from things that are not the code under test:
* the background work that the scheduler knows about, the external callbacks,
@@ -571,6 +580,17 @@
internal expect fun dumpCoroutines()
+private fun <T: Any> systemProperty(
+ name: String,
+ parse: (String) -> T,
+ default: T,
+): T {
+ val value = systemPropertyImpl(name) ?: return default
+ return parse(value)
+}
+
+internal expect fun systemPropertyImpl(name: String): String?
+
@Deprecated(
"This is for binary compatibility with the `runTest` overload that existed at some point",
level = DeprecationLevel.HIDDEN
diff --git a/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt b/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt
index 3777cd2..1b85bf9 100644
--- a/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt
+++ b/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
@@ -93,7 +89,8 @@
override fun isDispatchNeeded(context: CoroutineContext): Boolean = false
- @Suppress("INVISIBLE_MEMBER")
+ // do not remove the INVISIBLE_REFERENCE and INVISIBLE_SETTER suppressions: required in K2
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "INVISIBLE_SETTER")
override fun dispatch(context: CoroutineContext, block: Runnable) {
checkSchedulerInContext(scheduler, context)
scheduler.sendDispatchEvent(context)
diff --git a/kotlinx-coroutines-test/common/src/TestCoroutineScheduler.kt b/kotlinx-coroutines-test/common/src/TestCoroutineScheduler.kt
index 04e320d..8c70fa8 100644
--- a/kotlinx-coroutines-test/common/src/TestCoroutineScheduler.kt
+++ b/kotlinx-coroutines-test/common/src/TestCoroutineScheduler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.atomicfu.*
@@ -142,13 +138,13 @@
* scheduled tasks in the meantime.
*
* Breaking changes from [TestCoroutineDispatcher.advanceTimeBy]:
- * * Intentionally doesn't return a `Long` value, as its use cases are unclear. We may restore it in the future;
+ * - Intentionally doesn't return a `Long` value, as its use cases are unclear. We may restore it in the future;
* please describe your use cases at [the issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues/).
* For now, it's possible to query [currentTime] before and after execution of this method, to the same effect.
- * * It doesn't run the tasks that are scheduled at exactly [currentTime] + [delayTimeMillis]. For example,
+ * - It doesn't run the tasks that are scheduled at exactly [currentTime] + [delayTimeMillis]. For example,
* advancing the time by one millisecond used to run the tasks at the current millisecond *and* the next
* millisecond, but now will stop just before executing any task starting at the next millisecond.
- * * Overflowing the target time used to lead to nothing being done, but will now run the tasks scheduled at up to
+ * - Overflowing the target time used to lead to nothing being done, but will now run the tasks scheduled at up to
* (but not including) [Long.MAX_VALUE].
*
* @throws IllegalArgumentException if passed a negative [delay][delayTimeMillis].
@@ -223,7 +219,6 @@
/**
* Returns the [TimeSource] representation of the virtual time of this scheduler.
*/
- @ExperimentalTime
public val timeSource: TimeSource.WithComparableMarks = object : AbstractLongTimeSource(DurationUnit.MILLISECONDS) {
override fun read(): Long = currentTime
}
diff --git a/kotlinx-coroutines-test/common/src/TestDispatcher.kt b/kotlinx-coroutines-test/common/src/TestDispatcher.kt
index b027131..a4427a1 100644
--- a/kotlinx-coroutines-test/common/src/TestDispatcher.kt
+++ b/kotlinx-coroutines-test/common/src/TestDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
@@ -13,8 +9,8 @@
* A test dispatcher that can interface with a [TestCoroutineScheduler].
*
* The available implementations are:
- * * [StandardTestDispatcher] is a dispatcher that places new tasks into a queue.
- * * [UnconfinedTestDispatcher] is a dispatcher that behaves like [Dispatchers.Unconfined] while allowing to control
+ * - [StandardTestDispatcher] is a dispatcher that places new tasks into a queue.
+ * - [UnconfinedTestDispatcher] is a dispatcher that behaves like [Dispatchers.Unconfined] while allowing to control
* the virtual time.
*/
@Suppress("INVISIBLE_REFERENCE")
diff --git a/kotlinx-coroutines-test/common/src/TestDispatchers.kt b/kotlinx-coroutines-test/common/src/TestDispatchers.kt
index 4454597..a9e4524 100644
--- a/kotlinx-coroutines-test/common/src/TestDispatchers.kt
+++ b/kotlinx-coroutines-test/common/src/TestDispatchers.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:JvmName("TestDispatchers")
package kotlinx.coroutines.test
diff --git a/kotlinx-coroutines-test/common/src/TestScope.kt b/kotlinx-coroutines-test/common/src/TestScope.kt
index fa6e393..180e76d 100644
--- a/kotlinx-coroutines-test/common/src/TestScope.kt
+++ b/kotlinx-coroutines-test/common/src/TestScope.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
@@ -14,12 +10,12 @@
* A coroutine scope that for launching test coroutines.
*
* The scope provides the following functionality:
- * * The [coroutineContext] includes a [coroutine dispatcher][TestDispatcher] that supports delay-skipping, using
+ * - The [coroutineContext] includes a [coroutine dispatcher][TestDispatcher] that supports delay-skipping, using
* a [TestCoroutineScheduler] for orchestrating the virtual time.
* This scheduler is also available via the [testScheduler] property, and some helper extension
* methods are defined to more conveniently interact with it: see [TestScope.currentTime], [TestScope.runCurrent],
* [TestScope.advanceTimeBy], and [TestScope.advanceUntilIdle].
- * * When inside [runTest], uncaught exceptions from the child coroutines of this scope will be reported at the end of
+ * - When inside [runTest], uncaught exceptions from the child coroutines of this scope will be reported at the end of
* the test.
* It is invalid for child coroutines to throw uncaught exceptions when outside the call to [TestScope.runTest]:
* the only guarantee in this case is the best effort to deliver the exception.
@@ -29,16 +25,16 @@
*
* #### Differences from the deprecated [TestCoroutineScope]
*
- * * This doesn't provide an equivalent of [TestCoroutineScope.cleanupTestCoroutines], and so can't be used as a
+ * - This doesn't provide an equivalent of [TestCoroutineScope.cleanupTestCoroutines], and so can't be used as a
* standalone mechanism for writing tests: it does require that [runTest] is eventually called.
* The reason for this is that a proper cleanup procedure that supports using non-test dispatchers and arbitrary
* coroutine suspensions would be equivalent to [runTest], but would also be more error-prone, due to the potential
* for forgetting to perform the cleanup.
- * * [TestCoroutineScope.advanceTimeBy] also calls [TestCoroutineScheduler.runCurrent] after advancing the virtual time.
- * * No support for dispatcher pausing, like [DelayController] allows. [TestCoroutineDispatcher], which supported
+ * - [TestCoroutineScope.advanceTimeBy] also calls [TestCoroutineScheduler.runCurrent] after advancing the virtual time.
+ * - No support for dispatcher pausing, like [DelayController] allows. [TestCoroutineDispatcher], which supported
* pausing, is deprecated; now, instead of pausing a dispatcher, one can use [withContext] to run a dispatcher that's
* paused by default, like [StandardTestDispatcher].
- * * No access to the list of unhandled exceptions.
+ * - No access to the list of unhandled exceptions.
*/
public sealed interface TestScope : CoroutineScope {
/**
@@ -135,27 +131,26 @@
* @see TestCoroutineScheduler.timeSource
*/
@ExperimentalCoroutinesApi
-@ExperimentalTime
public val TestScope.testTimeSource: TimeSource.WithComparableMarks get() = testScheduler.timeSource
/**
* Creates a [TestScope].
*
* It ensures that all the test module machinery is properly initialized.
- * * If [context] doesn't provide a [TestCoroutineScheduler] for orchestrating the virtual time used for delay-skipping,
+ * - If [context] doesn't provide a [TestCoroutineScheduler] for orchestrating the virtual time used for delay-skipping,
* a new one is created, unless either
* - a [TestDispatcher] is provided, in which case [TestDispatcher.scheduler] is used;
* - at the moment of the creation of the scope, [Dispatchers.Main] is delegated to a [TestDispatcher], in which case
* its [TestCoroutineScheduler] is used.
- * * If [context] doesn't have a [TestDispatcher], a [StandardTestDispatcher] is created.
- * * A [CoroutineExceptionHandler] is created that makes [TestCoroutineScope.cleanupTestCoroutines] throw if there were
+ * - If [context] doesn't have a [TestDispatcher], a [StandardTestDispatcher] is created.
+ * - A [CoroutineExceptionHandler] is created that makes [TestCoroutineScope.cleanupTestCoroutines] throw if there were
* any uncaught exceptions, or forwards the exceptions further in a platform-specific manner if the cleanup was
* already performed when an exception happened. Passing a [CoroutineExceptionHandler] is illegal, unless it's an
* [UncaughtExceptionCaptor], in which case the behavior is preserved for the time being for backward compatibility.
* If you need to have a specific [CoroutineExceptionHandler], please pass it to [launch] on an already-created
* [TestCoroutineScope] and share your use case at
* [our issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues).
- * * If [context] provides a [Job], that job is used as a parent for the new scope.
+ * - If [context] provides a [Job], that job is used as a parent for the new scope.
*
* @throws IllegalArgumentException if [context] has both [TestCoroutineScheduler] and a [TestDispatcher] linked to a
* different scheduler.
@@ -231,7 +226,7 @@
* However, we also want [uncaughtExceptions] to be queried after the callback is registered,
* because the exception collector will be able to report the exceptions that arrived before this test but
* after the previous one, and learning about such exceptions as soon is possible is nice. */
- @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
run { ensurePlatformExceptionHandlerLoaded(ExceptionCollector) }
if (catchNonTestRelatedExceptions) {
ExceptionCollector.addOnExceptionCallback(lock, this::reportException)
@@ -239,6 +234,7 @@
uncaughtExceptions
}
if (exceptions.isNotEmpty()) {
+ ExceptionCollector.removeOnExceptionCallback(lock)
throw UncaughtExceptionsBeforeTest().apply {
for (e in exceptions)
addSuppressed(e)
@@ -287,7 +283,7 @@
if (finished) {
throw throwable
} else {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
for (existingThrowable in uncaughtExceptions) {
// avoid reporting exceptions that already were reported.
if (unwrap(throwable) == unwrap(existingThrowable))
diff --git a/kotlinx-coroutines-test/common/src/internal/ExceptionCollector.kt b/kotlinx-coroutines-test/common/src/internal/ExceptionCollector.kt
index 70fcb94..67341dd 100644
--- a/kotlinx-coroutines-test/common/src/internal/ExceptionCollector.kt
+++ b/kotlinx-coroutines-test/common/src/internal/ExceptionCollector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test.internal
import kotlinx.coroutines.*
@@ -81,7 +77,7 @@
return executedACallback
}
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
override fun handleException(context: CoroutineContext, exception: Throwable) {
if (handleException(exception)) {
throw ExceptionSuccessfullyProcessed
diff --git a/kotlinx-coroutines-test/common/src/internal/ReportingSupervisorJob.kt b/kotlinx-coroutines-test/common/src/internal/ReportingSupervisorJob.kt
index e3091bc..3752f4e 100644
--- a/kotlinx-coroutines-test/common/src/internal/ReportingSupervisorJob.kt
+++ b/kotlinx-coroutines-test/common/src/internal/ReportingSupervisorJob.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/common/src/internal/TestMainDispatcher.kt b/kotlinx-coroutines-test/common/src/internal/TestMainDispatcher.kt
index 411699b..b94e261 100644
--- a/kotlinx-coroutines-test/common/src/internal/TestMainDispatcher.kt
+++ b/kotlinx-coroutines-test/common/src/internal/TestMainDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test.internal
import kotlinx.atomicfu.*
@@ -91,9 +87,9 @@
}
}
-@Suppress("INVISIBLE_MEMBER")
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
private val defaultDelay
inline get() = DefaultDelay
-@Suppress("INVISIBLE_MEMBER")
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
internal expect fun Dispatchers.getTestMainDispatcher(): TestMainDispatcher
diff --git a/kotlinx-coroutines-test/common/test/Helpers.kt b/kotlinx-coroutines-test/common/test/Helpers.kt
index 345c66f..8679739 100644
--- a/kotlinx-coroutines-test/common/test/Helpers.kt
+++ b/kotlinx-coroutines-test/common/test/Helpers.kt
@@ -1,39 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
-import kotlinx.atomicfu.*
-import kotlin.test.*
-import kotlin.time.*
-import kotlin.time.Duration.Companion.seconds
-
-/**
- * The number of milliseconds that is sure not to pass [assertRunsFast].
- */
-const val SLOW = 100_000L
-
-/**
- * Asserts that a block completed within [timeout].
- */
-@OptIn(ExperimentalTime::class)
-inline fun <T> assertRunsFast(timeout: Duration, block: () -> T): T {
- val result: T
- val elapsed = TimeSource.Monotonic.measureTime { result = block() }
- assertTrue("Should complete in $timeout, but took $elapsed") { elapsed < timeout }
- return result
-}
-
-/**
- * Asserts that a block completed within two seconds.
- */
-inline fun <T> assertRunsFast(block: () -> T): T = assertRunsFast(2.seconds, block)
-
/**
* Runs [test], and then invokes [block], passing to it the lambda that functionally behaves
* the same way [test] does.
-*/
+ */
fun testResultMap(block: (() -> Unit) -> Unit, test: () -> TestResult): TestResult = testResultChain(
block = test,
after = {
@@ -47,50 +17,15 @@
*/
expect fun testResultChain(block: () -> TestResult, after: (Result<Unit>) -> TestResult): TestResult
-fun testResultChain(vararg chained: (Result<Unit>) -> TestResult): TestResult =
+fun testResultChain(vararg chained: (Result<Unit>) -> TestResult, initialResult: Result<Unit> = Result.success(Unit)): TestResult =
if (chained.isEmpty()) {
- createTestResult { }
+ createTestResult {
+ initialResult.getOrThrow()
+ }
} else {
testResultChain(block = {
- chained[0](Result.success(Unit))
+ chained[0](initialResult)
}) {
- testResultChain(*chained.drop(1).toTypedArray())
+ testResultChain(*chained.drop(1).toTypedArray(), initialResult = it)
}
}
-
-class TestException(message: String? = null): Exception(message)
-
-/**
- * A class inheriting from which allows to check the execution order inside tests.
- *
- * @see TestBase
- */
-open class OrderedExecutionTestBase {
- private val actionIndex = atomic(0)
- private val finished = atomic(false)
-
- /** Expect the next action to be [index] in order. */
- protected fun expect(index: Int) {
- val wasIndex = actionIndex.incrementAndGet()
- check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" }
- }
-
- /** Expect this action to be final, with the given [index]. */
- protected fun finish(index: Int) {
- expect(index)
- check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" }
- }
-
- @AfterTest
- fun ensureFinishCalls() {
- assertTrue(finished.value || actionIndex.value == 0, "Expected `finish` to be called")
- }
-}
-
-internal fun <T> T.void() { }
-
-@OptionalExpectation
-expect annotation class NoJs()
-
-@OptionalExpectation
-expect annotation class NoNative()
diff --git a/kotlinx-coroutines-test/common/test/RunTestTest.kt b/kotlinx-coroutines-test/common/test/RunTestTest.kt
index da2bdcf..799bcae 100644
--- a/kotlinx-coroutines-test/common/test/RunTestTest.kt
+++ b/kotlinx-coroutines-test/common/test/RunTestTest.kt
@@ -1,14 +1,12 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
@@ -166,7 +164,7 @@
it()
fail("unreached")
} catch (e: UncompletedCoroutinesError) {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
val suppressed = unwrap(e).suppressedExceptions
assertEquals(1, suppressed.size, "$suppressed")
assertIs<TestException>(suppressed[0]).also {
@@ -207,7 +205,7 @@
fn()
fail("unreached")
} catch (e: UncompletedCoroutinesError) {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
val suppressed = unwrap(e).suppressedExceptions
assertEquals(1, suppressed.size, "$suppressed")
assertIs<TestException>(suppressed[0]).also {
@@ -408,4 +406,69 @@
fun testCoroutineCompletingWithoutDispatch() = runTest(timeout = Duration.INFINITE) {
launch(Dispatchers.Default) { delay(100) }
}
+
+ /**
+ * Tests that [runTest] cleans up the exception handler even if it threw on initialization.
+ *
+ * This test must be run manually, because it writes garbage to the log.
+ *
+ * The JVM-only source set contains a test equivalent to this one that isn't ignored.
+ */
+ @Test
+ @Ignore
+ fun testExceptionCaptorCleanedUpOnPreliminaryExit(): TestResult = testResultChain({
+ // step 1: installing the exception handler
+ println("step 1")
+ runTest { }
+ }, {
+ it.getOrThrow()
+ // step 2: throwing an uncaught exception to be caught by the exception-handling system
+ println("step 2")
+ createTestResult {
+ launch(NonCancellable) { throw TestException("A") }
+ }
+ }, {
+ it.getOrThrow()
+ // step 3: trying to run a test should immediately fail, even before entering the test body
+ println("step 3")
+ try {
+ runTest {
+ fail("unreached")
+ }
+ fail("unreached")
+ } catch (e: UncaughtExceptionsBeforeTest) {
+ val cause = e.suppressedExceptions.single()
+ assertIs<TestException>(cause)
+ assertEquals("A", cause.message)
+ }
+ // step 4: trying to run a test again should not fail with an exception
+ println("step 4")
+ runTest {
+ }
+ }, {
+ it.getOrThrow()
+ // step 5: throwing an uncaught exception to be caught by the exception-handling system, again
+ println("step 5")
+ createTestResult {
+ launch(NonCancellable) { throw TestException("B") }
+ }
+ }, {
+ it.getOrThrow()
+ // step 6: trying to run a test should immediately fail, again
+ println("step 6")
+ try {
+ runTest {
+ fail("unreached")
+ }
+ fail("unreached")
+ } catch (e: Exception) {
+ val cause = e.suppressedExceptions.single()
+ assertIs<TestException>(cause)
+ assertEquals("B", cause.message)
+ }
+ // step 7: trying to run a test again should not fail with an exception, again
+ println("step 7")
+ runTest {
+ }
+ })
}
diff --git a/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt b/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt
index 280d668..c0334c8 100644
--- a/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt
+++ b/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt
index 4aec773..a7dd8c6 100644
--- a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt
+++ b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
import kotlin.time.*
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Duration.Companion.milliseconds
@@ -312,7 +310,6 @@
}
@Test
- @ExperimentalTime
fun testAdvanceTimeSource() = runTest {
val expected = 1.seconds
val before = testTimeSource.markNow()
diff --git a/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt b/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt
index da48e7f..614c46a 100644
--- a/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt
+++ b/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.test
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.test.internal.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-test/common/test/TestScopeTest.kt b/kotlinx-coroutines-test/common/test/TestScopeTest.kt
index 433faef..ca98c6d 100644
--- a/kotlinx-coroutines-test/common/test/TestScopeTest.kt
+++ b/kotlinx-coroutines-test/common/test/TestScopeTest.kt
@@ -1,14 +1,12 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
import kotlin.time.Duration.Companion.milliseconds
class TestScopeTest {
@@ -495,9 +493,11 @@
* Tests that the [TestScope] exception reporting mechanism will report the exceptions that happen between
* different tests.
*
- * This test must be ran manually, because such exceptions still go through the global exception handler
+ * This test must be run manually, because such exceptions still go through the global exception handler
* (as there's no guarantee that another test will happen), and the global exception handler will
* log the exceptions or, on Native, crash the test suite.
+ *
+ * The JVM-only source set contains a test equivalent to this one that isn't ignored.
*/
@Test
@Ignore
diff --git a/kotlinx-coroutines-test/common/test/UnconfinedTestDispatcherTest.kt b/kotlinx-coroutines-test/common/test/UnconfinedTestDispatcherTest.kt
index 23ff0ac..ddcdc4a 100644
--- a/kotlinx-coroutines-test/common/test/UnconfinedTestDispatcherTest.kt
+++ b/kotlinx-coroutines-test/common/test/UnconfinedTestDispatcherTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/js/src/TestBuilders.kt b/kotlinx-coroutines-test/js/src/TestBuilders.kt
index 97c9da0..8d30201 100644
--- a/kotlinx-coroutines-test/js/src/TestBuilders.kt
+++ b/kotlinx-coroutines-test/js/src/TestBuilders.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
import kotlin.js.*
@@ -9,6 +5,8 @@
@Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE")
public actual typealias TestResult = Promise<Unit>
+internal actual fun systemPropertyImpl(name: String): String? = null
+
internal actual fun createTestResult(testProcedure: suspend CoroutineScope.() -> Unit): TestResult =
GlobalScope.promise {
testProcedure()
diff --git a/kotlinx-coroutines-test/js/src/internal/TestMainDispatcher.kt b/kotlinx-coroutines-test/js/src/internal/TestMainDispatcher.kt
index 4d865f8..5fca894 100644
--- a/kotlinx-coroutines-test/js/src/internal/TestMainDispatcher.kt
+++ b/kotlinx-coroutines-test/js/src/internal/TestMainDispatcher.kt
@@ -1,11 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test.internal
import kotlinx.coroutines.*
-@Suppress("INVISIBLE_MEMBER")
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
internal actual fun Dispatchers.getTestMainDispatcher(): TestMainDispatcher =
when (val mainDispatcher = Main) {
is TestMainDispatcher -> mainDispatcher
diff --git a/kotlinx-coroutines-test/js/test/Helpers.kt b/kotlinx-coroutines-test/js/test/Helpers.kt
index 5fd0291..9464f8c 100644
--- a/kotlinx-coroutines-test/js/test/Helpers.kt
+++ b/kotlinx-coroutines-test/js/test/Helpers.kt
@@ -1,11 +1,5 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
-import kotlin.test.*
-
actual fun testResultChain(block: () -> TestResult, after: (Result<Unit>) -> TestResult): TestResult =
block().then(
{
@@ -13,5 +7,3 @@
}, {
after(Result.failure(it))
})
-
-actual typealias NoJs = Ignore
diff --git a/kotlinx-coroutines-test/js/test/PromiseTest.kt b/kotlinx-coroutines-test/js/test/PromiseTest.kt
index ff09d9a..8774e4a 100644
--- a/kotlinx-coroutines-test/js/test/PromiseTest.kt
+++ b/kotlinx-coroutines-test/js/test/PromiseTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.test
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/jvm/src/TestBuildersJvm.kt b/kotlinx-coroutines-test/jvm/src/TestBuildersJvm.kt
index 0521fd2..dc7e098 100644
--- a/kotlinx-coroutines-test/jvm/src/TestBuildersJvm.kt
+++ b/kotlinx-coroutines-test/jvm/src/TestBuildersJvm.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.test
import kotlinx.coroutines.*
@@ -15,6 +12,13 @@
}
}
+internal actual fun systemPropertyImpl(name: String): String? =
+ try {
+ System.getProperty(name)
+ } catch (e: SecurityException) {
+ null
+ }
+
internal actual fun dumpCoroutines() {
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
if (DebugProbesImpl.isInstalled) {
diff --git a/kotlinx-coroutines-test/jvm/src/internal/TestMainDispatcherJvm.kt b/kotlinx-coroutines-test/jvm/src/internal/TestMainDispatcherJvm.kt
index f86b08e..1b2d753 100644
--- a/kotlinx-coroutines-test/jvm/src/internal/TestMainDispatcherJvm.kt
+++ b/kotlinx-coroutines-test/jvm/src/internal/TestMainDispatcherJvm.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test.internal
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/jvm/src/migration/DelayController.kt b/kotlinx-coroutines-test/jvm/src/migration/DelayController.kt
index ab84da1..f1aa213 100644
--- a/kotlinx-coroutines-test/jvm/src/migration/DelayController.kt
+++ b/kotlinx-coroutines-test/jvm/src/migration/DelayController.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.coroutines.test
diff --git a/kotlinx-coroutines-test/jvm/src/migration/TestBuildersDeprecated.kt b/kotlinx-coroutines-test/jvm/src/migration/TestBuildersDeprecated.kt
index 7a98fd1..2e0155b 100644
--- a/kotlinx-coroutines-test/jvm/src/migration/TestBuildersDeprecated.kt
+++ b/kotlinx-coroutines-test/jvm/src/migration/TestBuildersDeprecated.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION")
@file:JvmName("TestBuildersKt")
@file:JvmMultifileClass
diff --git a/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineDispatcher.kt b/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineDispatcher.kt
index 3f049b6..1c72a2f 100644
--- a/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineDispatcher.kt
+++ b/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineExceptionHandler.kt b/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineExceptionHandler.kt
index 150055f..eeff64d 100644
--- a/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineExceptionHandler.kt
+++ b/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineExceptionHandler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
@@ -55,7 +51,7 @@
private val _lock = SynchronizedObject()
private var _coroutinesCleanedUp = false
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
override fun handleException(context: CoroutineContext, exception: Throwable) {
synchronized(_lock) {
if (_coroutinesCleanedUp) {
diff --git a/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineScope.kt b/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineScope.kt
index 4a503c5..d026e32 100644
--- a/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineScope.kt
+++ b/kotlinx-coroutines-test/jvm/src/migration/TestCoroutineScope.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION_ERROR", "DEPRECATION")
package kotlinx.coroutines.test
@@ -27,11 +24,11 @@
/**
* Called after the test completes.
*
- * * It checks that there were no uncaught exceptions caught by its [CoroutineExceptionHandler].
+ * - It checks that there were no uncaught exceptions caught by its [CoroutineExceptionHandler].
* If there were any, then the first one is thrown, whereas the rest are suppressed by it.
- * * It runs the tasks pending in the scheduler at the current time. If there are any uncompleted tasks afterwards,
+ * - It runs the tasks pending in the scheduler at the current time. If there are any uncompleted tasks afterwards,
* it fails with [UncompletedCoroutinesError].
- * * It checks whether some new child [Job]s were created but not completed since this [TestCoroutineScope] was
+ * - It checks whether some new child [Job]s were created but not completed since this [TestCoroutineScope] was
* created. If so, it fails with [UncompletedCoroutinesError].
*
* For backward compatibility, if the [CoroutineExceptionHandler] is an [UncaughtExceptionCaptor], its
@@ -154,20 +151,20 @@
* for an instruction on how to update the code for the new API.
*
* It ensures that all the test module machinery is properly initialized.
- * * If [context] doesn't define a [TestCoroutineScheduler] for orchestrating the virtual time used for delay-skipping,
+ * - If [context] doesn't define a [TestCoroutineScheduler] for orchestrating the virtual time used for delay-skipping,
* a new one is created, unless either
* - a [TestDispatcher] is provided, in which case [TestDispatcher.scheduler] is used;
* - at the moment of the creation of the scope, [Dispatchers.Main] is delegated to a [TestDispatcher], in which case
* its [TestCoroutineScheduler] is used.
- * * If [context] doesn't have a [ContinuationInterceptor], a [StandardTestDispatcher] is created.
- * * A [CoroutineExceptionHandler] is created that makes [TestCoroutineScope.cleanupTestCoroutines] throw if there were
+ * - If [context] doesn't have a [ContinuationInterceptor], a [StandardTestDispatcher] is created.
+ * - A [CoroutineExceptionHandler] is created that makes [TestCoroutineScope.cleanupTestCoroutines] throw if there were
* any uncaught exceptions, or forwards the exceptions further in a platform-specific manner if the cleanup was
* already performed when an exception happened. Passing a [CoroutineExceptionHandler] is illegal, unless it's an
* [UncaughtExceptionCaptor], in which case the behavior is preserved for the time being for backward compatibility.
* If you need to have a specific [CoroutineExceptionHandler], please pass it to [launch] on an already-created
* [TestCoroutineScope] and share your use case at
* [our issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues).
- * * If [context] provides a [Job], that job is used for the new scope; otherwise, a [CompletableJob] is created.
+ * - If [context] provides a [Job], that job is used for the new scope; otherwise, a [CompletableJob] is created.
*
* @throws IllegalArgumentException if [context] has both [TestCoroutineScheduler] and a [TestDispatcher] linked to a
* different scheduler.
diff --git a/kotlinx-coroutines-test/jvm/test/DumpOnTimeoutTest.kt b/kotlinx-coroutines-test/jvm/test/DumpOnTimeoutTest.kt
index 814e5f0..36f73c2 100644
--- a/kotlinx-coroutines-test/jvm/test/DumpOnTimeoutTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/DumpOnTimeoutTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/jvm/test/HelpersJvm.kt b/kotlinx-coroutines-test/jvm/test/HelpersJvm.kt
index 8d40b07..ed3afa3 100644
--- a/kotlinx-coroutines-test/jvm/test/HelpersJvm.kt
+++ b/kotlinx-coroutines-test/jvm/test/HelpersJvm.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.test
actual fun testResultChain(block: () -> TestResult, after: (Result<Unit>) -> TestResult): TestResult {
diff --git a/kotlinx-coroutines-test/jvm/test/MemoryLeakTest.kt b/kotlinx-coroutines-test/jvm/test/MemoryLeakTest.kt
index 705c97e..218d8aa 100644
--- a/kotlinx-coroutines-test/jvm/test/MemoryLeakTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/MemoryLeakTest.kt
@@ -1,8 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
class MemoryLeakTest {
diff --git a/kotlinx-coroutines-test/jvm/test/MultithreadingTest.kt b/kotlinx-coroutines-test/jvm/test/MultithreadingTest.kt
index 2ac577c..4761769 100644
--- a/kotlinx-coroutines-test/jvm/test/MultithreadingTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/MultithreadingTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
import kotlin.concurrent.*
diff --git a/kotlinx-coroutines-test/jvm/test/RunTestStressTest.kt b/kotlinx-coroutines-test/jvm/test/RunTestStressTest.kt
index 3edaa48..d6469c5 100644
--- a/kotlinx-coroutines-test/jvm/test/RunTestStressTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/RunTestStressTest.kt
@@ -1,9 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.test
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.concurrent.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -23,4 +21,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-test/jvm/test/UncaughtExceptionsTest.kt b/kotlinx-coroutines-test/jvm/test/UncaughtExceptionsTest.kt
new file mode 100644
index 0000000..57893b8
--- /dev/null
+++ b/kotlinx-coroutines-test/jvm/test/UncaughtExceptionsTest.kt
@@ -0,0 +1,49 @@
+package kotlinx.coroutines.test
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
+import org.junit.Test
+import kotlin.test.*
+
+/**
+ * Tests that check the behavior of the test framework when there are stray uncaught exceptions.
+ * These tests are JVM-only because only the JVM allows to set a global uncaught exception handler and validate the
+ * behavior without checking the test logs.
+ * Nevertheless, each test here has a corresponding test in the common source set that can be run manually.
+ */
+class UncaughtExceptionsTest {
+
+ val oldExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
+ val uncaughtExceptions = mutableListOf<Throwable>()
+
+ @BeforeTest
+ fun setUp() {
+ Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
+ uncaughtExceptions.add(throwable)
+ }
+ }
+
+ @AfterTest
+ fun tearDown() {
+ Thread.setDefaultUncaughtExceptionHandler(oldExceptionHandler)
+ }
+
+ @Test
+ fun testReportingStrayUncaughtExceptionsBetweenTests() {
+ TestScopeTest().testReportingStrayUncaughtExceptionsBetweenTests()
+ assertEquals(1, uncaughtExceptions.size, "Expected 1 uncaught exception, but got $uncaughtExceptions")
+ val exception = assertIs<TestException>(uncaughtExceptions.single())
+ assertEquals("x", exception.message)
+ }
+
+ @Test
+ fun testExceptionCaptorCleanedUpOnPreliminaryExit() {
+ RunTestTest().testExceptionCaptorCleanedUpOnPreliminaryExit()
+ assertEquals(2, uncaughtExceptions.size, "Expected 2 uncaught exceptions, but got $uncaughtExceptions")
+ for (exception in uncaughtExceptions) {
+ assertIs<TestException>(exception)
+ }
+ assertEquals("A", uncaughtExceptions[0].message)
+ assertEquals("B", uncaughtExceptions[1].message)
+ }
+}
diff --git a/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt b/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt
index 8065920..aec937d 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/RunBlockingTestOnTestScopeTest.kt
@@ -1,13 +1,11 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
/** Copy of [RunTestTest], but for [runBlockingTestOnTestScope], where applicable. */
@Suppress("DEPRECATION")
diff --git a/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt b/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt
index ed5b157..caae1a5 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/RunTestLegacyScopeTest.kt
@@ -1,14 +1,12 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.internal.*
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
/** Copy of [RunTestTest], but for [TestCoroutineScope] */
@Suppress("DEPRECATION")
@@ -92,7 +90,7 @@
fn()
fail("unreached")
} catch (e: UncompletedCoroutinesError) {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
val suppressed = unwrap(e).suppressedExceptions
assertEquals(1, suppressed.size)
assertIs<TestException>(suppressed[0]).also {
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestBuildersTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestBuildersTest.kt
index 4b0428d..d58d0f5 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestBuildersTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestBuildersTest.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherOrderTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherOrderTest.kt
index 115c272..93792b5 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherOrderTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherOrderTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
+import kotlinx.coroutines.testing.*
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherTest.kt
index ea9762f..d5f3e0f 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineDispatcherTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineExceptionHandlerTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineExceptionHandlerTest.kt
index 332634e..72fae5d 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineExceptionHandlerTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineExceptionHandlerTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlin.test.*
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineScopeTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineScopeTest.kt
index 1a62613..c201623 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineScopeTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestCoroutineScopeTest.kt
@@ -1,13 +1,12 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
@file:Suppress("DEPRECATION")
package kotlinx.coroutines.test
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.coroutines.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
class TestCoroutineScopeTest {
/** Tests failing to create a [TestCoroutineScope] with incorrect contexts. */
@@ -214,4 +213,4 @@
StandardTestDispatcher() + TestCoroutineScheduler(), // the dispatcher is not linked to the scheduler
)
}
-}
\ No newline at end of file
+}
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingOrderTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingOrderTest.kt
index 32514d9..a8315fc 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingOrderTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingOrderTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlin.test.*
diff --git a/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt b/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt
index ebdd973..f7d420d 100644
--- a/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt
+++ b/kotlinx-coroutines-test/jvm/test/migration/TestRunBlockingTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import kotlin.test.*
+import kotlin.test.assertFailsWith
@Suppress("DEPRECATION", "DEPRECATION_ERROR")
class TestRunBlockingTest {
diff --git a/kotlinx-coroutines-test/native/src/TestBuilders.kt b/kotlinx-coroutines-test/native/src/TestBuilders.kt
index 607dec6..b1d8387 100644
--- a/kotlinx-coroutines-test/native/src/TestBuilders.kt
+++ b/kotlinx-coroutines-test/native/src/TestBuilders.kt
@@ -1,10 +1,5 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test
import kotlinx.coroutines.*
-import kotlin.native.concurrent.*
@Suppress("ACTUAL_WITHOUT_EXPECT")
public actual typealias TestResult = Unit
@@ -15,4 +10,6 @@
}
}
+internal actual fun systemPropertyImpl(name: String): String? = null
+
internal actual fun dumpCoroutines() { }
diff --git a/kotlinx-coroutines-test/native/src/internal/TestMainDispatcher.kt b/kotlinx-coroutines-test/native/src/internal/TestMainDispatcher.kt
index 4d865f8..5fca894 100644
--- a/kotlinx-coroutines-test/native/src/internal/TestMainDispatcher.kt
+++ b/kotlinx-coroutines-test/native/src/internal/TestMainDispatcher.kt
@@ -1,11 +1,7 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.test.internal
import kotlinx.coroutines.*
-@Suppress("INVISIBLE_MEMBER")
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
internal actual fun Dispatchers.getTestMainDispatcher(): TestMainDispatcher =
when (val mainDispatcher = Main) {
is TestMainDispatcher -> mainDispatcher
diff --git a/kotlinx-coroutines-test/native/test/Helpers.kt b/kotlinx-coroutines-test/native/test/Helpers.kt
index be615fb..ed3afa3 100644
--- a/kotlinx-coroutines-test/native/test/Helpers.kt
+++ b/kotlinx-coroutines-test/native/test/Helpers.kt
@@ -1,10 +1,5 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.test
-import kotlin.test.*
-
actual fun testResultChain(block: () -> TestResult, after: (Result<Unit>) -> TestResult): TestResult {
try {
block()
@@ -13,5 +8,3 @@
after(Result.failure(e))
}
}
-
-actual typealias NoNative = Ignore
diff --git a/kotlinx-coroutines-test/wasmJs/src/TestBuilders.kt b/kotlinx-coroutines-test/wasmJs/src/TestBuilders.kt
new file mode 100644
index 0000000..7794b8e
--- /dev/null
+++ b/kotlinx-coroutines-test/wasmJs/src/TestBuilders.kt
@@ -0,0 +1,15 @@
+package kotlinx.coroutines.test
+import kotlinx.coroutines.*
+import kotlin.js.*
+
+@Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE")
+public actual typealias TestResult = Promise<JsAny?>
+
+internal actual fun systemPropertyImpl(name: String): String? = null
+
+internal actual fun createTestResult(testProcedure: suspend CoroutineScope.() -> Unit): TestResult =
+ GlobalScope.promise {
+ testProcedure()
+ }
+
+internal actual fun dumpCoroutines() { }
\ No newline at end of file
diff --git a/kotlinx-coroutines-test/wasmJs/src/internal/TestMainDispatcher.kt b/kotlinx-coroutines-test/wasmJs/src/internal/TestMainDispatcher.kt
new file mode 100644
index 0000000..175a846
--- /dev/null
+++ b/kotlinx-coroutines-test/wasmJs/src/internal/TestMainDispatcher.kt
@@ -0,0 +1,9 @@
+package kotlinx.coroutines.test.internal
+import kotlinx.coroutines.*
+
+@Suppress("INVISIBLE_MEMBER")
+internal actual fun Dispatchers.getTestMainDispatcher(): TestMainDispatcher =
+ when (val mainDispatcher = Main) {
+ is TestMainDispatcher -> mainDispatcher
+ else -> TestMainDispatcher(mainDispatcher).also { injectMain(it) }
+ }
diff --git a/kotlinx-coroutines-test/wasmJs/test/Helpers.kt b/kotlinx-coroutines-test/wasmJs/test/Helpers.kt
new file mode 100644
index 0000000..a394c1f
--- /dev/null
+++ b/kotlinx-coroutines-test/wasmJs/test/Helpers.kt
@@ -0,0 +1,11 @@
+package kotlinx.coroutines.test
+
+actual fun testResultChain(block: () -> TestResult, after: (Result<Unit>) -> TestResult): TestResult =
+ block().then(
+ {
+ after(Result.success(Unit))
+ null
+ }, {
+ after(Result.failure(it.toThrowableOrNull() ?: Throwable("Unexpected non-Kotlin exception $it")))
+ null
+ })
diff --git a/kotlinx-coroutines-test/wasmJs/test/PromiseTest.kt b/kotlinx-coroutines-test/wasmJs/test/PromiseTest.kt
new file mode 100644
index 0000000..f555171
--- /dev/null
+++ b/kotlinx-coroutines-test/wasmJs/test/PromiseTest.kt
@@ -0,0 +1,18 @@
+package kotlinx.coroutines.test
+
+import kotlinx.coroutines.*
+import kotlin.test.*
+
+class PromiseTest {
+ @Test
+ fun testCompletionFromPromise() = runTest {
+ var promiseEntered = false
+ val p = promise {
+ delay(1)
+ promiseEntered = true
+ }
+ delay(2)
+ p.await<JsAny>()
+ assertTrue(promiseEntered)
+ }
+}
\ No newline at end of file
diff --git a/license/NOTICE.txt b/license/NOTICE.txt
index 8d1100a..01d8138 100644
--- a/license/NOTICE.txt
+++ b/license/NOTICE.txt
@@ -5,4 +5,4 @@
=========================================================================
kotlinx.coroutines library.
-Copyright 2016-2021 JetBrains s.r.o and respective authors and developers
+Copyright 2016-2024 JetBrains s.r.o and contributors
diff --git a/reactive/knit.properties b/reactive/knit.properties
index 452cd2f..1a28ea5 100644
--- a/reactive/knit.properties
+++ b/reactive/knit.properties
@@ -1,6 +1,2 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
knit.package=kotlinx.coroutines.rx2.guide
knit.dir=kotlinx-coroutines-rx2/test/guide/
diff --git a/reactive/knit.test.include b/reactive/knit.test.include
index dd9e61d..8b62dcd 100644
--- a/reactive/knit.test.include
+++ b/reactive/knit.test.include
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from ${file.name} by Knit tool. Do not edit.
package ${test.package}
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.guide.test.*
import org.junit.Test
diff --git a/reactive/kotlinx-coroutines-jdk9/build.gradle.kts b/reactive/kotlinx-coroutines-jdk9/build.gradle.kts
index 0853a34..b8e05d6 100644
--- a/reactive/kotlinx-coroutines-jdk9/build.gradle.kts
+++ b/reactive/kotlinx-coroutines-jdk9/build.gradle.kts
@@ -1,6 +1,4 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+import org.jetbrains.kotlin.gradle.dsl.*
dependencies {
implementation(project(":kotlinx-coroutines-reactive"))
@@ -13,11 +11,11 @@
tasks {
compileKotlin {
- kotlinOptions.jvmTarget = "9"
+ compilerOptions.jvmTarget = JvmTarget.JVM_9
}
compileTestKotlin {
- kotlinOptions.jvmTarget = "9"
+ compilerOptions.jvmTarget = JvmTarget.JVM_9
}
}
diff --git a/reactive/kotlinx-coroutines-jdk9/src/Await.kt b/reactive/kotlinx-coroutines-jdk9/src/Await.kt
index dfe6ec5..2fba53d 100644
--- a/reactive/kotlinx-coroutines-jdk9/src/Await.kt
+++ b/reactive/kotlinx-coroutines-jdk9/src/Await.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
import kotlinx.coroutines.*
@@ -14,7 +10,7 @@
* the publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Flow.Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the publisher does not emit any value
@@ -28,7 +24,7 @@
* exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Flow.Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Flow.Publisher<T>.awaitFirstOrDefault(default: T): T =
@@ -39,7 +35,7 @@
* and returns the resulting value, or, if this publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Flow.Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Flow.Publisher<T>.awaitFirstOrNull(): T? =
@@ -51,7 +47,7 @@
* corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Flow.Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Flow.Publisher<T>.awaitFirstOrElse(defaultValue: () -> T): T =
@@ -62,7 +58,7 @@
* returns the resulting value, or, if this publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Flow.Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the publisher does not emit any value
@@ -75,7 +71,7 @@
* if this publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Flow.Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the publisher does not emit any value
diff --git a/reactive/kotlinx-coroutines-jdk9/src/Publish.kt b/reactive/kotlinx-coroutines-jdk9/src/Publish.kt
index 529bc12..019e604 100644
--- a/reactive/kotlinx-coroutines-jdk9/src/Publish.kt
+++ b/reactive/kotlinx-coroutines-jdk9/src/Publish.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt b/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt
index 6031e0a..11f3a95 100644
--- a/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt
+++ b/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-jdk9/test/AwaitTest.kt b/reactive/kotlinx-coroutines-jdk9/test/AwaitTest.kt
index 5a95d09..4b0b77c 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/AwaitTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/AwaitTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.Flow as JFlow
diff --git a/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt b/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt
index b860e16..b09324c 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/FlowAsPublisherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.Test
@@ -40,7 +37,7 @@
}
override fun onError(t: Throwable?) {
- assertTrue(t is TestException)
+ assertIs<TestException>(t)
expect(4)
}
})
diff --git a/reactive/kotlinx-coroutines-jdk9/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-jdk9/test/IntegrationTest.kt
index 5b3542a..400d11b 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/IntegrationTest.kt
@@ -1,16 +1,12 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
-import kotlinx.coroutines.exceptions.*
import org.junit.Test
import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.runner.*
import org.junit.runners.*
-import kotlin.contracts.*
import java.util.concurrent.Flow as JFlow
import kotlin.coroutines.*
import kotlin.test.*
@@ -133,18 +129,3 @@
}
-@OptIn(ExperimentalContracts::class)
-internal suspend inline fun <reified E: Throwable> assertCallsExceptionHandlerWith(
- crossinline operation: suspend (CoroutineExceptionHandler) -> Unit): E {
- contract {
- callsInPlace(operation, InvocationKind.EXACTLY_ONCE)
- }
- val handler = CapturingHandler()
- return withContext(handler) {
- operation(handler)
- handler.getException().let {
- assertTrue(it is E, it.toString())
- it
- }
- }
-}
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt
index 0479028..595c678 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/PublishTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.Test
import java.util.concurrent.Flow as JFlow
import kotlin.test.*
@@ -72,7 +70,7 @@
override fun onComplete() { expectUnreached() }
override fun onError(t: Throwable) {
expect(6)
- assertTrue(t is RuntimeException)
+ assertIs<RuntimeException>(t)
assertEquals("OK", t.message)
}
})
@@ -86,7 +84,7 @@
expect(1)
val eh = CoroutineExceptionHandler { _, t ->
- assertTrue(t is RuntimeException)
+ assertIs<RuntimeException>(t)
expect(6)
}
val publisher = flowPublish<Unit>(Dispatchers.Unconfined + eh) {
@@ -199,29 +197,34 @@
}
}
expect(2)
- publisher.subscribe(object: JFlow.Subscriber<Int> {
+ publisher.subscribe(object : JFlow.Subscriber<Int> {
override fun onSubscribe(s: JFlow.Subscription) {
expect(3)
s.request(Long.MAX_VALUE)
}
+
override fun onNext(t: Int) {
expect(6)
assertEquals(1, t)
job!!.cancel()
throw TestException()
}
+
override fun onError(t: Throwable?) {
/* Correct changes to the implementation could lead to us entering or not entering this method, but
it only matters that if we do, it is the "correct" exception that was validly used to cancel the
coroutine that gets passed here and not `TestException`. */
- assertTrue(t is CancellationException)
+ assertIs<CancellationException>(t)
}
- override fun onComplete() { expectUnreached() }
+
+ override fun onComplete() {
+ expectUnreached()
+ }
})
expect(5)
val result: ChannelResult<Unit> = producerScope!!.trySend(1)
val e = result.exceptionOrNull()!!
- assertTrue(e is CancellationException, "The actual error: $e")
+ assertIs<CancellationException>(e, "The actual error: $e")
assertTrue(producerScope!!.isClosedForSend)
assertTrue(result.isFailure)
}
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublisherAsFlowTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublisherAsFlowTest.kt
index b5b2a0a..ae1708b 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/PublisherAsFlowTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/PublisherAsFlowTest.kt
@@ -1,12 +1,10 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.flow.*
import kotlin.test.*
class PublisherAsFlowTest : TestBase() {
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublisherBackpressureTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublisherBackpressureTest.kt
index bc9d58e..b7bbcbd 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/PublisherBackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/PublisherBackpressureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.Flow as JFlow
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublisherCollectTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublisherCollectTest.kt
index c2e8848..aa2b679 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/PublisherCollectTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/PublisherCollectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.*
import org.junit.Test
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt
index 8462df2..abacdec 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/PublisherCompletionStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.*
diff --git a/reactive/kotlinx-coroutines-jdk9/test/PublisherMultiTest.kt b/reactive/kotlinx-coroutines-jdk9/test/PublisherMultiTest.kt
index a44850b..90fa5dd 100644
--- a/reactive/kotlinx-coroutines-jdk9/test/PublisherMultiTest.kt
+++ b/reactive/kotlinx-coroutines-jdk9/test/PublisherMultiTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.jdk9
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.*
diff --git a/reactive/kotlinx-coroutines-reactive/build.gradle.kts b/reactive/kotlinx-coroutines-reactive/build.gradle.kts
index fbcde96..3e6eccc 100644
--- a/reactive/kotlinx-coroutines-reactive/build.gradle.kts
+++ b/reactive/kotlinx-coroutines-reactive/build.gradle.kts
@@ -1,9 +1,3 @@
-import kotlinx.kover.gradle.plugin.dsl.*
-
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
plugins {
// apply plugin to use autocomplete for Kover DSL
id("org.jetbrains.kotlinx.kover")
@@ -18,7 +12,7 @@
val testNG by tasks.registering(Test::class) {
useTestNG()
- reports.html.destination = file("$buildDir/reports/testng")
+ reports.html.outputLocation = layout.buildDirectory.dir("reports/testng")
include("**/*ReactiveStreamTckTest.*")
// Skip testNG when tests are filtered with --tests, otherwise it simply fails
onlyIf {
@@ -31,7 +25,7 @@
}
tasks.test {
- reports.html.destination = file("$buildDir/reports/junit")
+ reports.html.outputLocation = layout.buildDirectory.dir("reports/junit")
}
tasks.check {
@@ -42,14 +36,16 @@
url = "https://www.reactive-streams.org/reactive-streams-$reactiveStreamsVersion-javadoc/"
)
-koverReport {
- filters {
- excludes {
- classes(
- "kotlinx.coroutines.reactive.FlowKt", // Deprecated
- "kotlinx.coroutines.reactive.FlowKt__MigrationKt", // Deprecated
- "kotlinx.coroutines.reactive.ConvertKt" // Deprecated
- )
+kover {
+ reports {
+ filters {
+ excludes {
+ classes(
+ "kotlinx.coroutines.reactive.FlowKt", // Deprecated
+ "kotlinx.coroutines.reactive.FlowKt__MigrationKt", // Deprecated
+ "kotlinx.coroutines.reactive.ConvertKt" // Deprecated
+ )
+ }
}
}
}
diff --git a/reactive/kotlinx-coroutines-reactive/src/Await.kt b/reactive/kotlinx-coroutines-reactive/src/Await.kt
index 446d986..73f0ca2 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Await.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Await.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import kotlinx.coroutines.*
@@ -16,7 +12,7 @@
* the publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the publisher does not emit any value
@@ -29,7 +25,7 @@
* exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Publisher<T>.awaitFirstOrDefault(default: T): T = awaitOne(Mode.FIRST_OR_DEFAULT, default)
@@ -39,7 +35,7 @@
* and returns the resulting value, or, if this publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Publisher<T>.awaitFirstOrNull(): T? = awaitOne(Mode.FIRST_OR_DEFAULT)
@@ -50,7 +46,7 @@
* corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Publisher<T>.awaitFirstOrElse(defaultValue: () -> T): T = awaitOne(Mode.FIRST_OR_DEFAULT) ?: defaultValue()
@@ -60,7 +56,7 @@
* returns the resulting value, or, if this publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the publisher does not emit any value
@@ -72,7 +68,7 @@
* if this publisher has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the publisher does not emit any value
@@ -86,7 +82,7 @@
* corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* ### Deprecation
@@ -116,7 +112,7 @@
* produced by the publisher, `null` is returned.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* ### Deprecation
@@ -146,7 +142,7 @@
* corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* ### Deprecation
diff --git a/reactive/kotlinx-coroutines-reactive/src/Channel.kt b/reactive/kotlinx-coroutines-reactive/src/Channel.kt
index 7836ed7..4b775f7 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Channel.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Channel.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import kotlinx.atomicfu.*
diff --git a/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt b/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt
index 043e223..abf0946 100644
--- a/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import kotlinx.coroutines.InternalCoroutinesApi
diff --git a/reactive/kotlinx-coroutines-reactive/src/Convert.kt b/reactive/kotlinx-coroutines-reactive/src/Convert.kt
index 9492b49..55bce6c 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Convert.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Convert.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import kotlinx.coroutines.channels.*
diff --git a/reactive/kotlinx-coroutines-reactive/src/Migration.kt b/reactive/kotlinx-coroutines-reactive/src/Migration.kt
index 858ab00..3fc94d5 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Migration.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Migration.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmMultifileClass
@file:JvmName("FlowKt")
diff --git a/reactive/kotlinx-coroutines-reactive/src/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/Publish.kt
index ae85e41..a58e01f 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Publish.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Publish.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package kotlinx.coroutines.reactive
import kotlinx.atomicfu.*
@@ -84,7 +81,7 @@
// Mutex is locked when either nRequested == 0 or while subscriber.onXXX is being invoked
private val mutex: Mutex = Mutex(locked = true)
- @Suppress("UNCHECKED_CAST", "INVISIBLE_MEMBER")
+ @Suppress("UNCHECKED_CAST", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
override val onSend: SelectClause2<T, SendChannel<T>> get() = SelectClause2Impl(
clauseObject = this,
regFunc = PublisherCoroutine<*>::registerSelectForSend as RegistrationFunction,
diff --git a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt
index 1a527a3..79cc87a 100644
--- a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import kotlinx.atomicfu.*
@@ -59,7 +55,7 @@
* It's too counter-intuitive to be public, and moving it to Flow companion
* will also create undesired effect.
*/
- @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
private val requestSize: Long
get() =
if (onBufferOverflow != BufferOverflow.SUSPEND) {
@@ -208,7 +204,7 @@
try {
consumeFlow()
} catch (cause: Throwable) {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
val unwrappedCause = unwrap(cause)
if (!cancellationRequested || isActive || unwrappedCause !== getCancellationException()) {
try {
diff --git a/reactive/kotlinx-coroutines-reactive/test/AwaitCancellationStressTest.kt b/reactive/kotlinx-coroutines-reactive/test/AwaitCancellationStressTest.kt
index aaf8df6..03676c7 100644
--- a/reactive/kotlinx-coroutines-reactive/test/AwaitCancellationStressTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/AwaitCancellationStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.reactivestreams.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/AwaitTest.kt b/reactive/kotlinx-coroutines-reactive/test/AwaitTest.kt
index 6749423..2277204 100644
--- a/reactive/kotlinx-coroutines-reactive/test/AwaitTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/AwaitTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.reactivestreams.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/CancelledParentAttachTest.kt b/reactive/kotlinx-coroutines-reactive/test/CancelledParentAttachTest.kt
index 1db10b2..05bb878 100644
--- a/reactive/kotlinx-coroutines-reactive/test/CancelledParentAttachTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/CancelledParentAttachTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt b/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt
index 02c9e24..18615e2 100644
--- a/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/FlowAsPublisherTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.*
@@ -41,7 +38,7 @@
}
override fun onError(t: Throwable?) {
- assertTrue(t is TestException)
+ assertIs<TestException>(t)
expect(4)
}
})
diff --git a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt
index fa03989..51e9562 100644
--- a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt
@@ -1,18 +1,14 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
-import kotlinx.coroutines.exceptions.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.Test
import org.junit.runner.*
import org.junit.runners.*
import org.reactivestreams.*
import java.lang.IllegalStateException
import java.lang.RuntimeException
-import kotlin.contracts.*
import kotlin.coroutines.*
import kotlin.test.*
@@ -227,18 +223,3 @@
}
-@OptIn(ExperimentalContracts::class)
-internal suspend inline fun <reified E: Throwable> assertCallsExceptionHandlerWith(
- crossinline operation: suspend (CoroutineExceptionHandler) -> Unit): E {
- contract {
- callsInPlace(operation, InvocationKind.EXACTLY_ONCE)
- }
- val handler = CapturingHandler()
- return withContext(handler) {
- operation(handler)
- handler.getException().let {
- assertTrue(it is E, it.toString())
- it
- }
- }
-}
diff --git a/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt b/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt
index cf935f9..13313d2 100644
--- a/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("UNCHECKED_CAST")
package kotlinx.coroutines.reactive
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt
index d92a888..df01e47 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt
@@ -1,14 +1,12 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.*
+import kotlinx.coroutines.testing.exceptions.*
import org.junit.Test
import org.reactivestreams.*
import java.util.concurrent.*
@@ -76,7 +74,7 @@
override fun onComplete() { expectUnreached() }
override fun onError(t: Throwable) {
expect(6)
- assertTrue(t is RuntimeException)
+ assertIs<RuntimeException>(t)
assertEquals("OK", t.message)
}
})
@@ -90,7 +88,7 @@
expect(1)
val eh = CoroutineExceptionHandler { _, t ->
- assertTrue(t is RuntimeException)
+ assertIs<RuntimeException>(t)
expect(6)
}
val publisher = publish<Unit>(Dispatchers.Unconfined + eh) {
@@ -203,29 +201,34 @@
}
}
expect(2)
- publisher.subscribe(object: Subscriber<Int> {
+ publisher.subscribe(object : Subscriber<Int> {
override fun onSubscribe(s: Subscription) {
expect(3)
s.request(Long.MAX_VALUE)
}
+
override fun onNext(t: Int) {
expect(6)
assertEquals(1, t)
job!!.cancel()
throw TestException()
}
+
override fun onError(t: Throwable?) {
/* Correct changes to the implementation could lead to us entering or not entering this method, but
it only matters that if we do, it is the "correct" exception that was validly used to cancel the
coroutine that gets passed here and not `TestException`. */
- assertTrue(t is CancellationException)
+ assertIs<CancellationException>(t)
}
- override fun onComplete() { expectUnreached() }
+
+ override fun onComplete() {
+ expectUnreached()
+ }
})
expect(5)
val result: ChannelResult<Unit> = producerScope!!.trySend(1)
val e = result.exceptionOrNull()!!
- assertTrue(e is CancellationException, "The actual error: $e")
+ assertIs<CancellationException>(e, "The actual error: $e")
assertTrue(producerScope!!.isClosedForSend)
assertTrue(result.isFailure)
}
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt
index 7a0e0fa..42dd681 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt
@@ -1,12 +1,10 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.flow.*
import org.reactivestreams.*
import kotlin.test.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherBackpressureTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherBackpressureTest.kt
index 258632b..8b8d0fc 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherBackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherBackpressureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.reactivestreams.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherCollectTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherCollectTest.kt
index e4753f0..a7f94df 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherCollectTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherCollectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.reactivestreams.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt
index b16310d..f3ea685 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherCompletionStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt
index 4a552b5..2ac658d 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
import org.junit.Test
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherRequestStressTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherRequestStressTest.kt
index a19ce2f..18ab7c3 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherRequestStressTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherRequestStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.Flow
diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt
index 740fd86..ab22d12 100644
--- a/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/RangePublisherBufferedTest.kt b/reactive/kotlinx-coroutines-reactive/test/RangePublisherBufferedTest.kt
index b710c59..da1f3cc 100644
--- a/reactive/kotlinx-coroutines-reactive/test/RangePublisherBufferedTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/RangePublisherBufferedTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/RangePublisherTest.kt b/reactive/kotlinx-coroutines-reactive/test/RangePublisherTest.kt
index 72d5de5..9d1f85a 100644
--- a/reactive/kotlinx-coroutines-reactive/test/RangePublisherTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/RangePublisherTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/ReactiveStreamTckTest.kt b/reactive/kotlinx-coroutines-reactive/test/ReactiveStreamTckTest.kt
index a251d98..9a4fc52 100644
--- a/reactive/kotlinx-coroutines-reactive/test/ReactiveStreamTckTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/ReactiveStreamTckTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.reactivestreams.*
import org.reactivestreams.tck.*
diff --git a/reactive/kotlinx-coroutines-reactive/test/UnboundedIntegerIncrementPublisherTest.kt b/reactive/kotlinx-coroutines-reactive/test/UnboundedIntegerIncrementPublisherTest.kt
index 63d444c..c602a0c 100644
--- a/reactive/kotlinx-coroutines-reactive/test/UnboundedIntegerIncrementPublisherTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/test/UnboundedIntegerIncrementPublisherTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactive
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-reactor/build.gradle.kts b/reactive/kotlinx-coroutines-reactor/build.gradle.kts
index 7d3441c..6e46d91 100644
--- a/reactive/kotlinx-coroutines-reactor/build.gradle.kts
+++ b/reactive/kotlinx-coroutines-reactor/build.gradle.kts
@@ -1,16 +1,12 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+import org.jetbrains.kotlin.gradle.dsl.*
plugins {
// apply plugin to use autocomplete for Kover DSL
id("org.jetbrains.kotlinx.kover")
}
-val reactorVersion = version("reactor")
-
dependencies {
- api("io.projectreactor:reactor-core:$reactorVersion")
+ api("io.projectreactor:reactor-core:${version("reactor")}")
api(project(":kotlinx-coroutines-reactive"))
}
@@ -21,26 +17,30 @@
tasks {
compileKotlin {
- kotlinOptions.jvmTarget = "1.8"
+ compilerOptions.jvmTarget = JvmTarget.JVM_1_8
}
compileTestKotlin {
- kotlinOptions.jvmTarget = "1.8"
+ compilerOptions.jvmTarget = JvmTarget.JVM_1_8
}
}
+// the version of the docs can be different from the version of the Reactor
+// library itself: https://github.com/reactor/reactor-core/issues/3794
externalDocumentationLink(
- url = "https://projectreactor.io/docs/core/$reactorVersion/api/"
+ url = "https://projectreactor.io/docs/core/${version("reactor_docs")}/api/"
)
-koverReport {
- filters {
- excludes {
- classes(
- "kotlinx.coroutines.reactor.FlowKt", // Deprecated
- "kotlinx.coroutines.reactor.ConvertKt\$asFlux$1" // Deprecated
- )
+kover {
+ reports {
+ filters {
+ excludes {
+ classes(
+ "kotlinx.coroutines.reactor.FlowKt", // Deprecated
+ "kotlinx.coroutines.reactor.ConvertKt\$asFlux$1" // Deprecated
+ )
+ }
}
}
}
diff --git a/reactive/kotlinx-coroutines-reactor/src/Convert.kt b/reactive/kotlinx-coroutines-reactor/src/Convert.kt
index efdedf7..97a2649 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Convert.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Convert.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-reactor/src/Flux.kt b/reactive/kotlinx-coroutines-reactor/src/Flux.kt
index 1e408d8..e0355e2 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Flux.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Flux.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-reactor/src/Migration.kt b/reactive/kotlinx-coroutines-reactor/src/Migration.kt
index 8da0db2..dc13142 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Migration.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Migration.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:JvmName("FlowKt")
package kotlinx.coroutines.reactor
diff --git a/reactive/kotlinx-coroutines-reactor/src/Mono.kt b/reactive/kotlinx-coroutines-reactor/src/Mono.kt
index 27dea60..94b925a 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Mono.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Mono.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package kotlinx.coroutines.reactor
@@ -40,7 +36,7 @@
* `null` is returned.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*/
public suspend fun <T> Mono<T>.awaitSingleOrNull(): T? = suspendCancellableCoroutine { cont ->
@@ -72,7 +68,7 @@
* if this Mono has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately cancels its [Subscription] and resumes with [CancellationException].
*
* @throws NoSuchElementException if the Mono does not emit any value
diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt
index 912fb6e..db464c8 100644
--- a/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import kotlin.coroutines.*
diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt
index f65d2ec..7a5debf 100644
--- a/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import kotlinx.coroutines.reactive.*
diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt
index 6a77bbf..ba81977 100644
--- a/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt
index 03b052b..d780f51 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/BackpressureTest.kt b/reactive/kotlinx-coroutines-reactor/test/BackpressureTest.kt
index 3d6398a..16775eb 100644
--- a/reactive/kotlinx-coroutines-reactor/test/BackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/BackpressureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/Check.kt b/reactive/kotlinx-coroutines-reactor/test/Check.kt
index e092a6c..d5a9a57 100644
--- a/reactive/kotlinx-coroutines-reactor/test/Check.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/Check.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
import reactor.core.publisher.Flux
diff --git a/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt b/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt
index 8af6d3c..7da27cf 100644
--- a/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt b/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt
index d880738..0a94c8e 100644
--- a/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt
@@ -1,5 +1,6 @@
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.reactive.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt
index 6090408..6c3ca4c 100644
--- a/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/FluxCompletionStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.*
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt
index 1ed3a16..a9eb522 100644
--- a/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.reactive.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt
index 0d5f9e2..562f0a9 100644
--- a/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.*
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt
index 3879c62..6bc6dc1 100644
--- a/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.*
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt
index f575af4..634bbcd 100644
--- a/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
@@ -41,7 +38,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
diff --git a/reactive/kotlinx-coroutines-reactor/test/MonoAwaitStressTest.kt b/reactive/kotlinx-coroutines-reactor/test/MonoAwaitStressTest.kt
index 355aa68..a40ced8 100644
--- a/reactive/kotlinx-coroutines-reactor/test/MonoAwaitStressTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/MonoAwaitStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.reactivestreams.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt
index 2a5e5dc..8060357 100644
--- a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.*
@@ -53,7 +50,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -237,7 +234,7 @@
mono.awaitSingle()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -246,7 +243,7 @@
expect(1)
var subscription: Subscription? = null
val handler = BiFunction<Throwable, Any?, Throwable> { t, _ ->
- assertTrue(t is TestException)
+ assertIs<TestException>(t)
expect(5)
t
}
diff --git a/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt b/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt
index 577238b..5bc6d45 100644
--- a/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt
@@ -1,5 +1,6 @@
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt b/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt
index bed607c..7437d3a 100644
--- a/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.reactor
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Before
import org.junit.Test
diff --git a/reactive/kotlinx-coroutines-rx2/build.gradle b/reactive/kotlinx-coroutines-rx2/build.gradle
deleted file mode 100644
index b6fd932..0000000
--- a/reactive/kotlinx-coroutines-rx2/build.gradle
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-import org.jetbrains.dokka.gradle.DokkaTaskPartial
-
-dependencies {
- api project(':kotlinx-coroutines-reactive')
- testImplementation project(':kotlinx-coroutines-reactive').sourceSets.test.output
- testImplementation "org.reactivestreams:reactive-streams-tck:$reactive_streams_version"
- api "io.reactivex.rxjava2:rxjava:$rxjava2_version"
-}
-
-tasks.withType(DokkaTaskPartial.class) {
- dokkaSourceSets.configureEach {
- externalDocumentationLink {
- url.set(new URL('http://reactivex.io/RxJava/2.x/javadoc/'))
- packageListUrl.set(projectDir.toPath().resolve("package.list").toUri().toURL())
- }
- }
-}
-
-task testNG(type: Test) {
- useTestNG()
- reports.html.destination = file("$buildDir/reports/testng")
- include '**/*ReactiveStreamTckTest.*'
- // Skip testNG when tests are filtered with --tests, otherwise it simply fails
- onlyIf {
- filter.includePatterns.isEmpty()
- }
- doFirst {
- // Classic gradle, nothing works without doFirst
- println "TestNG tests: ($includes)"
- }
-}
-
-test {
- dependsOn(testNG)
- reports.html.destination = file("$buildDir/reports/junit")
-}
diff --git a/reactive/kotlinx-coroutines-rx2/build.gradle.kts b/reactive/kotlinx-coroutines-rx2/build.gradle.kts
new file mode 100644
index 0000000..09562c4
--- /dev/null
+++ b/reactive/kotlinx-coroutines-rx2/build.gradle.kts
@@ -0,0 +1,36 @@
+import org.jetbrains.dokka.gradle.DokkaTaskPartial
+import java.net.*
+
+dependencies {
+ api(project(":kotlinx-coroutines-reactive"))
+ testImplementation("org.reactivestreams:reactive-streams-tck:${version("reactive_streams")}")
+ api("io.reactivex.rxjava2:rxjava:${version("rxjava2")}")
+}
+
+tasks.withType(DokkaTaskPartial::class) {
+ dokkaSourceSets.configureEach {
+ externalDocumentationLink {
+ url = URL("http://reactivex.io/RxJava/2.x/javadoc/")
+ packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL()
+ }
+ }
+}
+
+val testNG by tasks.registering(Test::class) {
+ useTestNG()
+ reports.html.outputLocation = file("$buildDir/reports/testng")
+ include("**/*ReactiveStreamTckTest.*")
+ // Skip testNG when tests are filtered with --tests, otherwise it simply fails
+ onlyIf {
+ filter.includePatterns.isEmpty()
+ }
+ doFirst {
+ // Classic gradle, nothing works without doFirst
+ println("TestNG tests: ($includes)")
+ }
+}
+
+val test by tasks.getting(Test::class) {
+ dependsOn(testNG)
+ reports.html.outputLocation = file("$buildDir/reports/junit")
+}
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt
index aeaa1f4..cfcc95d 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
@@ -18,7 +14,7 @@
* Awaits for completion of this completable without blocking the thread.
* Returns `Unit`, or throws the corresponding exception if this completable produces an error.
*
- * This suspending function is cancellable. If the [Job] of the invoking coroutine is cancelled or completed while this
+ * This suspending function is cancellable. If the [Job] of the invoking coroutine is cancelled while this
* suspending function is suspended, this function immediately resumes with [CancellationException] and disposes of its
* subscription.
*/
@@ -46,7 +42,7 @@
* [MaybeSource] produces an error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this
* function immediately resumes with [CancellationException] and disposes of its subscription.
*/
public suspend fun <T> MaybeSource<T>.awaitSingleOrNull(): T? = suspendCancellableCoroutine { cont ->
@@ -74,7 +70,7 @@
* Returns the resulting value, or throws if either no value is produced or this [MaybeSource] produces an error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this
* function immediately resumes with [CancellationException] and disposes of its subscription.
*
* @throws NoSuchElementException if no elements were produced by this [MaybeSource].
@@ -87,7 +83,7 @@
* maybe had produced error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* immediately resumes with [CancellationException].
*
* ### Deprecation
@@ -109,7 +105,7 @@
* maybe had produced error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* immediately resumes with [CancellationException].
*
* ### Deprecation
@@ -132,7 +128,7 @@
* Returns the resulting value, or throws the corresponding exception if this response produces an error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> SingleSource<T>.await(): T = suspendCancellableCoroutine { cont ->
@@ -158,7 +154,7 @@
* if the observable has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*
* @throws NoSuchElementException if the observable does not emit any value
@@ -171,7 +167,7 @@
* corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> ObservableSource<T>.awaitFirstOrDefault(default: T): T = awaitOne(Mode.FIRST_OR_DEFAULT, default)
@@ -182,7 +178,7 @@
* exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> ObservableSource<T>.awaitFirstOrNull(): T? = awaitOne(Mode.FIRST_OR_DEFAULT)
@@ -193,7 +189,7 @@
* the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> ObservableSource<T>.awaitFirstOrElse(defaultValue: () -> T): T =
@@ -204,7 +200,7 @@
* returns the resulting value, or, if this observable has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*
* @throws NoSuchElementException if the observable does not emit any value
@@ -216,7 +212,7 @@
* if this observable has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*
* @throws NoSuchElementException if the observable does not emit any value
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt
index 3e39033..b015498 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.functions.*
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt
index 94c9c22..0235468 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt
index e4670f3..f1dc93d 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt
index a92d68e..980fb17 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt
index c856bb4..05cc0c6 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package kotlinx.coroutines.rx2
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt
index ab71312..ad846ef 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt
index ad8fac7..d9c9392 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
@@ -70,7 +66,7 @@
// Mutex is locked when either nRequested == 0 or while subscriber.onXXX is being invoked
private val mutex: Mutex = Mutex()
- @Suppress("UNCHECKED_CAST", "INVISIBLE_MEMBER")
+ @Suppress("UNCHECKED_CAST", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
override val onSend: SelectClause2<T, SendChannel<T>> get() = SelectClause2Impl(
clauseObject = this,
regFunc = RxObservableCoroutine<*>::registerSelectForSend as RegistrationFunction,
@@ -165,7 +161,7 @@
if (_signal.value == SIGNALLED)
return
_signal.value = SIGNALLED // we'll signal onError/onCompleted (that the final state -- no CAS needed)
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
val unwrappedCause = cause?.let { unwrap(it) }
if (unwrappedCause == null) {
try {
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt
index d7d5f6c..bac2021 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
@@ -136,7 +132,7 @@
if (delayMillis <= 0) {
toSchedule.run()
} else {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
ctx.delay.invokeOnTimeout(delayMillis, toSchedule, ctx).let { handle = it }
}
return disposable
@@ -178,4 +174,4 @@
/** @suppress */
override fun hashCode(): Int = System.identityHashCode(scheduler)
-}
\ No newline at end of file
+}
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt
index 27842a2..1bdbaa5 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/BackpressureTest.kt b/reactive/kotlinx-coroutines-rx2/test/BackpressureTest.kt
index ed0bc36..033df37 100644
--- a/reactive/kotlinx-coroutines-rx2/test/BackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/BackpressureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/Check.kt b/reactive/kotlinx-coroutines-rx2/test/Check.kt
index beb2c43..ded4b7a 100644
--- a/reactive/kotlinx-coroutines-rx2/test/Check.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/Check.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt b/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt
index 16f0005..c271a2f 100644
--- a/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import io.reactivex.exceptions.*
@@ -39,7 +36,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -139,7 +136,7 @@
completable.await()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -199,7 +196,7 @@
fun testFatalExceptionInSingle() = runTest {
rxCompletable(Dispatchers.Unconfined) {
throw LinkageError()
- }.subscribe({ expectUnreached() }, { expect(1); assertTrue(it is LinkageError) })
+ }.subscribe({ expectUnreached() }, { expect(1); assertIs<LinkageError>(it) })
finish(2)
}
}
diff --git a/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt b/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt
index cfc3240..d57f6fa 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowAsFlowableTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowAsFlowableTest.kt
index 1cbded6..0bcacef 100644
--- a/reactive/kotlinx-coroutines-rx2/test/FlowAsFlowableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/FlowAsFlowableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.Test
diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt
index 3cde182..c976d9b 100644
--- a/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import kotlinx.coroutines.*
@@ -41,7 +38,7 @@
expect(2)
observable.subscribe({ expectUnreached() }, { error ->
expect(4)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
finish(5)
diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt
index 2cc3243..295250e 100644
--- a/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowableExceptionHandlingTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowableExceptionHandlingTest.kt
index 3164392..bcfd32a 100644
--- a/reactive/kotlinx-coroutines-rx2/test/FlowableExceptionHandlingTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/FlowableExceptionHandlingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.exceptions.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt
index 148d1f9..94fc7d6 100644
--- a/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.*
import org.junit.*
@@ -40,7 +37,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -124,4 +121,4 @@
finish(3)
}
}
-}
\ No newline at end of file
+}
diff --git a/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt
index 8a6362a..8469af4 100644
--- a/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/IterableFlowAsFlowableTckTest.kt b/reactive/kotlinx-coroutines-rx2/test/IterableFlowAsFlowableTckTest.kt
index cc22e33..89423a8 100644
--- a/reactive/kotlinx-coroutines-rx2/test/IterableFlowAsFlowableTckTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/IterableFlowAsFlowableTckTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
import io.reactivex.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt b/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt
index 7252ca2..4f16966 100644
--- a/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.exceptions.*
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt b/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt
index f5d128d..74bc832 100644
--- a/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import io.reactivex.exceptions.*
@@ -66,7 +63,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -320,7 +317,7 @@
maybe.awaitSingleOrNull()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -386,7 +383,7 @@
fun testFatalExceptionInSingle() = runTest {
rxMaybe(Dispatchers.Unconfined) {
throw LinkageError()
- }.subscribe({ expectUnreached() }, { expect(1); assertTrue(it is LinkageError) })
+ }.subscribe({ expectUnreached() }, { expect(1); assertIs<LinkageError>(it) })
finish(2)
}
}
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt
index c14c3cc..1391d7e 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.Observer
@@ -12,6 +9,7 @@
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.flow.*
import kotlin.test.*
class ObservableAsFlowTest : TestBase() {
@@ -182,4 +180,4 @@
channel.consumeEach { result.add(it) }
assertEquals(expected, result)
}
-}
\ No newline at end of file
+}
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableCollectTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableCollectTest.kt
index 508f594..59c886d 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableCollectTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableCollectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt
index 7e1d335..3d2546a 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableCompletionStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableExceptionHandlingTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableExceptionHandlingTest.kt
index fb3d0f6..0d34a4e 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableExceptionHandlingTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableExceptionHandlingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.exceptions.*
import kotlinx.coroutines.*
import org.junit.*
@@ -88,8 +85,8 @@
expect(1)
val result = trySend(Unit)
val exception = result.exceptionOrNull()
- assertTrue(exception is UndeliverableException)
- assertTrue(exception.cause is LinkageError)
+ assertIs<UndeliverableException>(exception)
+ assertIs<LinkageError>(exception.cause)
assertTrue(isClosedForSend)
expect(4)
latch.countDown()
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt
index 7023211..09562fb 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt
index e246407..5bd6d0d 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import kotlinx.coroutines.*
@@ -64,7 +61,7 @@
}
checkErroneous(observable) {
- assertTrue(it is IllegalArgumentException)
+ assertIs<IllegalArgumentException>(it)
}
}
@@ -204,7 +201,7 @@
}
checkErroneous(observable) {
- assertTrue(it is IllegalStateException)
+ assertIs<IllegalStateException>(it)
assertEquals("OK", it.message)
}
}
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableSourceAsFlowStressTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableSourceAsFlowStressTest.kt
index 0253fce..2e44de8 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableSourceAsFlowStressTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableSourceAsFlowStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt
index 2c22cbf..0c77a55 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt
index 4f7fa54..06ee05b 100644
--- a/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.plugins.*
import kotlinx.coroutines.*
@@ -48,7 +45,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -161,4 +158,4 @@
}
private fun timeBomb() = Single.timer(1, TimeUnit.MILLISECONDS).doOnSuccess { throw TestException() }
-}
\ No newline at end of file
+}
diff --git a/reactive/kotlinx-coroutines-rx2/test/SchedulerStressTest.kt b/reactive/kotlinx-coroutines-rx2/test/SchedulerStressTest.kt
index ea33a9f..5b77e6a 100644
--- a/reactive/kotlinx-coroutines-rx2/test/SchedulerStressTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/SchedulerStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt b/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt
index 1941867..cf163b7 100644
--- a/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import io.reactivex.plugins.*
diff --git a/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt b/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt
index b359d96..0d9f0f3 100644
--- a/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx2
+import kotlinx.coroutines.testing.*
import io.reactivex.*
import io.reactivex.disposables.*
import io.reactivex.exceptions.*
@@ -50,7 +47,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -222,7 +219,7 @@
single.await()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -247,7 +244,7 @@
fun testFatalExceptionInSingle() = runTest {
rxSingle(Dispatchers.Unconfined) {
throw LinkageError()
- }.subscribe { _, e -> assertTrue(e is LinkageError); expect(1) }
+ }.subscribe { _, e -> assertIs<LinkageError>(e); expect(1) }
finish(2)
}
diff --git a/reactive/kotlinx-coroutines-rx3/build.gradle b/reactive/kotlinx-coroutines-rx3/build.gradle
deleted file mode 100644
index 7676b6e..0000000
--- a/reactive/kotlinx-coroutines-rx3/build.gradle
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-import org.jetbrains.dokka.gradle.DokkaTaskPartial
-
-targetCompatibility = JavaVersion.VERSION_1_8
-
-dependencies {
- api project(':kotlinx-coroutines-reactive')
- testImplementation project(':kotlinx-coroutines-reactive').sourceSets.test.output
- testImplementation "org.reactivestreams:reactive-streams-tck:$reactive_streams_version"
- api "io.reactivex.rxjava3:rxjava:$rxjava3_version"
-}
-
-compileTestKotlin {
- kotlinOptions.jvmTarget = "1.8"
-}
-
-compileKotlin {
- kotlinOptions.jvmTarget = "1.8"
-}
-
-tasks.withType(DokkaTaskPartial.class) {
- dokkaSourceSets.configureEach {
- externalDocumentationLink {
- url.set(new URL('https://reactivex.io/RxJava/3.x/javadoc/'))
- packageListUrl.set(projectDir.toPath().resolve("package.list").toUri().toURL())
- }
- }
-}
-
-task testNG(type: Test) {
- useTestNG()
- reports.html.destination = file("$buildDir/reports/testng")
- include '**/*ReactiveStreamTckTest.*'
- // Skip testNG when tests are filtered with --tests, otherwise it simply fails
- onlyIf {
- filter.includePatterns.isEmpty()
- }
- doFirst {
- // Classic gradle, nothing works without doFirst
- println "TestNG tests: ($includes)"
- }
-}
-
-test {
- dependsOn(testNG)
- reports.html.destination = file("$buildDir/reports/junit")
-}
diff --git a/reactive/kotlinx-coroutines-rx3/build.gradle.kts b/reactive/kotlinx-coroutines-rx3/build.gradle.kts
new file mode 100644
index 0000000..1b761b6
--- /dev/null
+++ b/reactive/kotlinx-coroutines-rx3/build.gradle.kts
@@ -0,0 +1,36 @@
+import org.jetbrains.dokka.gradle.DokkaTaskPartial
+import java.net.*
+
+dependencies {
+ api(project(":kotlinx-coroutines-reactive"))
+ testImplementation("org.reactivestreams:reactive-streams-tck:${version("reactive_streams")}")
+ api("io.reactivex.rxjava3:rxjava:${version("rxjava3")}")
+}
+
+tasks.withType(DokkaTaskPartial::class) {
+ dokkaSourceSets.configureEach {
+ externalDocumentationLink {
+ url = URL("https://reactivex.io/RxJava/3.x/javadoc/")
+ packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL()
+ }
+ }
+}
+
+val testNG by tasks.registering(Test::class) {
+ useTestNG()
+ reports.html.outputLocation = file("$buildDir/reports/testng")
+ include("**/*ReactiveStreamTckTest.*")
+ // Skip testNG when tests are filtered with --tests, otherwise it simply fails
+ onlyIf {
+ filter.includePatterns.isEmpty()
+ }
+ doFirst {
+ // Classic gradle, nothing works without doFirst
+ println("TestNG tests: ($includes)")
+ }
+}
+
+val test by tasks.getting(Test::class) {
+ dependsOn(testNG)
+ reports.html.outputLocation = file("$buildDir/reports/junit")
+}
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt b/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt
index 33ec848..0353d77 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
@@ -18,7 +14,7 @@
* Awaits for completion of this completable without blocking the thread.
* Returns `Unit`, or throws the corresponding exception if this completable produces an error.
*
- * This suspending function is cancellable. If the [Job] of the invoking coroutine is cancelled or completed while this
+ * This suspending function is cancellable. If the [Job] of the invoking coroutine is cancelled while this
* suspending function is suspended, this function immediately resumes with [CancellationException] and disposes of its
* subscription.
*/
@@ -38,7 +34,7 @@
* [MaybeSource] produces an error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this
* function immediately resumes with [CancellationException] and disposes of its subscription.
*/
public suspend fun <T> MaybeSource<T & Any>.awaitSingleOrNull(): T? = suspendCancellableCoroutine { cont ->
@@ -55,7 +51,7 @@
* Returns the resulting value, or throws if either no value is produced or this [MaybeSource] produces an error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this
* function immediately resumes with [CancellationException] and disposes of its subscription.
*
* @throws NoSuchElementException if no elements were produced by this [MaybeSource].
@@ -68,7 +64,7 @@
* maybe had produced error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* immediately resumes with [CancellationException].
*
* ### Deprecation
@@ -91,7 +87,7 @@
* maybe had produced error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * If the [Job] of the current coroutine is cancelled while this suspending function is waiting, this function
* immediately resumes with [CancellationException].
*
* ### Deprecation
@@ -115,7 +111,7 @@
* Returns the resulting value, or throws the corresponding exception if this response produces an error.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> SingleSource<T & Any>.await(): T = suspendCancellableCoroutine { cont ->
@@ -133,7 +129,7 @@
* if the observable has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*
* @throws NoSuchElementException if the observable does not emit any value
@@ -147,7 +143,7 @@
* corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
@Suppress("UNCHECKED_CAST")
@@ -160,7 +156,7 @@
* exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> ObservableSource<T & Any>.awaitFirstOrNull(): T? = awaitOne(Mode.FIRST_OR_DEFAULT)
@@ -171,7 +167,7 @@
* the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*/
public suspend fun <T> ObservableSource<T & Any>.awaitFirstOrElse(defaultValue: () -> T): T =
@@ -182,7 +178,7 @@
* returns the resulting value, or, if this observable has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*
* @throws NoSuchElementException if the observable does not emit any value
@@ -195,7 +191,7 @@
* if this observable has produced an error, throws the corresponding exception.
*
* This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while the suspending function is waiting, this
+ * If the [Job] of the current coroutine is cancelled while the suspending function is waiting, this
* function immediately disposes of its subscription and resumes with [CancellationException].
*
* @throws NoSuchElementException if the observable does not emit any value
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt b/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt
index 1017b11..041c5a2 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.functions.*
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt b/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt
index 6144944..d65dde0 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt b/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt
index 47cc6ad..87f302f 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt
index 57d2dfb..a3731f8 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt b/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt
index 9357f28..0dfd68c 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt
index defb2b7..abc59a2 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt
index 8ea761c..0b26f47 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
@@ -70,7 +66,7 @@
// Mutex is locked when either nRequested == 0 or while subscriber.onXXX is being invoked
private val mutex: Mutex = Mutex()
- @Suppress("UNCHECKED_CAST", "INVISIBLE_MEMBER")
+ @Suppress("UNCHECKED_CAST", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
override val onSend: SelectClause2<T, SendChannel<T>> get() = SelectClause2Impl(
clauseObject = this,
regFunc = RxObservableCoroutine<*>::registerSelectForSend as RegistrationFunction,
@@ -165,7 +161,7 @@
if (_signal.value == SIGNALLED)
return
_signal.value = SIGNALLED // we'll signal onError/onCompleted (that the final state -- no CAS needed)
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
val unwrappedCause = cause?.let { unwrap(it) }
if (unwrappedCause == null) {
try {
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt b/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt
index e7f9386..8f77d4c 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
@@ -136,7 +132,7 @@
if (delayMillis <= 0) {
toSchedule.run()
} else {
- @Suppress("INVISIBLE_MEMBER")
+ @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // do not remove the INVISIBLE_REFERENCE suppression: required in K2
ctx.delay.invokeOnTimeout(delayMillis, toSchedule, ctx).let { handle = it }
}
return disposable
diff --git a/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt b/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt
index e7678f0..b424a14 100644
--- a/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt
+++ b/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/BackpressureTest.kt b/reactive/kotlinx-coroutines-rx3/test/BackpressureTest.kt
index 9cec483..bfffe15 100644
--- a/reactive/kotlinx-coroutines-rx3/test/BackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/BackpressureTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/Check.kt b/reactive/kotlinx-coroutines-rx3/test/Check.kt
index 37a1b32..c1e6d2e 100644
--- a/reactive/kotlinx-coroutines-rx3/test/Check.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/Check.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/CompletableTest.kt b/reactive/kotlinx-coroutines-rx3/test/CompletableTest.kt
index cfdb6d4..b9355cc 100644
--- a/reactive/kotlinx-coroutines-rx3/test/CompletableTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/CompletableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.disposables.*
import io.reactivex.rxjava3.exceptions.*
@@ -39,7 +36,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -139,7 +136,7 @@
completable.await()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -199,7 +196,7 @@
fun testFatalExceptionInSingle() = runTest {
rxCompletable(Dispatchers.Unconfined) {
throw LinkageError()
- }.subscribe({ expectUnreached() }, { expect(1); assertTrue(it is LinkageError) })
+ }.subscribe({ expectUnreached() }, { expect(1); assertIs<LinkageError>(it) })
finish(2)
}
}
diff --git a/reactive/kotlinx-coroutines-rx3/test/ConvertTest.kt b/reactive/kotlinx-coroutines-rx3/test/ConvertTest.kt
index e2fe533..5013bb9 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ConvertTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ConvertTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.consumeAsFlow
diff --git a/reactive/kotlinx-coroutines-rx3/test/FlowAsFlowableTest.kt b/reactive/kotlinx-coroutines-rx3/test/FlowAsFlowableTest.kt
index a73fee4..cc565c8 100644
--- a/reactive/kotlinx-coroutines-rx3/test/FlowAsFlowableTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/FlowAsFlowableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.Test
diff --git a/reactive/kotlinx-coroutines-rx3/test/FlowAsObservableTest.kt b/reactive/kotlinx-coroutines-rx3/test/FlowAsObservableTest.kt
index 5759f9f..8bacb2f 100644
--- a/reactive/kotlinx-coroutines-rx3/test/FlowAsObservableTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/FlowAsObservableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.disposables.*
import kotlinx.coroutines.*
@@ -41,7 +38,7 @@
expect(2)
observable.subscribe({ expectUnreached() }, { error ->
expect(4)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
finish(5)
diff --git a/reactive/kotlinx-coroutines-rx3/test/FlowableContextTest.kt b/reactive/kotlinx-coroutines-rx3/test/FlowableContextTest.kt
index b70e0d5..5e87d71 100644
--- a/reactive/kotlinx-coroutines-rx3/test/FlowableContextTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/FlowableContextTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/FlowableExceptionHandlingTest.kt b/reactive/kotlinx-coroutines-rx3/test/FlowableExceptionHandlingTest.kt
index 126cb81..d250de9 100644
--- a/reactive/kotlinx-coroutines-rx3/test/FlowableExceptionHandlingTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/FlowableExceptionHandlingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.exceptions.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/FlowableTest.kt b/reactive/kotlinx-coroutines-rx3/test/FlowableTest.kt
index 746d6e8..2460bd6 100644
--- a/reactive/kotlinx-coroutines-rx3/test/FlowableTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/FlowableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.*
import org.junit.Test
@@ -39,7 +36,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
diff --git a/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt
index 1302124..f51d7cd 100644
--- a/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/IntegrationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.consumeAsFlow
diff --git a/reactive/kotlinx-coroutines-rx3/test/IterableFlowAsFlowableTckTest.kt b/reactive/kotlinx-coroutines-rx3/test/IterableFlowAsFlowableTckTest.kt
index 8e54922..295f055 100644
--- a/reactive/kotlinx-coroutines-rx3/test/IterableFlowAsFlowableTckTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/IterableFlowAsFlowableTckTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
import io.reactivex.rxjava3.core.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/LeakedExceptionTest.kt b/reactive/kotlinx-coroutines-rx3/test/LeakedExceptionTest.kt
index 028ded0..5f9caf5 100644
--- a/reactive/kotlinx-coroutines-rx3/test/LeakedExceptionTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/LeakedExceptionTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.exceptions.*
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/MaybeTest.kt b/reactive/kotlinx-coroutines-rx3/test/MaybeTest.kt
index bea939e..3746d43 100644
--- a/reactive/kotlinx-coroutines-rx3/test/MaybeTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/MaybeTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.disposables.*
import io.reactivex.rxjava3.exceptions.*
@@ -66,7 +63,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -320,7 +317,7 @@
maybe.awaitSingleOrNull()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -386,7 +383,7 @@
fun testFatalExceptionInSingle() = runTest {
rxMaybe(Dispatchers.Unconfined) {
throw LinkageError()
- }.subscribe({ expectUnreached() }, { expect(1); assertTrue(it is LinkageError) })
+ }.subscribe({ expectUnreached() }, { expect(1); assertIs<LinkageError>(it) })
finish(2)
}
}
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableAsFlowTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableAsFlowTest.kt
index 262da9a..79d7052 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableAsFlowTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableAsFlowTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.ObservableSource
import io.reactivex.rxjava3.core.Observer
@@ -12,6 +9,7 @@
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.testing.flow.*
import kotlin.test.*
class ObservableAsFlowTest : TestBase() {
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableCollectTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableCollectTest.kt
index 680786f..ebfb8e6 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableCollectTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableCollectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.ObservableSource
import io.reactivex.rxjava3.disposables.*
import kotlinx.coroutines.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt
index c1d25bc..c0acd07 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableCompletionStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableExceptionHandlingTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableExceptionHandlingTest.kt
index 5ddb36e..63fb73b 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableExceptionHandlingTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableExceptionHandlingTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.exceptions.*
import kotlinx.coroutines.*
import org.junit.*
@@ -88,8 +85,8 @@
expect(1)
val result = trySend(Unit)
val exception = result.exceptionOrNull()
- assertTrue(exception is UndeliverableException)
- assertTrue(exception.cause is LinkageError)
+ assertIs<UndeliverableException>(exception)
+ assertIs<LinkageError>(exception.cause)
assertTrue(isClosedForSend)
expect(4)
latch.countDown()
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableMultiTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableMultiTest.kt
index d7c799d..83005e9 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableMultiTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableMultiTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableSingleTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableSingleTest.kt
index 692f014..ea09a22 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableSingleTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableSingleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.disposables.*
import kotlinx.coroutines.*
@@ -64,7 +61,7 @@
}
checkErroneous(observable) {
- assertTrue(it is IllegalArgumentException)
+ assertIs<IllegalArgumentException>(it)
}
}
@@ -204,7 +201,7 @@
}
checkErroneous(observable) {
- assertTrue(it is IllegalStateException)
+ assertIs<IllegalStateException>(it)
assertEquals("OK", it.message)
}
}
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableSourceAsFlowStressTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableSourceAsFlowStressTest.kt
index 01d6a20..13b6a84 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableSourceAsFlowStressTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableSourceAsFlowStressTest.kt
@@ -1,11 +1,7 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
-import io.reactivex.rxjava3.exceptions.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableSubscriptionSelectTest.kt
index 58a5461..7e21c5c 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableSubscriptionSelectTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableSubscriptionSelectTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/ObservableTest.kt b/reactive/kotlinx-coroutines-rx3/test/ObservableTest.kt
index c6a6be5..59031e3 100644
--- a/reactive/kotlinx-coroutines-rx3/test/ObservableTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/ObservableTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.plugins.*
import kotlinx.coroutines.*
@@ -48,7 +45,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
diff --git a/reactive/kotlinx-coroutines-rx3/test/SchedulerStressTest.kt b/reactive/kotlinx-coroutines-rx3/test/SchedulerStressTest.kt
index 5abb511..96e2141 100644
--- a/reactive/kotlinx-coroutines-rx3/test/SchedulerStressTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/SchedulerStressTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/SchedulerTest.kt b/reactive/kotlinx-coroutines-rx3/test/SchedulerTest.kt
index c966cdf..fd59503 100644
--- a/reactive/kotlinx-coroutines-rx3/test/SchedulerTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/SchedulerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.disposables.*
import io.reactivex.rxjava3.plugins.*
diff --git a/reactive/kotlinx-coroutines-rx3/test/SingleTest.kt b/reactive/kotlinx-coroutines-rx3/test/SingleTest.kt
index 3e763aa..381a9df 100644
--- a/reactive/kotlinx-coroutines-rx3/test/SingleTest.kt
+++ b/reactive/kotlinx-coroutines-rx3/test/SingleTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.rx3
+import kotlinx.coroutines.testing.*
import io.reactivex.rxjava3.core.*
import io.reactivex.rxjava3.disposables.*
import io.reactivex.rxjava3.exceptions.*
@@ -50,7 +47,7 @@
expectUnreached()
}, { error ->
expect(5)
- assertTrue(error is RuntimeException)
+ assertIs<RuntimeException>(error)
assertEquals("OK", error.message)
})
expect(3)
@@ -222,7 +219,7 @@
single.await()
expectUnreached()
} catch (e: TestException) {
- assertTrue(e.suppressed[0] is TestException2)
+ assertIs<TestException2>(e.suppressed[0])
}
}
@@ -247,7 +244,7 @@
fun testFatalExceptionInSingle() = runTest {
rxSingle(Dispatchers.Unconfined) {
throw LinkageError()
- }.subscribe { _, e -> assertTrue(e is LinkageError); expect(1) }
+ }.subscribe { _, e -> assertIs<LinkageError>(e); expect(1) }
finish(2)
}
diff --git a/settings.gradle b/settings.gradle
deleted file mode 100644
index 151c087..0000000
--- a/settings.gradle
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-pluginManagement {
- plugins {
- id "org.openjfx.javafxplugin" version javafx_plugin_version
- id "me.champeau.jmh" version "0.6.8"
- }
-
- repositories {
- maven { url "https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev/" }
- gradlePluginPortal()
- }
-}
-
-rootProject.name = 'kotlinx.coroutines'
-
-def module(String path) {
- int i = path.lastIndexOf('/')
- def name = path.substring(i + 1)
- include(name)
- project(":$name").projectDir = file(path)
-}
-def prop = System.getProperty("build_snapshot_train")
-ext.build_snapshot_train = prop != null && prop != ""
-// ---------------------------
-
-include('benchmarks')
-
-include "kotlinx-coroutines-core"
-
-module('kotlinx-coroutines-test')
-module('kotlinx-coroutines-debug')
-module('kotlinx-coroutines-bom')
-
-
-module('integration/kotlinx-coroutines-guava')
-module('integration/kotlinx-coroutines-jdk8')
-module('integration/kotlinx-coroutines-slf4j')
-module('integration/kotlinx-coroutines-play-services')
-
-module('reactive/kotlinx-coroutines-reactive')
-module('reactive/kotlinx-coroutines-reactor')
-module('reactive/kotlinx-coroutines-jdk9')
-module('reactive/kotlinx-coroutines-rx2')
-module('reactive/kotlinx-coroutines-rx3')
-module('ui/kotlinx-coroutines-android')
-module('ui/kotlinx-coroutines-android/android-unit-tests')
-if (JavaVersion.current().isJava11Compatible()) {
- module('ui/kotlinx-coroutines-javafx')
-}
-module('ui/kotlinx-coroutines-swing')
-
-if (!build_snapshot_train) {
- module('js/example-frontend-js')
-}
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 0000000..423c613
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1,52 @@
+pluginManagement {
+ val javafx_plugin_version: String by settings
+ plugins {
+ id("org.openjfx.javafxplugin") version javafx_plugin_version
+ id("me.champeau.jmh") version "0.7.2"
+ }
+
+ repositories {
+ maven(url = "https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev/")
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "kotlinx.coroutines"
+
+fun module(path: String) {
+ val i = path.lastIndexOf("/")
+ val name = path.substring(i + 1)
+ include(name)
+ project(":$name").projectDir = file(path)
+}
+val prop = System.getProperty("build_snapshot_train")
+var build_snapshot_train: String by extra
+build_snapshot_train = if (prop != null && prop != "") "true" else "false"
+// ---------------------------
+
+include("benchmarks")
+module("test-utils")
+
+include("kotlinx-coroutines-core")
+
+module("kotlinx-coroutines-test")
+module("kotlinx-coroutines-debug")
+module("kotlinx-coroutines-bom")
+
+
+module("integration/kotlinx-coroutines-guava")
+module("integration/kotlinx-coroutines-jdk8")
+module("integration/kotlinx-coroutines-slf4j")
+module("integration/kotlinx-coroutines-play-services")
+
+module("reactive/kotlinx-coroutines-reactive")
+module("reactive/kotlinx-coroutines-reactor")
+module("reactive/kotlinx-coroutines-jdk9")
+module("reactive/kotlinx-coroutines-rx2")
+module("reactive/kotlinx-coroutines-rx3")
+module("ui/kotlinx-coroutines-android")
+module("ui/kotlinx-coroutines-android/android-unit-tests")
+if (JavaVersion.current().isJava11Compatible()) {
+ module("ui/kotlinx-coroutines-javafx")
+}
+module("ui/kotlinx-coroutines-swing")
diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts
new file mode 100644
index 0000000..66074fb
--- /dev/null
+++ b/test-utils/build.gradle.kts
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+kotlin {
+ sourceSets {
+ commonMain.dependencies {
+ api("org.jetbrains.kotlin:kotlin-test-common:${version("kotlin")}")
+ api("org.jetbrains.kotlin:kotlin-test-annotations-common:${version("kotlin")}")
+ }
+ jvmMain.dependencies {
+ api("org.jetbrains.kotlin:kotlin-test:${version("kotlin")}")
+ // Workaround to make addSuppressed work in tests
+ api("org.jetbrains.kotlin:kotlin-reflect:${version("kotlin")}")
+ api("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${version("kotlin")}")
+ api("org.jetbrains.kotlin:kotlin-test-junit:${version("kotlin")}")
+ api("junit:junit:${version("junit")}")
+ }
+ jsMain.dependencies {
+ api("org.jetbrains.kotlin:kotlin-test-js:${version("kotlin")}")
+ }
+ val wasmJsMain by getting {
+ dependencies {
+ api("org.jetbrains.kotlin:kotlin-test-wasm-js:${version("kotlin")}")
+ }
+ }
+ }
+}
diff --git a/kotlinx-coroutines-core/common/test/flow/terminal/LaunchFlow.kt b/test-utils/common/src/LaunchFlow.kt
similarity index 93%
rename from kotlinx-coroutines-core/common/test/flow/terminal/LaunchFlow.kt
rename to test-utils/common/src/LaunchFlow.kt
index ceefa73..c13e07f 100644
--- a/kotlinx-coroutines-core/common/test/flow/terminal/LaunchFlow.kt
+++ b/test-utils/common/src/LaunchFlow.kt
@@ -1,10 +1,7 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.flow
+package kotlinx.coroutines.testing.flow
import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
import kotlin.jvm.*
import kotlin.reflect.*
@@ -38,7 +35,7 @@
check(onEach != null) { "onEach block should be registered first" }
check(finally == null) { "exceptionHandlers block should be registered before finally block" }
@Suppress("UNCHECKED_CAST")
- exceptionHandlers[T::class] = action as Handler<Throwable>
+ exceptionHandlers[T::class] = action as Handler<Throwable>
}
public fun finally(action: suspend CoroutineScope.(cause: Throwable?) -> Unit) {
diff --git a/test-utils/common/src/MainDispatcherTestBase.kt b/test-utils/common/src/MainDispatcherTestBase.kt
new file mode 100644
index 0000000..dd867a2
--- /dev/null
+++ b/test-utils/common/src/MainDispatcherTestBase.kt
@@ -0,0 +1,270 @@
+package kotlinx.coroutines.testing
+
+import kotlinx.coroutines.*
+import kotlin.test.*
+
+abstract class MainDispatcherTestBase: TestBase() {
+
+ open fun shouldSkipTesting(): Boolean = false
+
+ open suspend fun spinTest(testBody: Job) {
+ testBody.join()
+ }
+
+ abstract fun isMainThread(): Boolean?
+
+ /** Runs the given block as a test, unless [shouldSkipTesting] indicates that the environment is not suitable. */
+ fun runTestOrSkip(block: suspend CoroutineScope.() -> Unit): TestResult {
+ // written as a block body to make the need to return `TestResult` explicit
+ return runTest {
+ if (shouldSkipTesting()) return@runTest
+ val testBody = launch(Dispatchers.Default) {
+ block()
+ }
+ spinTest(testBody)
+ }
+ }
+
+ /** Tests the [toString] behavior of [Dispatchers.Main] and [MainCoroutineDispatcher.immediate] */
+ @Test
+ fun testMainDispatcherToString() {
+ assertEquals("Dispatchers.Main", Dispatchers.Main.toString())
+ assertEquals("Dispatchers.Main.immediate", Dispatchers.Main.immediate.toString())
+ }
+
+ /** Tests that the tasks scheduled earlier from [MainCoroutineDispatcher.immediate] will be executed earlier,
+ * even if the immediate dispatcher was entered from the main thread. */
+ @Test
+ fun testMainDispatcherOrderingInMainThread() = runTestOrSkip {
+ withContext(Dispatchers.Main) {
+ testMainDispatcherOrdering()
+ }
+ }
+
+ /** Tests that the tasks scheduled earlier from [MainCoroutineDispatcher.immediate] will be executed earlier
+ * if the immediate dispatcher was entered from outside the main thread. */
+ @Test
+ fun testMainDispatcherOrderingOutsideMainThread() = runTestOrSkip {
+ testMainDispatcherOrdering()
+ }
+
+ /** Tests that [Dispatchers.Main] and its [MainCoroutineDispatcher.immediate] are treated as different values. */
+ @Test
+ fun testHandlerDispatcherNotEqualToImmediate() {
+ assertNotEquals(Dispatchers.Main, Dispatchers.Main.immediate)
+ }
+
+ /** Tests that [Dispatchers.Main] shares its queue with [MainCoroutineDispatcher.immediate]. */
+ @Test
+ fun testImmediateDispatcherYield() = runTestOrSkip {
+ withContext(Dispatchers.Main) {
+ expect(1)
+ checkIsMainThread()
+ // launch in the immediate dispatcher
+ launch(Dispatchers.Main.immediate) {
+ expect(2)
+ yield()
+ expect(4)
+ }
+ expect(3) // after yield
+ yield() // yield back
+ expect(5)
+ }
+ finish(6)
+ }
+
+ /** Tests that entering [MainCoroutineDispatcher.immediate] from [Dispatchers.Main] happens immediately. */
+ @Test
+ fun testEnteringImmediateFromMain() = runTestOrSkip {
+ withContext(Dispatchers.Main) {
+ expect(1)
+ val job = launch { expect(3) }
+ withContext(Dispatchers.Main.immediate) {
+ expect(2)
+ }
+ job.join()
+ }
+ finish(4)
+ }
+
+ /** Tests that dispatching to [MainCoroutineDispatcher.immediate] is required from and only from dispatchers
+ * other than the main dispatchers and that it's always required for [Dispatchers.Main] itself. */
+ @Test
+ fun testDispatchRequirements() = runTestOrSkip {
+ checkDispatchRequirements()
+ withContext(Dispatchers.Main) {
+ checkDispatchRequirements()
+ withContext(Dispatchers.Main.immediate) {
+ checkDispatchRequirements()
+ }
+ checkDispatchRequirements()
+ }
+ checkDispatchRequirements()
+ }
+
+ private suspend fun checkDispatchRequirements() {
+ isMainThread()?.let {
+ assertNotEquals(
+ it,
+ Dispatchers.Main.immediate.isDispatchNeeded(currentCoroutineContext())
+ )
+ }
+ assertTrue(Dispatchers.Main.isDispatchNeeded(currentCoroutineContext()))
+ assertTrue(Dispatchers.Default.isDispatchNeeded(currentCoroutineContext()))
+ }
+
+ /** Tests that launching a coroutine in [MainScope] will execute it in the main thread. */
+ @Test
+ fun testLaunchInMainScope() = runTestOrSkip {
+ var executed = false
+ withMainScope {
+ launch {
+ checkIsMainThread()
+ executed = true
+ }.join()
+ if (!executed) throw AssertionError("Should be executed")
+ }
+ }
+
+ /** Tests that a failure in [MainScope] will not propagate upwards. */
+ @Test
+ fun testFailureInMainScope() = runTestOrSkip {
+ var exception: Throwable? = null
+ withMainScope {
+ launch(CoroutineExceptionHandler { ctx, e -> exception = e }) {
+ checkIsMainThread()
+ throw TestException()
+ }.join()
+ }
+ if (exception!! !is TestException) throw AssertionError("Expected TestException, but had $exception")
+ }
+
+ /** Tests cancellation in [MainScope]. */
+ @Test
+ fun testCancellationInMainScope() = runTestOrSkip {
+ withMainScope {
+ cancel()
+ launch(start = CoroutineStart.ATOMIC) {
+ checkIsMainThread()
+ delay(Long.MAX_VALUE)
+ }.join()
+ }
+ }
+
+ private suspend fun <R> withMainScope(block: suspend CoroutineScope.() -> R): R {
+ MainScope().apply {
+ return block().also { coroutineContext[Job]!!.cancelAndJoin() }
+ }
+ }
+
+ private suspend fun testMainDispatcherOrdering() {
+ withContext(Dispatchers.Main.immediate) {
+ expect(1)
+ launch(Dispatchers.Main) {
+ expect(2)
+ }
+ withContext(Dispatchers.Main) {
+ finish(3)
+ }
+ }
+ }
+
+ abstract class WithRealTimeDelay : MainDispatcherTestBase() {
+ abstract fun scheduleOnMainQueue(block: () -> Unit)
+
+ /** Tests that after a delay, the execution gets back to the main thread. */
+ @Test
+ fun testDelay() = runTestOrSkip {
+ expect(1)
+ checkNotMainThread()
+ scheduleOnMainQueue { expect(2) }
+ withContext(Dispatchers.Main) {
+ checkIsMainThread()
+ expect(3)
+ scheduleOnMainQueue { expect(4) }
+ delay(100)
+ checkIsMainThread()
+ expect(5)
+ }
+ checkNotMainThread()
+ finish(6)
+ }
+
+ /** Tests that [Dispatchers.Main] is in agreement with the default time source: it's not much slower. */
+ @Test
+ fun testWithTimeoutContextDelayNoTimeout() = runTestOrSkip {
+ expect(1)
+ withTimeout(1000) {
+ withContext(Dispatchers.Main) {
+ checkIsMainThread()
+ expect(2)
+ delay(100)
+ checkIsMainThread()
+ expect(3)
+ }
+ }
+ checkNotMainThread()
+ finish(4)
+ }
+
+ /** Tests that [Dispatchers.Main] is in agreement with the default time source: it's not much faster. */
+ @Test
+ fun testWithTimeoutContextDelayTimeout() = runTestOrSkip {
+ expect(1)
+ assertFailsWith<TimeoutCancellationException> {
+ withTimeout(300) {
+ // A substitute for withContext(Dispatcher.Main) that is started even if the 300ms
+ // timeout happens fsater then dispatch
+ launch(Dispatchers.Main, start = CoroutineStart.ATOMIC) {
+ checkIsMainThread()
+ expect(2)
+ delay(1000)
+ expectUnreached()
+ }.join()
+ }
+ expectUnreached()
+ }
+ checkNotMainThread()
+ finish(3)
+ }
+
+ /** Tests that the timeout of [Dispatchers.Main] is in agreement with its [delay]: it's not much faster. */
+ @Test
+ fun testWithContextTimeoutDelayNoTimeout() = runTestOrSkip {
+ expect(1)
+ withContext(Dispatchers.Main) {
+ withTimeout(1000) {
+ checkIsMainThread()
+ expect(2)
+ delay(100)
+ checkIsMainThread()
+ expect(3)
+ }
+ }
+ checkNotMainThread()
+ finish(4)
+ }
+
+ /** Tests that the timeout of [Dispatchers.Main] is in agreement with its [delay]: it's not much slower. */
+ @Test
+ fun testWithContextTimeoutDelayTimeout() = runTestOrSkip {
+ expect(1)
+ assertFailsWith<TimeoutCancellationException> {
+ withContext(Dispatchers.Main) {
+ withTimeout(100) {
+ checkIsMainThread()
+ expect(2)
+ delay(1000)
+ expectUnreached()
+ }
+ }
+ expectUnreached()
+ }
+ checkNotMainThread()
+ finish(3)
+ }
+ }
+
+ fun checkIsMainThread() { isMainThread()?.let { check(it) } }
+ fun checkNotMainThread() { isMainThread()?.let { check(!it) } }
+}
diff --git a/test-utils/common/src/TestBase.common.kt b/test-utils/common/src/TestBase.common.kt
new file mode 100644
index 0000000..5c0cba4
--- /dev/null
+++ b/test-utils/common/src/TestBase.common.kt
@@ -0,0 +1,284 @@
+@file:Suppress("unused")
+package kotlinx.coroutines.testing
+
+import kotlinx.atomicfu.*
+import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.*
+import kotlinx.coroutines.internal.*
+import kotlin.coroutines.*
+import kotlin.test.*
+import kotlin.time.*
+import kotlin.time.Duration.Companion.seconds
+
+/**
+ * The number of milliseconds that is sure not to pass [assertRunsFast].
+ */
+const val SLOW = 100_000L
+
+/**
+ * Asserts that a block completed within [timeout].
+ */
+inline fun <T> assertRunsFast(timeout: Duration, block: () -> T): T {
+ val result: T
+ val elapsed = TimeSource.Monotonic.measureTime { result = block() }
+ assertTrue("Should complete in $timeout, but took $elapsed") { elapsed < timeout }
+ return result
+}
+
+/**
+ * Asserts that a block completed within two seconds.
+ */
+inline fun <T> assertRunsFast(block: () -> T): T = assertRunsFast(2.seconds, block)
+
+/**
+ * Whether the tests should trace their calls to `expect` and `finish` with `println`.
+ * `false` by default. On the JVM, can be set to `true` by setting the `test.verbose` system property.
+ */
+expect val VERBOSE: Boolean
+
+interface OrderedExecution {
+ /** Expect the next action to be [index] in order. */
+ fun expect(index: Int)
+
+ /** Expect this action to be final, with the given [index]. */
+ fun finish(index: Int)
+
+ /** * Asserts that this line is never executed. */
+ fun expectUnreached()
+
+ /**
+ * Checks that [finish] was called.
+ *
+ * By default, it is allowed to not call [finish] if [expect] was not called.
+ * This is useful for tests that don't check the ordering of events.
+ * When [allowNotUsingExpect] is set to `false`, it is an error to not call [finish] in any case.
+ */
+ fun checkFinishCall(allowNotUsingExpect: Boolean = true)
+
+ class Impl : OrderedExecution {
+ private val actionIndex = atomic(0)
+
+ override fun expect(index: Int) {
+ val wasIndex = actionIndex.incrementAndGet()
+ if (VERBOSE) println("expect($index), wasIndex=$wasIndex")
+ check(index == wasIndex) {
+ if (wasIndex < 0) "Expecting action index $index but it is actually finished"
+ else "Expecting action index $index but it is actually $wasIndex"
+ }
+ }
+
+ override fun finish(index: Int) {
+ val wasIndex = actionIndex.getAndSet(Int.MIN_VALUE) + 1
+ if (VERBOSE) println("finish($index), wasIndex=${if (wasIndex < 0) "finished" else wasIndex}")
+ check(index == wasIndex) {
+ if (wasIndex < 0) "Finished more than once"
+ else "Finishing with action index $index but it is actually $wasIndex"
+ }
+ }
+
+ override fun expectUnreached() {
+ error("Should not be reached, ${
+ actionIndex.value.let {
+ when {
+ it < 0 -> "already finished"
+ it == 0 -> "'expect' was not called yet"
+ else -> "the last executed action was $it"
+ }
+ }
+ }")
+ }
+
+ override fun checkFinishCall(allowNotUsingExpect: Boolean) {
+ actionIndex.value.let {
+ assertTrue(
+ it < 0 || allowNotUsingExpect && it == 0,
+ "Expected `finish(${actionIndex.value + 1})` to be called, but the test finished"
+ )
+ }
+ }
+ }
+}
+
+interface ErrorCatching {
+ /**
+ * Returns `true` if errors were logged in the test.
+ */
+ fun hasError(): Boolean
+
+ /**
+ * Directly reports an error to the test catching facilities.
+ */
+ fun reportError(error: Throwable)
+
+ class Impl : ErrorCatching {
+
+ private val errors = mutableListOf<Throwable>()
+ private val lock = SynchronizedObject()
+ private var closed = false
+
+ override fun hasError(): Boolean = synchronized(lock) {
+ errors.isNotEmpty()
+ }
+
+ override fun reportError(error: Throwable) {
+ synchronized(lock) {
+ if (closed) {
+ lastResortReportException(error)
+ } else {
+ errors.add(error)
+ }
+ }
+ }
+
+ fun close() {
+ synchronized(lock) {
+ if (closed) {
+ lastResortReportException(IllegalStateException("ErrorCatching closed more than once"))
+ }
+ closed = true
+ errors.firstOrNull()?.let {
+ for (error in errors.drop(1))
+ it.addSuppressed(error)
+ throw it
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Reports an error *somehow* so that it doesn't get completely forgotten.
+ */
+internal expect fun lastResortReportException(error: Throwable)
+
+/**
+ * Throws [IllegalStateException] when `value` is false, like `check` in stdlib, but also ensures that the
+ * test will not complete successfully even if this exception is consumed somewhere in the test.
+ */
+public inline fun ErrorCatching.check(value: Boolean, lazyMessage: () -> Any) {
+ if (!value) error(lazyMessage())
+}
+
+/**
+ * Throws [IllegalStateException], like `error` in stdlib, but also ensures that the test will not
+ * complete successfully even if this exception is consumed somewhere in the test.
+ */
+fun ErrorCatching.error(message: Any, cause: Throwable? = null): Nothing {
+ throw IllegalStateException(message.toString(), cause).also {
+ reportError(it)
+ }
+}
+
+/**
+ * A class inheriting from which allows to check the execution order inside tests.
+ *
+ * @see TestBase
+ */
+open class OrderedExecutionTestBase : OrderedExecution
+{
+ // TODO: move to by-delegation when [reset] is no longer needed.
+ private var orderedExecutionDelegate = OrderedExecution.Impl()
+
+ @AfterTest
+ fun checkFinished() { orderedExecutionDelegate.checkFinishCall() }
+
+ /** Resets counter and finish flag. Workaround for parametrized tests absence in common */
+ public fun reset() {
+ orderedExecutionDelegate.checkFinishCall()
+ orderedExecutionDelegate = OrderedExecution.Impl()
+ }
+
+ override fun expect(index: Int) = orderedExecutionDelegate.expect(index)
+
+ override fun finish(index: Int) = orderedExecutionDelegate.finish(index)
+
+ override fun expectUnreached() = orderedExecutionDelegate.expectUnreached()
+
+ override fun checkFinishCall(allowNotUsingExpect: Boolean) =
+ orderedExecutionDelegate.checkFinishCall(allowNotUsingExpect)
+}
+
+fun <T> T.void() {}
+
+@OptionalExpectation
+expect annotation class NoJs()
+
+@OptionalExpectation
+expect annotation class NoNative()
+
+expect val isStressTest: Boolean
+expect val stressTestMultiplier: Int
+expect val stressTestMultiplierSqrt: Int
+
+/**
+ * The result of a multiplatform asynchronous test.
+ * Aliases into Unit on K/JVM and K/N, and into Promise on K/JS.
+ */
+@Suppress("NO_ACTUAL_FOR_EXPECT")
+public expect class TestResult
+
+public expect open class TestBase(): OrderedExecutionTestBase, ErrorCatching {
+ public fun println(message: Any?)
+
+ public fun runTest(
+ expected: ((Throwable) -> Boolean)? = null,
+ unhandled: List<(Throwable) -> Boolean> = emptyList(),
+ block: suspend CoroutineScope.() -> Unit
+ ): TestResult
+}
+
+public suspend inline fun hang(onCancellation: () -> Unit) {
+ try {
+ suspendCancellableCoroutine<Unit> { }
+ } finally {
+ onCancellation()
+ }
+}
+
+suspend inline fun <reified T : Throwable> assertFailsWith(flow: Flow<*>) = assertFailsWith<T> { flow.collect() }
+
+public suspend fun Flow<Int>.sum() = fold(0) { acc, value -> acc + value }
+public suspend fun Flow<Long>.longSum() = fold(0L) { acc, value -> acc + value }
+
+// data is added to avoid stacktrace recovery because CopyableThrowable is not accessible from common modules
+public class TestException(message: String? = null, private val data: Any? = null) : Throwable(message)
+public class TestException1(message: String? = null, private val data: Any? = null) : Throwable(message)
+public class TestException2(message: String? = null, private val data: Any? = null) : Throwable(message)
+public class TestException3(message: String? = null, private val data: Any? = null) : Throwable(message)
+public class TestCancellationException(message: String? = null, private val data: Any? = null) :
+ CancellationException(message)
+
+public class TestRuntimeException(message: String? = null, private val data: Any? = null) : RuntimeException(message)
+public class RecoverableTestException(message: String? = null) : RuntimeException(message)
+public class RecoverableTestCancellationException(message: String? = null) : CancellationException(message)
+
+public fun wrapperDispatcher(context: CoroutineContext): CoroutineContext {
+ val dispatcher = context[ContinuationInterceptor] as CoroutineDispatcher
+ return object : CoroutineDispatcher() {
+ override fun isDispatchNeeded(context: CoroutineContext): Boolean =
+ dispatcher.isDispatchNeeded(context)
+
+ override fun dispatch(context: CoroutineContext, block: Runnable) =
+ dispatcher.dispatch(context, block)
+ }
+}
+
+public suspend fun wrapperDispatcher(): CoroutineContext = wrapperDispatcher(coroutineContext)
+class BadClass {
+ override fun equals(other: Any?): Boolean = error("equals")
+ override fun hashCode(): Int = error("hashCode")
+ override fun toString(): String = error("toString")
+}
+
+public expect val isJavaAndWindows: Boolean
+
+public expect val isNative: Boolean
+
+/*
+ * In common tests we emulate parameterized tests
+ * by iterating over parameters space in the single @Test method.
+ * This kind of tests is too slow for JS and does not fit into
+ * the default Mocha timeout, so we're using this flag to bail-out
+ * and run such tests only on JVM and K/N.
+ */
+public expect val isBoundByJsTestTimeout: Boolean
diff --git a/test-utils/js/src/TestBase.kt b/test-utils/js/src/TestBase.kt
new file mode 100644
index 0000000..61887af
--- /dev/null
+++ b/test-utils/js/src/TestBase.kt
@@ -0,0 +1,97 @@
+package kotlinx.coroutines.testing
+
+import kotlinx.coroutines.*
+import kotlin.test.*
+import kotlin.js.*
+
+actual typealias NoJs = Ignore
+
+actual val VERBOSE = false
+
+actual val isStressTest: Boolean = false
+actual val stressTestMultiplier: Int = 1
+actual val stressTestMultiplierSqrt: Int = 1
+
+@Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE")
+actual typealias TestResult = Promise<Unit>
+
+internal actual fun lastResortReportException(error: Throwable) {
+ println(error)
+ console.log(error)
+}
+
+actual open class TestBase(
+ private val errorCatching: ErrorCatching.Impl
+): OrderedExecutionTestBase(), ErrorCatching by errorCatching {
+ private var lastTestPromise: Promise<*>? = null
+
+ actual constructor(): this(errorCatching = ErrorCatching.Impl())
+
+ actual fun println(message: Any?) {
+ kotlin.io.println(message)
+ }
+
+ actual fun runTest(
+ expected: ((Throwable) -> Boolean)?,
+ unhandled: List<(Throwable) -> Boolean>,
+ block: suspend CoroutineScope.() -> Unit
+ ): TestResult {
+ var exCount = 0
+ var ex: Throwable? = null
+ /*
+ * This is an additional sanity check against `runTest` mis-usage on JS.
+ * The only way to write an async test on JS is to return Promise from the test function.
+ * _Just_ launching promise and returning `Unit` won't suffice as the underlying test framework
+ * won't be able to detect an asynchronous failure in a timely manner.
+ * We cannot detect such situations, but we can detect the most common erroneous pattern
+ * in our code base, an attempt to use multiple `runTest` in the same `@Test` method,
+ * which typically is a premise to the same error:
+ * ```
+ * @Test
+ * fun incorrectTestForJs() { // <- promise is not returned
+ * for (parameter in parameters) {
+ * runTest {
+ * runTestForParameter(parameter)
+ * }
+ * }
+ * }
+ * ```
+ */
+ if (lastTestPromise != null) {
+ error("Attempt to run multiple asynchronous test within one @Test method")
+ }
+ val result = GlobalScope.promise(block = block, context = CoroutineExceptionHandler { _, e ->
+ if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
+ exCount++
+ when {
+ exCount > unhandled.size ->
+ error("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
+ !unhandled[exCount - 1](e) ->
+ error("Unhandled exception was unexpected: $e", e)
+ }
+ }).catch { e ->
+ ex = e
+ if (expected != null) {
+ if (!expected(e)) {
+ console.log(e)
+ error("Unexpected exception $e", e)
+ }
+ } else
+ throw e
+ }.finally {
+ if (ex == null && expected != null) error("Exception was expected but none produced")
+ if (exCount < unhandled.size)
+ error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
+ errorCatching.close()
+ checkFinishCall()
+ }
+ lastTestPromise = result
+ return result
+ }
+}
+
+actual val isNative = false
+
+actual val isBoundByJsTestTimeout = true
+
+actual val isJavaAndWindows: Boolean get() = false
diff --git a/test-utils/jvm/src/Exceptions.kt b/test-utils/jvm/src/Exceptions.kt
new file mode 100644
index 0000000..a06958b
--- /dev/null
+++ b/test-utils/jvm/src/Exceptions.kt
@@ -0,0 +1,58 @@
+package kotlinx.coroutines.testing.exceptions
+
+import kotlinx.coroutines.*
+import java.io.*
+import java.util.*
+import kotlin.contracts.*
+import kotlin.coroutines.*
+import kotlin.test.*
+
+inline fun <reified T : Throwable> checkException(exception: Throwable) {
+ assertIs<T>(exception)
+ assertTrue(exception.suppressed.isEmpty())
+ assertNull(exception.cause)
+}
+
+fun checkCycles(t: Throwable) {
+ val sw = StringWriter()
+ t.printStackTrace(PrintWriter(sw))
+ assertFalse(sw.toString().contains("CIRCULAR REFERENCE"))
+}
+
+class CapturingHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler),
+ CoroutineExceptionHandler
+{
+ private var unhandled: ArrayList<Throwable>? = ArrayList()
+
+ override fun handleException(context: CoroutineContext, exception: Throwable) = synchronized<Unit>(this) {
+ unhandled!!.add(exception)
+ }
+
+ fun getException(): Throwable = synchronized(this) {
+ val size = unhandled!!.size
+ assert(size == 1) { "Expected one unhandled exception, but have $size: $unhandled" }
+ return unhandled!![0].also { unhandled = null }
+ }
+}
+
+fun captureExceptionsRun(
+ context: CoroutineContext = EmptyCoroutineContext,
+ block: suspend CoroutineScope.() -> Unit
+): Throwable {
+ val handler = CapturingHandler()
+ runBlocking(context + handler, block = block)
+ return handler.getException()
+}
+
+@OptIn(ExperimentalContracts::class)
+suspend inline fun <reified E: Throwable> assertCallsExceptionHandlerWith(
+ crossinline operation: suspend (CoroutineExceptionHandler) -> Unit): E {
+ contract {
+ callsInPlace(operation, InvocationKind.EXACTLY_ONCE)
+ }
+ val handler = CapturingHandler()
+ return withContext(handler) {
+ operation(handler)
+ assertIs<E>(handler.getException())
+ }
+}
diff --git a/kotlinx-coroutines-core/jvm/test/ExecutorRule.kt b/test-utils/jvm/src/ExecutorRule.kt
similarity index 90%
rename from kotlinx-coroutines-core/jvm/test/ExecutorRule.kt
rename to test-utils/jvm/src/ExecutorRule.kt
index e9cf6bc..ed0c87f 100644
--- a/kotlinx-coroutines-core/jvm/test/ExecutorRule.kt
+++ b/test-utils/jvm/src/ExecutorRule.kt
@@ -1,12 +1,10 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+package kotlinx.coroutines.testing
-package kotlinx.coroutines
-
+import kotlinx.coroutines.*
import org.junit.rules.*
import org.junit.runner.*
import org.junit.runners.model.*
+import java.lang.Runnable
import java.util.concurrent.*
import kotlin.coroutines.*
diff --git a/kotlinx-coroutines-core/jvm/test/FieldWalker.kt b/test-utils/jvm/src/FieldWalker.kt
similarity index 96%
rename from kotlinx-coroutines-core/jvm/test/FieldWalker.kt
rename to test-utils/jvm/src/FieldWalker.kt
index 7b2aaf6..a807ce6 100644
--- a/kotlinx-coroutines-core/jvm/test/FieldWalker.kt
+++ b/test-utils/jvm/src/FieldWalker.kt
@@ -1,8 +1,4 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines
+package kotlinx.coroutines.testing
import java.lang.ref.*
import java.lang.reflect.*
@@ -29,6 +25,7 @@
Any::class, String::class, Thread::class, Throwable::class, StackTraceElement::class,
WeakReference::class, ReferenceQueue::class, AbstractMap::class, Enum::class,
ReentrantLock::class, ReentrantReadWriteLock::class, SimpleDateFormat::class, ThreadPoolExecutor::class,
+ CountDownLatch::class,
)
.map { it.java }
.associateWith { emptyList() }
@@ -162,7 +159,7 @@
}
check(fields.isEmpty() || !type.name.startsWith("java.")) {
"""
- Trying to walk trough JDK's '$type' will get into illegal reflective access on JDK 9+.
+ Trying to walk through JDK's '$type' will get into illegal reflective access on JDK 9+.
Either modify your test to avoid usage of this class or update FieldWalker code to retrieve
the captured state of this class without going through reflection (see how collections are handled).
""".trimIndent()
diff --git a/test-utils/jvm/src/TestBase.kt b/test-utils/jvm/src/TestBase.kt
new file mode 100644
index 0000000..31ccd7e
--- /dev/null
+++ b/test-utils/jvm/src/TestBase.kt
@@ -0,0 +1,188 @@
+package kotlinx.coroutines.testing
+
+import kotlinx.coroutines.scheduling.*
+import java.io.*
+import java.util.*
+import kotlin.coroutines.*
+import kotlinx.coroutines.*
+import kotlin.test.*
+
+actual val VERBOSE = try {
+ System.getProperty("test.verbose")?.toBoolean() ?: false
+} catch (e: SecurityException) {
+ false
+}
+
+/**
+ * Is `true` when running in a nightly stress test mode.
+ */
+actual val isStressTest = System.getProperty("stressTest")?.toBoolean() ?: false
+
+actual val stressTestMultiplierSqrt = if (isStressTest) 5 else 1
+
+private const val SHUTDOWN_TIMEOUT = 1_000L // 1s at most to wait per thread
+
+/**
+ * Multiply various constants in stress tests by this factor, so that they run longer during nightly stress test.
+ */
+actual val stressTestMultiplier = stressTestMultiplierSqrt * stressTestMultiplierSqrt
+
+
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+actual typealias TestResult = Unit
+
+internal actual fun lastResortReportException(error: Throwable) {
+ System.err.println("${error.message}${error.cause?.let { ": $it" } ?: ""}")
+ error.cause?.printStackTrace(System.err)
+ System.err.println("--- Detected at ---")
+ Throwable().printStackTrace(System.err)
+}
+
+/**
+ * Base class for tests, so that tests for predictable scheduling of actions in multiple coroutines sharing a single
+ * thread can be written. Use it like this:
+ *
+ * ```
+ * class MyTest : TestBase() {
+ * @Test
+ * fun testSomething() = runBlocking { // run in the context of the main thread
+ * expect(1) // initiate action counter
+ * launch { // use the context of the main thread
+ * expect(3) // the body of this coroutine in going to be executed in the 3rd step
+ * }
+ * expect(2) // launch just scheduled coroutine for execution later, so this line is executed second
+ * yield() // yield main thread to the launched job
+ * finish(4) // fourth step is the last one. `finish` must be invoked or test fails
+ * }
+ * }
+ * ```
+ */
+actual open class TestBase(
+ private var disableOutCheck: Boolean,
+ private val errorCatching: ErrorCatching.Impl = ErrorCatching.Impl()
+): OrderedExecutionTestBase(), ErrorCatching by errorCatching {
+
+ actual constructor(): this(false)
+
+ // Shutdown sequence
+ private lateinit var threadsBefore: Set<Thread>
+ private val uncaughtExceptions = Collections.synchronizedList(ArrayList<Throwable>())
+ private var originalUncaughtExceptionHandler: Thread.UncaughtExceptionHandler? = null
+ /*
+ * System.out that we redefine in order to catch any debugging/diagnostics
+ * 'println' from main source set.
+ * NB: We do rely on the name 'previousOut' in the FieldWalker in order to skip its
+ * processing
+ */
+ private lateinit var previousOut: PrintStream
+
+ private object TestOutputStream : PrintStream(object : OutputStream() {
+ override fun write(b: Int) {
+ error("Detected unexpected call to 'println' from source code")
+ }
+ })
+
+ actual fun println(message: Any?) {
+ if (disableOutCheck) kotlin.io.println(message)
+ else previousOut.println(message)
+ }
+
+ @BeforeTest
+ fun before() {
+ initPoolsBeforeTest()
+ threadsBefore = currentThreads()
+ originalUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
+ Thread.setDefaultUncaughtExceptionHandler { t, e ->
+ println("Exception in thread $t: $e") // The same message as in default handler
+ e.printStackTrace()
+ uncaughtExceptions.add(e)
+ }
+ if (!disableOutCheck) {
+ previousOut = System.out
+ System.setOut(TestOutputStream)
+ }
+ }
+
+ @AfterTest
+ fun onCompletion() {
+ // onCompletion should not throw exceptions before it finishes all cleanup, so that other tests always
+ // start in a clear, restored state
+ checkFinishCall()
+ if (!disableOutCheck) { // Restore global System.out first
+ System.setOut(previousOut)
+ }
+ // Shutdown all thread pools
+ shutdownPoolsAfterTest()
+ // Check that are now leftover threads
+ runCatching {
+ checkTestThreads(threadsBefore)
+ }.onFailure {
+ reportError(it)
+ }
+ // Restore original uncaught exception handler after the main shutdown sequence
+ Thread.setDefaultUncaughtExceptionHandler(originalUncaughtExceptionHandler)
+ if (uncaughtExceptions.isNotEmpty()) {
+ error("Expected no uncaught exceptions, but got $uncaughtExceptions")
+ }
+ // The very last action -- throw error if any was detected
+ errorCatching.close()
+ }
+
+ actual fun runTest(
+ expected: ((Throwable) -> Boolean)?,
+ unhandled: List<(Throwable) -> Boolean>,
+ block: suspend CoroutineScope.() -> Unit
+ ): TestResult {
+ var exCount = 0
+ var ex: Throwable? = null
+ try {
+ runBlocking(block = block, context = CoroutineExceptionHandler { _, e ->
+ if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
+ exCount++
+ when {
+ exCount > unhandled.size ->
+ error("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
+ !unhandled[exCount - 1](e) ->
+ error("Unhandled exception was unexpected: $e", e)
+ }
+ })
+ } catch (e: Throwable) {
+ ex = e
+ if (expected != null) {
+ if (!expected(e))
+ error("Unexpected exception: $e", e)
+ } else {
+ throw e
+ }
+ } finally {
+ if (ex == null && expected != null) error("Exception was expected but none produced")
+ }
+ if (exCount < unhandled.size)
+ error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
+ }
+
+ protected suspend fun currentDispatcher() = coroutineContext[ContinuationInterceptor]!!
+}
+
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+fun initPoolsBeforeTest() {
+ DefaultScheduler.usePrivateScheduler()
+}
+
+@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+fun shutdownPoolsAfterTest() {
+ DefaultScheduler.shutdown(SHUTDOWN_TIMEOUT)
+ DefaultExecutor.shutdownForTests(SHUTDOWN_TIMEOUT)
+ DefaultScheduler.restore()
+}
+
+actual val isNative = false
+
+actual val isBoundByJsTestTimeout = false
+
+/*
+ * We ignore tests that test **real** non-virtualized tests with time on Windows, because
+ * our CI Windows is virtualized itself (oh, the irony) and its clock resolution is dozens of ms,
+ * which makes such tests flaky.
+ */
+actual val isJavaAndWindows: Boolean = System.getProperty("os.name")!!.contains("Windows")
diff --git a/kotlinx-coroutines-core/jvm/test/Threads.kt b/test-utils/jvm/src/Threads.kt
similarity index 86%
rename from kotlinx-coroutines-core/jvm/test/Threads.kt
rename to test-utils/jvm/src/Threads.kt
index 1d52dc6..956b334 100644
--- a/kotlinx-coroutines-core/jvm/test/Threads.kt
+++ b/test-utils/jvm/src/Threads.kt
@@ -1,8 +1,7 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
+package kotlinx.coroutines.testing
-package kotlinx.coroutines
+import kotlinx.coroutines.*
+import java.lang.Runnable
private const val WAIT_LOST_THREADS = 10_000L // 10s
private val ignoreLostThreads = mutableSetOf<String>()
@@ -37,6 +36,15 @@
println("===")
}
+class PoolThread(
+ @JvmField val dispatcher: ExecutorCoroutineDispatcher, // for debugging & tests
+ target: Runnable, name: String
+) : Thread(target, name) {
+ init {
+ isDaemon = true
+ }
+}
+
fun ExecutorCoroutineDispatcher.dumpThreads(header: String) =
currentThreads().filter { it is PoolThread && it.dispatcher == this@dumpThreads }.dumpThreads(header)
diff --git a/test-utils/native/src/TestBase.kt b/test-utils/native/src/TestBase.kt
new file mode 100644
index 0000000..d0e0c1a
--- /dev/null
+++ b/test-utils/native/src/TestBase.kt
@@ -0,0 +1,63 @@
+package kotlinx.coroutines.testing
+
+import kotlin.test.*
+import kotlinx.coroutines.*
+
+actual val VERBOSE = false
+
+actual typealias NoNative = Ignore
+
+public actual val isStressTest: Boolean = false
+public actual val stressTestMultiplier: Int = 1
+public actual val stressTestMultiplierSqrt: Int = 1
+
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+public actual typealias TestResult = Unit
+
+internal actual fun lastResortReportException(error: Throwable) {
+ println(error)
+}
+
+public actual open class TestBase actual constructor(): OrderedExecutionTestBase(), ErrorCatching by ErrorCatching.Impl() {
+ actual fun println(message: Any?) {
+ kotlin.io.println(message)
+ }
+
+ public actual fun runTest(
+ expected: ((Throwable) -> Boolean)?,
+ unhandled: List<(Throwable) -> Boolean>,
+ block: suspend CoroutineScope.() -> Unit
+ ): TestResult {
+ var exCount = 0
+ var ex: Throwable? = null
+ try {
+ runBlocking(block = block, context = CoroutineExceptionHandler { _, e ->
+ if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
+ exCount++
+ when {
+ exCount > unhandled.size ->
+ error("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
+ !unhandled[exCount - 1](e) ->
+ error("Unhandled exception was unexpected: $e", e)
+ }
+ })
+ } catch (e: Throwable) {
+ ex = e
+ if (expected != null) {
+ if (!expected(e))
+ error("Unexpected exception: $e", e)
+ } else
+ throw e
+ } finally {
+ if (ex == null && expected != null) error("Exception was expected but none produced")
+ }
+ if (exCount < unhandled.size)
+ error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
+ }
+}
+
+public actual val isNative = true
+
+public actual val isBoundByJsTestTimeout = false
+
+public actual val isJavaAndWindows: Boolean get() = false
diff --git a/test-utils/wasmJs/src/TestBase.kt b/test-utils/wasmJs/src/TestBase.kt
new file mode 100644
index 0000000..0edd291
--- /dev/null
+++ b/test-utils/wasmJs/src/TestBase.kt
@@ -0,0 +1,98 @@
+package kotlinx.coroutines.testing
+
+import kotlin.test.*
+import kotlin.js.*
+import kotlinx.coroutines.*
+
+actual val VERBOSE = false
+
+actual typealias NoJs = Ignore
+
+actual val isStressTest: Boolean = false
+actual val stressTestMultiplier: Int = 1
+actual val stressTestMultiplierSqrt: Int = 1
+
+@Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE")
+actual typealias TestResult = Promise<JsAny?>
+
+internal actual fun lastResortReportException(error: Throwable) {
+ println(error)
+}
+
+actual open class TestBase(
+ private val errorCatching: ErrorCatching.Impl
+): OrderedExecutionTestBase(), ErrorCatching by errorCatching {
+ private var lastTestPromise: Promise<JsAny?>? = null
+
+ actual constructor(): this(errorCatching = ErrorCatching.Impl())
+
+ actual fun println(message: Any?) {
+ kotlin.io.println(message)
+ }
+
+ actual fun runTest(
+ expected: ((Throwable) -> Boolean)?,
+ unhandled: List<(Throwable) -> Boolean>,
+ block: suspend CoroutineScope.() -> Unit
+ ): TestResult {
+ var exCount = 0
+ var ex: Throwable? = null
+ /*
+ * This is an additional sanity check against `runTest` mis-usage on JS.
+ * The only way to write an async test on JS is to return Promise from the test function.
+ * _Just_ launching promise and returning `Unit` won't suffice as the underlying test framework
+ * won't be able to detect an asynchronous failure in a timely manner.
+ * We cannot detect such situations, but we can detect the most common erroneous pattern
+ * in our code base, an attempt to use multiple `runTest` in the same `@Test` method,
+ * which typically is a premise to the same error:
+ * ```
+ * @Test
+ * fun incorrectTestForJs() { // <- promise is not returned
+ * for (parameter in parameters) {
+ * runTest {
+ * runTestForParameter(parameter)
+ * }
+ * }
+ * }
+ * ```
+ */
+ if (lastTestPromise != null) {
+ error("Attempt to run multiple asynchronous test within one @Test method")
+ }
+ val result = GlobalScope.promise(block = block, context = CoroutineExceptionHandler { _, e ->
+ if (e is CancellationException) return@CoroutineExceptionHandler // are ignored
+ exCount++
+ when {
+ exCount > unhandled.size ->
+ error("Too many unhandled exceptions $exCount, expected ${unhandled.size}, got: $e", e)
+ !unhandled[exCount - 1](e) ->
+ error("Unhandled exception was unexpected: $e", e)
+ }
+ }).catch { jsE ->
+ val e = jsE.toThrowableOrNull() ?: error("Unexpected non-Kotlin exception $jsE")
+ ex = e
+ if (expected != null) {
+ if (!expected(e)) {
+ println(e)
+ error("Unexpected exception $e", e)
+ }
+ } else
+ throw e
+ null
+ }.finally {
+ if (ex == null && expected != null) error("Exception was expected but none produced")
+ if (exCount < unhandled.size)
+ error("Too few unhandled exceptions $exCount, expected ${unhandled.size}")
+ errorCatching.close()
+ checkFinishCall()
+ }
+ lastTestPromise = result
+ return result
+ }
+}
+
+actual val isNative = false
+
+actual val isBoundByJsTestTimeout = true
+
+actual val isJavaAndWindows: Boolean get() = false
diff --git a/ui/coroutines-guide-ui.md b/ui/coroutines-guide-ui.md
index 3d11254..3b2087d 100644
--- a/ui/coroutines-guide-ui.md
+++ b/ui/coroutines-guide-ui.md
@@ -110,7 +110,7 @@
`app/build.gradle` file:
```groovy
-implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2"
+implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"
```
You can clone [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) project from GitHub onto your
diff --git a/ui/knit.code.include b/ui/knit.code.include
index adf1957..c5a3e57 100644
--- a/ui/knit.code.include
+++ b/ui/knit.code.include
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from ${file.name} by Knit tool. Do not edit.
package ${knit.package}.${knit.name}
diff --git a/ui/knit.properties b/ui/knit.properties
index 76a1d77..5bb873a 100644
--- a/ui/knit.properties
+++ b/ui/knit.properties
@@ -1,7 +1,3 @@
-#
-# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
knit.dir=kotlinx-coroutines-javafx/test/guide/
knit.package=kotlinx.coroutines.javafx.guide
knit.include=knit.code.include
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts b/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts
index 625ce72..2f01e03 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
project.configureAar()
dependencies {
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt b/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt
index 1c5c6ab..d1f9200 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
import kotlinx.coroutines.*
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/CustomizedRobolectricTest.kt b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/CustomizedRobolectricTest.kt
index 676ee43..69dd0ed 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/CustomizedRobolectricTest.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/CustomizedRobolectricTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package ordered.tests
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
import org.junit.Test
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstMockedMainTest.kt b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstMockedMainTest.kt
index c134ec5..30f1796 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstMockedMainTest.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstMockedMainTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package ordered.tests
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
import org.junit.*
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstRobolectricTest.kt b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstRobolectricTest.kt
index 99744f8..8777ed9 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstRobolectricTest.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/FirstRobolectricTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package ordered.tests
import kotlinx.coroutines.*
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/MockedMainTest.kt b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/MockedMainTest.kt
index d68d9eb..221186e 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/MockedMainTest.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/MockedMainTest.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package ordered.tests
class MockedMainTest : FirstMockedMainTest()
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/RobolectricTest.kt b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/RobolectricTest.kt
index 4213cb4..eff0c33 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/RobolectricTest.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/RobolectricTest.kt
@@ -1,6 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
package ordered.tests
open class RobolectricTest : FirstRobolectricTest()
diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/TestComponent.kt b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/TestComponent.kt
index c677d99..fbd6d81 100644
--- a/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/TestComponent.kt
+++ b/ui/kotlinx-coroutines-android/android-unit-tests/test/ordered/tests/TestComponent.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package ordered.tests
import kotlinx.coroutines.*
diff --git a/ui/kotlinx-coroutines-android/build.gradle.kts b/ui/kotlinx-coroutines-android/build.gradle.kts
index 70bc615..adbafe4 100644
--- a/ui/kotlinx-coroutines-android/build.gradle.kts
+++ b/ui/kotlinx-coroutines-android/build.gradle.kts
@@ -1,9 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-import kotlinx.kover.api.*
-
configurations {
create("r8")
}
@@ -28,24 +22,24 @@
testImplementation("org.smali:baksmali:${version("baksmali")}")
- "r8"("com.android.tools.build:builder:7.1.0-alpha01")
+ "r8"("com.android.tools.build:builder:8.1.0")
}
-val optimizedDexDir = File(buildDir, "dex-optim/")
-val unOptimizedDexDir = File(buildDir, "dex-unoptim/")
+val optimizedDexDir = layout.buildDirectory.dir("dex-optim/")
+val unOptimizedDexDir = layout.buildDirectory.dir("dex-unoptim/")
-val optimizedDexFile = File(optimizedDexDir, "classes.dex")
-val unOptimizedDexFile = File(unOptimizedDexDir, "classes.dex")
+val optimizedDexFile = optimizedDexDir.map { it.dir("classes.dex") } .get().asFile
+val unOptimizedDexFile = unOptimizedDexDir.map { it.dir("classes.dex") }.get().asFile
val runR8 by tasks.registering(RunR8::class) {
- outputDex = optimizedDexDir
+ outputDex = optimizedDexDir.get().asFile
inputConfig = file("testdata/r8-test-rules.pro")
dependsOn("jar")
}
val runR8NoOptim by tasks.registering(RunR8::class) {
- outputDex = unOptimizedDexDir
+ outputDex = unOptimizedDexDir.get().asFile
inputConfig = file("testdata/r8-test-rules-no-optim.pro")
dependsOn("jar")
@@ -85,11 +79,11 @@
val inputConfigCommon: File = File("testdata/r8-test-common.pro")
@InputFiles
- val jarFile: File = project.tasks.named<Zip>("jar").get().archivePath
+ val jarFile: File = project.tasks.named<Zip>("jar").get().archiveFile.get().asFile
init {
classpath = project.configurations["r8"]
- main = "com.android.tools.r8.R8"
+ mainClass = "com.android.tools.r8.R8"
}
override fun exec() {
diff --git a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt
index 0bc603e..d622f35 100644
--- a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt
+++ b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
import android.os.*
diff --git a/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt b/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt
index 7012c23..5ce3315 100644
--- a/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt
+++ b/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
@file:Suppress("unused")
package kotlinx.coroutines.android
@@ -127,11 +123,8 @@
name: String? = null
) : this(handler, name, false)
- @Volatile
- private var _immediate: HandlerContext? = if (invokeImmediately) this else null
-
- override val immediate: HandlerContext = _immediate ?:
- HandlerContext(handler, name, true).also { _immediate = it }
+ override val immediate: HandlerContext = if (invokeImmediately) this else
+ HandlerContext(handler, name, true)
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
return !invokeImmediately || Looper.myLooper() != handler.looper
@@ -172,8 +165,10 @@
if (invokeImmediately) "$str.immediate" else str
}
- override fun equals(other: Any?): Boolean = other is HandlerContext && other.handler === handler
- override fun hashCode(): Int = System.identityHashCode(handler)
+ override fun equals(other: Any?): Boolean =
+ other is HandlerContext && other.handler === handler && other.invokeImmediately == invokeImmediately
+ // inlining `Boolean.hashCode()` for Android compatibility, as requested by Animal Sniffer
+ override fun hashCode(): Int = System.identityHashCode(handler) xor if (invokeImmediately) 1231 else 1237
}
@Volatile
diff --git a/ui/kotlinx-coroutines-android/test/AndroidExceptionPreHandlerTest.kt b/ui/kotlinx-coroutines-android/test/AndroidExceptionPreHandlerTest.kt
index 1220797..d35d4ff 100644
--- a/ui/kotlinx-coroutines-android/test/AndroidExceptionPreHandlerTest.kt
+++ b/ui/kotlinx-coroutines-android/test/AndroidExceptionPreHandlerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.runner.*
diff --git a/ui/kotlinx-coroutines-android/test/DisabledHandlerTest.kt b/ui/kotlinx-coroutines-android/test/DisabledHandlerTest.kt
index a5b5ec9..e5a877e 100644
--- a/ui/kotlinx-coroutines-android/test/DisabledHandlerTest.kt
+++ b/ui/kotlinx-coroutines-android/test/DisabledHandlerTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
+import kotlinx.coroutines.testing.*
import android.os.*
import kotlinx.coroutines.*
import org.junit.*
diff --git a/ui/kotlinx-coroutines-android/test/HandlerDispatcherAsyncTest.kt b/ui/kotlinx-coroutines-android/test/HandlerDispatcherAsyncTest.kt
index c2091f3..ee5bc24 100644
--- a/ui/kotlinx-coroutines-android/test/HandlerDispatcherAsyncTest.kt
+++ b/ui/kotlinx-coroutines-android/test/HandlerDispatcherAsyncTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
+import kotlinx.coroutines.testing.*
import android.os.*
import kotlinx.coroutines.*
import org.junit.Test
diff --git a/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt b/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt
index afe6cff..89f027a 100644
--- a/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt
+++ b/ui/kotlinx-coroutines-android/test/HandlerDispatcherTest.kt
@@ -1,11 +1,9 @@
-/*
- * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
+import kotlinx.coroutines.testing.*
import android.os.*
import kotlinx.coroutines.*
+import kotlinx.coroutines.testing.*
import org.junit.Test
import org.junit.runner.*
import org.robolectric.*
@@ -15,29 +13,9 @@
import kotlin.test.*
@RunWith(RobolectricTestRunner::class)
-@Config(manifest = Config.NONE, sdk = [28])
@LooperMode(LooperMode.Mode.LEGACY)
-class HandlerDispatcherTest : TestBase() {
- @Test
- fun testImmediateDispatcherYield() = runBlocking(Dispatchers.Main) {
- expect(1)
- // launch in the immediate dispatcher
- launch(Dispatchers.Main.immediate) {
- expect(2)
- yield()
- expect(4)
- }
- expect(3) // after yield
- yield() // yield back
- finish(5)
- }
-
- @Test
- fun testMainDispatcherToString() {
- assertEquals("Dispatchers.Main", Dispatchers.Main.toString())
- assertEquals("Dispatchers.Main.immediate", Dispatchers.Main.immediate.toString())
- }
-
+@Config(manifest = Config.NONE, sdk = [28])
+class HandlerDispatcherTest : MainDispatcherTestBase.WithRealTimeDelay() {
@Test
fun testDefaultDelayIsNotDelegatedToMain() = runTest {
val mainLooper = Shadows.shadowOf(Looper.getMainLooper())
@@ -132,4 +110,20 @@
mainLooper.scheduler.advanceBy(51, TimeUnit.MILLISECONDS)
finish(5)
}
+
+ override fun isMainThread(): Boolean = Looper.getMainLooper().thread === Thread.currentThread()
+
+ override fun scheduleOnMainQueue(block: () -> Unit) {
+ Handler(Looper.getMainLooper()).post(block)
+ }
+
+ // by default, Robolectric only schedules tasks on the main thread but doesn't run them.
+ // This function nudges it to run them, 10 milliseconds of virtual time at a time.
+ override suspend fun spinTest(testBody: Job) {
+ val mainLooper = Shadows.shadowOf(Looper.getMainLooper())
+ while (testBody.isActive) {
+ Thread.sleep(10, 0)
+ mainLooper.idleFor(10, TimeUnit.MILLISECONDS)
+ }
+ }
}
diff --git a/ui/kotlinx-coroutines-android/test/R8ServiceLoaderOptimizationTest.kt b/ui/kotlinx-coroutines-android/test/R8ServiceLoaderOptimizationTest.kt
index 47beb85..c7e24fa 100644
--- a/ui/kotlinx-coroutines-android/test/R8ServiceLoaderOptimizationTest.kt
+++ b/ui/kotlinx-coroutines-android/test/R8ServiceLoaderOptimizationTest.kt
@@ -1,9 +1,6 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.android
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.jf.dexlib2.*
import org.junit.Test
diff --git a/ui/kotlinx-coroutines-javafx/build.gradle.kts b/ui/kotlinx-coroutines-javafx/build.gradle.kts
index 634423a..be99d66 100644
--- a/ui/kotlinx-coroutines-javafx/build.gradle.kts
+++ b/ui/kotlinx-coroutines-javafx/build.gradle.kts
@@ -1,16 +1,5 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-buildscript {
- dependencies {
- // this line can be removed when https://github.com/openjfx/javafx-gradle-plugin/pull/135 is released
- classpath("org.javamodularity:moduleplugin:1.8.12")
- }
-}
-
plugins {
- id("org.openjfx.javafxplugin") version "0.0.13"
+ id("org.openjfx.javafxplugin") version "0.0.14"
}
configurations {
@@ -33,16 +22,8 @@
tasks {
test {
extensions.configure(org.javamodularity.moduleplugin.extensions.TestModuleOptions::class) {
- addReads["kotlinx.coroutines.core"] = "junit"
- addReads["kotlinx.coroutines.javafx"] = "kotlin.test"
+ addReads["kotlinx.coroutines.javafx"] = "kotlin.test,test.utils.jvm"
+ addReads["test.utils.jvm"] = "junit,kotlin.test"
}
- jvmArgs = listOf(
- "--patch-module",
- "kotlinx.coroutines.core=${
- project(":kotlinx-coroutines-core").tasks.named<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>(
- "compileTestKotlinJvm"
- ).get().destinationDirectory.get()
- }"
- )
}
}
diff --git a/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt b/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt
index ebeaa3b..8e9bfff 100644
--- a/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt
+++ b/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.javafx
import javafx.beans.value.*
diff --git a/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt b/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
index 61583aa..941f458 100644
--- a/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
+++ b/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.javafx
import javafx.animation.*
diff --git a/ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt b/ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt
index 24c5c13..57289cb 100644
--- a/ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt
+++ b/ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt
@@ -1,67 +1,36 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.javafx
+import kotlinx.coroutines.testing.*
import javafx.application.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
import kotlin.test.*
-class JavaFxDispatcherTest : TestBase() {
+class JavaFxDispatcherTest : MainDispatcherTestBase.WithRealTimeDelay() {
@Before
fun setup() {
ignoreLostThreads("JavaFX Application Thread", "Thread-", "QuantumRenderer-", "InvokeLaterDispatcher")
}
- @Test
- fun testDelay() {
+ override fun shouldSkipTesting(): Boolean {
if (!initPlatform()) {
println("Skipping JavaFxTest in headless environment")
- return // ignore test in headless environments
+ return true // ignore test in headless environments
}
-
- runBlocking {
- expect(1)
- val job = launch(Dispatchers.JavaFx) {
- check(Platform.isFxApplicationThread())
- expect(2)
- delay(100)
- check(Platform.isFxApplicationThread())
- expect(3)
- }
- job.join()
- finish(4)
- }
+ return false
}
+ override fun isMainThread() = Platform.isFxApplicationThread()
+
+ override fun scheduleOnMainQueue(block: () -> Unit) {
+ Platform.runLater { block() }
+ }
+
+ /** Tests that the Main dispatcher is in fact the JavaFx one. */
@Test
- fun testImmediateDispatcherYield() {
- if (!initPlatform()) {
- println("Skipping JavaFxTest in headless environment")
- return // ignore test in headless environments
- }
-
- runBlocking(Dispatchers.JavaFx) {
- expect(1)
- check(Platform.isFxApplicationThread())
- // launch in the immediate dispatcher
- launch(Dispatchers.JavaFx.immediate) {
- expect(2)
- yield()
- expect(4)
- }
- expect(3) // after yield
- yield() // yield back
- finish(5)
- }
+ fun testMainIsJavaFx() {
+ assertSame(Dispatchers.JavaFx, Dispatchers.Main)
}
- @Test
- fun testMainDispatcherToString() {
- assertEquals("Dispatchers.Main", Dispatchers.Main.toString())
- assertEquals("Dispatchers.Main.immediate", Dispatchers.Main.immediate.toString())
- }
-}
\ No newline at end of file
+}
diff --git a/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt b/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt
index bc40b0f..ec210d2 100644
--- a/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt
+++ b/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt
@@ -1,7 +1,8 @@
package kotlinx.coroutines.javafx
+import kotlinx.coroutines.testing.*
import javafx.beans.property.SimpleIntegerProperty
-import kotlinx.coroutines.TestBase
+import kotlinx.coroutines.testing.TestBase
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.junit.Before
diff --git a/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt b/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt
index 5338835..1634f59 100644
--- a/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt
+++ b/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt
@@ -1,5 +1,6 @@
package kotlinx.coroutines.javafx
+import kotlinx.coroutines.testing.*
import javafx.beans.property.SimpleIntegerProperty
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.first
diff --git a/ui/kotlinx-coroutines-javafx/test/examples/FxExampleApp.kt b/ui/kotlinx-coroutines-javafx/test/examples/FxExampleApp.kt
index f2b7fe0..6ef81d6 100644
--- a/ui/kotlinx-coroutines-javafx/test/examples/FxExampleApp.kt
+++ b/ui/kotlinx-coroutines-javafx/test/examples/FxExampleApp.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package examples
import javafx.application.*
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-01.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-01.kt
index d02a77a..2d10632 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-01.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiActor01
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-02.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-02.kt
index ec8a09f..ba78af3 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-02.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiActor02
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-03.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-03.kt
index aa152b7..9e7a16d 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-03.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-actor-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiActor03
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-01.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-01.kt
index 06e439e..12271c2 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-01.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiAdvanced01
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-02.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-02.kt
index a3f89fc..cdd29db 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-02.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-advanced-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiAdvanced02
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-01.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-01.kt
index f54be59..8390e7a 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-01.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiBasic01
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-02.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-02.kt
index 42751c4..9b8a376 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-02.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiBasic02
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-03.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-03.kt
index dd778ce..653fb3f 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-03.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-basic-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiBasic03
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-01.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-01.kt
index 0c89ea7..7937fbb 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-01.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-01.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiBlocking01
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-02.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-02.kt
index 6e8b984..a6b884e 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-02.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-02.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiBlocking02
diff --git a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-03.kt b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-03.kt
index 3ff5d7d..802c088 100644
--- a/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-03.kt
+++ b/ui/kotlinx-coroutines-javafx/test/guide/example-ui-blocking-03.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
// This file was automatically generated from coroutines-guide-ui.md by Knit tool. Do not edit.
package kotlinx.coroutines.javafx.guide.exampleUiBlocking03
diff --git a/ui/kotlinx-coroutines-swing/build.gradle.kts b/ui/kotlinx-coroutines-swing/build.gradle.kts
index 157ce40..b801b37 100644
--- a/ui/kotlinx-coroutines-swing/build.gradle.kts
+++ b/ui/kotlinx-coroutines-swing/build.gradle.kts
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
dependencies {
testImplementation(project(":kotlinx-coroutines-jdk8"))
}
diff --git a/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt b/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt
index 010f18c..aa378be 100644
--- a/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt
+++ b/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.swing
import kotlinx.coroutines.*
diff --git a/ui/kotlinx-coroutines-swing/test/SwingTest.kt b/ui/kotlinx-coroutines-swing/test/SwingTest.kt
index 7e53e57..59808e9 100644
--- a/ui/kotlinx-coroutines-swing/test/SwingTest.kt
+++ b/ui/kotlinx-coroutines-swing/test/SwingTest.kt
@@ -1,106 +1,27 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package kotlinx.coroutines.swing
+import kotlinx.coroutines.testing.*
import kotlinx.coroutines.*
import org.junit.*
import org.junit.Test
import javax.swing.*
-import kotlin.coroutines.*
import kotlin.test.*
-class SwingTest : TestBase() {
+class SwingTest : MainDispatcherTestBase.WithRealTimeDelay() {
@Before
fun setup() {
ignoreLostThreads("AWT-EventQueue-")
}
+ override fun isMainThread() = SwingUtilities.isEventDispatchThread()
+
+ override fun scheduleOnMainQueue(block: () -> Unit) {
+ SwingUtilities.invokeLater { block() }
+ }
+
+ /** Tests that the Main dispatcher is in fact the JavaFx one. */
@Test
- fun testDelay() = runBlocking {
- expect(1)
- SwingUtilities.invokeLater { expect(2) }
- val job = launch(Dispatchers.Swing) {
- check(SwingUtilities.isEventDispatchThread())
- expect(3)
- SwingUtilities.invokeLater { expect(4) }
- delay(100)
- check(SwingUtilities.isEventDispatchThread())
- expect(5)
- }
- job.join()
- finish(6)
+ fun testMainIsJavaFx() {
+ assertSame(Dispatchers.Swing, Dispatchers.Main)
}
-
- private class SwingComponent(coroutineContext: CoroutineContext = EmptyCoroutineContext) :
- CoroutineScope by MainScope() + coroutineContext
- {
- public var executed = false
- fun testLaunch(): Job = launch {
- check(SwingUtilities.isEventDispatchThread())
- executed = true
- }
- fun testFailure(): Job = launch {
- check(SwingUtilities.isEventDispatchThread())
- throw TestException()
- }
- fun testCancellation() : Job = launch(start = CoroutineStart.ATOMIC) {
- check(SwingUtilities.isEventDispatchThread())
- delay(Long.MAX_VALUE)
- }
- }
-
- @Test
- fun testLaunchInMainScope() = runTest {
- val component = SwingComponent()
- val job = component.testLaunch()
- job.join()
- assertTrue(component.executed)
- component.cancel()
- component.coroutineContext[Job]!!.join()
- }
-
- @Test
- fun testFailureInMainScope() = runTest {
- var exception: Throwable? = null
- val component = SwingComponent(CoroutineExceptionHandler { ctx, e -> exception = e})
- val job = component.testFailure()
- job.join()
- assertTrue(exception!! is TestException)
- component.cancel()
- join(component)
- }
-
- @Test
- fun testCancellationInMainScope() = runTest {
- val component = SwingComponent()
- component.cancel()
- component.testCancellation().join()
- join(component)
- }
-
- private suspend fun join(component: SwingComponent) {
- component.coroutineContext[Job]!!.join()
- }
-
- @Test
- fun testImmediateDispatcherYield() = runBlocking(Dispatchers.Swing) {
- expect(1)
- // launch in the immediate dispatcher
- launch(Dispatchers.Swing.immediate) {
- expect(2)
- yield()
- expect(4)
- }
- expect(3) // after yield
- yield() // yield back
- finish(5)
- }
-
- @Test
- fun testMainDispatcherToString() {
- assertEquals("Dispatchers.Main", Dispatchers.Main.toString())
- assertEquals("Dispatchers.Main.immediate", Dispatchers.Main.immediate.toString())
- }
-}
\ No newline at end of file
+}
diff --git a/ui/kotlinx-coroutines-swing/test/examples/SwingExampleApp.kt b/ui/kotlinx-coroutines-swing/test/examples/SwingExampleApp.kt
index 7c396bf..6fab58f 100644
--- a/ui/kotlinx-coroutines-swing/test/examples/SwingExampleApp.kt
+++ b/ui/kotlinx-coroutines-swing/test/examples/SwingExampleApp.kt
@@ -1,7 +1,3 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
package examples
import kotlinx.coroutines.*