From 645d2634746f10d14afce19eae9bfba5b96852aa Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Tue, 14 Nov 2023 11:10:22 +0100 Subject: [PATCH] [Gradle] Test that source set have own Cinterop configurations It is necessary to prevent leaking dependencies in source set hierarchy i.e. if linuxMain depends on some project with cinterops and nativeMain also have the same set of underlying targets it is important that nativeMain should not see any dependencies from linuxMain! And vice versa, if linuxMain should see own + parents dependencies. ^KT-63338 --- .../CInteropCommonizerConfigurationTests.kt | 80 ++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropCommonizerConfigurationTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropCommonizerConfigurationTests.kt index ca50f9fbe1d..417eba6eb52 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropCommonizerConfigurationTests.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropCommonizerConfigurationTests.kt @@ -7,14 +7,24 @@ package org.jetbrains.kotlin.gradle.unitTests +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ProjectDependency import org.gradle.kotlin.dsl.dependencies import org.jetbrains.kotlin.commonizer.CommonizerTarget import org.jetbrains.kotlin.commonizer.identityString +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventionsImpl.commonMain +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventionsImpl.linuxMain +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle +import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.ReadyForExecution +import org.jetbrains.kotlin.gradle.plugin.await import org.jetbrains.kotlin.gradle.targets.native.internal.CommonizerTargetAttribute -import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP +import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrCreateCommonizedCInteropDependencyConfiguration +import org.jetbrains.kotlin.gradle.util.* import org.jetbrains.kotlin.gradle.utils.markConsumable import org.jetbrains.kotlin.gradle.utils.markResolvable import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.tooling.core.UnsafeApi import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.fail @@ -114,4 +124,72 @@ class CInteropCommonizerConfigurationTests { val resolved = resolvedDependencies.single() assertEquals(consumableSpecific.name, resolved.configuration) } + + @Test + fun `test - KT-63338 - source sets have own cinterop configurations`() { + val rootProject = buildProject() + + val producerAProject = buildProjectWithMPP( + projectBuilder = { withParent(rootProject).withName("producer-a") } + ) { + kotlin { + linuxX64().compilations.main.cinterops.create("myInterop") + linuxArm64().compilations.main.cinterops.create("myInterop") + } + } + + val producerBProject = buildProjectWithMPP( + projectBuilder = { withParent(rootProject).withName("producer-b") } + ) { + kotlin { + linuxX64().compilations.main.cinterops.create("myInterop") + linuxArm64().compilations.main.cinterops.create("myInterop") + } + } + + + val consumerProject = buildProjectWithMPP( + projectBuilder = { withParent(rootProject).withName("consumer") } + ) { + kotlin { + linuxX64() + linuxArm64() + + sourceSets.commonMain.dependencies { + implementation(project(":producer-a")) + } + + sourceSets.linuxMain.dependencies { + implementation(project(":producer-b")) + } + } + } + + producerAProject.evaluate() + + consumerProject.runLifecycleAwareTest { + val commonMain = consumerProject.multiplatformExtension.sourceSets.commonMain + val linuxMain = consumerProject.multiplatformExtension.sourceSets.linuxMain + + @OptIn(UnsafeApi::class) + val commonMainCinterop = consumerProject.locateOrCreateCommonizedCInteropDependencyConfiguration(commonMain.get())!! + + @OptIn(UnsafeApi::class) + val linuxMainCinterop = consumerProject.locateOrCreateCommonizedCInteropDependencyConfiguration(linuxMain.get())!! + + if (linuxMainCinterop == commonMainCinterop) + fail("Expected different source sets have different resolvable Cinterop configurations") + + fun Configuration.allProjectDependencies() = allDependencies + .filterIsInstance() + .map { it.dependencyProject } + .toSet() + + if (commonMainCinterop.allProjectDependencies() != setOf(producerAProject)) + fail("commonMain Cinterop configuration should depend only on `producer-a` project") + + if (linuxMainCinterop.allProjectDependencies() != setOf(producerAProject, producerBProject)) + fail("linuxMain Cinterop configuration should depend on both `producer-a` and `producer-b` projects") + } + } } \ No newline at end of file