[Gradle] Implement MppIdeDependencyResolutionIT.testCommonizedPlatformDependencyResolution

^KT-55238 Verification Pending
This commit is contained in:
Sebastian Sellmair
2022-12-02 16:04:41 +01:00
committed by Space Team
parent ee07fcc00b
commit 1ec7e404fd
4 changed files with 162 additions and 0 deletions
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2022 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.idea.testFixtures.tcs
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
internal class IdeaKotlinDependencyInstanceMatcher(private val instance: IdeaKotlinDependency) : IdeaKotlinDependencyMatcher {
override val description: String
get() = instance.toString()
override fun matches(dependency: IdeaKotlinDependency): Boolean {
return instance == dependency
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency
fun buildIdeaKotlinDependencyMatchers(notation: Any?): List<IdeaKotlinDependencyMatcher> {
return when (notation) {
null -> return emptyList()
is IdeaKotlinDependency -> listOf(IdeaKotlinDependencyInstanceMatcher(notation))
is IdeaKotlinDependencyMatcher -> listOf(notation)
is Iterable<*> -> notation.flatMap { buildIdeaKotlinDependencyMatchers(it) }
else -> error("Can't build ${IdeaKotlinSourceDependencyMatcher::class.java.simpleName} from $notation")
@@ -54,6 +54,11 @@ dependencies {
requireCapability("org.jetbrains.kotlin:atomicfu-common")
}
}
testImplementation(project(":kotlin-gradle-plugin-idea"))
testImplementation(testFixtures(project(":kotlin-gradle-plugin-idea")))
testImplementation(project(":kotlin-gradle-plugin-idea-proto"))
testImplementation(project(":kotlin-gradle-plugin-model"))
testImplementation(project(":kotlin-gradle-build-metrics"))
testImplementation(project(":kotlin-project-model"))
@@ -0,0 +1,139 @@
/*
* Copyright 2010-2022 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 org.gradle.testkit.runner.BuildResult
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.identityString
import org.jetbrains.kotlin.gradle.idea.proto.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinSerializationContext
import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinSerializationLogger
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency.Companion.CLASSPATH_BINARY_TYPE
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isCommonized
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeDistribution
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeStdlib
import org.jetbrains.kotlin.gradle.idea.tcs.extras.klibExtra
import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.assertMatches
import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.binaryCoordinates
import org.jetbrains.kotlin.gradle.plugin.ide.kotlinExtrasSerialization
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.konan.target.KonanTarget.*
import org.junit.jupiter.api.DisplayName
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.fail
@MppGradlePluginTests
@DisplayName("Multiplatform IDE dependency resolution")
class MppIdeDependencyResolutionIT : KGPBaseTest() {
@GradleTest
fun testCommonizedPlatformDependencyResolution(gradleVersion: GradleVersion) {
with(project("commonizeHierarchically", gradleVersion)) {
resolveIdeDependencies(":p1") { dependencies ->
if (task(":commonizeNativeDistribution") == null) fail("Missing :commonizeNativeDistribution task")
fun Iterable<IdeaKotlinDependency>.filterNativePlatformDependencies() =
filterIsInstance<IdeaKotlinResolvedBinaryDependency>()
.filter { !it.isNativeStdlib }
.filter { it.isNativeDistribution }
.filter { it.binaryType == CLASSPATH_BINARY_TYPE }
val nativeMainDependencies = dependencies.getDependenciesForSourceSet("nativeMain").filterNativePlatformDependencies()
val nativeTestDependencies = dependencies.getDependenciesForSourceSet("nativeTest").filterNativePlatformDependencies()
val linuxMainDependencies = dependencies.getDependenciesForSourceSet("linuxMain").filterNativePlatformDependencies()
val linuxTestDependencies = dependencies.getDependenciesForSourceSet("linuxTest").filterNativePlatformDependencies()
/* Check test and main receive the same dependencies */
run {
nativeMainDependencies.assertMatches(nativeTestDependencies)
linuxMainDependencies.assertMatches(linuxTestDependencies)
}
/* Check all dependencies are marked as commonized and commonizer target match */
run {
nativeMainDependencies.plus(linuxMainDependencies).forEach { dependency ->
if (!dependency.isCommonized) fail("$dependency is not marked as 'isCommonized'")
}
val nativeMainTarget = CommonizerTarget(
LINUX_X64, LINUX_ARM64, MACOS_X64, MACOS_ARM64, IOS_X64, IOS_ARM64, IOS_SIMULATOR_ARM64, MINGW_X64, MINGW_X86
)
nativeMainDependencies.forEach { dependency ->
assertEquals(nativeMainTarget.identityString, dependency.klibExtra?.commonizerTarget)
}
val linuxMainTarget = CommonizerTarget(LINUX_X64, LINUX_ARM64)
linuxMainDependencies.forEach { dependency ->
assertEquals(linuxMainTarget.identityString, dependency.klibExtra?.commonizerTarget)
}
}
/* Find posix library */
run {
nativeMainDependencies.assertMatches(
binaryCoordinates(Regex("org\\.jetbrains\\.kotlin\\.native:platform.posix:.*")),
binaryCoordinates(Regex("org\\.jetbrains\\.kotlin\\.native:platform.*"))
)
linuxMainDependencies.assertMatches(
binaryCoordinates(Regex("org\\.jetbrains\\.kotlin\\.native:platform.posix:.*")),
binaryCoordinates(Regex("org\\.jetbrains\\.kotlin\\.native:platform.*"))
)
}
}
}
}
}
private fun TestProject.resolveIdeDependencies(
subproject: String? = null,
assertions: BuildResult.(dependencies: ResolvedIdeDependencies) -> Unit
) {
build("${subproject.orEmpty()}:resolveIdeDependencies") {
val subprojectPathPrefix = subproject?.removePrefix(":")?.replace(":", "/")?.plus("/") ?: ""
val output = projectPath.resolve("${subprojectPathPrefix}build/ide/dependencies/proto").toFile()
if (!output.isDirectory) fail("Missing output directory: $output")
val dependenciesBySourceSetName = output.listFiles().orEmpty().associate { sourceSetDirectory ->
if (!sourceSetDirectory.isDirectory) fail("Expected $sourceSetDirectory to be directory")
val serializedDependencyFiles = sourceSetDirectory.listFiles().orEmpty()
val deserializedDependencies = serializedDependencyFiles.map { dependencyFile ->
deserializeIdeaKotlinDependencyOrFail(dependencyFile)
}
sourceSetDirectory.name to deserializedDependencies.toSet()
}
assertions(ResolvedIdeDependencies(dependenciesBySourceSetName))
}
}
private fun deserializeIdeaKotlinDependencyOrFail(file: File): IdeaKotlinDependency {
return GradleIntegrationTestIdeaKotlinSerializationContext.IdeaKotlinDependency(file.readBytes())
?: fail("Failed to deserialize dependency. $file")
}
private object GradleIntegrationTestIdeaKotlinSerializationContext : IdeaKotlinSerializationContext {
override val extrasSerializationExtension = kotlinExtrasSerialization
override val logger: IdeaKotlinSerializationLogger = object : IdeaKotlinSerializationLogger {
override fun report(severity: IdeaKotlinSerializationLogger.Severity, message: String, cause: Throwable?) {
println("$severity: $message")
if (cause != null) println(cause.stackTraceToString())
}
}
}
private class ResolvedIdeDependencies(
private val dependencies: Map<String, Set<IdeaKotlinDependency>>
) {
fun getDependenciesForSourceSet(sourceSetName: String) = dependencies[sourceSetName]
?: fail("SourceSet with name $sourceSetName not found. Found: ${dependencies.keys}")
}