Fix compilation of the tests in kotlin-project-model

This commit is contained in:
Sergey Igushkin
2021-04-13 12:22:51 +03:00
parent fe351f26ef
commit d602470027
3 changed files with 78 additions and 156 deletions
@@ -1,105 +0,0 @@
/*
* Copyright 2010-2020 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.project.model
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DefaultInternalDependencyExpansionTest {
/** Create a module without internal depends edges, those need to be added manually afterwards */
fun createTemplateModule(vararg purposes: String) = module("foo").apply {
listOf(*purposes).forEach { purpose ->
val common = fragment("common", purpose)
val (jvm, js, linux) = listOf("jvm", "js", "linux").map { platform ->
variant(platform, purpose).apply {
variantAttributes[KotlinPlatformTypeAttribute] = when (platform) {
"jvm" -> KotlinPlatformTypeAttribute.JVM
"js" -> KotlinPlatformTypeAttribute.JS
else -> {
variantAttributes[KotlinNativeTargetAttribute] = platform
KotlinPlatformTypeAttribute.NATIVE
}
}
}
}
val jvmAndJs = fragment("jvmAndJs", purpose).apply {
refines(common)
refinedBy(jvm)
refinedBy(js)
}
val jsAndLinux = fragment("jsAndLinux", purpose).apply {
refines(common)
refinedBy(js)
refinedBy(linux)
}
}
}
val expansion = DefaultInternalDependencyExpansion(AssociateVariants())
@Test
fun testSimpleCommonTestToCommonMainDependency() {
val module = createTemplateModule("main", "test").apply {
// Manually associate the variants:
listOf("jvm", "js", "linux").forEach {
variant(it, "test").depends(variant(it, "main"))
}
// Add just a single dependency from commonTest to commonMain
fragment("commonTest").depends(fragment("commonMain"))
}
val expectedFragments = mapOf(
"commonTest" to setOf("commonMain"),
"jvmAndJsTest" to setOf("jvmAndJsMain", "commonMain"),
"jsAndLinuxTest" to setOf("jsAndLinuxMain", "commonMain"),
"jvmTest" to setOf("jvmMain", "jvmAndJsMain", "commonMain"),
"jsTest" to setOf("jsMain", "jsAndLinuxMain", "jvmAndJsMain", "commonMain"),
"linuxTest" to setOf("linuxMain", "jsAndLinuxMain", "commonMain")
)
module.fragments.forEach { fragment ->
val result =
expansion.expandInternalFragmentDependencies(fragment).visibleFragments().map { it.fragmentName }.toSet()
val expected = expectedFragments[fragment.fragmentName].orEmpty()
assertEquals(expected, result)
}
}
@Test
fun testDeclaredDependenciesFromExpansion() {
val module = createTemplateModule("main", "test", "integration").apply {
/** Manually associate the variants: */
listOf("jvm", "js", "linux").forEach {
variant(it, "test").depends(variant(it, "main"))
variant(it, "integration").depends(variant(it, "test"))
variant(it, "integration").depends(variant(it, "main"))
}
/**
* Add a dependency from `commonIntegration` to `commonTest` and from (a more specific fragment)
* `jvmAndJsTest` to `jvmAndJsMain`.
*/
fragment("commonIntegration").depends(fragment("commonTest"))
fragment("jvmAndJsTest").depends(fragment("jvmAndJsMain"))
/**
* Expect that the fragment `jvmAndJsIntegration` receives the dependency on `jvmAndJsMain` through
* the declared dependency added to the fragment `jvmAndJsTest`, which is only visible in expansion.
*/
val result = expansion.expandInternalFragmentDependencies(fragment("jvmAndJsIntegration"))
val expected = setOf("commonMain", "jvmAndJsMain", "commonTest", "jvmAndJsTest")
assertEquals(expected, result.visibleFragments().map { it.fragmentName }.toSet())
assertTrue {
result.entries.any {
it.dependingFragment == fragment("jvmAndJsTest") &&
it.dependencyFragment == fragment("jvmAndJsMain") &&
it.outcome.visibleFragments().map { it.fragmentName }.toSet() == setOf("commonMain", "jvmAndJsMain")
}
}
}
}
}
@@ -8,27 +8,32 @@ package org.jetbrains.kotlin.project.model
import org.junit.Assume.assumeTrue import org.junit.Assume.assumeTrue
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DefaultModuleFragmentsResolverTest { internal class DefaultModuleFragmentsResolverTest {
val moduleFoo = simpleModule("foo") val bundleFoo = simpleModuleBundle("foo")
val moduleBar = simpleModule("bar") val bundleBar = simpleModuleBundle("bar")
val fragmentResolver = DefaultModuleFragmentsResolver(MatchVariantsByExactAttributes()) val fragmentResolver = DefaultModuleFragmentsResolver(MatchVariantsByExactAttributes())
@Test @Test
fun testFragmentVisibility() { fun testFragmentVisibility() {
val moduleFooMain = bundleFoo.main
val moduleBarMain = bundleBar.main
val expectedVisibleFragments = mapOf( val expectedVisibleFragments = mapOf(
"common" to setOf("commonMain"), "common" to setOf("common"),
"jvmAndJs" to setOf("commonMain", "jvmAndJsMain"), "jvmAndJs" to setOf("common", "jvmAndJs"),
"jsAndLinux" to setOf("commonMain", "jsAndLinuxMain"), "jsAndLinux" to setOf("common", "jsAndLinux"),
"jvm" to setOf("commonMain", "jvmAndJsMain", "jvmMain"), "jvm" to setOf("common", "jvmAndJs", "jvm"),
"js" to setOf("commonMain", "jvmAndJsMain", "jsAndLinuxMain", "jsMain"), "js" to setOf("common", "jvmAndJs", "jsAndLinux", "js"),
"linux" to setOf("commonMain", "jsAndLinuxMain", "linuxMain") "linux" to setOf("common", "jsAndLinux", "linux")
) )
moduleBar.fragments.forEach { consumingFragment -> moduleBarMain.fragments.forEach { consumingFragment ->
val result = fragmentResolver.getChosenFragments(consumingFragment, moduleFoo) val result = fragmentResolver.getChosenFragments(consumingFragment, moduleFooMain)
val expected = expectedVisibleFragments.getValue(consumingFragment.fragmentName.removeSuffix("Main").removeSuffix("Test")) assertTrue(result is FragmentResolution.ChosenFragments)
val expected = expectedVisibleFragments.getValue(consumingFragment.fragmentName)
assertEquals(expected, result.visibleFragments.map { it.fragmentName }.toSet()) assertEquals(expected, result.visibleFragments.map { it.fragmentName }.toSet())
} }
} }
@@ -38,16 +43,20 @@ class DefaultModuleFragmentsResolverTest {
// TODO this behavior replicates 1.3.x MPP where a mismatched variant gets ignored and only matched variants are intersected. // TODO this behavior replicates 1.3.x MPP where a mismatched variant gets ignored and only matched variants are intersected.
// This helps with non-published local native targets. // This helps with non-published local native targets.
// Consider making it more strict when we have a solution to the original problem. // Consider making it more strict when we have a solution to the original problem.
val dependingModule = simpleModule("baz").apply { val dependingModule = simpleModuleBundle("baz").main.apply {
variant("linuxMain").variantAttributes.replace(KotlinNativeTargetAttribute, "notLinux") variant("linux").variantAttributes.replace(KotlinNativeTargetAttribute, "notLinux")
} }
assumeTrue(MatchVariantsByExactAttributes().getChosenVariant(dependingModule.variant("linuxMain"), moduleFoo) is NoVariantMatch) val moduleFooMain = bundleFoo.main
val variantResolution = MatchVariantsByExactAttributes().getChosenVariant(dependingModule.variant("linux"), moduleFooMain)
assumeTrue(variantResolution is VariantResolution.NoVariantMatch)
val (commonMainResult, jsAndLinuxResult) = listOf("commonMain", "jsAndLinuxMain").map { val (commonMainResult, jsAndLinuxResult) = listOf("common", "jsAndLinux").map {
fragmentResolver.getChosenFragments(dependingModule.fragment(it), moduleFoo).visibleFragments.map { it.fragmentName }.toSet() val chosenFragments = fragmentResolver.getChosenFragments(dependingModule.fragment(it), moduleFooMain)
assertTrue(chosenFragments is FragmentResolution.ChosenFragments)
chosenFragments.visibleFragments.map { it.fragmentName }.toSet()
} }
assertEquals(setOf("commonMain", "jvmAndJsMain"), commonMainResult) assertEquals(setOf("common", "jvmAndJs"), commonMainResult)
assertEquals(setOf("commonMain", "jvmAndJsMain", "jsAndLinuxMain", "jsMain"), jsAndLinuxResult) assertEquals(setOf("common", "jvmAndJs", "jsAndLinux", "js"), jsAndLinuxResult)
} }
} }
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.project.model package org.jetbrains.kotlin.project.model
fun module(name: String) = BasicKotlinModule(LocalModuleIdentifier("current", name)) fun module(name: String, classifier: String? = null) = BasicKotlinModule(LocalModuleIdentifier("current", name, classifier))
fun BasicKotlinModule.fragment(vararg nameParts: String): BasicKotlinModuleFragment = fun BasicKotlinModule.fragment(vararg nameParts: String): BasicKotlinModuleFragment =
fragment(nameParts.drop(1).joinToString("", nameParts.first()) { it.capitalize() }) fragment(nameParts.drop(1).joinToString("", nameParts.first()) { it.capitalize() })
@@ -21,10 +21,16 @@ fun BasicKotlinModule.variant(name: String): BasicKotlinModuleVariant =
?.let { it as? BasicKotlinModuleVariant ?: error("$name is not a variant") } ?.let { it as? BasicKotlinModuleVariant ?: error("$name is not a variant") }
?: BasicKotlinModuleVariant(this, name).also { fragments.add(it) } ?: BasicKotlinModuleVariant(this, name).also { fragments.add(it) }
fun KotlinModuleIdentifier.equalsWithoutClassifier(other: KotlinModuleIdentifier) = when (this) {
is LocalModuleIdentifier -> other is LocalModuleIdentifier &&
LocalModuleIdentifier(buildId, projectId, null) == LocalModuleIdentifier(other.buildId, other.projectId, null)
is MavenModuleIdentifier -> other is MavenModuleIdentifier &&
MavenModuleIdentifier(group, name, null) == MavenModuleIdentifier(other.group, other.name, null)
else -> error("can't check equality yet")
}
fun BasicKotlinModuleFragment.depends(fragment: BasicKotlinModuleFragment) { fun BasicKotlinModuleFragment.depends(module: BasicKotlinModule) {
require(fragment.containingModule == containingModule) this.declaredModuleDependencies += KotlinModuleDependency(module.moduleIdentifier)
declaredContainingModuleFragmentDependencies.add(fragment)
} }
fun BasicKotlinModuleFragment.refinedBy(fragment: BasicKotlinModuleFragment) { fun BasicKotlinModuleFragment.refinedBy(fragment: BasicKotlinModuleFragment) {
@@ -38,38 +44,50 @@ fun BasicKotlinModuleFragment.refines(fragment: BasicKotlinModuleFragment) {
// --- // ---
fun simpleModule(name: String) = module(name).apply { internal data class ModuleBundle(val modules: List<BasicKotlinModule>) {
listOf("main", "test").forEach { purpose -> val main: BasicKotlinModule
val common = fragment("common", purpose) get() = modules.single { it.moduleIdentifier.moduleClassifier == null }
if (purpose == "test")
common.depends(fragment("common", "main"))
val (jvm, js, linux) = listOf("jvm", "js", "linux").map { platform -> operator fun get(modulePurpose: String): BasicKotlinModule = when (modulePurpose) {
variant(platform, purpose).apply { "main" -> main
variantAttributes[KotlinPlatformTypeAttribute] = when (platform) { else -> modules.single { it.moduleIdentifier.moduleClassifier == modulePurpose }
"jvm" -> KotlinPlatformTypeAttribute.JVM }
"js" -> KotlinPlatformTypeAttribute.JS }
else -> {
variantAttributes[KotlinNativeTargetAttribute] = platform internal fun simpleModuleBundle(name: String): ModuleBundle {
KotlinPlatformTypeAttribute.NATIVE fun createModule(purpose: String): BasicKotlinModule =
module(name, purpose.takeIf { it != "main" }).apply {
val common = fragment("common")
val (jvm, js, linux) = listOf("jvm", "js", "linux").map { platform ->
variant(platform).apply {
variantAttributes[KotlinPlatformTypeAttribute] = when (platform) {
"jvm" -> KotlinPlatformTypeAttribute.JVM
"js" -> KotlinPlatformTypeAttribute.JS
else -> {
variantAttributes[KotlinNativeTargetAttribute] = platform
KotlinPlatformTypeAttribute.NATIVE
}
} }
} }
if (purpose == "test") { }
isExported = false
depends(variant(platform, "main")) fragment("jvmAndJs").apply {
} refines(common)
refinedBy(jvm)
refinedBy(js)
}
fragment("jsAndLinux").apply {
refines(common)
refinedBy(js)
refinedBy(linux)
} }
} }
fragment("jvmAndJs", purpose).apply { val main = createModule("main")
refines(common) val test = createModule("test")
refinedBy(jvm)
refinedBy(js) test.fragment("common").depends(main)
}
fragment("jsAndLinux", purpose).apply { return ModuleBundle(listOf(main, test))
refines(common)
refinedBy(js)
refinedBy(linux)
}
}
} }