diff --git a/gradle-plugins/buildSrc/src/main/kotlin/osUtils.kt b/gradle-plugins/buildSrc/src/main/kotlin/osUtils.kt new file mode 100644 index 0000000000..564e870792 --- /dev/null +++ b/gradle-plugins/buildSrc/src/main/kotlin/osUtils.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +enum class OS(val id: String) { + Linux("linux"), + Windows("windows"), + MacOS("macos") +} + +val hostOS: OS by lazy { + val osName = System.getProperty("os.name") + when { + osName == "Mac OS X" -> OS.MacOS + osName == "Linux" -> OS.Linux + osName.startsWith("Win") -> OS.Windows + else -> throw Error("Unknown OS $osName") + } +} \ No newline at end of file diff --git a/gradle-plugins/compose/build.gradle.kts b/gradle-plugins/compose/build.gradle.kts index 3c9085dc65..5e18e1fe6a 100644 --- a/gradle-plugins/compose/build.gradle.kts +++ b/gradle-plugins/compose/build.gradle.kts @@ -1,4 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import de.undercouch.gradle.tasks.download.Download plugins { kotlin("jvm") @@ -7,6 +8,7 @@ plugins { id("java-gradle-plugin") id("maven-publish") id("com.github.johnrengelman.shadow") version "7.0.0" + id("de.undercouch.download") version "5.3.0" } gradlePluginConfig { @@ -107,10 +109,46 @@ tasks.test { } } +/** + * Gradle 8.0 removed auto downloading of requested toolchains unless a toolchain repository is configured. + * For now, the only option to enable auto downloading out-of-the-box is to use Foojay Disco resolver, + * which uses api.foojay.io service. + * It is not desirable to depend on little known service for provisioning JDK distributions, even for tests. + * Thus, the only option is to download the necessary JDK distributions ourselves. + */ +val jdkVersionsForTests = listOf(11, 15, 18, 19) +val jdkForTestsRoot = project.rootProject.layout.buildDirectory.dir("jdks").get().asFile +val downloadJdksForTests = tasks.register("downloadJdksForTests") {} +for (jdkVersion in jdkVersionsForTests) { + val ext = if (hostOS == OS.Windows) ".zip" else ".tar.gz" + val archive = jdkForTestsRoot.resolve("$jdkVersion$ext") + val unpackDir = jdkForTestsRoot.resolve("$jdkVersion").apply { mkdirs() } + val downloadJdkTask = tasks.register("downloadJdk$jdkVersion", Download::class) { + src("https://corretto.aws/downloads/latest/amazon-corretto-$jdkVersion-x64-${hostOS.id}-jdk$ext") + dest(archive) + onlyIf { !dest.exists() } + } + val unpackJdkTask = tasks.register("unpackJdk$jdkVersion", Copy::class) { + dependsOn(downloadJdkTask) + val archive = archive + val archiveTree = when { + archive.name.endsWith(".tar.gz") -> tarTree(archive) + archive.name.endsWith(".zip") -> zipTree(archive) + else -> error("Unsupported archive format: ${archive.name}") + } + from(archiveTree) + into(unpackDir) + onlyIf { (unpackDir.listFiles()?.size ?: 0) == 0 } + } + downloadJdksForTests.dependsOn(unpackJdkTask) +} + for (gradleVersion in supportedGradleVersions) { tasks.registerVerificationTask("testGradle-${gradleVersion.version}") { classpath = tasks.test.get().classpath + dependsOn(downloadJdksForTests) + systemProperty("compose.tests.gradle.test.jdks.root", jdkForTestsRoot.absolutePath) if (gradleVersion >= GradleVersion.version("7.6")) { systemProperty("compose.tests.gradle.configuration.cache", "true") } diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt index e59076ba76..f1d5e4f794 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProject.kt @@ -38,15 +38,24 @@ data class TestEnvironment( } } +private val testJdks = TestProperties + .testJdksRoot?.let { listTestJdks(it) }.orEmpty() + class TestProject( private val name: String, private val testEnvironment: TestEnvironment ) { private val testProjectsRootDir = File("src/test/test-projects") - private val additionalArgs = listOf( + + private val additionalArgs = listOfNotNull( "--stacktrace", "--init-script", testProjectsRootDir.resolve("init.gradle").absolutePath, - "-P${ComposeProperties.VERBOSE}=${testEnvironment.composeVerbose}" + "-P${ComposeProperties.VERBOSE}=${testEnvironment.composeVerbose}", + if (GradleVersion.version(TestProperties.gradleVersionForTests).baseVersion < GradleVersion.version("8.0")) { + null + } else { + "-Porg.gradle.java.installations.paths=${testJdks.joinToString(",")}" + } ) init { @@ -68,7 +77,7 @@ class TestProject( internal fun gradle(vararg args: String): BuildResult { if (TestProperties.gradleConfigurationCache) { - if (GradleVersion.version(TestProperties.gradleVersionForTests) < GradleVersion.version("8.0-rc-1")) { + if (GradleVersion.version(TestProperties.gradleVersionForTests).baseVersion < GradleVersion.version("8.0")) { // Gradle 7.* does not use the configuration cache in the same build. // In other words, if cache misses, Gradle performs configuration, // but does not, use the serialized task graph. diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt index 8de829c9c5..eb5bd4b85b 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/TestProperties.kt @@ -29,6 +29,8 @@ object TestProperties { val summaryFile: File? get() = System.getProperty("compose.tests.summary.file")?.let { File(it) } + val testJdksRoot: File? + get() = System.getProperty("compose.tests.gradle.test.jdks.root")?.let { File(it) } private fun notNullSystemProperty(property: String): String = System.getProperty(property) ?: error("The '$property' system property is not set") diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/jdkUtls.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/jdkUtls.kt index 2b344fede5..e9d368d4b2 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/jdkUtls.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/jdkUtls.kt @@ -6,6 +6,7 @@ package org.jetbrains.compose.test.utils import java.io.File +import kotlin.io.path.isExecutable const val JDK_11_BYTECODE_VERSION = 55 @@ -22,10 +23,38 @@ fun readClassFileVersion(classFile: File): Int { return match.groupValues[1].toInt() } -fun runJavaTool(toolName: String, vararg args: String): ProcessRunResult { +internal fun javaToolExecutableName(name: String): String = + if (isWindows) "$name.exe" else name + +internal fun runJavaTool(toolName: String, vararg args: String): ProcessRunResult { val javaHome = File(System.getProperty("java.home")) - val toolExecutableName = if (isWindows) "$toolName.exe" else toolName - val executable = javaHome.resolve("bin/$toolExecutableName") + val executable = javaHome.resolve("bin/${javaToolExecutableName(toolName)}") check(executable.isFile) { "Could not find tool '$toolName' at specified path: $executable" } return runProcess(executable, args.toList()) +} + +/** + * Expects the following structure: + * [rootDir] + * -- JDK_VERSION_1 + * -- UNPACKED_JDK_1_DISTRIBUTION_ARCHIVE + * -- JDK_VERSION_2 + * -- UNPACKED_JDK_2_DISTRIBUTION_ARCHIVE + * + * where JDK_VERSION_* is an integer corresponding to the major version of JDK distribution + */ +internal fun listTestJdks(rootDir: File): List { + if (!rootDir.isDirectory) return emptyList() + + return rootDir.listFiles()!! + .filter { it.isDirectory } + .map { findJavaHome(it).absolutePath } +} + +private fun findJavaHome(dir: File): File { + val javaExecutableName = javaToolExecutableName("java") + val javaExecutable = dir.walk() + .firstOrNull { it.isFile && it.name == javaExecutableName && it.toPath().isExecutable() } + ?: error("Could not find executable '$javaExecutableName' in '$dir' directory") + return javaExecutable.parentFile.parentFile.absoluteFile } \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle b/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle index 910b7dd022..803a5dd02c 100644 --- a/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle +++ b/gradle-plugins/compose/src/test/test-projects/application/mpp/build.gradle @@ -16,9 +16,9 @@ kotlin { // like https://github.com/JetBrains/compose-jb/issues/2345 android() - jvm("desktop") + jvm() sourceSets { - desktopMain { + jvmMain { dependsOn(commonMain) dependencies { diff --git a/gradle-plugins/compose/src/test/test-projects/application/mpp/src/desktopMain/kotlin/main.kt b/gradle-plugins/compose/src/test/test-projects/application/mpp/src/jvmMain/kotlin/main.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/application/mpp/src/desktopMain/kotlin/main.kt rename to gradle-plugins/compose/src/test/test-projects/application/mpp/src/jvmMain/kotlin/main.kt diff --git a/gradle-plugins/gradle.properties b/gradle-plugins/gradle.properties index 14d07f54f2..a0fc5f6b45 100644 --- a/gradle-plugins/gradle.properties +++ b/gradle-plugins/gradle.properties @@ -10,7 +10,7 @@ compose.tests.compiler.compatible.kotlin.version=1.8.0 # The latest version of Kotlin compatible with compose.tests.compiler.version for JS target. Used only on CI. compose.tests.js.compiler.compatible.kotlin.version=1.8.0 # __SUPPORTED_GRADLE_VERSIONS__ -compose.tests.gradle.versions=7.0.2, 7.6 +compose.tests.gradle.versions=7.0.2, 8.0-rc-1 # A version of Gradle plugin, that will be published, # unless overridden by COMPOSE_GRADLE_PLUGIN_VERSION env var.