[Commonizer] Implement AbstractInlineSourcesCommonizationTest and hierarchical commonization tests

This commit is contained in:
sebastian.sellmair
2021-03-30 14:33:19 +02:00
parent a2436699ea
commit 250915f377
26 changed files with 1019 additions and 132 deletions
@@ -122,6 +122,10 @@ public infix fun CommonizerTarget.isAncestorOf(other: CommonizerTarget): Boolean
return false
}
public infix fun CommonizerTarget.isEqualOrAncestorOf(other: CommonizerTarget): Boolean {
return this == other || this.isAncestorOf(other)
}
public infix fun CommonizerTarget.isDescendentOf(other: CommonizerTarget): Boolean {
return other.isAncestorOf(this)
}
@@ -0,0 +1,215 @@
/*
* Copyright 2010-2021 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.commonizer
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest.DependencyAwareInlineSourceTestFactory
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest.Parameters
import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult.Commonized
import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider
import org.jetbrains.kotlin.commonizer.utils.*
import kotlin.test.assertIs
data class HierarchicalCommonizationResult(
val inlineSourceTestFactory: DependencyAwareInlineSourceTestFactory,
val testParameters: Parameters,
val commonizerParameters: CommonizerParameters,
val results: Map<CommonizerTarget, List<ResultsConsumer.ModuleResult>>
)
abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizerTestCase() {
data class Parameters(
val outputTarget: SharedCommonizerTarget,
val dependencies: TargetDependent<List<InlineSourceBuilder.Module>>,
val targets: List<Target>
)
data class Target(
val target: CommonizerTarget,
val modules: List<InlineSourceBuilder.Module>
)
@DslMarker
annotation class InlineSourcesCommonizationTestDsl
@InlineSourcesCommonizationTestDsl
class ParametersBuilder(private val parentInlineSourceBuilder: InlineSourceBuilder) {
private var outputTarget: SharedCommonizerTarget? = null
private val dependencies: MutableMap<CommonizerTarget, MutableList<InlineSourceBuilder.Module>> = LinkedHashMap()
private var targets: List<Target> = emptyList()
private val inlineSourceBuilderFactory
get() = DependencyAwareInlineSourceTestFactory(parentInlineSourceBuilder, dependencies.toTargetDependent())
@InlineSourcesCommonizationTestDsl
fun outputTarget(target: String) {
outputTarget = parseCommonizerTarget(target) as SharedCommonizerTarget
}
@InlineSourcesCommonizationTestDsl
fun target(target: CommonizerTarget, builder: TargetBuilder.() -> Unit) {
targets = targets + TargetBuilder(target, inlineSourceBuilderFactory[target]).also(builder).build()
}
@InlineSourcesCommonizationTestDsl
fun target(target: String, builder: TargetBuilder.() -> Unit) {
return target(parseCommonizerTarget(target), builder)
}
@InlineSourcesCommonizationTestDsl
fun registerDependency(target: CommonizerTarget, builder: InlineSourceBuilder.ModuleBuilder.() -> Unit) {
val dependenciesList = dependencies.getOrPut(target) { mutableListOf() }
val dependency = inlineSourceBuilderFactory[target].createModule {
builder()
name = "${target.prettyName}-dependency-${dependenciesList.size}-$name"
}
dependenciesList.add(dependency)
}
@InlineSourcesCommonizationTestDsl
fun registerDependency(target: String, builder: InlineSourceBuilder.ModuleBuilder.() -> Unit) {
registerDependency(parseCommonizerTarget(target), builder)
}
@InlineSourcesCommonizationTestDsl
fun simpleSingleSourceTarget(target: CommonizerTarget, @Language("kotlin") sourceContent: String) {
target(target) {
module {
source(sourceContent)
}
}
}
@InlineSourcesCommonizationTestDsl
fun simpleSingleSourceTarget(target: String, @Language("kotlin") sourceCode: String) {
simpleSingleSourceTarget(parseCommonizerTarget(target), sourceCode)
}
fun build(): Parameters = Parameters(
outputTarget = outputTarget ?: SharedCommonizerTarget(targets.map { it.target }.toSet()),
dependencies = dependencies.toTargetDependent(),
targets = targets.toList()
)
}
data class DependencyAwareInlineSourceTestFactory(
private val inlineSourceBuilder: InlineSourceBuilder,
private val dependencies: TargetDependent<List<InlineSourceBuilder.Module>>
) {
operator fun get(target: CommonizerTarget): InlineSourceBuilder {
return object : InlineSourceBuilder by inlineSourceBuilder {
override fun createModule(builder: InlineSourceBuilder.ModuleBuilder.() -> Unit): InlineSourceBuilder.Module {
return inlineSourceBuilder.createModule {
dependencies.toMap()
.filterKeys { dependencyTarget -> dependencyTarget.isEqualOrAncestorOf(target) }.values.flatten()
.forEach { dependencyModule -> dependency(dependencyModule) }
builder()
}
}
}
}
}
@InlineSourcesCommonizationTestDsl
class TargetBuilder(private val target: CommonizerTarget, private val inlineSourceBuilder: InlineSourceBuilder) {
private var modules: List<InlineSourceBuilder.Module> = emptyList()
@InlineSourcesCommonizationTestDsl
fun module(builder: InlineSourceBuilder.ModuleBuilder.() -> Unit) {
modules = modules + inlineSourceBuilder.createModule(builder)
}
fun build(): Target = Target(target, modules = modules)
}
fun commonize(builder: ParametersBuilder.() -> Unit): HierarchicalCommonizationResult {
val consumer = MockResultsConsumer()
val testParameters = ParametersBuilder(this).also(builder).build()
val commonizerParameters = testParameters.toCommonizerParameters(consumer)
runCommonization(commonizerParameters)
assertEquals(ResultsConsumer.Status.DONE, consumer.status)
return HierarchicalCommonizationResult(
inlineSourceTestFactory = DependencyAwareInlineSourceTestFactory(inlineSourceBuilder, testParameters.dependencies),
testParameters = testParameters,
commonizerParameters = commonizerParameters,
results = consumer.modulesByTargets.mapValues { (_, collection) -> collection.toList() }
)
}
private fun Parameters.toCommonizerParameters(
resultsConsumer: ResultsConsumer,
manifestDataProvider: NativeManifestDataProvider = MockNativeManifestDataProvider()
): CommonizerParameters {
return CommonizerParameters(
outputTarget = outputTarget,
manifestProvider = TargetDependent(outputTarget.withAllAncestors()) { manifestDataProvider },
dependenciesProvider = TargetDependent(outputTarget.withAllAncestors()) { target ->
val explicitDependencies = dependencies.getOrNull(target).orEmpty().map { module -> createModuleDescriptor(module) }
val implicitDependencies = listOfNotNull(if (target == outputTarget) DefaultBuiltIns.Instance.builtInsModule else null)
val dependencies = explicitDependencies + implicitDependencies
if (dependencies.isEmpty()) null
else MockModulesProvider.create(dependencies)
},
targetProviders = TargetDependent(targets.map { it.target }) { commonizerTarget ->
val target = targets.single { it.target == commonizerTarget }
TargetProvider(
target = commonizerTarget,
modulesProvider = MockModulesProvider.create(target.modules.map { createModuleDescriptor(it) })
)
},
resultsConsumer = resultsConsumer
)
}
}
/* ASSERTIONS */
fun HierarchicalCommonizationResult.getTarget(target: CommonizerTarget): List<ResultsConsumer.ModuleResult> {
return this.results[target] ?: kotlin.test.fail("Missing target $target in results ${this.results.keys}")
}
fun HierarchicalCommonizationResult.getTarget(target: String): List<ResultsConsumer.ModuleResult> {
return getTarget(parseCommonizerTarget(target))
}
fun HierarchicalCommonizationResult.assertCommonized(
target: CommonizerTarget,
moduleBuilder: InlineSourceBuilder.ModuleBuilder.() -> Unit
) {
val inlineSourceTest = inlineSourceTestFactory[target]
val commonizedModule = getTarget(target).assertSingleCommonizedModule()
val referenceModule = inlineSourceTest.createModule {
moduleBuilder()
}
assertModulesAreEqual(
inlineSourceTest.createMetadata(referenceModule), commonizedModule.metadata, target
)
}
fun HierarchicalCommonizationResult.assertCommonized(target: CommonizerTarget, @Language("kotlin") sourceContent: String) {
assertCommonized(target) {
source(sourceContent)
}
}
fun HierarchicalCommonizationResult.assertCommonized(target: String, @Language("kotlin") sourceContent: String) =
assertCommonized(parseCommonizerTarget(target), sourceContent)
fun HierarchicalCommonizationResult.assertCommonized(target: String, moduleBuilder: InlineSourceBuilder.ModuleBuilder.() -> Unit) =
assertCommonized(parseCommonizerTarget(target), moduleBuilder)
fun Collection<ResultsConsumer.ModuleResult>.assertSingleCommonizedModule(): Commonized {
kotlin.test.assertEquals(1, size, "Expected exactly one module. Found: ${this.map { it.libraryName }}")
return assertIs(single(), "Expected single module to be 'Commonized'")
}
@@ -0,0 +1,145 @@
/*
* Copyright 2010-2021 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.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.assertCommonized
class HierarchicalClassCommonizationTest : AbstractInlineSourcesCommonizationTest() {
fun `test simple class`() {
val result = commonize {
outputTarget("((a,b), (c,d), e)")
simpleSingleSourceTarget("a", "class X")
simpleSingleSourceTarget("b", "class X")
simpleSingleSourceTarget("c", "class X")
simpleSingleSourceTarget("d", "class X")
simpleSingleSourceTarget("e", "class X")
}
result.assertCommonized("a", "actual class X")
result.assertCommonized("b", "actual class X")
result.assertCommonized("c", "actual class X")
result.assertCommonized("d", "actual class X")
result.assertCommonized("e", "actual class X")
result.assertCommonized("(a,b)", "class X")
result.assertCommonized("(c,d)", "class X")
result.assertCommonized("(a,b)", "class X")
result.assertCommonized("((a,b), (c,d), e)", "expect class X expect constructor()")
}
fun `test sample class`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
simpleSingleSourceTarget(
"a", """
class X {
val a: Int = 42
val ab: Int = 42
val abcd: Int = 42
}
"""
)
simpleSingleSourceTarget(
"b", """
class X {
val b: Int = 42
val ab: Int = 42
val abcd: Int = 42
}
"""
)
simpleSingleSourceTarget(
"c", """
class X {
val c: Int = 42
val cd: Int = 42
val abcd: Int = 42
}
"""
)
simpleSingleSourceTarget(
"d", """
class X {
val d: Int = 42
val cd: Int = 42
val abcd: Int = 42
}
"""
)
}
result.assertCommonized(
"a", """
actual class X {
actual val a: Int = 42
actual val ab: Int = 42
actual val abcd: Int = 42
}
"""
)
result.assertCommonized(
"b", """
actual class X {
actual val b: Int = 42
actual val ab: Int = 42
actual val abcd: Int = 42
}
"""
)
result.assertCommonized(
"c", """
actual class X {
actual val c: Int = 42
actual val cd: Int = 42
actual val abcd: Int = 42
}
"""
)
result.assertCommonized(
"d", """
actual class X {
actual val d: Int = 42
actual val cd: Int = 42
actual val abcd: Int = 42
}
"""
)
result.assertCommonized(
"(a,b)", """
class X {
val ab: Int
val abcd: Int
}
"""
)
result.assertCommonized(
"(c,d)", """
class X {
val cd: Int
val abcd: Int
}
"""
)
result.assertCommonized(
"((a,b), (c,d))", """
expect class X expect constructor() {
expect val abcd: Int
}
"""
)
}
}
@@ -0,0 +1,181 @@
/*
* Copyright 2010-2021 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.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.assertCommonized
class HierarchicalFunctionCommonizationTest : AbstractInlineSourcesCommonizationTest() {
fun `test simple function 1`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
simpleSingleSourceTarget("a", "fun x(): Int = 42")
simpleSingleSourceTarget("b", "fun x(): Int = 42")
simpleSingleSourceTarget("c", "fun x(): Int = 42")
simpleSingleSourceTarget("d", "fun x(): Int = 42")
}
result.assertCommonized("((a,b), (c,d))", "expect fun x(): Int")
result.assertCommonized("(a,b)", "actual fun x(): Int = 42")
result.assertCommonized("(c,d)", "actual fun x(): Int = 42")
result.assertCommonized("a", "actual fun x(): Int = 42")
result.assertCommonized("b", "actual fun x(): Int = 42")
result.assertCommonized("c", "actual fun x(): Int = 42")
result.assertCommonized("d", "actual fun x(): Int = 42")
}
fun `test simple function 2`() {
val result = commonize {
outputTarget("((a,b), c)")
simpleSingleSourceTarget("a", "fun x(): Int = 42")
simpleSingleSourceTarget("b", "fun x(): Int = 42")
simpleSingleSourceTarget("c", "fun x(): Int = 42")
}
result.assertCommonized("((a,b), c)", "expect fun x(): Int")
result.assertCommonized("(a,b)", "actual fun x(): Int = 42")
result.assertCommonized("a", "actual fun x(): Int = 42")
result.assertCommonized("b", "actual fun x(): Int = 42")
result.assertCommonized("c", "actual fun x(): Int = 42")
}
fun `test function with returnType`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
simpleSingleSourceTarget(
"a", """
interface ABCD
fun x(): ABCD = TODO()
"""
)
simpleSingleSourceTarget(
"b", """
interface ABCD
fun x(): ABCD = TODO()
"""
)
simpleSingleSourceTarget(
"c", """
interface ABCD
fun x(): ABCD = TODO()
"""
)
simpleSingleSourceTarget(
"d", """
interface ABCD
fun x(): ABCD = TODO()
"""
)
}
result.assertCommonized(
"a", """
actual interface ABCD
actual fun x(): ABCD = TODO()
"""
)
result.assertCommonized(
"b", """
actual interface ABCD
actual fun x(): ABCD = TODO()
"""
)
result.assertCommonized(
"c", """
actual interface ABCD
actual fun x(): ABCD = TODO()
"""
)
result.assertCommonized(
"d", """
actual interface ABCD
actual fun x(): ABCD = TODO()
"""
)
result.assertCommonized(
"(a, b)", """
actual interface ABCD
actual fun x(): ABCD
"""
)
result.assertCommonized(
"(c, d)", """
actual interface ABCD
actual fun x(): ABCD
"""
)
result.assertCommonized(
"((a,b), (c,d))", """
expect interface ABCD
expect fun x(): ABCD
"""
)
}
fun `test function with returnType from dependency 1`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
registerDependency("((a,b), (c,d))") { source("interface ABCD") }
simpleSingleSourceTarget("a", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("b", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("c", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("d", "fun x(): ABCD = TODO()")
}
result.assertCommonized("a", "actual fun x(): ABCD")
result.assertCommonized("b", "actual fun x(): ABCD")
result.assertCommonized("c", "actual fun x(): ABCD")
result.assertCommonized("d", "actual fun x(): ABCD")
result.assertCommonized("(c, d)", "fun x(): ABCD")
result.assertCommonized("(a, b)", "fun x(): ABCD")
result.assertCommonized("((a,b), (c,d))", "expect fun x(): ABCD")
}
fun `test function with returnType from dependency 2`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
registerDependency("(a,b)") { source("interface ABCD") }
registerDependency("(c,d)") { source("interface ABCD") }
simpleSingleSourceTarget("a", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("b", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("c", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("d", "fun x(): ABCD = TODO()")
}
result.assertCommonized("a", "actual fun x(): ABCD")
result.assertCommonized("b", "actual fun x(): ABCD")
result.assertCommonized("c", "actual fun x(): ABCD")
result.assertCommonized("d", "actual fun x(): ABCD")
result.assertCommonized("(c, d)", "fun x(): ABCD")
result.assertCommonized("(a, b)", "fun x(): ABCD")
result.assertCommonized("((a,b), (c,d))", "")
}
fun `test function with returnType from dependency 3`() {
val result = commonize {
outputTarget("((a,b), c)")
registerDependency("((a,b), c)") { source("interface ABCD") }
registerDependency("(a,b)") { source("interface ABCD") }
simpleSingleSourceTarget("a", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("b", "fun x(): ABCD = TODO()")
simpleSingleSourceTarget("c", "fun x(): ABCD = TODO()")
}
result.assertCommonized("a", "actual fun x(): ABCD")
result.assertCommonized("b", "actual fun x(): ABCD")
result.assertCommonized("c", "actual fun x(): ABCD")
result.assertCommonized("(a, b)", "fun x(): ABCD")
result.assertCommonized("((a,b), c)", "expect fun x(): ABCD")
}
}
@@ -0,0 +1,233 @@
/*
* Copyright 2010-2021 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.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.assertCommonized
class HierarchicalPackageCommonizationTest : AbstractInlineSourcesCommonizationTest() {
fun `test package with dummy`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
target("a") {
module {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.ab
val dummy = "me"
""", "ab.kt"
)
source(
"""
package pkg.a
val dummy = "me"
""", "a.kt"
)
}
}
target("b") {
module {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.ab
val dummy = "me"
""", "ab.kt"
)
source(
"""
package pkg.b
val dummy = "me"
""", "b.kt"
)
}
}
target("c") {
module {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.cd
val dummy = "me"
""", "cd.kt"
)
source(
"""
package pkg.c
val dummy = "me"
""", "c.kt"
)
}
}
target("d") {
module {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.cd
val dummy = "me"
""", "cd.kt"
)
source(
"""
package pkg.d
val dummy = "me"
""", "d.kt"
)
}
}
}
result.assertCommonized("a") {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.ab
val dummy = "me"
""", "ab.kt"
)
source(
"""
package pkg.a
val dummy = "me"
""", "a.kt"
)
}
result.assertCommonized("b") {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.ab
val dummy = "me"
""", "ab.kt"
)
source(
"""
package pkg.b
val dummy = "me"
""", "b.kt"
)
}
result.assertCommonized("c") {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.cd
val dummy = "me"
""", "cd.kt"
)
source(
"""
package pkg.c
val dummy = "me"
""", "c.kt"
)
}
result.assertCommonized("d") {
source(
"""
package pkg.abcd
val dummy = "me"
""", "abcd.kt"
)
source(
"""
package pkg.cd
val dummy = "me"
""", "cd.kt"
)
source(
"""
package pkg.d
val dummy = "me"
""", "d.kt"
)
}
result.assertCommonized("(a,b)") {
source(
"""
package pkg.abcd
val dummy: String
""", "abcd.kt"
)
source(
"""
package pkg.ab
val dummy: String
""", "ab.kt"
)
}
result.assertCommonized("(c,d)") {
source(
"""
package pkg.abcd
val dummy: String
""", "abcd.kt"
)
source(
"""
package pkg.cd
val dummy: String
""", "cd.kt"
)
}
result.assertCommonized("((a,b), (c,d))") {
source(
"""
package pkg.abcd
expect val dummy: String
""", "abcd.kt"
)
}
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2021 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.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.assertCommonized
import org.jetbrains.kotlin.commonizer.parseCommonizerTarget
class HierarchicalPropertyCommonizationTest : AbstractInlineSourcesCommonizationTest() {
fun `test simple property`() {
val result = commonize {
outputTarget("((a, b), (c, d))")
simpleSingleSourceTarget("a", "val x: Int = 42")
simpleSingleSourceTarget("b", "val x: Int = 42")
simpleSingleSourceTarget("c", "val x: Int = 42")
simpleSingleSourceTarget("d", "val x: Int = 42")
}
result.assertCommonized("((a,b), (c,d))", "expect val x: Int")
result.assertCommonized("(a, b)", "actual val x: Int")
result.assertCommonized("(c, d)", "actual val x: Int")
result.assertCommonized("a", "actual val x: Int = 42")
result.assertCommonized("b", "actual val x: Int = 42")
result.assertCommonized("c", "actual val x: Int = 42")
result.assertCommonized("d", "actual val x: Int = 42")
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2021 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.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.assertCommonized
class HierarchicalTypeAliasCommonizationTest : AbstractInlineSourcesCommonizationTest() {
fun `test simple type alias`() {
val result = commonize {
outputTarget("((a,b), (c,d))")
simpleSingleSourceTarget("a", "typealias X = Int")
simpleSingleSourceTarget("b", "typealias X = Int")
simpleSingleSourceTarget("c", "typealias X = Int")
simpleSingleSourceTarget("d", "typealias X = Int")
}
result.assertCommonized("((a,b), (c,d))", "typealias X = Int")
result.assertCommonized("(a,b)", "")
result.assertCommonized("(c, d)", "")
result.assertCommonized("a", "")
result.assertCommonized("b", "")
result.assertCommonized("c", "")
result.assertCommonized("d", "")
}
}
@@ -6,8 +6,6 @@
package org.jetbrains.kotlin.commonizer.tree.deserializer
import org.jetbrains.kotlin.commonizer.tree.*
import org.jetbrains.kotlin.commonizer.utils.InlineSourceTest
import org.jetbrains.kotlin.commonizer.utils.InlineSourceTestImpl
import org.jetbrains.kotlin.commonizer.utils.KtInlineSourceCommonizerTestCase
abstract class AbstractCirTreeDeserializerTest : KtInlineSourceCommonizerTestCase() {
@@ -14,7 +14,7 @@ import kotlin.test.*
class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple class`() {
val module = deserializeSourceFile("class X")
val module = createCirTreeFromSourceCode("class X")
val clazz = module.assertSingleClass().clazz
assertEquals(Visibilities.Public, clazz.visibility, "Expected class to be public")
assertNull(clazz.companion, "Expected class *not* having a companion")
@@ -29,7 +29,7 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test nested class`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
class Outer {
class Inner
@@ -46,7 +46,7 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test inner class`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
class Outer {
inner class Inner
@@ -64,7 +64,7 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test data class`() {
val module = deserializeSourceFile("data class X(val x: String)")
val module = createCirTreeFromSourceCode("data class X(val x: String)")
val clazz = module.assertSingleClass()
assertTrue(clazz.clazz.isData, "Expected is data class")
assertEquals(1, clazz.constructors.size, "Expected single constructor")
@@ -72,7 +72,7 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test companion`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
class Outer {
companion object {
@@ -88,19 +88,19 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test object`() {
val module = deserializeSourceFile("object X")
val module = createCirTreeFromSourceCode("object X")
val clazz = module.assertSingleClass()
assertEquals(ClassKind.OBJECT, clazz.clazz.kind, "Expected object class kind")
}
fun `test interface`() {
val module = deserializeSourceFile("interface X")
val module = createCirTreeFromSourceCode("interface X")
val clazz = module.assertSingleClass()
assertEquals(ClassKind.INTERFACE, clazz.clazz.kind)
}
fun `test supertypes`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
interface A
interface B: A
@@ -118,19 +118,19 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test abstract class`() {
val module = deserializeSourceFile("abstract class X")
val module = createCirTreeFromSourceCode("abstract class X")
val clazz = module.assertSingleClass()
assertEquals(Modality.ABSTRACT, clazz.clazz.modality)
}
fun `test open class`() {
val module = deserializeSourceFile("open class X")
val module = createCirTreeFromSourceCode("open class X")
val clazz = module.assertSingleClass()
assertEquals(Modality.OPEN, clazz.clazz.modality)
}
fun `test class with properties functions and nested classes`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
class X {
val myInt: Int = 42
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.commonizer.tree.deserializer
import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.utils.createCirTree
import org.jetbrains.kotlin.descriptors.ClassKind
import kotlin.test.assertEquals
import kotlin.test.assertIs
@@ -13,11 +14,11 @@ import kotlin.test.assertIs
class CirTreeDependenciesDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test deserialize with dependencies`() {
val module = deserializeModule {
val module = createCirTree {
dependency {
source("dependencies.kt", "interface Dependency")
source("interface Dependency", "dependencies.kt")
}
source("source.kt", "object X: Dependency")
source("object X: Dependency", "source.kt")
}
val xObject = module.assertSingleClass()
@@ -16,7 +16,7 @@ import kotlin.test.*
class CirTreeFunctionDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple function`() {
val module = deserializeSourceFile("fun x() = Unit")
val module = createCirTreeFromSourceCode("fun x() = Unit")
val (_, function) = module.assertSingleFunction()
assertNull(function.containingClass, "Expected function to *not* have containing class")
@@ -29,7 +29,7 @@ class CirTreeFunctionDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test generic function`() {
val module = deserializeSourceFile("""fun <T: Any> T.isHappy(): Boolean = true""")
val module = createCirTreeFromSourceCode("""fun <T: Any> T.isHappy(): Boolean = true""")
val (_, function) = module.assertSingleFunction()
val extensionReceiver = assertNotNull(function.extensionReceiver, "Expected function being extension receiver")
@@ -50,7 +50,7 @@ class CirTreeFunctionDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test function with outer object`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
object Parent {
fun x(): String = "Hello, you're reading a test"
@@ -5,37 +5,39 @@
package org.jetbrains.kotlin.commonizer.tree.deserializer
import org.jetbrains.kotlin.commonizer.utils.createCirTree
class CirTreePackageDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test package with multiple classes properties and functions`() {
val module = deserializeModule {
val module = createCirTree {
source(
"root.kt", """
"""
typealias rootTypeAlias = Int
val rootProperty: String = "hello,"
fun rootFunction(): String = "it is me"
class RootClass
""".trimIndent()
""".trimIndent(), "root.kt"
)
source(
"pkg1.kt", """
"""
package test.pkg1
typealias pkg1TypeAlias = Int
val pkg1Property: Int = 42
fun pkg1Function(): String = "answer"
class Pkg1
""".trimIndent()
""".trimIndent(), "pkg1.kt"
)
source(
"pkg2.kt", """
"""
package test.pkg2
typealias pkg2TypeAlias = Int
val pkg2Property: Int = 42
fun pkg2Function(): String = "answer"
class Pkg2
""".trimIndent()
""".trimIndent(), "pkg2.kt"
)
}
@@ -16,7 +16,7 @@ import kotlin.test.*
class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple val property`() {
val module = deserializeSourceFile("val x: Int = 42")
val module = createCirTreeFromSourceCode("val x: Int = 42")
val (key, property) = module.assertSingleProperty()
assertEquals(PropertyApproximationKey(CirName.Companion.create("x"), null), key)
@@ -32,7 +32,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test simple var property`() {
val module = deserializeSourceFile("var x: Int = 42")
val module = createCirTreeFromSourceCode("var x: Int = 42")
val (_, property) = module.assertSingleProperty()
assertNotNull(property.getter, "Expected property has getter")
assertNotNull(property.setter, "Expected property has setter")
@@ -41,7 +41,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test lateinit var property`() {
val module = deserializeSourceFile("lateinit var x: Int")
val module = createCirTreeFromSourceCode("lateinit var x: Int")
val (_, property) = module.assertSingleProperty()
assertNotNull(property.getter, "Expected property has getter")
@@ -51,7 +51,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test generic var property`() {
val module = deserializeSourceFile("var <T> T.x: T get() = this")
val module = createCirTreeFromSourceCode("var <T> T.x: T get() = this")
val (_, property) = module.assertSingleProperty()
assertNotNull(property.extensionReceiver, "Expected property has extension receiver")
@@ -62,7 +62,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test multiple properties`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
val x: Int = 42
val y: Float = 42f
@@ -18,7 +18,7 @@ import kotlin.test.assertIs
class CirTreeTypeAliasDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple type alias`() {
val module = deserializeSourceFile("typealias x = Int")
val module = createCirTreeFromSourceCode("typealias x = Int")
val typeAlias = module.assertSingleTypeAlias().typeAlias
assertEquals(CirName.create("x"), typeAlias.name, "Expected correct type alias name")
assertEquals("kotlin/Int", typeAlias.expandedType.toString())
@@ -26,7 +26,7 @@ class CirTreeTypeAliasDeserializerTest : AbstractCirTreeDeserializerTest() {
}
fun `test transitive type alias`() {
val module = deserializeSourceFile(
val module = createCirTreeFromSourceCode(
"""
interface Map<K, V>
typealias IntMap<V> = Map<Int, V>
@@ -8,16 +8,16 @@ package org.jetbrains.kotlin.commonizer.tree.merge
class MergeCirTreeClassConstructorTest : AbstractMergeCirTreeTest() {
fun `test simple constructors`() {
val aTree = deserializeSourceFile("class X(val x: Int)")
val bTree = deserializeSourceFile("class X(val x: Int)")
val aTree = createCirTreeFromSourceCode("class X(val x: Int)")
val bTree = createCirTreeFromSourceCode("class X(val x: Int)")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val constructor = merged.assertSingleModule().assertSinglePackage().assertSingleClass().assertSingleConstructor()
constructor.assertNoMissingTargetDeclaration()
}
fun `test missing target declaration`() {
val aTree = deserializeSourceFile("class X(val a: Int)")
val bTree = deserializeSourceFile("class X(val b: Short)")
val aTree = createCirTreeFromSourceCode("class X(val a: Int)")
val bTree = createCirTreeFromSourceCode("class X(val b: Short)")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val clazz = merged.assertSingleModule().assertSinglePackage().assertSingleClass()
kotlin.test.assertEquals(2, clazz.constructors.size, "Expected two constructors")
@@ -10,16 +10,16 @@ import org.jetbrains.kotlin.commonizer.mergedtree.PropertyApproximationKey
class MergeCirTreeClassTest : AbstractMergeCirTreeTest() {
fun `test simple class`() {
val aTree = deserializeSourceFile("class X")
val bTree = deserializeSourceFile("class X")
val aTree = createCirTreeFromSourceCode("class X")
val bTree = createCirTreeFromSourceCode("class X")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val clazz = merged.assertSingleModule().assertSinglePackage().assertSingleClass()
clazz.assertNoMissingTargetDeclaration()
}
fun `test missing target declarations`() {
val aTree = deserializeSourceFile("class A")
val bTree = deserializeSourceFile("class B")
val aTree = createCirTreeFromSourceCode("class A")
val bTree = createCirTreeFromSourceCode("class B")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val pkg = merged.assertSingleModule().assertSinglePackage()
kotlin.test.assertEquals(2, pkg.classes.size, "Expected two classes (A, B)")
@@ -31,7 +31,7 @@ class MergeCirTreeClassTest : AbstractMergeCirTreeTest() {
}
fun `test with children`() {
val aTree = deserializeSourceFile(
val aTree = createCirTreeFromSourceCode(
"""
class X {
val x: Int = 42
@@ -40,7 +40,7 @@ class MergeCirTreeClassTest : AbstractMergeCirTreeTest() {
""".trimIndent()
)
val bTree = deserializeSourceFile(
val bTree = createCirTreeFromSourceCode(
"""
class X {
val x: Int = 42
@@ -8,8 +8,8 @@ package org.jetbrains.kotlin.commonizer.tree.merge
class MergeCirTreeFunctionTest : AbstractMergeCirTreeTest() {
fun `test simple function`() {
val aTree = deserializeSourceFile("fun x(): Int = 42")
val bTree = deserializeSourceFile("fun x(): Int = 42")
val aTree = createCirTreeFromSourceCode("fun x(): Int = 42")
val bTree = createCirTreeFromSourceCode("fun x(): Int = 42")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val function = merged.assertSingleModule().assertSinglePackage().assertSingleFunction()
@@ -22,8 +22,8 @@ class MergeCirTreeFunctionTest : AbstractMergeCirTreeTest() {
}
fun `test missing target declarations`() {
val aTree = deserializeSourceFile("fun a(): Int = 42")
val bTree = deserializeSourceFile("fun b(): Int = 42")
val aTree = createCirTreeFromSourceCode("fun a(): Int = 42")
val bTree = createCirTreeFromSourceCode("fun b(): Int = 42")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val pkg = merged.assertSingleModule().assertSinglePackage()
@@ -11,8 +11,8 @@ import org.jetbrains.kotlin.commonizer.cir.CirPackageName
class MergeCirTreePackageTest : AbstractMergeCirTreeTest() {
fun `test simple package`() {
val aTree = deserializeSourceFile("package test.pkg")
val bTree = deserializeSourceFile("package test.pkg")
val aTree = createCirTreeFromSourceCode("package test.pkg")
val bTree = createCirTreeFromSourceCode("package test.pkg")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val module = merged.assertSingleModule()
kotlin.test.assertEquals(3, module.packages.size, "Expected 3 packages (root, test, test.pkg)")
@@ -28,8 +28,8 @@ class MergeCirTreePackageTest : AbstractMergeCirTreeTest() {
}
fun `test missing target declarations`() {
val aTree = deserializeSourceFile("package a")
val bTree = deserializeSourceFile("package b")
val aTree = createCirTreeFromSourceCode("package a")
val bTree = createCirTreeFromSourceCode("package b")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val module = merged.assertSingleModule()
kotlin.test.assertEquals(3, module.packages.size, "Expected 3 packages (root, a, b)")
@@ -14,8 +14,8 @@ import kotlin.test.assertNotNull
class MergeCirTreePropertyTest : AbstractMergeCirTreeTest() {
fun `test simple property`() {
val aTree = deserializeSourceFile("""val a: Int = 42""")
val bTree = deserializeSourceFile("""val a: Int = 42""")
val aTree = createCirTreeFromSourceCode("""val a: Int = 42""")
val bTree = createCirTreeFromSourceCode("""val a: Int = 42""")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val property = merged.assertSingleModule().assertSinglePackage().assertSingleProperty()
@@ -27,7 +27,7 @@ class MergeCirTreePropertyTest : AbstractMergeCirTreeTest() {
}
fun `test multiple properties`() {
val aTree = deserializeSourceFile(
val aTree = createCirTreeFromSourceCode(
"""
val a: Int = 42
val b: Int = 42
@@ -35,7 +35,7 @@ class MergeCirTreePropertyTest : AbstractMergeCirTreeTest() {
""".trimIndent()
)
val bTree = deserializeSourceFile(
val bTree = createCirTreeFromSourceCode(
"""
val a: Int = 42
val b: Int = 42
@@ -57,8 +57,8 @@ class MergeCirTreePropertyTest : AbstractMergeCirTreeTest() {
}
fun `test missing target declarations`() {
val aTree = deserializeSourceFile("val a: Int = 42")
val bTree = deserializeSourceFile("val b: Int = 42")
val aTree = createCirTreeFromSourceCode("val a: Int = 42")
val bTree = createCirTreeFromSourceCode("val b: Int = 42")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val pkg = merged.assertSingleModule().assertSinglePackage()
@@ -11,16 +11,16 @@ import kotlin.test.assertEquals
class MergeCirTreeTypeAliasTest : AbstractMergeCirTreeTest() {
fun `test simple type alias`() {
val aTree = deserializeSourceFile("typealias a = Int")
val bTree = deserializeSourceFile("typealias a = Int")
val aTree = createCirTreeFromSourceCode("typealias a = Int")
val bTree = createCirTreeFromSourceCode("typealias a = Int")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val typeAlias = merged.assertSingleModule().assertSinglePackage().assertSingleTypeAlias()
typeAlias.assertNoMissingTargetDeclaration()
}
fun `test missing target declarations`() {
val aTree = deserializeSourceFile("typealias a = Int")
val bTree = deserializeSourceFile("typealias b = Int")
val aTree = createCirTreeFromSourceCode("typealias a = Int")
val bTree = createCirTreeFromSourceCode("typealias b = Int")
val merged = mergeCirTree("a" to aTree, "b" to bTree)
val pkg = merged.assertSingleModule().assertSinglePackage()
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2021 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.commonizer.utils
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.commonizer.tree.CirTreeModule
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.library.SerializedMetadata
interface InlineSourceBuilder {
annotation class ModuleBuilderDsl
data class SourceFile(val name: String, @Language("kotlin") val content: String)
data class Module(
val name: String, val sourceFiles: List<SourceFile>, val dependencies: List<Module>
)
@ModuleBuilderDsl
class ModuleBuilder {
var name: String = "test-module"
private var sourceFiles: List<SourceFile> = emptyList()
private var dependencies: List<Module> = emptyList()
@ModuleBuilderDsl
fun source(@Language("kotlin") content: String, name: String = "test.kt") {
sourceFiles = sourceFiles + SourceFile(name, content)
}
@ModuleBuilderDsl
fun dependency(builder: ModuleBuilder.() -> Unit) {
dependency(ModuleBuilder().also(builder).build())
}
@ModuleBuilderDsl
fun dependency(module: Module) {
this.dependencies += module.copy(name = "${this.name}-dependency-${module.name}-${dependencies.size}")
}
fun build(): Module = Module(name, sourceFiles.toList(), dependencies.toList())
}
fun createModule(builder: ModuleBuilder.() -> Unit): Module {
return ModuleBuilder().also(builder).build()
}
fun createCirTreeFromSourceCode(@Language("kotlin") sourceCode: String): CirTreeModule {
return createCirTree {
source(content = sourceCode, "test.kt")
}
}
fun createCirTree(module: Module): CirTreeModule
fun createModuleDescriptor(module: Module): ModuleDescriptor
fun createMetadata(module: Module): SerializedMetadata = createModuleDescriptor(module).toMetadata()
}
@InlineSourceBuilder.ModuleBuilderDsl
fun InlineSourceBuilder.createCirTree(builder: InlineSourceBuilder.ModuleBuilder.() -> Unit): CirTreeModule {
return createCirTree(createModule(builder))
}
@InlineSourceBuilder.ModuleBuilderDsl
fun InlineSourceBuilder.createModuleDescriptor(builder: InlineSourceBuilder.ModuleBuilder.() -> Unit): ModuleDescriptor {
return createModuleDescriptor(createModule(builder))
}
@InlineSourceBuilder.ModuleBuilderDsl
fun InlineSourceBuilder.createMetadata(builder: InlineSourceBuilder.ModuleBuilder.() -> Unit): SerializedMetadata {
return createMetadata(createModule(builder))
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2021 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.commonizer.utils
import org.jetbrains.kotlin.commonizer.tree.CirTreeModule
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
internal interface InlineSourceBuilderDelegate : InlineSourceBuilder {
val inlineSourceBuilder: InlineSourceBuilder
override fun createCirTree(module: InlineSourceBuilder.Module): CirTreeModule {
return inlineSourceBuilder.createCirTree(module)
}
override fun createModuleDescriptor(module: InlineSourceBuilder.Module): ModuleDescriptor {
return inlineSourceBuilder.createModuleDescriptor(module)
}
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.commonizer.utils
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.io.FileUtil
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
@@ -20,7 +19,6 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
import org.jetbrains.kotlin.commonizer.tree.CirTreeModule
import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeModuleDeserializer
import org.jetbrains.kotlin.commonizer.utils.InlineSourceTest.Module
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -37,66 +35,8 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File
interface InlineSourceTest {
annotation class ModuleBuilderDsl
data class SourceFile(val name: String, @Language("kotlin") val content: String)
data class Module(
val name: String, val sourceFiles: List<SourceFile>, val dependencies: List<Module>
)
@ModuleBuilderDsl
class ModuleBuilder {
var name: String = "test-module"
private var sourceFiles: List<SourceFile> = emptyList()
private var dependencies: List<Module> = emptyList()
@ModuleBuilderDsl
fun source(name: String = "test.kt", @Language("kotlin") content: String) {
sourceFiles = sourceFiles + SourceFile(name, content)
}
@ModuleBuilderDsl
fun dependency(builder: ModuleBuilder.() -> Unit) {
val dependency = ModuleBuilder().also(builder).build().run {
copy(name = "$name-dependency-${dependencies.size}")
}
dependencies = dependencies + dependency
}
fun build(): Module = Module(name, sourceFiles.toList(), dependencies.toList())
}
@ModuleBuilderDsl
fun module(builder: ModuleBuilder.() -> Unit): Module {
return ModuleBuilder().also(builder).build()
}
fun deserializeSourceFile(@Language("kotlin") sourceFileContent: String): CirTreeModule {
return deserializeModule {
source("test.kt", content = sourceFileContent)
}
}
fun deserializeModule(builder: ModuleBuilder.() -> Unit): CirTreeModule {
return deserializeModule(module(builder))
}
fun deserializeModule(module: Module): CirTreeModule
}
internal interface InlineSourceTestDelegate : InlineSourceTest {
val inlineSourceTest: InlineSourceTest
override fun deserializeModule(module: Module): CirTreeModule {
return inlineSourceTest.deserializeModule(module)
}
}
class InlineSourceTestImpl(private val disposable: Disposable) : InlineSourceTest {
override fun deserializeModule(module: Module): CirTreeModule {
class InlineSourceBuilderImpl(private val disposable: Disposable) : InlineSourceBuilder {
override fun createCirTree(module: InlineSourceBuilder.Module): CirTreeModule {
val moduleDescriptor = createModuleDescriptor(module)
val metadata = MockModulesProvider.SERIALIZER.serializeModule(moduleDescriptor)
@@ -113,7 +53,7 @@ class InlineSourceTestImpl(private val disposable: Disposable) : InlineSourceTes
return defaultCirTreeModuleDeserializer(metadata, typeResolver)
}
private fun createModuleDescriptor(module: Module): ModuleDescriptor {
override fun createModuleDescriptor(module: InlineSourceBuilder.Module): ModuleDescriptor {
val moduleRoot = FileUtil.createTempDirectory(module.name, null)
module.sourceFiles.forEach { sourceFile ->
moduleRoot.resolve(sourceFile.name).writeText(sourceFile.content)
@@ -121,7 +61,7 @@ class InlineSourceTestImpl(private val disposable: Disposable) : InlineSourceTes
return createModuleDescriptor(moduleRoot, module)
}
private fun createModuleDescriptor(moduleRoot: File, module: Module): ModuleDescriptor {
private fun createModuleDescriptor(moduleRoot: File, module: InlineSourceBuilder.Module): ModuleDescriptor {
check(Name.isValidIdentifier(module.name))
val configuration = KotlinTestUtils.newConfiguration()
configuration.put(CommonConfigurationKeys.MODULE_NAME, module.name)
@@ -153,14 +93,14 @@ class InlineSourceTestImpl(private val disposable: Disposable) : InlineSourceTes
}
private inner class DependenciesContainerImpl(
dependencies: List<Module>
dependencies: List<InlineSourceBuilder.Module>
) : CommonDependenciesContainer {
private val dependenciesByModuleInfos = dependencies.associate { module ->
ModuleInfoImpl(module) to createModuleDescriptor(module)
}
private inner class ModuleInfoImpl(module: Module) : ModuleInfo {
private inner class ModuleInfoImpl(module: InlineSourceBuilder.Module) : ModuleInfo {
private val dependencyModules = module.dependencies.associateBy(::ModuleInfoImpl)
override val name: Name = Name.special("<${module.name}>")
override fun dependencies(): List<ModuleInfo> = listOf(this) + dependencyModules.keys
@@ -7,6 +7,6 @@ package org.jetbrains.kotlin.commonizer.utils
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
abstract class KtInlineSourceCommonizerTestCase : KtUsefulTestCase(), InlineSourceTestDelegate {
override val inlineSourceTest: InlineSourceTest = InlineSourceTestImpl(testRootDisposable)
abstract class KtInlineSourceCommonizerTestCase : KtUsefulTestCase(), InlineSourceBuilderDelegate {
override val inlineSourceBuilder: InlineSourceBuilder = InlineSourceBuilderImpl(testRootDisposable)
}
@@ -22,7 +22,7 @@ fun assertIsDirectory(file: File) {
fail("Not a directory: $file")
}
@ExperimentalContracts
@OptIn(ExperimentalContracts::class)
fun assertModulesAreEqual(reference: SerializedMetadata, generated: SerializedMetadata, target: CommonizerTarget) {
val referenceModule = KlibModuleMetadata.read(SerializedMetadataLibraryProvider(reference))
val generatedModule = KlibModuleMetadata.read(SerializedMetadataLibraryProvider(generated))
@@ -39,7 +39,10 @@ fun assertModulesAreEqual(reference: SerializedMetadata, generated: SerializedMe
val digitCount = mismatches.size.toString().length
val failureMessage = buildString {
appendLine("${mismatches.size} mismatches found while comparing reference module ${referenceModule.name} (A) and generated module ${generatedModule.name} (B) for target ${target.identityString}:")
appendLine(
"${mismatches.size} mismatches found while comparing reference module ${referenceModule.name} (A) " +
"and generated module ${generatedModule.name} (B) for target ${target.identityString}:"
)
mismatches.forEachIndexed { index, mismatch ->
appendLine((index + 1).toString().padStart(digitCount, ' ') + ". " + mismatch)
}
@@ -129,6 +129,8 @@ internal class MockModulesProvider private constructor(
}
}
fun ModuleDescriptor.toMetadata(): SerializedMetadata = MockModulesProvider.SERIALIZER.serializeModule(this)
private typealias ModuleName = String
private typealias ModuleResults = HashMap<ModuleName, ModuleResult>
@@ -146,7 +148,7 @@ internal class MockResultsConsumer : ResultsConsumer {
override fun consume(target: CommonizerTarget, moduleResult: ModuleResult) {
check(!this::status.isInitialized)
check(target !in finishedTargets)
check(target !in finishedTargets) { "$target already finished"}
val moduleResults: ModuleResults = _modulesByTargets.getOrPut(target) { ModuleResults() }
val oldResult = moduleResults.put(moduleResult.libraryName, moduleResult)
check(oldResult == null) // to avoid accidental overwriting