From 0e1c15735474cdb680643f0482e042d1b194b88d Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy <52952525+dkhalanskyjb@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:09:58 +0100 Subject: [PATCH] Avoid using Java9+ APIs in JUnit5 CoroutineTimeout (#4279) Fixes #4278 --- integration-testing/README.md | 1 + integration-testing/build.gradle | 2 +- integration-testing/gradle.properties | 1 + .../java8Test/build.gradle.kts | 25 +++++++++++++++++++ .../test/kotlin/JUnit5TimeoutCompilation.kt | 9 +++++++ integration-testing/settings.gradle | 1 + integration-testing/smokeTest/build.gradle | 2 +- .../junit5/CoroutinesTimeoutExtension.kt | 10 +++++--- 8 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 integration-testing/java8Test/build.gradle.kts create mode 100644 integration-testing/java8Test/src/test/kotlin/JUnit5TimeoutCompilation.kt diff --git a/integration-testing/README.md b/integration-testing/README.md index deed97b35a..040ca684d3 100644 --- a/integration-testing/README.md +++ b/integration-testing/README.md @@ -10,6 +10,7 @@ The tests are the following: * `debugDynamicAgentTest` checks that `kotlinx-coroutines-debug` agent can self-attach dynamically to JVM as a standalone dependency. * `debugDynamicAgentJpmsTest` checks that `kotlinx-coroutines-debug` agent can self-attach dynamically to JVM as a standalone dependency (with JPMS) * `smokeTest` builds the multiplatform test project that depends on coroutines. +* `java8Test` checks that some APIs built with Java 9+ can be used with Java 8. The `integration-testing` project is expected to be in a subdirectory of the main `kotlinx.coroutines` project. diff --git a/integration-testing/build.gradle b/integration-testing/build.gradle index 9aef3ead2c..32392f2b19 100644 --- a/integration-testing/build.gradle +++ b/integration-testing/build.gradle @@ -167,7 +167,7 @@ compileTestKotlin { } check { - dependsOn([jvmCoreTest, debugDynamicAgentTest, mavenTest, debugAgentTest, coreAgentTest, ":jpmsTest:check", 'smokeTest:build']) + dependsOn([jvmCoreTest, debugDynamicAgentTest, mavenTest, debugAgentTest, coreAgentTest, ":jpmsTest:check", 'smokeTest:build', "java8Test:check"]) } compileKotlin { kotlinOptions { diff --git a/integration-testing/gradle.properties b/integration-testing/gradle.properties index 60d2fb547e..d13d7168d7 100644 --- a/integration-testing/gradle.properties +++ b/integration-testing/gradle.properties @@ -1,6 +1,7 @@ kotlin_version=2.0.0 coroutines_version=1.9.0-SNAPSHOT asm_version=9.3 +junit5_version=5.7.0 kotlin.code.style=official kotlin.mpp.stability.nowarn=true diff --git a/integration-testing/java8Test/build.gradle.kts b/integration-testing/java8Test/build.gradle.kts new file mode 100644 index 0000000000..ada90adaab --- /dev/null +++ b/integration-testing/java8Test/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + kotlin("jvm") +} + +repositories { + mavenCentral() + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") + // Coroutines from the outer project are published by previous CI buils step + mavenLocal() +} + +tasks.test { + useJUnitPlatform() +} + +val coroutinesVersion = property("coroutines_version") +val junit5Version = property("junit5_version") + +kotlin { + jvmToolchain(8) + dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-debug:$coroutinesVersion") + testImplementation("org.junit.jupiter:junit-jupiter-engine:$junit5Version") + } +} diff --git a/integration-testing/java8Test/src/test/kotlin/JUnit5TimeoutCompilation.kt b/integration-testing/java8Test/src/test/kotlin/JUnit5TimeoutCompilation.kt new file mode 100644 index 0000000000..573a7a5c7d --- /dev/null +++ b/integration-testing/java8Test/src/test/kotlin/JUnit5TimeoutCompilation.kt @@ -0,0 +1,9 @@ +import kotlinx.coroutines.debug.junit5.CoroutinesTimeout +import org.junit.jupiter.api.* + +class JUnit5TimeoutCompilation { + @CoroutinesTimeout(1000) + @Test + fun testCoroutinesTimeoutNotFailing() { + } +} diff --git a/integration-testing/settings.gradle b/integration-testing/settings.gradle index 5ff68ef809..f1b946b191 100644 --- a/integration-testing/settings.gradle +++ b/integration-testing/settings.gradle @@ -8,6 +8,7 @@ pluginManagement { } include 'smokeTest' +include 'java8Test' include(":jpmsTest") rootProject.name = "kotlinx-coroutines-integration-testing" diff --git a/integration-testing/smokeTest/build.gradle b/integration-testing/smokeTest/build.gradle index 65d09dfa32..f7a46aca57 100644 --- a/integration-testing/smokeTest/build.gradle +++ b/integration-testing/smokeTest/build.gradle @@ -76,4 +76,4 @@ rootProject.extensions.findByType(org.jetbrains.kotlin.gradle.targets.js.nodejs. // 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/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt b/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt index 3179dc1ada..edb72815ad 100644 --- a/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt +++ b/kotlinx-coroutines-debug/src/junit/junit5/CoroutinesTimeoutExtension.kt @@ -206,8 +206,12 @@ internal class CoroutinesTimeoutExtension internal constructor( } private fun Class.coroutinesTimeoutAnnotation(): Optional = - AnnotationSupport.findAnnotation(this, CoroutinesTimeout::class.java).or { - enclosingClass?.coroutinesTimeoutAnnotation() ?: Optional.empty() + AnnotationSupport.findAnnotation(this, CoroutinesTimeout::class.java).let { + when { + it.isPresent -> it + enclosingClass != null -> enclosingClass.coroutinesTimeoutAnnotation() + else -> Optional.empty() + } } private fun interceptMethod( @@ -232,7 +236,7 @@ internal class CoroutinesTimeoutExtension internal constructor( } /* The extension was registered via an annotation; check that we succeeded in finding the annotation that led to the extension being registered and taking its parameters. */ - if (testAnnotationOptional.isEmpty && classAnnotationOptional.isEmpty) { + if (!testAnnotationOptional.isPresent && !classAnnotationOptional.isPresent) { throw UnsupportedOperationException("Timeout was registered with a CoroutinesTimeout annotation, but we were unable to find it. Please report this.") } return when {