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.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DefaultModuleFragmentsResolverTest {
val moduleFoo = simpleModule("foo")
val moduleBar = simpleModule("bar")
internal class DefaultModuleFragmentsResolverTest {
val bundleFoo = simpleModuleBundle("foo")
val bundleBar = simpleModuleBundle("bar")
val fragmentResolver = DefaultModuleFragmentsResolver(MatchVariantsByExactAttributes())
@Test
fun testFragmentVisibility() {
val moduleFooMain = bundleFoo.main
val moduleBarMain = bundleBar.main
val expectedVisibleFragments = mapOf(
"common" to setOf("commonMain"),
"jvmAndJs" to setOf("commonMain", "jvmAndJsMain"),
"jsAndLinux" to setOf("commonMain", "jsAndLinuxMain"),
"jvm" to setOf("commonMain", "jvmAndJsMain", "jvmMain"),
"js" to setOf("commonMain", "jvmAndJsMain", "jsAndLinuxMain", "jsMain"),
"linux" to setOf("commonMain", "jsAndLinuxMain", "linuxMain")
"common" to setOf("common"),
"jvmAndJs" to setOf("common", "jvmAndJs"),
"jsAndLinux" to setOf("common", "jsAndLinux"),
"jvm" to setOf("common", "jvmAndJs", "jvm"),
"js" to setOf("common", "jvmAndJs", "jsAndLinux", "js"),
"linux" to setOf("common", "jsAndLinux", "linux")
)
moduleBar.fragments.forEach { consumingFragment ->
val result = fragmentResolver.getChosenFragments(consumingFragment, moduleFoo)
val expected = expectedVisibleFragments.getValue(consumingFragment.fragmentName.removeSuffix("Main").removeSuffix("Test"))
moduleBarMain.fragments.forEach { consumingFragment ->
val result = fragmentResolver.getChosenFragments(consumingFragment, moduleFooMain)
assertTrue(result is FragmentResolution.ChosenFragments)
val expected = expectedVisibleFragments.getValue(consumingFragment.fragmentName)
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.
// This helps with non-published local native targets.
// Consider making it more strict when we have a solution to the original problem.
val dependingModule = simpleModule("baz").apply {
variant("linuxMain").variantAttributes.replace(KotlinNativeTargetAttribute, "notLinux")
val dependingModule = simpleModuleBundle("baz").main.apply {
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 {
fragmentResolver.getChosenFragments(dependingModule.fragment(it), moduleFoo).visibleFragments.map { it.fragmentName }.toSet()
val (commonMainResult, jsAndLinuxResult) = listOf("common", "jsAndLinux").map {
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("commonMain", "jvmAndJsMain", "jsAndLinuxMain", "jsMain"), jsAndLinuxResult)
assertEquals(setOf("common", "jvmAndJs"), commonMainResult)
assertEquals(setOf("common", "jvmAndJs", "jsAndLinux", "js"), jsAndLinuxResult)
}
}
@@ -5,7 +5,7 @@
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 =
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") }
?: 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) {
require(fragment.containingModule == containingModule)
declaredContainingModuleFragmentDependencies.add(fragment)
fun BasicKotlinModuleFragment.depends(module: BasicKotlinModule) {
this.declaredModuleDependencies += KotlinModuleDependency(module.moduleIdentifier)
}
fun BasicKotlinModuleFragment.refinedBy(fragment: BasicKotlinModuleFragment) {
@@ -38,38 +44,50 @@ fun BasicKotlinModuleFragment.refines(fragment: BasicKotlinModuleFragment) {
// ---
fun simpleModule(name: String) = module(name).apply {
listOf("main", "test").forEach { purpose ->
val common = fragment("common", purpose)
if (purpose == "test")
common.depends(fragment("common", "main"))
internal data class ModuleBundle(val modules: List<BasicKotlinModule>) {
val main: BasicKotlinModule
get() = modules.single { it.moduleIdentifier.moduleClassifier == null }
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
operator fun get(modulePurpose: String): BasicKotlinModule = when (modulePurpose) {
"main" -> main
else -> modules.single { it.moduleIdentifier.moduleClassifier == modulePurpose }
}
}
internal fun simpleModuleBundle(name: String): ModuleBundle {
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 {
refines(common)
refinedBy(jvm)
refinedBy(js)
}
fragment("jsAndLinux", purpose).apply {
refines(common)
refinedBy(js)
refinedBy(linux)
}
}
val main = createModule("main")
val test = createModule("test")
test.fragment("common").depends(main)
return ModuleBundle(listOf(main, test))
}