diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index 2d62ade67c3..1c23cdf0281 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -10,7 +10,6 @@ import org.gradle.api.logging.LogLevel import org.gradle.api.logging.configuration.WarningMode import org.gradle.tooling.GradleConnector import org.gradle.util.GradleVersion -import org.intellij.lang.annotations.Language import org.jetbrains.kotlin.cli.common.CompilerSystemProperties.COMPILE_INCREMENTAL_WITH_ARTIFACT_TRANSFORM import org.jetbrains.kotlin.gradle.model.ModelContainer import org.jetbrains.kotlin.gradle.model.ModelFetcherBuildAction @@ -743,29 +742,6 @@ abstract class BaseGradleIT { } } - fun CompiledProject.getOutputForTask(taskName: String): String { - @Language("RegExp") - val taskOutputRegex = """ - \[org\.gradle\.internal\.operations\.DefaultBuildOperationRunner] Build operation 'Task :$taskName' started - ([\s\S]+?) - \[org\.gradle\.internal\.operations\.DefaultBuildOperationRunner] Build operation 'Task :$taskName' completed - """.trimIndent() - .replace("\n", "") - .toRegex() - - return taskOutputRegex.find(output)?.run { groupValues[1] } ?: error("Cannot find output for task $taskName") - } - - fun CompiledProject.assertCompiledKotlinSources( - sources: Iterable, - weakTesting: Boolean = false, - tasks: List - ) { - for (task in tasks) { - assertCompiledKotlinSources(sources, weakTesting, getOutputForTask(task), suffix = " in task ${task}") - } - } - fun CompiledProject.assertCompiledKotlinSources( expectedSourcesRelativePaths: Iterable, weakTesting: Boolean = false, diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt index 0aa2d480e36..06cd54c6ddf 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt @@ -8,12 +8,10 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.logging.LogLevel import org.gradle.util.GradleVersion import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.gradle.util.parseCompilerArguments import org.jetbrains.kotlin.gradle.util.parseCompilerArgumentsFromBuildOutput import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.fail import kotlin.io.path.appendText import kotlin.test.assertEquals import kotlin.test.fail @@ -255,7 +253,7 @@ internal class CompilerOptionsIT : KGPBaseTest() { build("compileNativeMainKotlinMetadata") { assertTasksExecuted(":compileNativeMainKotlinMetadata") - val taskOutput = getOutputForTask("compileNativeMainKotlinMetadata") + val taskOutput = getOutputForTask(":compileNativeMainKotlinMetadata") val arguments = parseCompilerArgumentsFromBuildOutput(K2NativeCompilerArguments::class, taskOutput) assertEquals( setOf("another.custom.UnderOptIn", "my.custom.OptInAnnotation"), arguments.optIn?.toSet(), @@ -265,7 +263,7 @@ internal class CompilerOptionsIT : KGPBaseTest() { build("compileKotlinLinux64") { assertTasksExecuted(":compileKotlinLinux64") - val taskOutput = getOutputForTask("compileKotlinLinux64") + val taskOutput = getOutputForTask(":compileKotlinLinux64") val arguments = parseCompilerArgumentsFromBuildOutput(K2NativeCompilerArguments::class, taskOutput) assertEquals( setOf("another.custom.UnderOptIn", "my.custom.OptInAnnotation"), arguments.optIn?.toSet(), diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt index 178bc963499..7299fe9f010 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt @@ -283,7 +283,7 @@ open class KaptIncrementalIT : KGPBaseTest() { val useBKt = javaSourcesDir().resolve("bar/useB.kt") assertCompiledKotlinSources( listOf(projectPath.relativize(bKt), projectPath.relativize(useBKt)), - getOutputForTask("kaptGenerateStubsKotlin"), + getOutputForTask(":kaptGenerateStubsKotlin"), errorMessageSuffix = " in task 'kaptGenerateStubsKotlin'" ) @@ -344,13 +344,13 @@ open class KaptIncrementalIT : KGPBaseTest() { ) { assertCompiledKotlinSources( sources, - buildResult.getOutputForTask("kaptGenerateStubsKotlin"), + buildResult.getOutputForTask(":kaptGenerateStubsKotlin"), errorMessageSuffix = " in task 'kaptGenerateStubsKotlin" ) assertCompiledKotlinSources( sources, - buildResult.getOutputForTask("compileKotlin"), + buildResult.getOutputForTask(":compileKotlin"), errorMessageSuffix = " in task 'compileKotlin'" ) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIncrementalIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIncrementalIT.kt index ef9f4ac141d..46c31bfa3a4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIncrementalIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIncrementalIT.kt @@ -185,12 +185,12 @@ open class Kapt3AndroidIncrementalIT : Kapt3BaseIT() { .resolve(useUtilFileName).relativeTo(projectPath) assertCompiledKotlinSources( listOf(affectedFile), - getOutputForTask("app:kaptGenerateStubsDebugKotlin"), + getOutputForTask(":app:kaptGenerateStubsDebugKotlin"), errorMessageSuffix = " in task ':app:kaptGenerateStubsDebugKotlin" ) assertCompiledKotlinSources( listOf(affectedFile), - getOutputForTask("app:compileDebugKotlin"), + getOutputForTask(":app:compileDebugKotlin"), errorMessageSuffix = " in task ':app:compileDebugKotlin" ) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt index ccd4fa7287b..0e8403fafe4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.gradle.native import com.intellij.testFramework.TestDataFile +import org.gradle.api.logging.LogLevel import org.gradle.api.logging.configuration.WarningMode import org.gradle.util.GradleVersion import org.jdom.input.SAXBuilder @@ -15,8 +16,7 @@ import org.jetbrains.kotlin.gradle.internals.DISABLED_NATIVE_TARGETS_REPORTER_WA import org.jetbrains.kotlin.gradle.internals.NO_NATIVE_STDLIB_PROPERTY_WARNING import org.jetbrains.kotlin.gradle.internals.NO_NATIVE_STDLIB_WARNING import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind -import org.jetbrains.kotlin.gradle.testbase.TestVersions -import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl +import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.gradle.util.modify import org.jetbrains.kotlin.gradle.util.runProcess import org.jetbrains.kotlin.gradle.utils.Xcode @@ -498,7 +498,8 @@ class GeneralNativeIT : BaseGradleIT() { "releaseExecutable" to "native-binary", "bazDebugExecutable" to "my-baz", ) - val linkTasks = binaries.map { (name, _) -> "link${name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}Host" } + val linkTasks = + binaries.map { (name, _) -> "link${name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}Host" } val outputFiles = binaries.map { (name, fileBaseName) -> val outputKind = NativeOutputKind.values().single { name.endsWith(it.taskNameClassifier, true) }.compilerOutputKind val prefix = outputKind.prefix(HostManager.host) @@ -874,7 +875,7 @@ class GeneralNativeIT : BaseGradleIT() { assertSuccessful() assertTasksExecuted(":projectLibrary:cinteropAnotherNumberHost") libraryFiles("projectLibrary", "anotherNumber").forEach { assertFileExists(it) } - withNativeCustomEnvironment(":projectLibrary:cinteropAnotherNumberHost", toolName = "cinterop") { env -> + withNativeCustomEnvironment(":projectLibrary:cinteropAnotherNumberHost", toolName = NativeToolKind.C_INTEROP) { env -> assertEquals("1", env["LIBCLANG_DISABLE_CRASH_RECOVERY"]) } } @@ -1173,18 +1174,19 @@ class GeneralNativeIT : BaseGradleIT() { // KT-52303 @Test - fun testBuildDirChangeAppliedToBinaries() = with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { - gradleBuildScript().appendText( - """ + fun testBuildDirChangeAppliedToBinaries() = + with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { + gradleBuildScript().appendText( + """ project.buildDir = file("${'$'}{project.buildDir.absolutePath}/mydir") """.trimIndent() - ) - build(":linkDebugExecutableHost") { - assertSuccessful() - assertDirectoryExists("build/mydir/bin/host/debugExecutable") - assertNoSuchFile("build/bin") + ) + build(":linkDebugExecutableHost") { + assertSuccessful() + assertDirectoryExists("build/mydir/bin/host/debugExecutable") + assertNoSuchFile("build/bin") + } } - } // KT-54439 @Test @@ -1215,70 +1217,35 @@ class GeneralNativeIT : BaseGradleIT() { return Collections.indexOfSubList(this, elements.toList()) != -1 } - private enum class NativeToolSettingsKind(val title: String) { - COMPILER_CLASSPATH("Classpath"), - COMMAND_LINE_ARGUMENTS("Arguments"), - CUSTOM_ENV_VARIABLES("Custom ENV variables") - } + /** + * Filter output for specific task with given [taskPath] + * + * Requires using [LogLevel.DEBUG]. + */ + fun CompiledProject.getOutputForTask(taskPath: String): String = getOutputForTask(taskPath, output) - private fun CompiledProject.extractNativeToolSettings( - toolName: String, - taskPath: String?, - settingsKind: NativeToolSettingsKind - ): Sequence { - val settingsPrefix = "${settingsKind.title} = [" - val settings = output.lineSequence() - .run { - if (taskPath != null) dropWhile { "Executing actions for task '$taskPath'" !in it }.drop(1) else this - } - .dropWhile { - check(taskPath == null || "Executing actions for task" !in it) { "Unexpected log line with new Gradle task: $it" } - "Run in-process tool \"$toolName\"" !in it && "Run \"$toolName\" tool in a separate JVM process" !in it - } - .drop(1) - .dropWhile { - check(taskPath == null || "Executing actions for task" !in it) { "Unexpected log line with new Gradle task: $it" } - settingsPrefix !in it - } + fun CompiledProject.extractNativeCommandLineArguments(taskPath: String? = null, toolName: NativeToolKind): List = + extractNativeToolSettings(taskPath?.let { getOutputForTask(taskPath) } ?: output, + toolName, + NativeToolSettingsKind.COMMAND_LINE_ARGUMENTS).toList() - val settingsHeader = settings.firstOrNull() - check(settingsHeader != null && settingsPrefix in settingsHeader) { - "Cannot find setting '${settingsKind.title}' for task ${taskPath}" - } - - return if (settingsHeader.trimEnd().endsWith(']')) - emptySequence() // No parameters. - else - settings.drop(1).map { it.trim() }.takeWhile { it != "]" } - } - - fun CompiledProject.extractNativeCommandLineArguments(taskPath: String? = null, toolName: String): List = - extractNativeToolSettings(toolName, taskPath, NativeToolSettingsKind.COMMAND_LINE_ARGUMENTS).toList() - - fun CompiledProject.extractNativeCompilerClasspath(taskPath: String? = null, toolName: String): List = - extractNativeToolSettings(toolName, taskPath, NativeToolSettingsKind.COMPILER_CLASSPATH).toList() - - fun CompiledProject.extractNativeCustomEnvironment(taskPath: String? = null, toolName: String): Map = - extractNativeToolSettings(toolName, taskPath, NativeToolSettingsKind.CUSTOM_ENV_VARIABLES).map { + fun CompiledProject.extractNativeCustomEnvironment(taskPath: String? = null, toolName: NativeToolKind): Map = + extractNativeToolSettings(taskPath?.let { getOutputForTask(taskPath) } ?: output, + toolName, + NativeToolSettingsKind.CUSTOM_ENV_VARIABLES).map { val (key, value) = it.split("=") key.trim() to value.trim() }.toMap() fun CompiledProject.withNativeCommandLineArguments( vararg taskPaths: String, - toolName: String = "konanc", + toolName: NativeToolKind = NativeToolKind.KONANC, check: (List) -> Unit ) = taskPaths.forEach { taskPath -> check(extractNativeCommandLineArguments(taskPath, toolName)) } - fun CompiledProject.withNativeCompilerClasspath( - vararg taskPaths: String, - toolName: String = "konanc", - check: (List) -> Unit - ) = taskPaths.forEach { taskPath -> check(extractNativeCompilerClasspath(taskPath, toolName)) } - fun CompiledProject.withNativeCustomEnvironment( vararg taskPaths: String, - toolName: String = "konanc", + toolName: NativeToolKind = NativeToolKind.KONANC, check: (Map) -> Unit ) = taskPaths.forEach { taskPath -> check(extractNativeCustomEnvironment(taskPath, toolName)) } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt index 5355cd197b6..a613c1c2597 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.gradle.embedProject import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.containsSequentially import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.extractNativeCommandLineArguments import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.withNativeCommandLineArguments +import org.jetbrains.kotlin.gradle.testbase.NativeToolKind import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl import org.jetbrains.kotlin.gradle.util.modify import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader @@ -186,7 +187,7 @@ class NativeDownloadAndPlatformLibsIT : BaseGradleIT() { // Check that user can change generation mode used by the cinterop tool. buildWithLightDist("tasks", "-Pkotlin.native.platform.libraries.mode=metadata") { assertSuccessful() - assertTrue(extractNativeCommandLineArguments(toolName = "generatePlatformLibraries").containsSequentially("-mode", "metadata")) + assertTrue(extractNativeCommandLineArguments(toolName = NativeToolKind.GENERATE_PLATFORM_LIBRARIES).containsSequentially("-mode", "metadata")) } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeEmbeddableCompilerJarIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeEmbeddableCompilerJarIT.kt index bfcb9e9f26b..a75504e26d5 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeEmbeddableCompilerJarIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeEmbeddableCompilerJarIT.kt @@ -1,21 +1,21 @@ /* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 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. */ package org.jetbrains.kotlin.gradle.native -import org.jetbrains.kotlin.gradle.BaseGradleIT -import org.jetbrains.kotlin.gradle.GradleVersionRequired -import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.withNativeCompilerClasspath -import org.junit.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue +import org.gradle.api.logging.LogLevel +import org.gradle.testkit.runner.BuildResult +import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.gradle.testbase.* +import org.junit.jupiter.api.DisplayName -class NativeEmbeddableCompilerJarIT : BaseGradleIT() { +@DisplayName("Tests for K/N builds with embeddable compiler jar") +@NativeGradlePluginTests +internal class NativeEmbeddableCompilerJarIT : KGPBaseTest() { - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.FOR_MPP_SUPPORT + override val defaultBuildOptions = super.defaultBuildOptions.copy(logLevel = LogLevel.DEBUG) private fun String.isRegularJar() = this.endsWith("/kotlin-native.jar") private fun String.isEmbeddableJar() = this.endsWith("/kotlin-native-compiler-embeddable.jar") @@ -23,60 +23,103 @@ class NativeEmbeddableCompilerJarIT : BaseGradleIT() { private fun List.includesRegularJar() = any { it.isRegularJar() } private fun List.includesEmbeddableJar() = any { it.isEmbeddableJar() } - @Test - fun testDefault() = with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { - build(":linkDebugExecutableHost") { - assertSuccessful() - withNativeCompilerClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { - assertFalse(it.includesRegularJar()) - assertTrue(it.includesEmbeddableJar()) + private val String.withPrefix get() = "native-binaries/$this" + + @DisplayName("K/N with default config shouldn't contain kotlin-native.jar and should contain kotlin-native-compiler-embeddable.jar") + @GradleTest + fun shouldNotUseRegularJarInDefaultConfig(gradleVersion: GradleVersion) { + nativeProject("executables".withPrefix, gradleVersion) { + build(":linkDebugExecutableHost") { + assertNativeTasksClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { + assert(!it.includesRegularJar()) { + assertionFailedMessage(it) + } + assert(it.includesEmbeddableJar()) { + assertionFailedMessage(it) + } + } } } } - @Test - fun testEmbeddableJarFalse() = with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { - build(":linkDebugExecutableHost", "-Pkotlin.native.useEmbeddableCompilerJar=false") { - assertSuccessful() - withNativeCompilerClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { - assertTrue(it.includesRegularJar()) - assertFalse(it.includesEmbeddableJar()) + @DisplayName("K/N with embeddable compiler flag turned off config should contain kotlin-native.jar and shouldn't contain kotlin-native-compiler-embeddable.jar") + @GradleTest + fun shouldUseRegularJarWithoutUseEmbeddableCompilerJar(gradleVersion: GradleVersion) { + nativeProject("executables".withPrefix, gradleVersion) { + build( + ":linkDebugExecutableHost", + "-Pkotlin.native.useEmbeddableCompilerJar=false", + ) { + assertNativeTasksClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { + assert(it.includesRegularJar()) { + assertionFailedMessage(it) + } + assert(!it.includesEmbeddableJar()) { + assertionFailedMessage(it) + } + } } } } - @Test - fun testEmbeddableJarTrue() = with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { - build(":linkDebugExecutableHost", "-Pkotlin.native.useEmbeddableCompilerJar=true") { - assertSuccessful() - withNativeCompilerClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { - assertFalse(it.includesRegularJar()) - assertTrue(it.includesEmbeddableJar()) + @DisplayName("K/N with embeddable compiler flag turned on config shouldn't contain kotlin-native.jar and should contain kotlin-native-compiler-embeddable.jar") + @GradleTest + fun shouldUseRegularJarWithUseEmbeddableCompilerJar(gradleVersion: GradleVersion) { + nativeProject("executables".withPrefix, gradleVersion) { + build( + ":linkDebugExecutableHost", + "-Pkotlin.native.useEmbeddableCompilerJar=true", + ) { + assertNativeTasksClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { + assert(!it.includesRegularJar()) { + assertionFailedMessage(it) + } + assert(it.includesEmbeddableJar()) { + assertionFailedMessage(it) + } + } } } } - @Test - fun testSwitch() = with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { - build(":linkDebugExecutableHost") { - assertSuccessful() - withNativeCompilerClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { - assertFalse(it.includesRegularJar()) - assertTrue(it.includesEmbeddableJar()) + @DisplayName("K/N project's builds with switching embeddable compiler flag turned from on to off") + @GradleTest + fun testSwitch(gradleVersion: GradleVersion) { + nativeProject("executables".withPrefix, gradleVersion) { + build(":linkDebugExecutableHost") { + assertNativeTasksClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { + assert(!it.includesRegularJar()) { + assertionFailedMessage(it) + } + assert(it.includesEmbeddableJar()) { + assertionFailedMessage(it) + } + } } - } - build(":linkDebugExecutableHost") { - assertTasksUpToDate(":linkDebugExecutableHost", ":compileKotlinHost") - } + build(":linkDebugExecutableHost") { + assertTasksUpToDate(":linkDebugExecutableHost", ":compileKotlinHost") + } - build(":linkDebugExecutableHost", "-Pkotlin.native.useEmbeddableCompilerJar=false") { - assertSuccessful() - assertTasksExecuted(":linkDebugExecutableHost", ":compileKotlinHost") - withNativeCompilerClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { - assertTrue(it.includesRegularJar()) - assertFalse(it.includesEmbeddableJar()) + build( + ":linkDebugExecutableHost", + "-Pkotlin.native.useEmbeddableCompilerJar=false", + ) { + assertTasksExecuted(":linkDebugExecutableHost", ":compileKotlinHost") + assertNativeTasksClasspath(":linkDebugExecutableHost", ":compileKotlinHost") { + assert(it.includesRegularJar()) { + assertionFailedMessage(it) + } + assert(!it.includesEmbeddableJar()) { + assertionFailedMessage(it) + } + } } } } -} + + private fun BuildResult.assertionFailedMessage(classPathValues: List): String { + printBuildOutput() + return "Actual classpath is: ${classPathValues}" + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeIrLinkerIssuesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeIrLinkerIssuesIT.kt index f16e8b38df6..474d1831b69 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeIrLinkerIssuesIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeIrLinkerIssuesIT.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.native import org.jetbrains.kotlin.gradle.BaseGradleIT import org.jetbrains.kotlin.gradle.GradleVersionRequired +import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.getOutputForTask import org.jetbrains.kotlin.gradle.testbase.DEFAULT_CURRENT_PLATFORM_TARGET_NAME_POSTFIX import org.jetbrains.kotlin.gradle.testbase.findParameterInOutput import org.jetbrains.kotlin.konan.library.KONAN_PLATFORM_LIBS_NAME_PREFIX @@ -271,7 +272,7 @@ class NativeIrLinkerIssuesIT : BaseGradleIT() { val kotlinNativeCompilerVersion = findKotlinNativeCompilerVersion(output) assertNotNull(kotlinNativeCompilerVersion) - val errorMessage = ERROR_LINE_REGEX.findAll(getOutputForTask("linkDebugExecutableNative")) + val errorMessage = ERROR_LINE_REGEX.findAll(getOutputForTask(":linkDebugExecutableNative")) .map { matchResult -> matchResult.groupValues[1] } .filterNot { it.startsWith("w:") || it.startsWith("v:") || it.startsWith("i:") } .map { line -> diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/compilationAssertions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/compilationAssertions.kt index 87fc680cc23..a0fc4ae669c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/compilationAssertions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/compilationAssertions.kt @@ -17,27 +17,6 @@ private val kotlinSrcRegex by lazy { Regex("\\[KOTLIN] compile iteration: ([^\\r private val javaSrcRegex by lazy { Regex("\\[DEBUG] \\[[^]]*JavaCompiler] Compiler arguments: ([^\\r\\n]*)") } -@Language("RegExp") -private fun taskOutputRegex( - taskName: String -) = """ - \[org\.gradle\.internal\.operations\.DefaultBuildOperationRunner] Build operation 'Task :$taskName' started - ([\s\S]+?) - \[org\.gradle\.internal\.operations\.DefaultBuildOperationRunner] Build operation 'Task :$taskName' completed - """.trimIndent() - .replace("\n", "") - .toRegex() - -/** - * Filter [BuildResult.getOutput] for specific task with given [taskName]. - * - * Requires using [LogLevel.DEBUG]. - */ -fun BuildResult.getOutputForTask(taskName: String): String = taskOutputRegex(taskName) - .find(output) - ?.let { it.groupValues[1] } - ?: error("Could not find output for task $taskName") - /** * Extracts the list of compiled .kt files from the build output. * diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/nativeTestHelpers.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/nativeTestHelpers.kt index 638adf5f602..cc9069971c4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/nativeTestHelpers.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/nativeTestHelpers.kt @@ -9,4 +9,53 @@ import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.presetName import java.util.* -val DEFAULT_CURRENT_PLATFORM_TARGET_NAME_POSTFIX = HostManager.host.presetName.lowercase(Locale.getDefault()) \ No newline at end of file +val DEFAULT_CURRENT_PLATFORM_TARGET_NAME_POSTFIX = HostManager.host.presetName.lowercase(Locale.getDefault()) + +/** + * Extracts classpath of given task's output + * + * @param taskOutput debug level output of the task + * @param toolName compiler type + * + * @return list of dependencies in classpath + */ +fun extractNativeCompilerClasspath(taskOutput: String, toolName: NativeToolKind): List = + extractNativeToolSettings(taskOutput, toolName, NativeToolSettingsKind.COMPILER_CLASSPATH).toList() + +enum class NativeToolKind(val title: String) { + KONANC("konanc"), + GENERATE_PLATFORM_LIBRARIES("generatePlatformLibraries"), + C_INTEROP("cinterop") +} + +enum class NativeToolSettingsKind(val title: String) { + COMPILER_CLASSPATH("Classpath"), + COMMAND_LINE_ARGUMENTS("Arguments"), + CUSTOM_ENV_VARIABLES("Custom ENV variables") +} + +fun extractNativeToolSettings( + taskOutput: String, + toolName: NativeToolKind, + settingsKind: NativeToolSettingsKind +): Sequence { + val settingsPrefix = "${settingsKind.title} = [" + val settings = taskOutput.lineSequence() + .dropWhile { + "Run in-process tool \"${toolName.title}\"" !in it && "Run \"${toolName.title}\" tool in a separate JVM process" !in it + } + .drop(1) + .dropWhile { + settingsPrefix !in it + } + + val settingsHeader = settings.firstOrNull() + check(settingsHeader != null && settingsPrefix in settingsHeader) { + "Cannot find setting '${settingsKind.title}'" + } + + return if (settingsHeader.trimEnd().endsWith(']')) + emptySequence() // No parameters. + else + settings.drop(1).map { it.trim() }.takeWhile { it != "]" } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt new file mode 100644 index 00000000000..d7d62c19fc1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2023 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. + */ + +package org.jetbrains.kotlin.gradle.testbase + +import org.gradle.api.logging.LogLevel +import org.gradle.testkit.runner.BuildResult +import org.intellij.lang.annotations.Language + +@Language("RegExp") +private fun taskOutputRegex( + taskName: String +) = """ + \[org\.gradle\.internal\.operations\.DefaultBuildOperationRunner] Build operation 'Task $taskName' started + ([\s\S]+?) + \[org\.gradle\.internal\.operations\.DefaultBuildOperationRunner] Build operation 'Task $taskName' completed + """.trimIndent() + .replace("\n", "") + .toRegex() + +/** + * Filter [BuildResult.getOutput] for specific task with given [taskPath] + * + * Requires using [LogLevel.DEBUG]. + */ +fun BuildResult.getOutputForTask(taskPath: String): String = getOutputForTask(taskPath, output) + +/** + * Filter give output for specific task with given [taskPath] + * + * Requires using [LogLevel.DEBUG]. + */ +fun getOutputForTask(taskPath: String, output: String): String = taskOutputRegex(taskPath) + .find(output) + ?.let { it.groupValues[1] } + ?: error("Could not find output for task $taskPath") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/tasksAssertions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/tasksAssertions.kt index e3360b84543..96e8a593863 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/tasksAssertions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/tasksAssertions.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.gradle.testbase +import org.gradle.api.logging.LogLevel import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.TaskOutcome @@ -122,3 +123,18 @@ fun BuildResult.assertTasksPackedToCache(vararg tasks: String) { assertOutputContains("Stored cache entry for task '$it' with cache key ") } } + +/** + * Asserts classpath of the given K/N compiler tool for given tasks' paths. + * + * Note: Log level of output must be set to [LogLevel.DEBUG]. + * + * @param tasksPaths names of the tasks, which classpath should be checked with give assertions + * @param toolName name of build tool + * @param assertions assertions, with will be applied to each classpath of each given task + */ +fun BuildResult.assertNativeTasksClasspath( + vararg tasksPaths: String, + toolName: NativeToolKind = NativeToolKind.KONANC, + assertions: (List) -> Unit +) = tasksPaths.forEach { taskPath -> assertions(extractNativeCompilerClasspath(getOutputForTask(taskPath), toolName)) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/executables/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/executables/build.gradle.kts index 90c0a4f3378..f26c5cac910 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/executables/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/executables/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.jetbrains.kotlin.multiplatform").version("") + id("org.jetbrains.kotlin.multiplatform") } repositories {