Migrated CommonizerIT to new test dsl (junit 5 and gradle test kit)

This commit is contained in:
Dmitrii Krasnov
2023-06-13 16:00:59 +02:00
committed by Space Team
parent b22769919e
commit 0e51a00871
7 changed files with 424 additions and 408 deletions
@@ -1,71 +1,76 @@
/*
* 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
import groovy.json.StringEscapeUtils
import org.gradle.api.logging.LogLevel.INFO
import org.gradle.api.logging.LogLevel
import org.gradle.internal.os.OperatingSystem
import org.gradle.testkit.runner.BuildResult
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.replaceText
import org.jetbrains.kotlin.gradle.util.reportSourceSetCommonizerDependencies
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget.*
import kotlin.test.Test
import kotlin.test.assertFalse
import org.junit.jupiter.api.DisplayName
import kotlin.io.path.*
import kotlin.test.assertTrue
import kotlin.test.fail
open class CommonizerIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired = GradleVersionRequired.FOR_MPP_SUPPORT
@DisplayName("K/N tests for commonizer")
@NativeGradlePluginTests
open class CommonizerIT : KGPBaseTest() {
companion object {
private const val commonizerOutput = "Preparing commonized Kotlin/Native libraries"
}
@Test
fun `test commonizeNativeDistributionWithIosLinuxWindows`() {
with(Project("commonizeNativeDistributionWithIosLinuxWindows")) {
build(":cleanNativeDistributionCommonization") {
assertSuccessful()
}
@DisplayName("Commonize native distribution with Ios Linux and Windows")
@GradleTest
fun testCommonizeNativeDistributionWithIosLinuxWindows(gradleVersion: GradleVersion) {
nativeProject("commonizeNativeDistributionWithIosLinuxWindows", gradleVersion) {
build(":cleanNativeDistributionCommonization")
build("commonize", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false") {
assertTasksExecuted(":commonizeNativeDistribution")
assertContains(commonizerOutput)
assertSuccessful()
assertOutputContains(commonizerOutput)
}
build("commonize", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=true") {
assertTasksUpToDate(":commonizeNativeDistribution")
assertNativeDistributionCommonizationCacheHit()
assertContains("Native Distribution Commonization: All available targets are commonized already")
assertContains("Native Distribution Commonization: Lock acquired")
assertContains("Native Distribution Commonization: Lock released")
assertNotContains(commonizerOutput)
assertSuccessful()
assertOutputContains("Native Distribution Commonization: All available targets are commonized already")
assertOutputContains("Native Distribution Commonization: Lock acquired")
assertOutputContains("Native Distribution Commonization: Lock released")
assertOutputDoesNotContain(commonizerOutput)
}
build("commonize", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false") {
assertTasksExecuted(":commonizeNativeDistribution")
assertContains("Native Distribution Commonization: Cache disabled")
assertContains(commonizerOutput)
assertSuccessful()
assertOutputContains("Native Distribution Commonization: Cache disabled")
assertOutputContains(commonizerOutput)
}
}
}
@Test
fun `test commonizeCurlInterop UP-TO-DATE check`() {
with(preparedProject("commonizeCurlInterop")) {
@DisplayName("Commonize Curl Interop UP-TO-DATE check")
@GradleTest
fun testCommonizeCurlInteropUTDCheck(gradleVersion: GradleVersion) {
nativeProject("commonizeCurlInterop", gradleVersion) {
configureCommonizerTargets()
build(":commonize") {
assertTasksExecuted(":commonizeNativeDistribution")
assertTasksExecuted(":cinteropCurlTargetA")
assertTasksExecuted(":cinteropCurlTargetB")
assertTasksExecuted(":commonizeCInterop")
assertSuccessful()
}
build(":commonize") {
@@ -73,38 +78,37 @@ open class CommonizerIT : BaseGradleIT() {
assertTasksUpToDate(":cinteropCurlTargetA")
assertTasksUpToDate(":cinteropCurlTargetB")
assertTasksUpToDate(":commonizeCInterop")
assertSuccessful()
}
val buildGradleKts = projectFile("build.gradle.kts")
val originalBuildGradleKtsContent = buildGradleKts.readText()
buildGradleKts.writeText(originalBuildGradleKtsContent.replace("curl", "curl2"))
buildGradleKts.replaceText("curl", "curl2")
build(":commonize") {
assertNativeDistributionCommonizationCacheHit()
assertTasksExecuted(":cinteropCurl2TargetA")
assertTasksExecuted(":cinteropCurl2TargetB")
assertTasksExecuted(":commonizeCInterop")
assertSuccessful()
}
buildGradleKts.writeText(originalBuildGradleKtsContent.lineSequence().filter { "curl" !in it }.joinToString("\n"))
buildGradleKts.modify {
it.lineSequence().filter { "curl" !in it }.joinToString("\n")
}
build(":commonize") {
assertNativeDistributionCommonizationCacheHit()
assertTasksNotExecuted(":cinteropCurlTargetA")
assertTasksNotExecuted(":cinteropCurlTargetB")
assertSuccessful()
}
}
}
@Test
fun `test commonizeCurlInterop feature flag`() {
with(preparedProject("commonizeCurlInterop")) {
setupWorkingDir()
@DisplayName("Commonize Curl Interop feature flag")
@GradleTest
fun testCommonizeCurlInteropFeatureFlag(gradleVersion: GradleVersion) {
nativeProject("commonizeCurlInterop", gradleVersion) {
configureCommonizerTargets()
// Remove feature flag from gradle.properties
projectFile("gradle.properties").apply {
writeText(readText().lineSequence().filter { "enableCInteropCommonization" !in it }.joinToString("\n"))
gradleProperties.modify {
it.lineSequence().filter { "enableCInteropCommonization" !in it }.joinToString("\n")
}
build(":commonize") {
@@ -112,7 +116,6 @@ open class CommonizerIT : BaseGradleIT() {
assertTasksNotExecuted(":cinteropCurl2TargetA")
assertTasksNotExecuted(":cinteropCurl2TargetB")
assertTasksNotExecuted(":commonizeCInterop")
assertSuccessful()
}
build(":commonize", "-Pkotlin.mpp.enableCInteropCommonization=true") {
@@ -120,7 +123,6 @@ open class CommonizerIT : BaseGradleIT() {
assertTasksExecuted(":cinteropCurlTargetA")
assertTasksExecuted(":cinteropCurlTargetB")
assertTasksExecuted(":commonizeCInterop")
assertSuccessful()
}
build(":commonize", "-Pkotlin.mpp.enableCInteropCommonization=false") {
@@ -128,64 +130,67 @@ open class CommonizerIT : BaseGradleIT() {
assertTasksNotExecuted(":cinteropCurlTargetA")
assertTasksNotExecuted(":cinteropCurlTargetB")
assertTasksNotExecuted(":commonizeCInterop")
assertSuccessful()
}
}
}
@Test
fun `test commonizeCurlInterop copyCommonizeCInteropForIde`() {
with(preparedProject("commonizeCurlInterop")) {
setupWorkingDir()
val expectedOutputDirectoryForIde = projectDir.resolve(".gradle/kotlin/commonizer")
val expectedOutputDirectoryForBuild = projectDir.resolve("build/classes/kotlin/commonizer")
@DisplayName("Commonize Curl Interop copy CommonizeCInterop for Ide")
@GradleTest
fun testCommonizeCurlInteropcopyCommonizeCInteropForIde(gradleVersion: GradleVersion) {
nativeProject("commonizeCurlInterop", gradleVersion) {
configureCommonizerTargets()
val expectedOutputDirectoryForIde = projectPath.resolve(".gradle/kotlin/commonizer")
val expectedOutputDirectoryForBuild = projectPath.resolve("build/classes/kotlin/commonizer")
build(":copyCommonizeCInteropForIde") {
assertSuccessful()
assertTasksExecuted(":cinteropCurlTargetA")
assertTasksExecuted(":cinteropCurlTargetB")
assertTasksExecuted(":commonizeCInterop")
assertTrue(expectedOutputDirectoryForIde.isDirectory, "Missing output directory for IDE")
assertTrue(expectedOutputDirectoryForBuild.isDirectory, "Missing output directory for build")
assertEqualDirectories(expectedOutputDirectoryForBuild, expectedOutputDirectoryForIde, false)
assertDirectoryExists(expectedOutputDirectoryForIde, "Missing output directory for IDE")
assertDirectoryExists(expectedOutputDirectoryForBuild, "Missing output directory for build")
assertEqualDirectories(expectedOutputDirectoryForBuild.toFile(), expectedOutputDirectoryForIde.toFile(), false)
}
build(":clean") {
assertSuccessful()
assertTrue(expectedOutputDirectoryForIde.isDirectory, "Expected ide output directory to survive cleaning")
assertFalse(expectedOutputDirectoryForBuild.exists(), "Expected output directory for build to be cleaned")
assertDirectoryExists(expectedOutputDirectoryForIde, "Expected ide output directory to survive cleaning")
assertFileNotExists(expectedOutputDirectoryForBuild, "Expected output directory for build to be cleaned")
}
}
}
@Test
fun `test commonizeCurlInterop compilation`() {
with(preparedProject("commonizeCurlInterop")) {
@DisplayName("Commonize Curl Interop compilation")
@GradleTest
fun testCommonizeCurlInteropCopyCompilation(gradleVersion: GradleVersion) {
nativeProject("commonizeCurlInterop", gradleVersion) {
configureCommonizerTargets()
build(":compileNativeMainKotlinMetadata") {
assertTasksExecuted(":commonizeNativeDistribution")
assertTasksExecuted(":cinteropCurlTargetA")
assertTasksExecuted(":cinteropCurlTargetB")
assertTasksExecuted(":commonizeCInterop")
assertSuccessful()
}
// targetA will be macos
build(":compileTestKotlinTargetA") {
assertSuccessful()
}
build(":compileTestKotlinTargetA")
//targetB will be linuxArm64
build(":compileTestKotlinTargetB") {
assertSuccessful()
}
build(":compileTestKotlinTargetB")
}
}
@Test
fun `test commonizeSQLiteInterop`() {
with(preparedProject("commonizeSQLiteInterop")) {
@DisplayName("Commonize SQL Lite Interop")
@GradleTest
fun testCommonizeSQLiteInterop(gradleVersion: GradleVersion) {
nativeProject("commonizeSQLiteInterop", gradleVersion) {
configureCommonizerTargets()
build(":commonize") {
assertSuccessful()
assertTasksExecuted(":cinteropSqliteTargetA")
assertTasksExecuted(":cinteropSqliteTargetB")
assertTasksExecuted(":commonizeCInterop")
@@ -193,11 +198,14 @@ open class CommonizerIT : BaseGradleIT() {
}
}
@Test
fun `test commonizeSQLiteAndCurlInterop`() {
with(preparedProject("commonizeSQLiteAndCurlInterop")) {
@DisplayName("Commonize SQL Lite and Curl Interop")
@GradleTest
fun testCommonizeSQLiteAndCurlInterop(gradleVersion: GradleVersion) {
nativeProject("commonizeSQLiteAndCurlInterop", gradleVersion) {
configureCommonizerTargets()
build(":commonize") {
assertSuccessful()
assertTasksExecuted(":cinteropSqliteTargetA")
assertTasksExecuted(":cinteropSqliteTargetB")
assertTasksExecuted(":cinteropCurlTargetA")
@@ -206,7 +214,6 @@ open class CommonizerIT : BaseGradleIT() {
}
build(":compileNativeMainKotlinMetadata") {
assertSuccessful()
assertTasksUpToDate(":cinteropSqliteTargetA")
assertTasksUpToDate(":cinteropSqliteTargetB")
assertTasksUpToDate(":cinteropCurlTargetA")
@@ -216,11 +223,14 @@ open class CommonizerIT : BaseGradleIT() {
}
}
@Test
fun `test commonizeInterop using posix APIs`() {
with(preparedProject("commonizeInteropUsingPosixApis")) {
@DisplayName("Commonize Interop using posix APIs")
@GradleTest
fun testCommonizeInteropUsingPosixAPIs(gradleVersion: GradleVersion) {
nativeProject("commonizeInteropUsingPosixApis", gradleVersion) {
configureCommonizerTargets()
build(":commonizeCInterop") {
assertSuccessful()
assertTasksExecuted(":cinteropWithPosixTargetA")
assertTasksExecuted(":cinteropWithPosixTargetB")
assertTasksExecuted(":commonizeNativeDistribution")
@@ -228,7 +238,6 @@ open class CommonizerIT : BaseGradleIT() {
}
build(":compileNativeMainKotlinMetadata") {
assertSuccessful()
assertTasksUpToDate(":cinteropWithPosixTargetA")
assertTasksUpToDate(":cinteropWithPosixTargetB")
assertNativeDistributionCommonizationCacheHit()
@@ -237,184 +246,277 @@ open class CommonizerIT : BaseGradleIT() {
}
}
@Test
fun `test KT-46234 intermediate source set with only one native target`() {
`test single native platform`("commonize-kt-46234-singleNativeTarget")
@DisplayName("KT-46234 intermediate source set with only one native target")
@GradleTest
fun testIntermediateSourceSetWithOnlyOneNativeTarget(gradleVersion: GradleVersion) {
testSingleNativePlatform("commonize-kt-46234-singleNativeTarget", gradleVersion)
}
@Test
fun `test KT-46142 standalone native source set`() {
`test single native platform`("commonize-kt-46142-singleNativeTarget")
@DisplayName("KT-46142 standalone native source set")
@GradleTest
fun testStandaloneNativeSourceSet(gradleVersion: GradleVersion) {
testSingleNativePlatform("commonize-kt-46142-singleNativeTarget", gradleVersion)
}
private fun `test single native platform`(project: String) {
val posixInIntransitiveMetadataConfigurationRegex = Regex(""".*intransitiveMetadataConfiguration:.*([pP])osix""")
fun CompiledProject.containsPosixInIntransitiveMetadataConfiguration(): Boolean =
output.lineSequence().any { line ->
line.matches(posixInIntransitiveMetadataConfigurationRegex)
}
with(Project(project)) {
build(":p1:listNativePlatformMainDependencies", "-Pkotlin.mpp.enableIntransitiveMetadataConfiguration=false") {
assertSuccessful()
assertFalse(
containsPosixInIntransitiveMetadataConfiguration(),
"Expected **no** dependency on posix in intransitiveMetadataConfiguration"
)
}
build(":p1:listNativePlatformMainDependencies", "-Pkotlin.mpp.enableIntransitiveMetadataConfiguration=true") {
assertSuccessful()
assertTrue(
containsPosixInIntransitiveMetadataConfiguration(),
"Expected dependency on posix in intransitiveMetadataConfiguration"
)
}
build("assemble") {
assertSuccessful()
}
}
}
@Test
fun `test KT-46248 single supported native target dependency propagation`() {
fun CompiledProject.containsPosixDependency(): Boolean = output.lineSequence().any { line ->
line.matches(Regex(""".*Dependency:.*[pP]osix"""))
}
fun CompiledProject.containsDummyCInteropDependency(): Boolean = output.lineSequence().any { line ->
line.matches(Regex(""".*Dependency:.*cinterop-dummy.*"""))
}
with(Project("commonize-kt-46248-singleNativeTargetPropagation")) {
@DisplayName("KT-46248 single supported native target dependency propagation")
@GradleTest
fun testSingleSupportedNativeTargetDependencyPropagation(gradleVersion: GradleVersion) {
val posixDependencyRegex = Regex(""".*Dependency:.*[pP]osix""")
val dummyCInteropDependencyRegex = Regex(""".*Dependency:.*cinterop-dummy.*""")
nativeProject("commonize-kt-46248-singleNativeTargetPropagation", gradleVersion) {
build(":p1:listNativeMainDependencies") {
assertSuccessful()
assertTrue(containsPosixDependency(), "Expected dependency on posix in nativeMain")
assertTrue(containsDummyCInteropDependency(), "Expected dependency on dummy cinterop in nativeMain")
assertOutputContains(posixDependencyRegex)
assertOutputContains(dummyCInteropDependencyRegex)
}
build(":p1:listNativeMainParentDependencies") {
assertSuccessful()
assertTrue(containsPosixDependency(), "Expected dependency on posix in nativeMainParent")
assertTrue(containsDummyCInteropDependency(), "Expected dependency on dummy cinterop in nativeMain")
assertOutputContains(posixDependencyRegex)
assertOutputContains(dummyCInteropDependencyRegex)
}
build(":p1:listCommonMainDependencies") {
assertSuccessful()
assertFalse(containsPosixDependency(), "Expected **no** dependency on posix in commonMain (because of jvm target)")
assertFalse(containsDummyCInteropDependency(), "Expected **no** dependency on dummy cinterop in nativeMain")
assertOutputDoesNotContain(posixDependencyRegex)
assertOutputDoesNotContain(dummyCInteropDependencyRegex)
}
build("assemble") {
assertSuccessful()
assertTasksExecuted(":p1:compileCommonMainKotlinMetadata")
assertTasksExecuted(":p1:compileKotlinNativePlatform")
}
}
}
@Test
fun `test KT-46248 single supported native target dependency propagation - cinterop`() {
fun CompiledProject.containsCinteropDependency(): Boolean {
val nativeMainContainsCInteropDependencyRegex = Regex(""".*Dependency:.*cinterop-dummy.*""")
return output.lineSequence().any { line ->
line.matches(nativeMainContainsCInteropDependencyRegex)
}
}
with(Project("commonize-kt-47523-singleNativeTargetPropagation-cinterop")) {
@DisplayName("KT-46248 single supported native target dependency propagation - cinterop")
@GradleTest
fun testSingleSupportedNativeTargetDependencyPropagationCInterop(gradleVersion: GradleVersion) {
val nativeMainContainsCInteropDependencyRegex = Regex(""".*Dependency:.*cinterop-dummy.*""")
nativeProject("commonize-kt-47523-singleNativeTargetPropagation-cinterop", gradleVersion) {
build("listNativePlatformMainDependencies") {
assertSuccessful()
assertFalse(
containsCinteropDependency(),
"Expected sourceSet 'nativeMain' to list cinterop dependency (not necessary, since included in compilation)"
)
assertOutputDoesNotContain(nativeMainContainsCInteropDependencyRegex)
}
build("listNativeMainDependencies") {
assertSuccessful()
assertTrue(containsCinteropDependency(), "Expected sourceSet 'nativeMain' to list cinterop dependency")
assertOutputContains(nativeMainContainsCInteropDependencyRegex)
}
build("listCommonMainDependencies") {
assertSuccessful()
assertTrue(containsCinteropDependency(), "Expected sourceSet 'commonMain' to list cinterop dependency")
assertOutputContains(nativeMainContainsCInteropDependencyRegex)
}
build("assemble") {
assertSuccessful()
}
build("assemble")
}
}
@Test
fun `test KT-48856 single native target dependency propagation - test source set - cinterop`() {
fun CompiledProject.containsCinteropDependency(): Boolean {
val nativeMainContainsCInteropDependencyRegex = Regex(""".*Dependency:.*cinterop-sampleInterop.*""")
return output.lineSequence().any { line ->
line.matches(nativeMainContainsCInteropDependencyRegex)
}
}
with(Project("commonize-kt-48856-singleNativeTargetPropagation-testSourceSet")) {
@DisplayName("KT-48856 single native target dependency propagation - test source set - cinterop")
@GradleTest
fun testSingleSupportedNativeTargetDependencyPropagationTestSourceSetCInterop(gradleVersion: GradleVersion) {
val nativeMainContainsCInteropDependencyRegex = Regex(""".*Dependency:.*cinterop-sampleInterop.*""")
nativeProject("commonize-kt-48856-singleNativeTargetPropagation-testSourceSet", gradleVersion) {
build("listNativeTestDependencies") {
assertSuccessful()
assertTrue(containsCinteropDependency(), "Expected sourceSet 'nativeTest' to list cinterop dependency")
assertOutputContains(
nativeMainContainsCInteropDependencyRegex,
"Expected sourceSet 'nativeTest' to list cinterop dependency"
)
}
build("assemble") {
assertSuccessful()
}
build("assemble")
}
}
@Test
fun `test KT-46856 filename too long - all native targets configured`() {
with(Project("commonize-kt-46856-all-targets")) {
build(":commonize", options = BuildOptions(forceOutputToStdout = true)) {
assertSuccessful()
}
@DisplayName("KT-46856 filename too long - all native targets configured")
@GradleTest
fun testFilenameTooLongAllNativeTargetsConfigured(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-46856-all-targets", gradleVersion) {
build(":commonize")
}
}
@Test
fun `test multiple cinterops with test source sets and compilations - test source sets depending on main`() {
`test multiple cinterops with test source sets and compilations`(true)
@DisplayName("Multiple cinterops with test source sets and compilations - test source sets depending on main")
@GradleTest
fun testMultipleCinteropsWithTestSourceSetsAndCompilationsTestSourceSetsDependingOnMain(gradleVersion: GradleVersion) {
`test multiple cinterops with test source sets and compilations`(gradleVersion, true)
}
@Test
fun `test multiple cinterops with test source sets and compilations`() {
`test multiple cinterops with test source sets and compilations`(false)
@DisplayName("Multiple cinterops with test source sets and compilations")
@GradleTest
fun testMultipleCinteropsWithTestSourceSetsAndCompilations(gradleVersion: GradleVersion) {
`test multiple cinterops with test source sets and compilations`(gradleVersion, false)
}
@Test
fun `test KT-49735 two kotlin targets with same konanTarget`() {
with(Project("commonize-kt-49735-twoKotlinTargets-oneKonanTarget")) {
@DisplayName("KT-49735 two kotlin targets with same konanTarget")
@GradleTest
fun testTwoKotlinTargetsWithSameKonanTarget(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-49735-twoKotlinTargets-oneKonanTarget", gradleVersion) {
build(":assemble") {
assertTasksExecuted(":compileCommonMainKotlinMetadata")
assertSuccessful()
}
}
}
private fun `test multiple cinterops with test source sets and compilations`(testSourceSetsDependingOnMain: Boolean) {
with(Project("commonizeMultipleCInteropsWithTests", minLogLevel = INFO)) {
@DisplayName("KT-48118 c-interops available in commonMain")
@GradleTest
fun testCInteropsAvailableInCommonMain(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-48118-c-interop-in-common-main", gradleVersion) {
reportSourceSetCommonizerDependencies {
val upperMain = getCommonizerDependencies("upperMain")
upperMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
upperMain.onlyNativeDistributionDependencies().assertNotEmpty()
val commonMain = getCommonizerDependencies("commonMain")
commonMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
commonMain.onlyNativeDistributionDependencies().assertNotEmpty()
}
build(":compileCommonMainKotlinMetadata")
build(":compileUpperMainKotlinMetadata")
}
}
@DisplayName("KT-47641 commonizing c-interops does not depend on any source compilation")
@GradleTest
fun testCInteropsDoesNotDependOnAnySourceCompilation(gradleVersion: GradleVersion) {
nativeProject(
"commonize-kt-47641-cinterops-compilation-dependency",
gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) {
build("commonizeCInterop") {
assertTasksExecuted(":p1:commonizeCInterop")
assertTasksExecuted(":p2:commonizeCInterop")
assertAnyTaskHasBeenExecuted(findTasksByPattern(":p1:cinteropTestWithPosix.*".toRegex()))
assertAnyTaskHasBeenExecuted(findTasksByPattern(":p2:cinteropTestWithPosix.*".toRegex()))
assertAnyTaskHasBeenExecuted(findTasksByPattern(":p2:cinteropTestWithPosixP2.*".toRegex()))
/* Make sure that we correctly reference any compile tasks in this test (test is useless otherwise) */
assertOutputContains("Register task :p1.*compile.*".toRegex())
assertOutputContains("Register task :p2.*compile.*".toRegex())
/* CInterops *shall not* require any compilation */
assertOutputDoesNotContain("(Executing actions for task|Executing task) ':p0.*compile.*'".toRegex())
assertOutputDoesNotContain("(Executing actions for task|Executing task) ':p1.*compile.*'".toRegex())
assertOutputDoesNotContain("(Executing actions for task|Executing task) ':p2.*compile.*'".toRegex())
}
}
}
@DisplayName("KT-48138 commonizing c-interops when nativeTest and nativeMain have different targets")
@GradleTest
fun testCommonizingCInteropsWhenNativeTestAndNativeMainHaveDifferentTargets(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-48138-nativeMain-nativeTest-different-targets", gradleVersion) {
reportSourceSetCommonizerDependencies {
val nativeMain = getCommonizerDependencies("nativeMain")
nativeMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
nativeMain.onlyNativeDistributionDependencies().assertNotEmpty()
nativeMain.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64, MINGW_X64))
val nativeTest = getCommonizerDependencies("nativeTest")
nativeTest.onlyNativeDistributionDependencies().assertNotEmpty()
nativeTest.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
nativeTest.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64))
}
}
}
@DisplayName("KT-50847 missing cinterop in supported target")
@GradleTest
fun testMissingCinteropInSupportedTarget(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-50847-cinterop-missing-in-supported-target", gradleVersion) {
build(":compileCommonMainKotlinMetadata", "-PdisableTargetNumber=1") {
assertTasksSkipped(":cinteropSimpleTarget1")
assertTasksExecuted(":cinteropSimpleTarget2")
assertTasksExecuted(":commonizeCInterop")
}
build(":compileCommonMainKotlinMetadata", "-PdisableTargetNumber=2") {
assertTasksSkipped(":cinteropSimpleTarget2")
assertTasksExecuted(":cinteropSimpleTarget1")
assertTasksExecuted(":commonizeCInterop")
}
}
}
@DisplayName("KT-52243 cinterop caching")
@GradleTest
fun testCInteropCaching(gradleVersion: GradleVersion) {
nativeProject("commonizeCurlInterop", gradleVersion) {
configureCommonizerTargets()
val localBuildCacheDir = projectPath.resolve("local-build-cache-dir").also { assertTrue(it.toFile().mkdirs()) }
enableLocalBuildCache(localBuildCacheDir)
build(":commonize", buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)) {
assertTasksExecuted(":cinteropCurlTargetA", ":cinteropCurlTargetB")
}
build(":clean") {}
build(":commonize", buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)) {
assertTasksFromCache(":cinteropCurlTargetA", ":cinteropCurlTargetB")
}
}
}
@DisplayName("KT-51517 commonization with transitive cinterop")
@GradleTest
fun testCommonizationWithTransitiveCinterop(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-51517-transitive-cinterop", gradleVersion) {
build(":app:assemble") {
assertTasksExecuted(":lib:transformCommonMainCInteropDependenciesMetadata")
assertTasksExecuted(":lib:commonizeCInterop")
assertTasksExecuted(":lib:compileCommonMainKotlinMetadata")
assertTasksExecuted(":app:commonizeCInterop")
assertTasksExecuted(":app:compileNativeMainKotlinMetadata")
}
}
}
@DisplayName("KT-57796 commonization with two cinterop commonizer groups`")
@GradleTest
fun testCommonizationWithTwoCInteropCommonizerGroups(gradleVersion: GradleVersion) {
nativeProject("commonize-kt-57796-twoCInteropCommonizerGroups", gradleVersion) {
build(":app:commonizeCIntero") {
assertTasksExecuted(":lib:transformCommonMainCInteropDependenciesMetadata")
assertTasksExecuted(":lib:commonizeCInterop")
assertTasksExecuted(":app:transformCommonMainCInteropDependenciesMetadata")
assertTasksExecuted(":app:commonizeCInterop")
}
}
}
@DisplayName("KT-57796 commonization with two cinterop commonizer groups`")
@GradleTest
fun testCommonizationWithLibraryContainingTwoRoots(gradleVersion: GradleVersion) {
project("commonize-kt-56729-consume-library-with-two-roots", gradleVersion) {
build("publish")
build(":consumer:assemble") {
assertTasksExecuted(":consumer:compileCommonMainKotlinMetadata")
assertOutputDoesNotContain("Duplicated libraries:")
assertOutputDoesNotContain("w: duplicate library name")
}
}
}
private fun `test multiple cinterops with test source sets and compilations`(
gradleVersion: GradleVersion,
testSourceSetsDependingOnMain: Boolean,
) {
nativeProject("commonizeMultipleCInteropsWithTests", gradleVersion) {
val isMac = HostManager.hostIsMac
fun CompiledProject.assertTestSourceSetsDependingOnMainParameter() {
fun BuildResult.assertTestSourceSetsDependingOnMainParameter() {
val message = "testSourceSetsDependingOnMain is set"
if (testSourceSetsDependingOnMain) assertContains(message) else assertNotContains(message)
if (testSourceSetsDependingOnMain) assertOutputContains(message) else assertOutputDoesNotContain(message)
}
val testSourceSetsDependingOnMainParameterOption = defaultBuildOptions()
.withFreeCommandLineArgument("-PtestSourceSetsDependingOnMain=$testSourceSetsDependingOnMain")
val testSourceSetsDependingOnMainParameterOption = defaultBuildOptions.copy(
freeArgs = listOf("-PtestSourceSetsDependingOnMain=$testSourceSetsDependingOnMain")
)
reportSourceSetCommonizerDependencies(this, options = testSourceSetsDependingOnMainParameterOption) {
reportSourceSetCommonizerDependencies(options = testSourceSetsDependingOnMainParameterOption) {
it.assertTestSourceSetsDependingOnMainParameter()
/* this source sets are also shared with a jvm target */
@@ -495,208 +597,62 @@ open class CommonizerIT : BaseGradleIT() {
getCommonizerDependencies("windowsX64Test").assertEmpty()
}
build(":assemble", options = testSourceSetsDependingOnMainParameterOption) {
build(":assemble", buildOptions = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
assertTasksUpToDate(":commonizeNativeDistribution")
assertContains("Native Distribution Commonization: Cache hit")
assertOutputContains("Native Distribution Commonization: Cache hit")
assertTasksUpToDate(":commonizeCInterop")
}
build(":compileNativeMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
build(":compileNativeMainKotlinMetadata", buildOptions = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
build(":compileUnixMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
build(":compileUnixMainKotlinMetadata", buildOptions = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
build(":compileLinuxMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
build(":compileLinuxMainKotlinMetadata", buildOptions = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
if (isMac) {
build(":compileAppleMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
build(":compileAppleMainKotlinMetadata", buildOptions = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
build(":compileIosMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
build(":compileIosMainKotlinMetadata", buildOptions = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
}
}
}
@Test
fun `test KT-48118 c-interops available in commonMain`() {
with(Project("commonize-kt-48118-c-interop-in-common-main")) {
reportSourceSetCommonizerDependencies(this) {
val upperMain = getCommonizerDependencies("upperMain")
upperMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
upperMain.onlyNativeDistributionDependencies().assertNotEmpty()
private fun testSingleNativePlatform(projectName: String, gradleVersion: GradleVersion) {
val commonMain = getCommonizerDependencies("commonMain")
commonMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
commonMain.onlyNativeDistributionDependencies().assertNotEmpty()
val posixInIntransitiveMetadataConfigurationRegex = Regex(""".*intransitiveMetadataConfiguration:.*([pP])osix""")
nativeProject(projectName, gradleVersion) {
build(":p1:listNativePlatformMainDependencies", "-Pkotlin.mpp.enableIntransitiveMetadataConfiguration=false") {
assertOutputDoesNotContain(posixInIntransitiveMetadataConfigurationRegex)
}
build(":compileCommonMainKotlinMetadata") {
assertSuccessful()
build(":p1:listNativePlatformMainDependencies", "-Pkotlin.mpp.enableIntransitiveMetadataConfiguration=true") {
assertOutputContains(posixInIntransitiveMetadataConfigurationRegex)
}
build(":compileUpperMainKotlinMetadata") {
assertSuccessful()
}
build("assemble")
}
}
@Test
fun `test KT-47641 commonizing c-interops does not depend on any source compilation`() {
with(Project("commonize-kt-47641-cinterops-compilation-dependency")) {
build("commonizeCInterop", options = BuildOptions(forceOutputToStdout = true)) {
assertTasksExecuted(":p1:commonizeCInterop")
assertTasksExecuted(":p2:commonizeCInterop")
assertTasksExecuted(":p1:cinteropTestWithPosix.*")
assertTasksExecuted(":p2:cinteropTestWithPosix.*")
assertTasksExecuted(":p2:cinteropTestWithPosixP2.*")
/* Make sure that we correctly reference any compile tasks in this test (test is useless otherwise) */
assertTasksRegisteredRegex(":p1.*compile.*")
assertTasksRegisteredRegex(":p2.*compile.*")
/* CInterops *shall not* require any compilation */
assertTasksNotExecuted(":p0.*compile.*")
assertTasksNotExecuted(":p1.*compile.*")
assertTasksNotExecuted(":p2.*compile.*")
}
}
private fun TestProject.configureCommonizerTargets() {
buildGradleKts.replaceText("<targetA>", CommonizableTargets.targetA.value)
buildGradleKts.replaceText("<targetB>", CommonizableTargets.targetB.value)
}
@Test
fun `test KT-48138 commonizing c-interops when nativeTest and nativeMain have different targets`() {
with(Project("commonize-kt-48138-nativeMain-nativeTest-different-targets")) {
reportSourceSetCommonizerDependencies(this) {
val nativeMain = getCommonizerDependencies("nativeMain")
nativeMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
nativeMain.onlyNativeDistributionDependencies().assertNotEmpty()
nativeMain.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64, MINGW_X64))
val nativeTest = getCommonizerDependencies("nativeTest")
nativeTest.onlyNativeDistributionDependencies().assertNotEmpty()
nativeTest.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
nativeTest.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64))
}
}
}
@Test
fun `test KT-50847 missing cinterop in supported target`() {
with(Project("commonize-kt-50847-cinterop-missing-in-supported-target")) {
build(":compileCommonMainKotlinMetadata", "-PdisableTargetNumber=1") {
assertSuccessful()
assertTasksSkipped(":cinteropSimpleTarget1")
assertTasksExecuted(":cinteropSimpleTarget2")
assertTasksExecuted(":commonizeCInterop")
}
build(":compileCommonMainKotlinMetadata", "-PdisableTargetNumber=2") {
assertSuccessful()
assertTasksSkipped(":cinteropSimpleTarget2")
assertTasksExecuted(":cinteropSimpleTarget1")
assertTasksExecuted(":commonizeCInterop")
}
}
}
@Test
fun `test KT-52243 cinterop caching`() {
with(preparedProject("commonizeCurlInterop")) {
val localBuildCacheDir = projectDir.resolve("local-build-cache-dir").also { assertTrue(it.mkdirs()) }
gradleSettingsScript().appendText(
"""
buildCache {
local {
directory = "${StringEscapeUtils.escapeJava(localBuildCacheDir.absolutePath)}"
}
}
""".trimIndent()
)
build(":commonize", options = defaultBuildOptions().copy(withBuildCache = true)) {
assertTasksExecuted(":cinteropCurlTargetA", ":cinteropCurlTargetB")
}
build(":clean") {}
build(":commonize", options = defaultBuildOptions().copy(withBuildCache = true)) {
assertTasksRetrievedFromCache(":cinteropCurlTargetA", ":cinteropCurlTargetB")
}
}
}
@Test
fun `test KT-51517 commonization with transitive cinterop`() {
with(Project("commonize-kt-51517-transitive-cinterop")) {
build(":app:assemble") {
assertSuccessful()
assertTasksExecuted(":lib:transformCommonMainCInteropDependenciesMetadata")
assertTasksExecuted(":lib:commonizeCInterop")
assertTasksExecuted(":lib:compileCommonMainKotlinMetadata")
assertTasksExecuted(":app:commonizeCInterop")
assertTasksExecuted(":app:compileNativeMainKotlinMetadata")
}
}
}
@Test
fun `test KT-57796 commonization with two cinterop commonizer groups`() {
with(Project("commonize-kt-57796-twoCInteropCommonizerGroups")) {
build(":app:commonizeCIntero") {
assertSuccessful()
assertTasksExecuted(":lib:transformCommonMainCInteropDependenciesMetadata")
assertTasksExecuted(":lib:commonizeCInterop")
assertTasksExecuted(":app:transformCommonMainCInteropDependenciesMetadata")
assertTasksExecuted(":app:commonizeCInterop")
}
}
}
@Test
fun `test KT-56729 commonization with library containing two roots`() {
with(Project("commonize-kt-56729-consume-library-with-two-roots")) {
build("publish") {
assertSuccessful()
}
build(":consumer:assemble") {
assertSuccessful()
assertTasksExecuted(":consumer:compileCommonMainKotlinMetadata")
assertNotContains("Duplicated libraries:")
assertNotContains("w: duplicate library name")
}
}
}
private fun preparedProject(name: String): Project {
return Project(name).apply {
setupWorkingDir()
projectDir.walkTopDown().filter { it.name.startsWith("build.gradle") }.forEach { buildFile ->
val originalText = buildFile.readText()
val preparedText = originalText
.replace("<targetA>", CommonizableTargets.targetA.value)
.replace("<targetB>", CommonizableTargets.targetB.value)
buildFile.writeText(preparedText)
}
}
}
private fun CompiledProject.assertNativeDistributionCommonizationCacheHit() {
assertContains("Native Distribution Commonization: Cache hit")
private fun BuildResult.assertNativeDistributionCommonizationCacheHit() {
assertOutputContains("Native Distribution Commonization: Cache hit")
}
}
@@ -28,9 +28,9 @@ class K2NewMultiplatformIT : NewMultiplatformIT() {
override fun defaultBuildOptions(): BuildOptions = super.defaultBuildOptions().copy(languageVersion = "2.0")
}
@Ignore
@Disabled("Used for local testing only")
class K2CommonizerIT : CommonizerIT() {
override fun defaultBuildOptions(): BuildOptions = super.defaultBuildOptions().copy(languageVersion = "2.0")
override val defaultBuildOptions: BuildOptions get() = super.defaultBuildOptions.copy(languageVersion = "2.0")
}
@Ignore
@@ -89,7 +89,13 @@ class CustomK2Tests : KGPBaseTest() {
@GradleTest
@DisplayName("Compiling shared native source with FirFakeOverrideGenerator referencing a common entity. KT-58145")
fun kt581450MppNativeSharedCrash(gradleVersion: GradleVersion) {
with(project("kt-581450-mpp-native-shared-crash", gradleVersion, buildOptions = defaultBuildOptions.copy(languageVersion = "2.0"))) {
with(
project(
"kt-581450-mpp-native-shared-crash",
gradleVersion,
buildOptions = defaultBuildOptions.copy(languageVersion = "2.0")
)
) {
val taskToExecute = ":compileNativeMainKotlinMetadata"
build(taskToExecute) {
assertTasksExecuted(taskToExecute)
@@ -21,7 +21,7 @@ import kotlin.test.asserter
* Asserts file under [file] path exists and is a regular file.
*/
fun assertFileExists(
file: Path
file: Path,
) {
assert(Files.exists(file)) {
"File '${file}' does not exist!"
@@ -36,14 +36,14 @@ fun assertFileExists(
* Asserts file under [pathToFile] relative to the test project exists and is a regular file.
*/
fun GradleProject.assertFileInProjectExists(
pathToFile: String
pathToFile: String,
) {
assertFileExists(projectPath.resolve(pathToFile))
}
fun assertFileExistsInTree(
pathToTreeRoot: Path,
fileName: String
fileName: String,
) {
val foundFile = pathToTreeRoot
.toFile()
@@ -61,22 +61,23 @@ fun assertFileExistsInTree(
* Asserts file under [pathToFile] relative to the test project does not exist.
*/
fun GradleProject.assertFileInProjectNotExists(
pathToFile: String
pathToFile: String,
) {
assertFileNotExists(projectPath.resolve(pathToFile))
}
fun assertFileNotExists(
pathToFile: Path
pathToFile: Path,
message: String = "File '${pathToFile}' exists!"
) {
assert(!Files.exists(pathToFile)) {
"File '${pathToFile}' exists!"
message
}
}
fun assertFileNotExistsInTree(
pathToTreeRoot: Path,
fileName: String
fileName: String,
) {
val foundFile = pathToTreeRoot
.toFile()
@@ -92,7 +93,7 @@ fun assertFileNotExistsInTree(
fun GradleProject.assertFileNotExistsInTree(
pathToTreeRoot: String,
fileName: String
fileName: String,
) {
assertFileNotExistsInTree(projectPath.resolve(pathToTreeRoot), fileName)
}
@@ -101,7 +102,7 @@ fun GradleProject.assertFileNotExistsInTree(
* Asserts symlink under [path] exists and is a symlink
*/
fun assertSymlinkExists(
path: Path
path: Path,
) {
assert(Files.exists(path)) {
"Symlink '${path}' does not exist!"
@@ -116,7 +117,7 @@ fun assertSymlinkExists(
* Asserts symlink under [pathToFile] relative to the test project exists and is a symlink.
*/
fun TestProject.assertSymlinkInProjectExists(
pathToFile: String
pathToFile: String,
) {
assertSymlinkExists(projectPath.resolve(pathToFile))
}
@@ -125,24 +126,26 @@ fun TestProject.assertSymlinkInProjectExists(
* Asserts directory under [pathToDir] relative to the test project exists and is a directory.
*/
fun GradleProject.assertDirectoryInProjectExists(
pathToDir: String
pathToDir: String,
) = assertDirectoryExists(projectPath.resolve(pathToDir))
/**
* Asserts directory under [dirPath] exists and is a directory.
*/
fun assertDirectoryExists(
dirPath: Path
) = assertDirectoriesExist(dirPath)
dirPath: Path,
message: String? = null,
) = assertDirectoriesExist(dirPath, message = message)
fun assertDirectoriesExist(
vararg dirPaths: Path
vararg dirPaths: Path,
message: String? = null,
) {
val (exist, notExist) = dirPaths.partition { it.exists() }
val notDirectories = exist.filterNot { it.isDirectory() }
assert(notExist.isEmpty() && notDirectories.isEmpty()) {
buildString {
message ?: buildString {
if (notExist.isNotEmpty()) {
appendLine("Following directories does not exist:")
appendLine(notExist.joinToString(separator = "\n"))
@@ -160,7 +163,7 @@ fun assertDirectoriesExist(
*/
fun GradleProject.assertFileInProjectContains(
pathToFile: String,
vararg expectedText: String
vararg expectedText: String,
) {
assertFileContains(projectPath.resolve(pathToFile), *expectedText)
}
@@ -170,7 +173,7 @@ fun GradleProject.assertFileInProjectContains(
*/
fun GradleProject.assertFileInProjectDoesNotContain(
pathToFile: String,
vararg unexpectedText: String
vararg unexpectedText: String,
) {
assertFileDoesNotContain(projectPath.resolve(pathToFile), *unexpectedText)
}
@@ -180,7 +183,7 @@ fun GradleProject.assertFileInProjectDoesNotContain(
*/
fun assertFileContains(
file: Path,
vararg expectedText: String
vararg expectedText: String,
) {
assertFileExists(file)
val text = file.readText()
@@ -202,7 +205,7 @@ fun assertFileContains(
*/
fun assertFileDoesNotContain(
file: Path,
vararg unexpectedText: String
vararg unexpectedText: String,
) {
assertFileExists(file)
val text = file.readText()
@@ -258,7 +261,7 @@ fun assertFilesContentEquals(expected: Path, actual: Path) {
}
class GradleVariantAssertions(
val variantJson: JsonObject
val variantJson: JsonObject,
) {
fun assertAttributesEquals(expected: Map<String, String>) {
val attributesJson = variantJson.getAsJsonObject("attributes")
@@ -22,7 +22,7 @@ fun BuildResult.assertOutputContains(
}
/**
* Asserts Gradle output contains any of [expectedSubString] strings.
* Asserts Gradle output contains any of [expectedSubStrings] strings.
*/
fun BuildResult.assertOutputContainsAny(
vararg expectedSubStrings: String,
@@ -103,11 +103,12 @@ fun BuildResult.assertOutputDoesNotContain(
*/
fun BuildResult.assertOutputContains(
expected: Regex,
message: String = "Build output does not contain any line matching '$expected' regex.",
) {
assert(output.contains(expected)) {
printBuildOutput()
"Build output does not contain any line matching '$expected' regex."
message
}
}
@@ -41,6 +41,20 @@ fun BuildResult.assertTasksExecuted(vararg tasks: String) {
}
}
/**
* Asserts any of [tasks] has 'SUCCESS' execution state.
*/
fun BuildResult.assertAnyTaskHasBeenExecuted(tasks: Set<String>) {
assert(
tasks.any { task ->
task(task)?.outcome == TaskOutcome.SUCCESS
}
) {
printBuildOutput()
"There are no 'SUCCESS' tasks in the $tasks"
}
}
/**
* Asserts given [tasks] have not been executed.
*/
@@ -148,7 +162,7 @@ fun BuildResult.assertTasksPackedToCache(vararg tasks: String) {
fun BuildResult.assertNativeTasksClasspath(
vararg tasksPaths: String,
toolName: NativeToolKind = NativeToolKind.KONANC,
assertions: (List<String>) -> Unit
assertions: (List<String>) -> Unit,
) = tasksPaths.forEach { taskPath -> assertions(extractNativeCompilerClasspath(getOutputForTask(taskPath), toolName)) }
/**
@@ -189,7 +203,7 @@ fun TestProject.buildAndAssertAllTasks(
*/
fun BuildResult.assertTasksInBuildOutput(
expectedPresentTasks: List<String> = emptyList(),
expectedAbsentTasks: List<String> = emptyList()
expectedAbsentTasks: List<String> = emptyList(),
) {
val registeredTasks = getAllTasksFromTheOutput()
expectedPresentTasks.forEach {
@@ -240,12 +240,14 @@ internal inline fun <reified T> TestProject.getModels(
fun TestProject.enableLocalBuildCache(
buildCacheLocation: Path,
) {
// language=Groovy
settingsGradle.append(
val settingsFile = if (Files.exists(settingsGradle)) settingsGradle else settingsGradleKts
settingsFile.append(
"""
buildCache {
local {
directory = '${buildCacheLocation.toUri()}'
directory = "${buildCacheLocation.toUri()}"
}
}
""".trimIndent()
@@ -5,30 +5,34 @@
package org.jetbrains.kotlin.gradle.util
import org.gradle.testkit.runner.BuildResult
import org.intellij.lang.annotations.Language
import org.intellij.lang.annotations.RegExp
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.parseCommonizerTarget
import org.jetbrains.kotlin.gradle.BaseGradleIT
import org.jetbrains.kotlin.gradle.BaseGradleIT.CompiledProject
import org.jetbrains.kotlin.gradle.testbase.BuildOptions
import org.jetbrains.kotlin.gradle.testbase.TestProject
import org.jetbrains.kotlin.gradle.testbase.build
import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy
import org.jetbrains.kotlin.library.commonizerTarget
import org.jetbrains.kotlin.library.resolveSingleFileKlib
import org.jetbrains.kotlin.tooling.core.linearClosure
import java.io.File
import javax.annotation.RegEx
import kotlin.io.path.appendText
import kotlin.test.fail
data class SourceSetCommonizerDependency(
val sourceSetName: String,
val target: CommonizerTarget,
val file: File
val file: File,
)
data class SourceSetCommonizerDependencies(
val sourceSetName: String,
val dependencies: Set<SourceSetCommonizerDependency>
val dependencies: Set<SourceSetCommonizerDependency>,
) {
fun withoutNativeDistributionDependencies(): SourceSetCommonizerDependencies {
@@ -77,10 +81,6 @@ data class SourceSetCommonizerDependencies(
assertDependencyFilesMatches(fileMatchers.filterNotNull().map(::Regex).toSet())
}
fun assertDependencyFilesMatches(vararg fileMatchers: Regex?) = apply {
assertDependencyFilesMatches(fileMatchers.filterNotNull().toSet())
}
fun assertDependencyFilesMatches(fileMatchers: Set<Regex>) = apply {
val unmatchedDependencies = dependencies.filter { dependency ->
fileMatchers.none { matcher -> dependency.file.absolutePath.matches(matcher) }
@@ -120,7 +120,7 @@ fun BaseGradleIT.reportSourceSetCommonizerDependencies(
project: BaseGradleIT.Project,
subproject: String? = null,
options: BaseGradleIT.BuildOptions = defaultBuildOptions(),
test: WithSourceSetCommonizerDependencies.(compiledProject: CompiledProject) -> Unit
test: WithSourceSetCommonizerDependencies.(compiledProject: BaseGradleIT.CompiledProject) -> Unit
) = with(project) {
if (!projectDir.exists()) {
@@ -160,6 +160,40 @@ fun BaseGradleIT.reportSourceSetCommonizerDependencies(
}
}
fun TestProject.reportSourceSetCommonizerDependencies(
subproject: String? = null,
options: BuildOptions = this.buildOptions,
test: WithSourceSetCommonizerDependencies.(compiledProject: BuildResult) -> Unit,
) {
buildGradleKts.appendText("\n\n$taskSourceCode\n\n")
val taskName = buildString {
if (subproject != null) append(":$subproject")
append(":reportCommonizerSourceSetDependencies")
}
build(taskName, buildOptions = options) {
val dependencyReports = output.lineSequence().filter { line -> line.contains("SourceSetCommonizerDependencyReport") }.toList()
val withSourceSetCommonizerDependencies = WithSourceSetCommonizerDependencies { sourceSetName ->
val reportMarker = "Report[$sourceSetName]"
val reportForSourceSet = dependencyReports.firstOrNull { line -> line.contains(reportMarker) }
?: fail("Missing dependency report for $sourceSetName")
val files = reportForSourceSet.split(reportMarker, limit = 2).last().split("|#+#|")
.map(String::trim).filter(String::isNotEmpty).map(::File)
val dependencies = files.mapNotNull { file -> createSourceSetCommonizerDependencyOrNull(sourceSetName, file) }.toSet()
SourceSetCommonizerDependencies(sourceSetName, dependencies)
}
withSourceSetCommonizerDependencies.test(this)
}
}
private fun createSourceSetCommonizerDependencyOrNull(sourceSetName: String, libraryFile: File): SourceSetCommonizerDependency? {
return SourceSetCommonizerDependency(
sourceSetName,