diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt index 8a91bff35b8..0be7879e3fc 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt @@ -4,6 +4,8 @@ */ package org.jetbrains.kotlin.gradle +import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.checkNativeCommandLineArguments +import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.containsSequentially import org.jetbrains.kotlin.gradle.native.MPPNativeTargets import org.jetbrains.kotlin.gradle.native.configureMemoryInGradleProperties import org.jetbrains.kotlin.gradle.native.transformNativeTestProject @@ -123,14 +125,6 @@ class NewMultiplatformIT : BaseGradleIT() { // we use `maven { setUrl(...) }` because this syntax actually works both for Groovy and Kotlin DSLs in Gradle gradleBuildScript().appendText("\nrepositories { maven { setUrl(\"$libLocalRepoUri\") } }") - fun CompiledProject.checkProgramCompilationCommandLine(check: (String) -> Unit) { - output.lineSequence().filter { - it.contains("Run tool: \"konanc\"") && it.contains("-p program") - }.toList().also { - assertTrue(it.isNotEmpty()) - }.forEach(check) - } - fun CompiledProject.checkAppBuild() { assertSuccessful() assertTasksExecuted(*compileTasksNames.toTypedArray()) @@ -159,8 +153,8 @@ class NewMultiplatformIT : BaseGradleIT() { assertFileExists("build/bin/linux64/mainDebugExecutable/$nativeExeName") // Check that linker options were correctly passed to the K/N compiler. - checkProgramCompilationCommandLine { - assertTrue(it.contains("-linker-option -L.")) + checkNativeCommandLineArguments(":linkMainDebugExecutableLinux64") { arguments -> + assertTrue(arguments.containsSequentially("-linker-option", "-L.")) } } @@ -712,7 +706,7 @@ class NewMultiplatformIT : BaseGradleIT() { assertTasksExecuted(":$it") assertContains( "-XXLanguage:+InlineClasses", - " -progressive", "-Xopt-in=kotlin.ExperimentalUnsignedTypes", + "-progressive", "-Xopt-in=kotlin.ExperimentalUnsignedTypes", "-Xopt-in=kotlin.contracts.ExperimentalContracts", "-Xno-inline" ) 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 f5e6a2feb19..9590845785e 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 @@ -25,6 +25,7 @@ import org.junit.Assume import org.junit.Ignore import org.junit.Test import java.io.File +import java.util.* import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -261,27 +262,27 @@ class GeneralNativeIT : BaseGradleIT() { fileInWorkingDir(headerPaths[0]).readText().contains("+ (int32_t)exported") // Check that by default release frameworks have bitcode embedded. - checkNativeCommandLineFor(":linkMainReleaseFrameworkIos") { - assertTrue(it.contains("-Xembed-bitcode")) - assertTrue(it.contains("-opt")) + checkNativeCommandLineArguments(":linkMainReleaseFrameworkIos") { arguments -> + assertTrue("-Xembed-bitcode" in arguments) + assertTrue("-opt" in arguments) } // Check that by default debug frameworks have bitcode marker embedded. - checkNativeCommandLineFor(":linkMainDebugFrameworkIos") { - assertTrue(it.contains("-Xembed-bitcode-marker")) - assertTrue(it.contains("-g")) + checkNativeCommandLineArguments(":linkMainDebugFrameworkIos") { arguments -> + assertTrue("-Xembed-bitcode-marker" in arguments) + assertTrue("-g" in arguments) } // Check that bitcode can be disabled by setting custom compiler options - checkNativeCommandLineFor(":linkCustomDebugFrameworkIos") { - assertTrue(it.contains("-linker-option -L.")) - assertTrue(it.contains("-Xtime")) - assertTrue(it.contains("-Xstatic-framework")) - assertFalse(it.contains("-Xembed-bitcode-marker")) - assertFalse(it.contains("-Xembed-bitcode")) + checkNativeCommandLineArguments(":linkCustomDebugFrameworkIos") { arguments -> + assertTrue(arguments.containsSequentially("-linker-option", "-L.")) + assertTrue("-Xtime" in arguments) + assertTrue("-Xstatic-framework" in arguments) + assertFalse("-Xembed-bitcode-marker" in arguments) + assertFalse("-Xembed-bitcode" in arguments) } // Check that bitcode is disabled for iOS simulator. - checkNativeCommandLineFor(":linkMainReleaseFrameworkIosSim", ":linkMainDebugFrameworkIosSim") { - assertFalse(it.contains("-Xembed-bitcode")) - assertFalse(it.contains("-Xembed-bitcode-marker")) + checkNativeCommandLineArguments(":linkMainReleaseFrameworkIosSim", ":linkMainDebugFrameworkIosSim") { arguments -> + assertFalse("-Xembed-bitcode" in arguments) + assertFalse("-Xembed-bitcode-marker" in arguments) } } @@ -302,10 +303,12 @@ class GeneralNativeIT : BaseGradleIT() { fun testExportApiOnlyToLibraries() { val project = transformNativeTestProjectWithPluginDsl("libraries", directoryPrefix = "native-binaries") - testExportApi(project, listOf( - ExportApiTestData("linkDebugSharedHost", "debugShared"), - ExportApiTestData("linkDebugStaticHost", "debugStatic"), - )) + testExportApi( + project, listOf( + ExportApiTestData("linkDebugSharedHost", "debugShared"), + ExportApiTestData("linkDebugStaticHost", "debugStatic"), + ) + ) } @Test @@ -313,9 +316,11 @@ class GeneralNativeIT : BaseGradleIT() { Assume.assumeTrue(HostManager.hostIsMac) val project = transformNativeTestProjectWithPluginDsl("frameworks", directoryPrefix = "native-binaries") - testExportApi(project, listOf( - ExportApiTestData("linkMainDebugFrameworkIos", "mainDebugFramework") - )) + testExportApi( + project, listOf( + ExportApiTestData("linkMainDebugFrameworkIos", "mainDebugFramework") + ) + ) } private data class ExportApiTestData(val taskName: String, val binaryName: String) @@ -337,16 +342,6 @@ class GeneralNativeIT : BaseGradleIT() { } } - private fun CompiledProject.checkNativeCommandLineFor(vararg taskPaths: String, check: (String) -> Unit) = - taskPaths.forEach { taskPath -> - val commandLine = output.lineSequence().dropWhile { - !it.contains("Executing actions for task '$taskPath'") - }.first { - it.contains("Run tool: \"konanc\"") - } - check(commandLine) - } - @Test fun testNativeExecutables() = with(transformNativeTestProjectWithPluginDsl("executables", directoryPrefix = "native-binaries")) { val binaries = mutableListOf( @@ -424,8 +419,8 @@ class GeneralNativeIT : BaseGradleIT() { ) { build(":compileKotlinHost") { assertSuccessful() - checkNativeCommandLineFor(":compileKotlinHost") { - assertFalse(it.contains("-verbose")) + checkNativeCommandLineArguments(":compileKotlinHost") { arguments -> + assertFalse("-verbose" in arguments) } } @@ -438,8 +433,8 @@ class GeneralNativeIT : BaseGradleIT() { ) build(":compileKotlinHost") { assertSuccessful() - checkNativeCommandLineFor(":compileKotlinHost") { - assertTrue(it.contains("-verbose")) + checkNativeCommandLineArguments(":compileKotlinHost") { arguments -> + assertTrue("-verbose" in arguments) } } } @@ -822,9 +817,47 @@ class GeneralNativeIT : BaseGradleIT() { build("compileKotlin${nativeHostTargetName.capitalize()}") { assertSuccessful() - checkNativeCommandLineFor(":compileKotlin${nativeHostTargetName.capitalize()}") { - it.contains(fileWithSpacesInPath.absolutePath) + checkNativeCommandLineArguments(":compileKotlin${nativeHostTargetName.capitalize()}") { arguments -> + val escapedQuotedPath = "\"${fileWithSpacesInPath.absolutePath.replace("\"", "\\\"")}\"" + assertTrue(escapedQuotedPath in arguments) } } } + + companion object { + fun List.containsSequentially(vararg elements: String): Boolean { + check(elements.isNotEmpty()) + return Collections.indexOfSubList(this, elements.toList()) != -1 + } + + fun CompiledProject.extractNativeCommandLineArguments(taskPath: String? = null, toolName: String): List { + val arguments = 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) + "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) + "Arguments = [" !in it + } + + val argumentsHeader = arguments.firstOrNull() + check(argumentsHeader != null && "Arguments = [" in argumentsHeader) + + return if (argumentsHeader.trimEnd().endsWith(']')) + emptyList() // no arguments + else + arguments.drop(1).map { it.trim() }.takeWhile { it != "]" }.toList() + } + + fun CompiledProject.checkNativeCommandLineArguments( + vararg taskPaths: String, + toolName: String = "konanc", + check: (List) -> Unit + ) = taskPaths.forEach { taskPath -> check(extractNativeCommandLineArguments(taskPath, toolName)) } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativePlatformLibsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativePlatformLibsIT.kt index f38f0a5cf15..764396af6a8 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativePlatformLibsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativePlatformLibsIT.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.gradle.native import org.jetbrains.kotlin.gradle.* 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.transformProjectWithPluginsDsl import org.jetbrains.kotlin.gradle.util.modify import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader @@ -17,6 +19,7 @@ import org.jetbrains.kotlin.konan.util.DependencyDirectories import org.junit.Assume import org.junit.BeforeClass import org.junit.Test +import kotlin.test.assertTrue class NativePlatformLibsIT : BaseGradleIT() { @@ -213,7 +216,7 @@ class NativePlatformLibsIT : BaseGradleIT() { // Check that user can change generation mode used by the cinterop tool. buildWithLightDist("tasks", "-Pkotlin.native.platform.libraries.mode=metadata") { assertSuccessful() - assertContainsRegex("Run tool: \"generatePlatformLibraries\" with args: .* -mode metadata".toRegex()) + assertTrue(extractNativeCommandLineArguments(toolName = "generatePlatformLibraries").containsSequentially("-mode", "metadata")) } }