From dc268e83874fd7871759efdda17a7cc276ab63c5 Mon Sep 17 00:00:00 2001 From: Clemens Grabmann <6975408+cgrabmann@users.noreply.github.com> Date: Fri, 13 May 2022 13:11:20 +0200 Subject: [PATCH] * move test framework configuration into an action run directly before the tests run, to avoid to early dependency resolution (#30) * move JavaPlugin configuration outside `afterEvaluate` to enable the user to manipulate those settings * fix KotlinConfigurePlugin configuring the JavaToolchain.languageVersion Property to use itself as a provider * add check to Kotlin tests, to ensure the JDK of the JavaToolchain is used during Kotlin compilation Signed-off-by: Clemens Grabmann --- .../autoconfigure/java/JavaConfigurePlugin.kt | 73 ++++++++++--------- .../kotlin/KotlinConfigurePlugin.kt | 6 -- .../build.gradle | 16 ++-- .../build.gradle | 16 ++-- .../single-kotlin-module-server/build.gradle | 16 ++-- .../kotlin/single-kotlin-module/build.gradle | 16 ++-- .../kotlin/KotlinConfigurePluginTest.kt | 13 ++++ 7 files changed, 72 insertions(+), 84 deletions(-) diff --git a/src/main/kotlin/io/cloudflight/gradle/autoconfigure/java/JavaConfigurePlugin.kt b/src/main/kotlin/io/cloudflight/gradle/autoconfigure/java/JavaConfigurePlugin.kt index fc0c7b1..edde456 100644 --- a/src/main/kotlin/io/cloudflight/gradle/autoconfigure/java/JavaConfigurePlugin.kt +++ b/src/main/kotlin/io/cloudflight/gradle/autoconfigure/java/JavaConfigurePlugin.kt @@ -18,6 +18,7 @@ import org.gradle.api.tasks.testing.Test import org.gradle.jvm.tasks.Jar import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.testing.jacoco.plugins.JacocoPlugin +import org.jetbrains.kotlin.gradle.plugin.statistics.ReportStatisticsToElasticSearch.user import org.slf4j.LoggerFactory private const val GRADLE_VERSION = "Gradle-Version" @@ -34,21 +35,26 @@ class JavaConfigurePlugin : Plugin { val extensions = project.extensions val tasks = project.tasks - extensions.create(EXTENSION_NAME, JavaConfigurePluginExtension::class).apply { + val javaConfigureExtension = extensions.create(EXTENSION_NAME, JavaConfigurePluginExtension::class).apply { languageVersion.convention(JAVA_LANGUAGE_VERSION) encoding.convention(JAVA_ENCODING) vendorName.convention(VENDOR_NAME) applicationBuild.convention(false) } - project.afterEvaluate { + val javaPluginExtension = extensions.getByType(JavaPluginExtension::class) + javaPluginExtension.modularity.inferModulePath.set(true) + javaPluginExtension.toolchain.languageVersion.set(javaConfigureExtension.languageVersion) - val javaConfigureExtension = extensions.getByType(JavaConfigurePluginExtension::class) + tasks.named(JavaPlugin.JAR_TASK_NAME, Jar::class).configure { + it.doFirst(PopulateManifestAction) + } - val javaPluginExtension = extensions.getByType(JavaPluginExtension::class) + tasks.named(JavaPlugin.TEST_TASK_NAME, Test::class).configure { + it.doFirst(ConfigureUnitTestFrameworkAction) + } - javaPluginExtension.modularity.inferModulePath.set(true) - javaPluginExtension.toolchain.languageVersion.set(javaConfigureExtension.languageVersion) + project.afterEvaluate { if (!javaConfigureExtension.applicationBuild.get()) { javaPluginExtension.withSourcesJar() @@ -63,35 +69,34 @@ class JavaConfigurePlugin : Plugin { compileTest.configure { it.options.encoding = javaConfigureExtension.encoding.get() } + } + } - val jar = tasks.named(JavaPlugin.JAR_TASK_NAME, Jar::class).get() - jar.doFirst(PopulateManifestAction) - - val testTask = tasks.named(JavaPlugin.TEST_TASK_NAME, Test::class) - testTask.configure { - val testRuntimeDependencies = - project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME) - val useJunit = - testRuntimeDependencies.allDependencies.contains { dep -> dep.group == JUNIT_4_ARTIFACT_GROUP } - val useJunitPlatform = - testRuntimeDependencies.allDependencies.contains { dep -> dep.group == JUNIT_PLATFORM_ARTIFACT_GROUP } - val useTestNG = - testRuntimeDependencies.allDependencies.contains { dep -> dep.group == TESTNG_ARTIFACT_GROUP } - - if (arrayOf(useJunit, useJunitPlatform, useTestNG).filter { enabled -> enabled }.size > 1) { - LOG.warn("Multiple testing frameworks detected in runtime dependencies. No framework enabled automatically. junit4: $useJunit, junit5: $useJunitPlatform, testNg: $useTestNG") - } else if (useJunit) { - it.useJUnit() - LOG.info("Enabled Junit4 as test platform") - } else if (useJunitPlatform) { - it.useJUnitPlatform() - LOG.info("Enabled Junit5 as test platform") - } else if (useTestNG) { - it.useTestNG() - LOG.info("Enabled TestNG as test platform") - } else { - LOG.warn("No testing framework detected in runtime dependencies. No framework enabled automatically") - } + private object ConfigureUnitTestFrameworkAction : Action { + override fun execute(t: Task) { + val test = t as Test + val testRuntimeDependencies = + t.project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME) + val useJunit = + testRuntimeDependencies.allDependencies.contains { dep -> dep.group == JUNIT_4_ARTIFACT_GROUP } + val useJunitPlatform = + testRuntimeDependencies.allDependencies.contains { dep -> dep.group == JUNIT_PLATFORM_ARTIFACT_GROUP } + val useTestNG = + testRuntimeDependencies.allDependencies.contains { dep -> dep.group == TESTNG_ARTIFACT_GROUP } + + if (arrayOf(useJunit, useJunitPlatform, useTestNG).filter { enabled -> enabled }.size > 1) { + LOG.warn("Multiple testing frameworks detected in runtime dependencies. No framework enabled automatically. junit4: $useJunit, junit5: $useJunitPlatform, testNg: $useTestNG") + } else if (useJunit) { + test.useJUnit() + LOG.info("Enabled Junit4 as test platform") + } else if (useJunitPlatform) { + test.useJUnitPlatform() + LOG.info("Enabled Junit5 as test platform") + } else if (useTestNG) { + test.useTestNG() + LOG.info("Enabled TestNG as test platform") + } else { + LOG.warn("No testing framework detected in runtime dependencies. No framework enabled automatically") } } } diff --git a/src/main/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePlugin.kt b/src/main/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePlugin.kt index 8574040..f1a9c82 100644 --- a/src/main/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePlugin.kt +++ b/src/main/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePlugin.kt @@ -54,12 +54,6 @@ class KotlinConfigurePlugin : Plugin { ) } - // https://kotlinlang.org/docs/gradle.html#gradle-java-toolchains-support - val javaPluginExtension = extensions.getByType(JavaPluginExtension::class) - kotlin.jvmToolchain { - (it as JavaToolchainSpec).languageVersion.set(javaPluginExtension.toolchain.languageVersion) - } - project.afterEvaluate { val kotlinVersion = kotlinConfigureExtension.kotlinVersion.get() val kotlinMajorMinor = kotlinVersion.toMajorMinor() diff --git a/src/test/fixtures/kotlin/single-kotlin-module-constraints/build.gradle b/src/test/fixtures/kotlin/single-kotlin-module-constraints/build.gradle index 6d377b2..76cf0e7 100644 --- a/src/test/fixtures/kotlin/single-kotlin-module-constraints/build.gradle +++ b/src/test/fixtures/kotlin/single-kotlin-module-constraints/build.gradle @@ -28,15 +28,9 @@ dependencies { } } -tasks.getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME).doLast { - def javaPluginExtension = project.extensions.getByType(JavaPluginExtension) - def inferModulePath = javaPluginExtension.hasProperty("modularity") ? javaPluginExtension.modularity.inferModulePath.get() : false - logger.quiet("javaPluginExtension.modularity.inferModulePath: {}", inferModulePath) - logger.quiet("javaPluginExtension.sourceCompatibility: {}", javaPluginExtension.sourceCompatibility) - logger.quiet("javaPluginExtension.targetCompatibility: {}", javaPluginExtension.targetCompatibility) - logger.quiet("compileJava.options.encoding: {}", options.encoding) -} - -tasks.getByName(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME).doLast { - logger.quiet("compileTestJava.options.encoding: {}", options.encoding) +tasks.compileKotlin.doLast { + def compiler = javaToolchains.compilerFor { + languageVersion.set(project.javaConfigure.languageVersion) + } + logger.quiet("javaToolchain.jdkHome: {}", compiler.get().metadata.installationPath.asFile.absolutePath) } \ No newline at end of file diff --git a/src/test/fixtures/kotlin/single-kotlin-module-override-kotlinversion/build.gradle b/src/test/fixtures/kotlin/single-kotlin-module-override-kotlinversion/build.gradle index 4dc8108..9afdac3 100644 --- a/src/test/fixtures/kotlin/single-kotlin-module-override-kotlinversion/build.gradle +++ b/src/test/fixtures/kotlin/single-kotlin-module-override-kotlinversion/build.gradle @@ -20,15 +20,9 @@ kotlinConfigure { kotlinVersion = "1.5.20" } -tasks.getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME).doLast { - def javaPluginExtension = project.extensions.getByType(JavaPluginExtension) - def inferModulePath = javaPluginExtension.hasProperty("modularity") ? javaPluginExtension.modularity.inferModulePath.get() : false - logger.quiet("javaPluginExtension.modularity.inferModulePath: {}", inferModulePath) - logger.quiet("javaPluginExtension.sourceCompatibility: {}", javaPluginExtension.sourceCompatibility) - logger.quiet("javaPluginExtension.targetCompatibility: {}", javaPluginExtension.targetCompatibility) - logger.quiet("compileJava.options.encoding: {}", options.encoding) -} - -tasks.getByName(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME).doLast { - logger.quiet("compileTestJava.options.encoding: {}", options.encoding) +tasks.compileKotlin.doLast { + def compiler = javaToolchains.compilerFor { + languageVersion.set(project.javaConfigure.languageVersion) + } + logger.quiet("javaToolchain.jdkHome: {}", compiler.get().metadata.installationPath.asFile.absolutePath) } \ No newline at end of file diff --git a/src/test/fixtures/kotlin/single-kotlin-module-server/build.gradle b/src/test/fixtures/kotlin/single-kotlin-module-server/build.gradle index b24eaeb..b9f6ca0 100644 --- a/src/test/fixtures/kotlin/single-kotlin-module-server/build.gradle +++ b/src/test/fixtures/kotlin/single-kotlin-module-server/build.gradle @@ -29,15 +29,9 @@ dependencies { } } -tasks.getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME).doLast { - def javaPluginExtension = project.extensions.getByType(JavaPluginExtension) - def inferModulePath = javaPluginExtension.hasProperty("modularity") ? javaPluginExtension.modularity.inferModulePath.get() : false - logger.quiet("javaPluginExtension.modularity.inferModulePath: {}", inferModulePath) - logger.quiet("javaPluginExtension.sourceCompatibility: {}", javaPluginExtension.sourceCompatibility) - logger.quiet("javaPluginExtension.targetCompatibility: {}", javaPluginExtension.targetCompatibility) - logger.quiet("compileJava.options.encoding: {}", options.encoding) -} - -tasks.getByName(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME).doLast { - logger.quiet("compileTestJava.options.encoding: {}", options.encoding) +tasks.compileKotlin.doLast { + def compiler = javaToolchains.compilerFor { + languageVersion.set(project.javaConfigure.languageVersion) + } + logger.quiet("javaToolchain.jdkHome: {}", compiler.get().metadata.installationPath.asFile.absolutePath) } \ No newline at end of file diff --git a/src/test/fixtures/kotlin/single-kotlin-module/build.gradle b/src/test/fixtures/kotlin/single-kotlin-module/build.gradle index 52814bc..7c28cfa 100644 --- a/src/test/fixtures/kotlin/single-kotlin-module/build.gradle +++ b/src/test/fixtures/kotlin/single-kotlin-module/build.gradle @@ -16,15 +16,9 @@ javaConfigure { vendorName = "Cloudflight XYZ" } -tasks.getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME).doLast { - def javaPluginExtension = project.extensions.getByType(JavaPluginExtension) - def inferModulePath = javaPluginExtension.hasProperty("modularity") ? javaPluginExtension.modularity.inferModulePath.get() : false - logger.quiet("javaPluginExtension.modularity.inferModulePath: {}", inferModulePath) - logger.quiet("javaPluginExtension.sourceCompatibility: {}", javaPluginExtension.sourceCompatibility) - logger.quiet("javaPluginExtension.targetCompatibility: {}", javaPluginExtension.targetCompatibility) - logger.quiet("compileJava.options.encoding: {}", options.encoding) -} - -tasks.getByName(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME).doLast { - logger.quiet("compileTestJava.options.encoding: {}", options.encoding) +tasks.compileKotlin.doLast { + def compiler = javaToolchains.compilerFor { + languageVersion.set(project.javaConfigure.languageVersion) + } + logger.quiet("javaToolchain.jdkHome: {}", compiler.get().metadata.installationPath.asFile.absolutePath) } \ No newline at end of file diff --git a/src/test/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePluginTest.kt b/src/test/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePluginTest.kt index 34743db..0fb703f 100644 --- a/src/test/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePluginTest.kt +++ b/src/test/kotlin/io/cloudflight/gradle/autoconfigure/kotlin/KotlinConfigurePluginTest.kt @@ -4,6 +4,8 @@ import io.cloudflight.gradle.autoconfigure.test.util.ProjectFixture import io.cloudflight.gradle.autoconfigure.test.util.normalizedOutput import io.cloudflight.gradle.autoconfigure.test.util.useFixture import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.ThrowingConsumer +import org.gradle.testkit.runner.BuildResult import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.Arguments.arguments @@ -56,6 +58,12 @@ class KotlinConfigurePluginTest { assertThat(result.normalizedOutput).contains("--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:${options.kotlinVersion}") + // validate that Kotlin uses the jdk configured by the java toolchain + val jdkHome = result.extractJavaToolchainJdkHome() + val kotlinJdkLines = result.normalizedOutput.lines().filter { it.startsWith("[KOTLIN]") } + val validateJdkHome = ThrowingConsumer { input -> assertThat(input).contains(jdkHome) } + assertThat(kotlinJdkLines).isNotEmpty.allSatisfy(validateJdkHome) + println(result.output) } @@ -119,6 +127,11 @@ class KotlinConfigurePluginTest { } } +private fun BuildResult.extractJavaToolchainJdkHome(): String { + val prefix = "javaToolchain.jdkHome: " + return this.normalizedOutput.lines().first { it.startsWith(prefix) }.removePrefix(prefix) +} + private val KOTLIN_FIXTURE_PATH = Paths.get("kotlin") private fun javaFixture(fixtureName: String, gradleVersion: String?, testWork: ProjectFixture.() -> T): T = useFixture(KOTLIN_FIXTURE_PATH, fixtureName, gradleVersion, testWork) \ No newline at end of file