From 6eec64fccb1d4e39248cbc695612e78536b57b2e Mon Sep 17 00:00:00 2001 From: cristiangarcia Date: Fri, 3 May 2024 14:47:43 +0000 Subject: [PATCH] Make compiler tests cacheable: compiler-tests-convention - add compiler-tests-convention - track ideaHome directory - migrate the first project, tests-common-new - extract paths ^KTI-1685 --- build.gradle.kts | 1 - .../forTestCompile/ForTestCompileRuntime.java | 50 ++++------- .../forTestCompile/TestCompilePaths.kt | 19 ++++ .../jetbrains/kotlin/script/scriptTestUtil.kt | 4 + compiler/tests-common-new/build.gradle.kts | 24 ++++- .../KotlinStandardLibrariesPathProvider.kt | 88 +++++++++++++++--- .../JsEnvironmentConfigurator.kt | 18 +++- .../ScriptingEnvironmentConfigurator.kt | 7 +- .../js/JsVersionRequirementTest.kt | 3 +- .../jetbrains/kotlin/js/config/JsConfig.java | 6 -- .../kotlin/js/testOld/EncodeSignatureTest.kt | 6 +- .../kotlin/code/CodeConformanceTest.kt | 1 + .../buildsrc-compat/src/main/kotlin/tasks.kt | 2 + .../compiler-tests-convention/Readme.md | 28 ++++++ .../build.gradle.kts | 33 +++++++ .../src/main/kotlin/CompilerTestsExtension.kt | 89 +++++++++++++++++++ .../src/main/kotlin/TestCompilePaths.kt | 19 ++++ .../TestCompilerRuntimeArgumentProvider.kt | 84 +++++++++++++++++ .../compiler-tests-convention.gradle.kts | 18 ++++ .../settings.gradle.kts | 1 + 20 files changed, 438 insertions(+), 63 deletions(-) create mode 100644 compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/TestCompilePaths.kt create mode 100644 repo/gradle-build-conventions/compiler-tests-convention/Readme.md create mode 100644 repo/gradle-build-conventions/compiler-tests-convention/build.gradle.kts create mode 100644 repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/CompilerTestsExtension.kt create mode 100644 repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilePaths.kt create mode 100644 repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilerRuntimeArgumentProvider.kt create mode 100644 repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/compiler-tests-convention.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts index b261e6071f310..ce22f1891d6ea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -759,7 +759,6 @@ tasks { } register("testsForBootstrapBuildTest") { - dependsOn("dist") dependsOn(":compiler:tests-common-new:test") } diff --git a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java index e45c20281c1d5..863a2945952b9 100644 --- a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java +++ b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java @@ -16,18 +16,21 @@ import java.util.ArrayList; import java.util.List; +import static java.lang.System.*; +import static org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.*; + public class ForTestCompileRuntime { private static volatile SoftReference reflectJarClassLoader = new SoftReference<>(null); private static volatile SoftReference runtimeJarClassLoader = new SoftReference<>(null); @NotNull public static File runtimeJarForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-stdlib.jar")); + return propertyOrDist(KOTLIN_FULL_STDLIB_PATH, "dist/kotlinc/lib/kotlin-stdlib.jar"); } @NotNull public static File runtimeJarForTestsWithJdk8() { - return assertExists(new File("dist/kotlinc/lib/kotlin-stdlib-jdk8.jar")); + return propertyOrDist(KOTLIN_FULL_STDLIB_PATH, "dist/kotlinc/lib/kotlin-stdlib-jdk8.jar"); } @NotNull @@ -37,27 +40,17 @@ public static File minimalRuntimeJarForTests() { @NotNull public static File kotlinTestJarForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-test.jar")); - } - - @NotNull - public static File kotlinTestJUnitJarForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-test-junit.jar")); - } - - @NotNull - public static File kotlinTestJsJarForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-test-js.jar")); + return propertyOrDist(KOTLIN_TEST_JAR_PATH, "dist/kotlinc/lib/kotlin-test.jar"); } @NotNull public static File reflectJarForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-reflect.jar")); + return propertyOrDist(KOTLIN_REFLECT_JAR_PATH, "dist/kotlinc/lib/kotlin-reflect.jar"); } @NotNull public static File scriptRuntimeJarForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-script-runtime.jar")); + return propertyOrDist(KOTLIN_SCRIPT_RUNTIME_PATH, "dist/kotlinc/lib/kotlin-script-runtime.jar"); } @NotNull @@ -65,34 +58,21 @@ public static File runtimeSourcesJarForTests() { return assertExists(new File("dist/kotlinc/lib/kotlin-stdlib-sources.jar")); } - @NotNull - public static File stdlibMavenSourcesJarForTests() { - return assertExists(new File("dist/maven/kotlin-stdlib-sources.jar")); - } - @NotNull public static File stdlibCommonForTests() { - return assertExists(new File("dist/common/kotlin-stdlib-common.jar")); + return propertyOrDist(KOTLIN_COMMON_STDLIB_PATH, "dist/common/kotlin-stdlib-common.jar"); } - @NotNull - public static File stdlibCommonSourcesForTests() { - return assertExists(new File("dist/common/kotlin-stdlib-common-sources.jar")); - } - - @NotNull - public static File stdlibJsForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-stdlib-js.klib")); - } - - @NotNull - public static File jetbrainsAnnotationsForTests() { - return assertExists(new File("dist/kotlinc/lib/annotations-13.0.jar")); + private static File propertyOrDist(String property, String distPath) { + String path = getProperty(property, distPath); + File file = new File(path); + assert(file.exists()) : path + " doesn't exist"; + return file; } @NotNull public static File jvmAnnotationsForTests() { - return assertExists(new File("dist/kotlinc/lib/kotlin-annotations-jvm.jar")); + return propertyOrDist(KOTLIN_ANNOTATIONS_PATH, "dist/kotlinc/lib/kotlin-annotations-jvm.jar"); } @NotNull diff --git a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/TestCompilePaths.kt b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/TestCompilePaths.kt new file mode 100644 index 0000000000000..1ab76403f8861 --- /dev/null +++ b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/TestCompilePaths.kt @@ -0,0 +1,19 @@ +package org.jetbrains.kotlin.codegen.forTestCompile/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +// This file is duplicated at repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilePaths.kt +object TestCompilePaths { + const val KOTLIN_FULL_STDLIB_PATH: String = "kotlin.full.stdlib.path" + const val KOTLIN_MINIMAL_STDLIB_PATH: String = "kotlin.minimal.stdlib.path" + const val KOTLIN_TEST_JAR_PATH: String = "kotlin.test.jar.path" + const val KOTLIN_REFLECT_JAR_PATH: String = "kotlin.reflect.jar.path" + const val KOTLIN_SCRIPT_RUNTIME_PATH: String = "kotlin.script.runtime.path" + const val KOTLIN_COMMON_STDLIB_PATH: String = "kotlin.common.stdlib.path" + const val KOTLIN_ANNOTATIONS_PATH: String = "kotlin.annotations.path" + const val KOTLIN_JS_STDLIB_KLIB_PATH: String = "kotlin.js.stdlib.klib.path" + const val KOTLIN_JS_REDUCED_STDLIB_PATH: String = "kotlin.js.reduced.stdlib.path" + const val KOTLIN_JS_KOTLIN_TEST_KLIB_PATH: String = "kotlin.js.kotlin.test.klib.path" + const val KOTLIN_SCRIPTING_PLUGIN_CLASSPATH = "kotlin.scriptingPlugin.classpath" +} \ No newline at end of file diff --git a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/script/scriptTestUtil.kt b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/script/scriptTestUtil.kt index 2d4a7d3ac0412..6489bf4cbf219 100644 --- a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/script/scriptTestUtil.kt +++ b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/script/scriptTestUtil.kt @@ -22,3 +22,7 @@ fun loadScriptingPlugin(configuration: CompilerConfiguration) { } PluginCliParser.loadPluginsSafe(pluginClasspath, emptyList(), emptyList(), configuration) } + +fun loadScriptingPlugin(configuration: CompilerConfiguration, pluginClasspath: Collection) { + PluginCliParser.loadPluginsSafe(pluginClasspath, emptyList(), emptyList(), configuration) +} diff --git a/compiler/tests-common-new/build.gradle.kts b/compiler/tests-common-new/build.gradle.kts index 28ee66a487551..ce34f44cb9536 100644 --- a/compiler/tests-common-new/build.gradle.kts +++ b/compiler/tests-common-new/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("jvm") id("jps-compatible") + id("compiler-tests-convention") } dependencies { @@ -54,6 +55,16 @@ sourceSets { } } +compilerTests { + withStdlibCommon() + withScriptRuntime() + withTestJar() + withAnnotations() + withScriptingPlugin() + withStdlibJsRuntime() + withTestJsRuntime() +} + projectTest( jUnitMode = JUnitMode.JUnit5, defineJDKEnvVariables = listOf( @@ -61,9 +72,20 @@ projectTest( JdkMajorVersion.JDK_21_0, // e.g. org.jetbrains.kotlin.test.runners.codegen.FirLightTreeBlackBoxModernJdkCodegenTestGenerated.TestsWithJava21 ) ) { - dependsOn(":dist") workingDir = rootDir useJUnitPlatform() + + inputs.dir(layout.projectDirectory.dir("../testData")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file(File(rootDir, "compiler/cli/cli-common/resources/META-INF/extensions/compiler.xml")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file(File(rootDir, "compiler/testData/mockJDK/jre/lib/rt.jar")).withNormalizer(ClasspathNormalizer::class) + inputs.dir(File(rootDir, "third-party/annotations")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir(File(rootDir, "third-party/java8-annotations")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir(File(rootDir, "third-party/java9-annotations")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir(File(rootDir, "third-party/jsr305")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir(File(rootDir, "libraries/stdlib/unsigned/src/kotlin")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir(File(rootDir, "libraries/stdlib/jvm/src/kotlin")).withPathSensitivity(PathSensitivity.RELATIVE) //util/UnsignedJVM.kt + inputs.dir(File(rootDir, "libraries/stdlib/src/kotlin")).withPathSensitivity(PathSensitivity.RELATIVE) //ranges/Progressions.kt + inputs.dir(File(rootDir, "libraries/stdlib/jvm/runtime/kotlin")).withPathSensitivity(PathSensitivity.RELATIVE) //TypeAliases.kt } testsJar() diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/KotlinStandardLibrariesPathProvider.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/KotlinStandardLibrariesPathProvider.kt index 974bc16976d1c..62e82ddb0ecc5 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/KotlinStandardLibrariesPathProvider.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/KotlinStandardLibrariesPathProvider.kt @@ -8,8 +8,18 @@ package org.jetbrains.kotlin.test.services import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.jvm.configureStandardLibs import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_FULL_STDLIB_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_JS_KOTLIN_TEST_KLIB_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_JS_REDUCED_STDLIB_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_JS_STDLIB_KLIB_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_MINIMAL_STDLIB_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_REFLECT_JAR_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_SCRIPTING_PLUGIN_CLASSPATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_SCRIPT_RUNTIME_PATH +import org.jetbrains.kotlin.codegen.forTestCompile.TestCompilePaths.KOTLIN_TEST_JAR_PATH import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.test.util.KtTestUtil +import org.jetbrains.kotlin.utils.PathUtil import java.io.File import java.lang.ref.SoftReference import java.net.URL @@ -87,6 +97,11 @@ abstract class KotlinStandardLibrariesPathProvider : TestService { */ abstract fun kotlinTestJsKLib(): File + /** + * scriptingPlugin classpath jars + */ + abstract fun scriptingPluginFilesForTests(): Collection + fun getRuntimeJarClassLoader(): ClassLoader = synchronized(this) { var loader = runtimeJarClassLoader.get() if (loader == null) { @@ -107,7 +122,8 @@ abstract class KotlinStandardLibrariesPathProvider : TestService { runtimeJarForTests(), reflectJarForTests(), scriptRuntimeJarForTests(), - kotlinTestJarForTests()) + kotlinTestJarForTests() + ) reflectJarClassLoader = SoftReference(loader) } loader @@ -115,24 +131,73 @@ abstract class KotlinStandardLibrariesPathProvider : TestService { } object StandardLibrariesPathProviderForKotlinProject : KotlinStandardLibrariesPathProvider() { - override fun runtimeJarForTests(): File = ForTestCompileRuntime.runtimeJarForTests() + override fun runtimeJarForTests(): File = + extractFromPropertyFirstFile(KOTLIN_FULL_STDLIB_PATH) { ForTestCompileRuntime.runtimeJarForTests() } + override fun runtimeJarForTestsWithJdk8(): File = ForTestCompileRuntime.runtimeJarForTestsWithJdk8() - override fun minimalRuntimeJarForTests(): File = ForTestCompileRuntime.minimalRuntimeJarForTests() - override fun reflectJarForTests(): File = ForTestCompileRuntime.reflectJarForTests() - override fun kotlinTestJarForTests(): File = ForTestCompileRuntime.kotlinTestJarForTests() - override fun scriptRuntimeJarForTests(): File = ForTestCompileRuntime.scriptRuntimeJarForTests() + override fun minimalRuntimeJarForTests(): File = + extractFromPropertyFirstFile(KOTLIN_MINIMAL_STDLIB_PATH) { ForTestCompileRuntime.minimalRuntimeJarForTests() } + + override fun reflectJarForTests(): File = + extractFromPropertyFirstFile(KOTLIN_REFLECT_JAR_PATH) { ForTestCompileRuntime.reflectJarForTests() } + + override fun kotlinTestJarForTests(): File = + extractFromPropertyFirstFile(KOTLIN_TEST_JAR_PATH) { ForTestCompileRuntime.kotlinTestJarForTests() } + + override fun scriptRuntimeJarForTests(): File = + extractFromPropertyFirstFile(KOTLIN_SCRIPT_RUNTIME_PATH) { ForTestCompileRuntime.scriptRuntimeJarForTests() } + override fun jvmAnnotationsForTests(): File = ForTestCompileRuntime.jvmAnnotationsForTests() - override fun getAnnotationsJar(): File = KtTestUtil.getAnnotationsJar() + override fun getAnnotationsJar(): File = + KtTestUtil.getAnnotationsJar().also { + assert(it.exists()) { "AnnotationJar missing: $it does not exist" } + } - override fun fullJsStdlib(): File = extractFromPropertyFirst("kotlin.js.full.stdlib.path") { "kotlin-stdlib-js.klib".dist() } - override fun defaultJsStdlib(): File = extractFromPropertyFirst("kotlin.js.reduced.stdlib.path") { "kotlin-stdlib-js.klib".dist() } - override fun kotlinTestJsKLib(): File = extractFromPropertyFirst("kotlin.js.kotlin.test.klib.path") { "kotlin-test-js.klib".dist() } + override fun fullJsStdlib(): File = extractFromPropertyFirst(KOTLIN_JS_STDLIB_KLIB_PATH) { "kotlin-stdlib-js.klib".dist() } + override fun defaultJsStdlib(): File = extractFromPropertyFirst(KOTLIN_JS_REDUCED_STDLIB_PATH) { "kotlin-stdlib-js.klib".dist() } + override fun kotlinTestJsKLib(): File = extractFromPropertyFirst(KOTLIN_JS_KOTLIN_TEST_KLIB_PATH) { "kotlin-test-js.klib".dist() } + override fun scriptingPluginFilesForTests(): Collection = + extractFromPropertyFirstFiles(KOTLIN_SCRIPTING_PLUGIN_CLASSPATH) { + val libPath = PathUtil.kotlinPathsForCompiler.libPath + val pluginClasspath = with(PathUtil) { + listOf( + KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, + KOTLIN_SCRIPTING_COMPILER_IMPL_JAR, + KOTLIN_SCRIPTING_COMMON_JAR, + KOTLIN_SCRIPTING_JVM_JAR + ).map { + val file = File(libPath, it) + if (!file.exists()) { + throw Error("Missing ${file.path}") + } + file + } + } + pluginClasspath + } private inline fun extractFromPropertyFirst(prop: String, onMissingProperty: () -> String): File { val path = System.getProperty(prop, null) ?: onMissingProperty() + assert(File(path).exists()) { "$path not found" } return File(path) } + private inline fun extractFromPropertyFirstFile(prop: String, onMissingProperty: () -> File): File { + return System.getProperty(prop, null)?.let { + val f = File(it) + assert(f.exists()) { "$it not found" } + f + } ?: onMissingProperty() + } + + private inline fun extractFromPropertyFirstFiles(prop: String, onMissingProperty: () -> Collection): Collection { + return System.getProperty(prop, null)?.split(",")?.map { + val f = File(it) + assert(f.exists()) { "$it not found" } + f + } ?: onMissingProperty() + } + private fun String.dist(): String { return "dist/kotlinc/lib/$this" } @@ -166,6 +231,9 @@ object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPa override fun fullJsStdlib(): File = getFile(KOTLIN_STDLIB_JS_PROP) override fun defaultJsStdlib(): File = getFile(KOTLIN_STDLIB_JS_PROP) override fun kotlinTestJsKLib(): File = getFile(KOTLIN_TEST_JS_PROP) + override fun scriptingPluginFilesForTests(): Collection { + TODO("KT-67573") + } } val TestServices.standardLibrariesPathProvider: KotlinStandardLibrariesPathProvider by TestServices.testServiceAccessor() diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt index 91e905cdd7702..14c47832f09af 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt @@ -66,7 +66,7 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu } private val METADATA_CACHE by lazy { - (JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST).flatMap { path -> + listOf(StandardLibrariesPathProviderForKotlinProject.fullJsStdlib().absolutePath, StandardLibrariesPathProviderForKotlinProject.kotlinTestJsKLib().absolutePath).flatMap { path -> KotlinJavascriptMetadataUtils.loadMetadata(path).map { metadata -> val parts = KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version) JsModuleDescriptor(metadata.moduleName, parts.kind, parts.importedModules, parts) @@ -113,7 +113,14 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu project: Project, configuration: CompilerConfiguration, compilerEnvironment: TargetEnvironment = CompilerEnvironment ): JsConfig { return JsConfig( - project, configuration, compilerEnvironment, METADATA_CACHE, (JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST).toSet() + project, + configuration, + compilerEnvironment, + METADATA_CACHE, + setOf( + StandardLibrariesPathProviderForKotlinProject.fullJsStdlib().absolutePath, + StandardLibrariesPathProviderForKotlinProject.kotlinTestJsKLib().absolutePath + ) ) } @@ -206,9 +213,12 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu val friends = module.friendDependencies.map { getJsModuleArtifactPath(testServices, it.moduleName) + ".meta.js" } val libraries = when (module.targetBackend) { - null -> JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST + null -> listOf( + testServices.standardLibrariesPathProvider.fullJsStdlib().absolutePath, + testServices.standardLibrariesPathProvider.kotlinTestJsKLib().absolutePath + ) TargetBackend.JS_IR, TargetBackend.JS_IR_ES6 -> dependencies + friends - TargetBackend.JS -> JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST + dependencies + friends + TargetBackend.JS -> listOf(testServices.standardLibrariesPathProvider.fullJsStdlib().absolutePath, testServices.standardLibrariesPathProvider.kotlinTestJsKLib().absolutePath) + dependencies + friends else -> error("Unsupported target backend: ${module.targetBackend}") } configuration.put(JSConfigurationKeys.LIBRARIES, libraries) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/ScriptingEnvironmentConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/ScriptingEnvironmentConfigurator.kt index eca34894dfea8..6c4cbe423d9a4 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/ScriptingEnvironmentConfigurator.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/ScriptingEnvironmentConfigurator.kt @@ -8,14 +8,13 @@ package org.jetbrains.kotlin.test.services.configuration import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.script.loadScriptingPlugin import org.jetbrains.kotlin.test.model.TestModule -import org.jetbrains.kotlin.test.services.EnvironmentConfigurator -import org.jetbrains.kotlin.test.services.TestServices -import org.jetbrains.kotlin.test.services.isKtsFile +import org.jetbrains.kotlin.test.services.* class ScriptingEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) { override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) { if (module.files.any { it.isKtsFile }) { - loadScriptingPlugin(configuration) + val pluginFiles = testServices.standardLibrariesPathProvider.scriptingPluginFilesForTests().map { it.path } + loadScriptingPlugin(configuration, pluginFiles) } } } diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/js/JsVersionRequirementTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/js/JsVersionRequirementTest.kt index f314e1d9f444f..affdb28fc4b7d 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/js/JsVersionRequirementTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/js/JsVersionRequirementTest.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.serialization.AbstractVersionRequirementTest import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.TestJdkKind +import org.jetbrains.kotlin.test.services.StandardLibrariesPathProviderForKotlinProject import org.jetbrains.kotlin.test.util.KtTestUtil import java.io.File @@ -84,7 +85,7 @@ class JsVersionRequirementTest : AbstractVersionRequirementTest() { KotlinCoreEnvironment.createForTests( testRootDisposable, KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK).apply { - put(JSConfigurationKeys.LIBRARIES, extraDependencies.map(File::getPath) + JsConfig.JS_STDLIB) + put(JSConfigurationKeys.LIBRARIES, extraDependencies.map(File::getPath) + StandardLibrariesPathProviderForKotlinProject.fullJsStdlib().absolutePath) put(JSConfigurationKeys.META_INFO, true) if (languageVersion != null) { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java index 746a318b11eda..5efeaa5cd5d8d 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java @@ -41,12 +41,6 @@ import static org.jetbrains.kotlin.utils.PathUtil.getKotlinPathsForDistDirectory; public class JsConfig { - public static final List JS_STDLIB = - Collections.singletonList(getKotlinPathsForDistDirectory().getJsStdLibKlibPath().getAbsolutePath()); - - public static final List JS_KOTLIN_TEST = - Collections.singletonList(getKotlinPathsForDistDirectory().getJsKotlinTestKlibPath().getAbsolutePath()); - public static final String UNKNOWN_EXTERNAL_MODULE_NAME = ""; private final Project project; diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/EncodeSignatureTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/EncodeSignatureTest.kt index 2e2bd84d1e33f..c4ec84cfe77b3 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/EncodeSignatureTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/EncodeSignatureTest.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.CompilerEnvironment import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.test.services.StandardLibrariesPathProviderForKotlinProject import org.jetbrains.kotlin.test.testFramework.resetApplicationToNull import org.junit.Assert import org.junit.Test @@ -210,7 +211,10 @@ class EncodeSignatureTest { val psiFile = psiManager.findFile(file) as KtFile val configuration = environment.configuration.copy() - configuration.put(JSConfigurationKeys.LIBRARIES, JsConfig.JS_STDLIB) + configuration.put( + JSConfigurationKeys.LIBRARIES, + listOf(StandardLibrariesPathProviderForKotlinProject.fullJsStdlib().absolutePath) + ) configuration.put(CommonConfigurationKeys.MODULE_NAME, "sample") val analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles( diff --git a/repo/codebase-tests/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt b/repo/codebase-tests/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt index 8646c072e6f20..08eb2e599aab5 100644 --- a/repo/codebase-tests/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt +++ b/repo/codebase-tests/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt @@ -145,6 +145,7 @@ class CodeConformanceTest : TestCase() { "repo/gradle-settings-conventions/gradle-enterprise/build/generated-sources", "repo/gradle-settings-conventions/kotlin-daemon-config/build/generated-sources", "repo/gradle-build-conventions/buildsrc-compat/build/generated-sources", + "repo/gradle-build-conventions/compiler-tests-convention/build/generated-sources", ".gradle/expanded", ) ) diff --git a/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt b/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt index fb167e0a68acf..1af261932386a 100644 --- a/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt +++ b/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt @@ -16,6 +16,7 @@ import org.gradle.api.attributes.Usage import org.gradle.api.file.FileCollection import org.gradle.api.file.FileSystemOperations import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter +import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.testing.Test import org.gradle.kotlin.dsl.* @@ -152,6 +153,7 @@ fun Project.projectTest( } return getOrCreateTask(taskName) { dependsOn(":createIdeaHomeForTests") + inputs.dir(File(rootDir, "build/ideaHomeForTests")).withPathSensitivity(PathSensitivity.RELATIVE) doFirst { if (jUnitMode == JUnitMode.JUnit5) return@doFirst diff --git a/repo/gradle-build-conventions/compiler-tests-convention/Readme.md b/repo/gradle-build-conventions/compiler-tests-convention/Readme.md new file mode 100644 index 0000000000000..d39881b364475 --- /dev/null +++ b/repo/gradle-build-conventions/compiler-tests-convention/Readme.md @@ -0,0 +1,28 @@ +# compiler-test-convention + +## Description + +This plugin adds dependencies to the test tasks, building the required jars and tracking them as inputs, but it passes the absolute paths to the test as systemProperties. + +This plugin is key for: +- make tests cacheable, avoiding execution if no input changed +- allow Gradle Predictive Test Selection to understand the code changes and have an accurate prediction + +## Usage + +Apply it: +```kotlin +plugins { + id("compiler-test-convention") +} +``` + +Add dependencies to the test classpath (`kotlin-stdlib`, `kotlin-stdlib-jvm-minimal-for-test`, and `kotlin-reflect` are always added): +```kotlin +compilerTests { + withStdlibCommon() + withTestJar() + withAnnotations() + ... +} +``` diff --git a/repo/gradle-build-conventions/compiler-tests-convention/build.gradle.kts b/repo/gradle-build-conventions/compiler-tests-convention/build.gradle.kts new file mode 100644 index 0000000000000..009f83566c421 --- /dev/null +++ b/repo/gradle-build-conventions/compiler-tests-convention/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + `kotlin-dsl` + `java-gradle-plugin` + id("org.jetbrains.kotlin.jvm") +} + +repositories { + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies") + mavenCentral() + gradlePluginPortal() + + extra["bootstrapKotlinRepo"]?.let { + maven(url = it) + } +} + +kotlin { + jvmToolchain(8) + + compilerOptions { + allWarningsAsErrors.set(true) + optIn.add("kotlin.ExperimentalStdlibApi") + freeCompilerArgs.add("-Xsuppress-version-warnings") + } +} + +dependencies { + implementation(kotlin("stdlib", embeddedKotlinVersion)) + + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}") + implementation("org.jetbrains.kotlin:kotlin-stdlib:${project.bootstrapKotlinVersion}") + implementation("org.jetbrains.kotlin:kotlin-reflect:${project.bootstrapKotlinVersion}") +} diff --git a/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/CompilerTestsExtension.kt b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/CompilerTestsExtension.kt new file mode 100644 index 0000000000000..1a6f851025f84 --- /dev/null +++ b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/CompilerTestsExtension.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.project + +abstract class CompilerTestsExtension(private val project: Project) { + val stdlibRuntimeForTests: Configuration = project.configurations.create("stdlibRuntimeForTests") { + isTransitive = false + } + val stdlibMinimalRuntimeForTests: Configuration = project.configurations.create("stdlibMinimalRuntimeForTests") { + isTransitive = false + } + val kotlinReflectJarForTests: Configuration = project.configurations.create("kotlinReflectJarForTests") { + isTransitive = false + } + val stdlibCommonRuntimeForTests: Configuration = project.configurations.create("stdlibCommonRuntimeForTests") { + isTransitive = false + } + val scriptRuntimeForTests: Configuration = project.configurations.create("scriptRuntimeForTests") { + isTransitive = false + } + val kotlinTestJarForTests: Configuration = project.configurations.create("kotlinTestJarForTests") { + isTransitive = false + } + val kotlinAnnotationsForTests: Configuration = project.configurations.create("kotlinAnnotationsForTests") { + isTransitive = false + } + val scriptingPluginForTests: Configuration = project.configurations.create("scriptingPluginForTests") { + isTransitive = false + } + val stdlibJsRuntimeForTests: Configuration = project.configurations.create("stdlibJsRuntimeForTests") { + isTransitive = false + } + val testJsRuntimeForTests: Configuration = project.configurations.create("testJsRuntimeForTests") { + isTransitive = false + } + + init { + project.dependencies { + stdlibRuntimeForTests(project(":kotlin-stdlib")) + stdlibMinimalRuntimeForTests(project(":kotlin-stdlib-jvm-minimal-for-test")) + kotlinReflectJarForTests(project(":kotlin-reflect")) + } + } + + fun withStdlibCommon() { + project.dependencies { stdlibCommonRuntimeForTests(project(":kotlin-stdlib-common")) } + } + + fun withScriptRuntime() { + project.dependencies { scriptRuntimeForTests(project(":kotlin-script-runtime")) } + } + + fun withTestJar() { + project.dependencies { kotlinTestJarForTests(project(":kotlin-test")) } + } + + fun withAnnotations() { + project.dependencies { kotlinAnnotationsForTests(project(":kotlin-annotations-jvm")) } + } + + fun withStdlibJsRuntime() { + project.dependencies { stdlibJsRuntimeForTests(project(":kotlin-stdlib", "distJsKlib")) } + } + + fun withTestJsRuntime() { + project.dependencies { testJsRuntimeForTests(project(":kotlin-test", "jsRuntimeElements")) } + } + + fun withScriptingPlugin() { + project.dependencies { + scriptingPluginForTests(project(":kotlin-scripting-compiler")) + scriptingPluginForTests(project(":kotlin-scripting-compiler-impl")) + scriptingPluginForTests(project(":kotlin-scripting-common")) + scriptingPluginForTests(project(":kotlin-scripting-jvm")) + } + /* + KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR + KOTLIN_SCRIPTING_COMPILER_IMPL_JAR + KOTLIN_SCRIPTING_COMMON_JAR + KOTLIN_SCRIPTING_JVM_JAR + */ + } +} diff --git a/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilePaths.kt b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilePaths.kt new file mode 100644 index 0000000000000..4e2f8f4698198 --- /dev/null +++ b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilePaths.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +// This file is duplicated at compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/forTestCompile/TestCompilePaths.kt +object TestCompilePaths { + const val KOTLIN_FULL_STDLIB_PATH: String = "kotlin.full.stdlib.path" + const val KOTLIN_MINIMAL_STDLIB_PATH: String = "kotlin.minimal.stdlib.path" + const val KOTLIN_TEST_JAR_PATH: String = "kotlin.test.jar.path" + const val KOTLIN_REFLECT_JAR_PATH: String = "kotlin.reflect.jar.path" + const val KOTLIN_SCRIPT_RUNTIME_PATH: String = "kotlin.script.runtime.path" + const val KOTLIN_COMMON_STDLIB_PATH: String = "kotlin.common.stdlib.path" + const val KOTLIN_ANNOTATIONS_PATH: String = "kotlin.annotations.path" + const val KOTLIN_JS_STDLIB_KLIB_PATH: String = "kotlin.js.stdlib.klib.path" + const val KOTLIN_JS_REDUCED_STDLIB_PATH: String = "kotlin.js.reduced.stdlib.path" + const val KOTLIN_JS_KOTLIN_TEST_KLIB_PATH: String = "kotlin.js.kotlin.test.klib.path" + const val KOTLIN_SCRIPTING_PLUGIN_CLASSPATH = "kotlin.scriptingPlugin.classpath" +} \ No newline at end of file diff --git a/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilerRuntimeArgumentProvider.kt b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilerRuntimeArgumentProvider.kt new file mode 100644 index 0000000000000..b9385ea2dc74b --- /dev/null +++ b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/TestCompilerRuntimeArgumentProvider.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +import TestCompilePaths.KOTLIN_ANNOTATIONS_PATH +import TestCompilePaths.KOTLIN_COMMON_STDLIB_PATH +import TestCompilePaths.KOTLIN_FULL_STDLIB_PATH +import TestCompilePaths.KOTLIN_JS_KOTLIN_TEST_KLIB_PATH +import TestCompilePaths.KOTLIN_JS_REDUCED_STDLIB_PATH +import TestCompilePaths.KOTLIN_JS_STDLIB_KLIB_PATH +import TestCompilePaths.KOTLIN_MINIMAL_STDLIB_PATH +import TestCompilePaths.KOTLIN_REFLECT_JAR_PATH +import TestCompilePaths.KOTLIN_SCRIPTING_PLUGIN_CLASSPATH +import TestCompilePaths.KOTLIN_SCRIPT_RUNTIME_PATH +import TestCompilePaths.KOTLIN_TEST_JAR_PATH +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.InputFiles +import org.gradle.process.CommandLineArgumentProvider + +abstract class TestCompilerRuntimeArgumentProvider : CommandLineArgumentProvider { + @get:InputFiles + @get:Classpath + abstract val stdlibRuntimeForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val stdlibMinimalRuntimeForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val kotlinReflectJarForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val stdlibCommonRuntimeForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val scriptRuntimeForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val kotlinTestJarForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val kotlinAnnotationsForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val scriptingPluginForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val stdlibJsRuntimeForTests: ConfigurableFileCollection + + @get:InputFiles + @get:Classpath + abstract val testJsRuntimeForTests: ConfigurableFileCollection + + private fun ifNotEmpty(property: String, fileCollection: ConfigurableFileCollection): String? = + if (fileCollection.isEmpty) null else argument(property, fileCollection) + + private fun argument(property: String, fileCollection: ConfigurableFileCollection) = + "-D$property=${fileCollection.joinToString(",") { it.absolutePath }}" + + override fun asArguments(): Iterable { + return listOfNotNull( + argument(KOTLIN_FULL_STDLIB_PATH, stdlibRuntimeForTests), + argument(KOTLIN_MINIMAL_STDLIB_PATH, stdlibMinimalRuntimeForTests), + argument(KOTLIN_REFLECT_JAR_PATH, kotlinReflectJarForTests), + ifNotEmpty(KOTLIN_COMMON_STDLIB_PATH, stdlibCommonRuntimeForTests), + ifNotEmpty(KOTLIN_SCRIPT_RUNTIME_PATH, scriptRuntimeForTests), + ifNotEmpty(KOTLIN_TEST_JAR_PATH, kotlinTestJarForTests), + ifNotEmpty(KOTLIN_ANNOTATIONS_PATH, kotlinAnnotationsForTests), + ifNotEmpty(KOTLIN_SCRIPTING_PLUGIN_CLASSPATH, scriptingPluginForTests), + ifNotEmpty(KOTLIN_JS_STDLIB_KLIB_PATH, stdlibJsRuntimeForTests), + ifNotEmpty(KOTLIN_JS_REDUCED_STDLIB_PATH, stdlibJsRuntimeForTests), + ifNotEmpty(KOTLIN_JS_KOTLIN_TEST_KLIB_PATH, testJsRuntimeForTests), + ) + } +} \ No newline at end of file diff --git a/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/compiler-tests-convention.gradle.kts b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/compiler-tests-convention.gradle.kts new file mode 100644 index 0000000000000..a81ddba37f518 --- /dev/null +++ b/repo/gradle-build-conventions/compiler-tests-convention/src/main/kotlin/compiler-tests-convention.gradle.kts @@ -0,0 +1,18 @@ +val extension = extensions.create("compilerTests", CompilerTestsExtension::class) + +val provider = objects.newInstance().apply { + stdlibRuntimeForTests.from(extension.stdlibRuntimeForTests) + stdlibMinimalRuntimeForTests.from(extension.stdlibMinimalRuntimeForTests) + kotlinReflectJarForTests.from(extension.kotlinReflectJarForTests) + stdlibCommonRuntimeForTests.from(extension.stdlibCommonRuntimeForTests) + scriptRuntimeForTests.from(extension.scriptRuntimeForTests) + kotlinTestJarForTests.from(extension.kotlinTestJarForTests) + kotlinAnnotationsForTests.from(extension.kotlinAnnotationsForTests) + scriptingPluginForTests.from(extension.scriptingPluginForTests) + stdlibJsRuntimeForTests.from(extension.stdlibJsRuntimeForTests) + testJsRuntimeForTests.from(extension.testJsRuntimeForTests) +} + +tasks.withType().configureEach { + jvmArgumentProviders.add(provider) +} diff --git a/repo/gradle-build-conventions/settings.gradle.kts b/repo/gradle-build-conventions/settings.gradle.kts index a56b079aa97ee..eda9112fb0229 100644 --- a/repo/gradle-build-conventions/settings.gradle.kts +++ b/repo/gradle-build-conventions/settings.gradle.kts @@ -31,3 +31,4 @@ dependencyResolutionManagement { include(":buildsrc-compat") include(":prepare-deps") +include(":compiler-tests-convention")