diff --git a/libraries/kotlin.test/build.gradle.kts b/libraries/kotlin.test/build.gradle.kts index 74545518343..fc7659823e8 100644 --- a/libraries/kotlin.test/build.gradle.kts +++ b/libraries/kotlin.test/build.gradle.kts @@ -119,11 +119,14 @@ val rootComponent = componentFactory.adhoc("root").apply { } +val kotlinTestCapability = "$group:kotlin-test:$version" // add to variants with explicit capabilities when the default one is needed, too val baseCapability = "$group:kotlin-test-framework:$version" val implCapability = "$group:kotlin-test-framework-impl:$version" val jvmTestFrameworks = listOf("junit", "junit5", "testng") +val frameworkCapabilities = mutableSetOf() + jvmTestFrameworks.forEach { framework -> val (apiVariant, runtimeVariant) = listOf("api", "runtime").map { usage -> configurations.create("${framework}${usage.capitalize()}Variant") { @@ -134,7 +137,9 @@ jvmTestFrameworks.forEach { framework -> attribute(KotlinPlatformType.attribute, KotlinPlatformType.jvm) } outgoing.capability(baseCapability) // C0 - outgoing.capability("$group:kotlin-test-framework-$framework:$version") // C0 + outgoing.capability( + "$group:kotlin-test-framework-$framework:$version".also { frameworkCapabilities.add(it) } + ) // C0 } } runtimeVariant.extendsFrom(apiVariant) @@ -188,6 +193,18 @@ jvmTestFrameworks.forEach { framework -> }.let { components.add(it) } } +/** + * When a consumer's dependency requires a specific test framework (like with auto framework selection), their configurations requesting + * "common" artifacts (such as `*DependenciesMetadata` in MPP) should choose this variant anyway. Otherwise, choosing this variant + * (from a "pure", capability-less dependency on `kotlin-test` appearing transitively in the dependency graph) along with some + * capability-providing *platform* variant leads to incompatible variants being chosen together, causing dependency resolution errors, + * see KTIJ-6098 + */ +commonVariant.apply { + frameworkCapabilities.forEach(outgoing::capability) + outgoing.capability(kotlinTestCapability) +} + val (jsApi, jsRuntime) = listOf("api", "runtime").map { usage -> configurations.create("js${usage.capitalize()}") { isCanBeConsumed = true diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt index e52c6caf889..210edf35cb5 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt @@ -163,6 +163,21 @@ class KotlinSpecificDependenciesIT : BaseGradleIT() { "jvmAndJsTestCompileOnlyDependenciesMetadata" to listOf("kotlin-test-common"), "jvmAndJsTestImplementationDependenciesMetadata" to listOf("!kotlin-test-common"), ) + ), + TestCase( + /** + * Check that in a single-platform project the common metadata configurations resolve the + * framework-specific dependency (inferred as JUnit) correctly to the common artifact + * KTIJ-6098 + */ + Project("mpp-single-jvm-target"), + listOf("commonTestImplementation"), + mapOf( + "compileTestKotlinJvm" to listOf("kotlin-test-junit"), + ), + mapOf( + "commonTestImplementationDependenciesMetadata" to listOf("kotlin-test-common", "kotlin-test-annotations-common") + ) ) ).forEach { testCase -> with(testCase) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/build.gradle.kts new file mode 100644 index 00000000000..abce9c1c157 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + kotlin("multiplatform") +} + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin { + jvm() +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/gradle.properties new file mode 100755 index 00000000000..2a391fe78b0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/gradle.properties @@ -0,0 +1 @@ +kotlin.mpp.enableGranularSourceSetsMetadata=true \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/settings.gradle.kts new file mode 100644 index 00000000000..92e9d3068fc --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/settings.gradle.kts @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } + val kotlin_version: String by settings + plugins { + kotlin("multiplatform").version(kotlin_version) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/src/commonMain/kotlin/ThirdParty.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/src/commonMain/kotlin/ThirdParty.kt new file mode 100644 index 00000000000..52ee4ee68a6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/src/commonMain/kotlin/ThirdParty.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +expect fun thirdPartyFun(): String + +private fun useStdlibInCommonMain() = listOf(1, 2, 3).joinToString() \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/src/jvmMain/kotlin/ThirdPartyJvm.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/src/jvmMain/kotlin/ThirdPartyJvm.kt new file mode 100644 index 00000000000..ad7e11903d8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/mpp-single-jvm-target/src/jvmMain/kotlin/ThirdPartyJvm.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +actual fun thirdPartyFun(): String = "thirdPartyFun @ jvm" + +fun thirdPartyJvmFun() { } \ No newline at end of file