[IR][tests] Support friend-dependencies in KLIB ABI compatibility tests
This commit is contained in:
@@ -18,8 +18,8 @@ object KlibABITestUtils {
|
|||||||
val buildDir: File
|
val buildDir: File
|
||||||
val stdlibFile: File
|
val stdlibFile: File
|
||||||
|
|
||||||
fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection<File>, klibFile: File)
|
fun buildKlib(moduleName: String, moduleSourceDir: File, dependencies: Dependencies, klibFile: File)
|
||||||
fun buildBinaryAndRun(mainModuleKlibFile: File, allDependencies: Collection<File>)
|
fun buildBinaryAndRun(mainModuleKlibFile: File, dependencies: Dependencies)
|
||||||
|
|
||||||
fun onNonEmptyBuildDirectory(directory: File)
|
fun onNonEmptyBuildDirectory(directory: File)
|
||||||
|
|
||||||
@@ -27,6 +27,15 @@ object KlibABITestUtils {
|
|||||||
fun onIgnoredTest()
|
fun onIgnoredTest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Dependencies(val regularDependencies: Set<File>, val friendDependencies: Set<File>) {
|
||||||
|
fun mergeWith(other: Dependencies): Dependencies =
|
||||||
|
Dependencies(regularDependencies + other.regularDependencies, friendDependencies + other.friendDependencies)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val EMPTY = Dependencies(emptySet(), emptySet())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun runTest(testConfiguration: TestConfiguration) = with(testConfiguration) {
|
fun runTest(testConfiguration: TestConfiguration) = with(testConfiguration) {
|
||||||
val projectName = testDir.name
|
val projectName = testDir.name
|
||||||
|
|
||||||
@@ -70,6 +79,9 @@ object KlibABITestUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect all dependencies for building the final binary file.
|
||||||
|
var binaryDependencies = Dependencies.EMPTY
|
||||||
|
|
||||||
projectInfo.steps.forEach { projectStep ->
|
projectInfo.steps.forEach { projectStep ->
|
||||||
projectStep.order.forEach { moduleName ->
|
projectStep.order.forEach { moduleName ->
|
||||||
val (moduleInfo, moduleTestDir, moduleBuildDirs, klibFile) = modulesMap[moduleName]
|
val (moduleInfo, moduleTestDir, moduleBuildDirs, klibFile) = modulesMap[moduleName]
|
||||||
@@ -84,24 +96,31 @@ object KlibABITestUtils {
|
|||||||
if (!moduleBuildDirs.outputDir.list().isNullOrEmpty())
|
if (!moduleBuildDirs.outputDir.list().isNullOrEmpty())
|
||||||
onNonEmptyBuildDirectory(moduleBuildDirs.outputDir)
|
onNonEmptyBuildDirectory(moduleBuildDirs.outputDir)
|
||||||
|
|
||||||
val moduleDependencies = moduleStep.dependencies.map { dependencyName ->
|
val regularDependencies = hashSetOf<File>()
|
||||||
if (dependencyName == "stdlib")
|
val friendDependencies = hashSetOf<File>()
|
||||||
stdlibFile
|
|
||||||
else
|
moduleStep.dependencies.forEach { dependency ->
|
||||||
modulesMap[dependencyName]?.klibFile ?: fail { "No module $dependencyName found on step ${projectStep.id}" }
|
if (dependency.moduleName == "stdlib")
|
||||||
|
regularDependencies += stdlibFile
|
||||||
|
else {
|
||||||
|
val moduleFile = modulesMap[dependency.moduleName]?.klibFile
|
||||||
|
?: fail { "No module ${dependency.moduleName} found on step ${projectStep.id}" }
|
||||||
|
regularDependencies += moduleFile
|
||||||
|
if (dependency.isFriend) friendDependencies += moduleFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildKlib(moduleInfo.moduleName, moduleBuildDirs.sourceDir, moduleDependencies, klibFile)
|
val dependencies = Dependencies(regularDependencies, friendDependencies)
|
||||||
|
binaryDependencies = binaryDependencies.mergeWith(dependencies)
|
||||||
|
|
||||||
|
buildKlib(moduleInfo.moduleName, moduleBuildDirs.sourceDir, dependencies, klibFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val mainModuleKlibFile = modulesMap[MAIN_MODULE_NAME]?.klibFile ?: fail { "No main module $MAIN_MODULE_NAME found" }
|
val mainModuleKlibFile = modulesMap[MAIN_MODULE_NAME]?.klibFile ?: fail { "No main module $MAIN_MODULE_NAME found" }
|
||||||
val allKlibs = buildSet {
|
binaryDependencies = binaryDependencies.mergeWith(Dependencies(setOf(mainModuleKlibFile), emptySet()))
|
||||||
this += stdlibFile
|
|
||||||
modulesMap.mapTo(this) { (_, module) -> module.klibFile }
|
|
||||||
}
|
|
||||||
|
|
||||||
buildBinaryAndRun(mainModuleKlibFile, allKlibs)
|
buildBinaryAndRun(mainModuleKlibFile, binaryDependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copySources(from: File, to: File) {
|
private fun copySources(from: File, to: File) {
|
||||||
|
|||||||
@@ -41,9 +41,11 @@ class ModuleInfo(val moduleName: String) {
|
|||||||
abstract fun execute(testDirectory: File, sourceDirectory: File, deletedFilesCollector: (File) -> Unit = {})
|
abstract fun execute(testDirectory: File, sourceDirectory: File, deletedFilesCollector: (File) -> Unit = {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Dependency(val moduleName: String, val isFriend: Boolean)
|
||||||
|
|
||||||
class ModuleStep(
|
class ModuleStep(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val dependencies: Collection<String>,
|
val dependencies: Collection<Dependency>,
|
||||||
val modifications: List<Modification>,
|
val modifications: List<Modification>,
|
||||||
val expectedFileStats: Map<String, Set<String>>
|
val expectedFileStats: Map<String, Set<String>>
|
||||||
)
|
)
|
||||||
@@ -51,9 +53,18 @@ class ModuleInfo(val moduleName: String) {
|
|||||||
val steps = mutableListOf<ModuleStep>()
|
val steps = mutableListOf<ModuleStep>()
|
||||||
}
|
}
|
||||||
|
|
||||||
const val MODULES_LIST = "MODULES"
|
|
||||||
const val PROJECT_INFO_FILE = "project.info"
|
const val PROJECT_INFO_FILE = "project.info"
|
||||||
|
private const val MODULES_LIST = "MODULES"
|
||||||
|
private const val LIBS_LIST = "libs"
|
||||||
|
private const val DIRTY_JS_MODULES_LIST = "dirty js"
|
||||||
|
private const val LANGUAGE = "language"
|
||||||
|
|
||||||
const val MODULE_INFO_FILE = "module.info"
|
const val MODULE_INFO_FILE = "module.info"
|
||||||
|
private const val DEPENDENCIES = "dependencies"
|
||||||
|
private const val FRIENDS = "friends"
|
||||||
|
private const val MODIFICATIONS = "modifications"
|
||||||
|
private const val MODIFICATION_UPDATE = "U"
|
||||||
|
private const val MODIFICATION_DELETE = "D"
|
||||||
|
|
||||||
private val STEP_PATTERN = Pattern.compile("^\\s*STEP\\s+(\\d+)\\.*(\\d+)?\\s*:?$")
|
private val STEP_PATTERN = Pattern.compile("^\\s*STEP\\s+(\\d+)\\.*(\\d+)?\\s*:?$")
|
||||||
|
|
||||||
@@ -104,8 +115,8 @@ class ProjectInfoParser(infoFile: File) : InfoParser<ProjectInfo>(infoFile) {
|
|||||||
val splitIndex = line.indexOf(':')
|
val splitIndex = line.indexOf(':')
|
||||||
if (splitIndex < 0) throwSyntaxError(line)
|
if (splitIndex < 0) throwSyntaxError(line)
|
||||||
|
|
||||||
val splitted = line.split(":")
|
val split = line.split(":")
|
||||||
val op = splitted[0]
|
val op = split[0]
|
||||||
|
|
||||||
if (op.matches(STEP_PATTERN.toRegex())) {
|
if (op.matches(STEP_PATTERN.toRegex())) {
|
||||||
return@loop true // break the loop
|
return@loop true // break the loop
|
||||||
@@ -115,15 +126,9 @@ class ProjectInfoParser(infoFile: File) : InfoParser<ProjectInfo>(infoFile) {
|
|||||||
|
|
||||||
|
|
||||||
when (op) {
|
when (op) {
|
||||||
"libs" -> {
|
LIBS_LIST -> order += split[1].splitAndTrim()
|
||||||
order += splitted[1].splitAndTrim()
|
DIRTY_JS_MODULES_LIST -> dirtyJS += split[1].splitAndTrim()
|
||||||
}
|
LANGUAGE -> language += split[1].splitAndTrim()
|
||||||
"dirty js" -> {
|
|
||||||
dirtyJS += splitted[1].splitAndTrim()
|
|
||||||
}
|
|
||||||
"language" -> {
|
|
||||||
language += splitted[1].splitAndTrim()
|
|
||||||
}
|
|
||||||
else -> println(diagnosticMessage("Unknown op $op", line))
|
else -> println(diagnosticMessage("Unknown op $op", line))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +154,11 @@ class ProjectInfoParser(infoFile: File) : InfoParser<ProjectInfo>(infoFile) {
|
|||||||
val splitIndex = line.indexOf(':')
|
val splitIndex = line.indexOf(':')
|
||||||
if (splitIndex < 0) throwSyntaxError(line)
|
if (splitIndex < 0) throwSyntaxError(line)
|
||||||
|
|
||||||
val splitted = line.split(":")
|
val split = line.split(":")
|
||||||
val op = splitted[0]
|
val op = split[0]
|
||||||
|
|
||||||
when {
|
when {
|
||||||
op == MODULES_LIST -> {
|
op == MODULES_LIST -> libraries += split[1].splitAndTrim()
|
||||||
libraries += splitted[1].splitAndTrim()
|
|
||||||
}
|
|
||||||
op.matches(STEP_PATTERN.toRegex()) -> {
|
op.matches(STEP_PATTERN.toRegex()) -> {
|
||||||
val m = STEP_PATTERN.matcher(op)
|
val m = STEP_PATTERN.matcher(op)
|
||||||
if (!m.matches()) throwSyntaxError(line)
|
if (!m.matches()) throwSyntaxError(line)
|
||||||
@@ -164,7 +167,7 @@ class ProjectInfoParser(infoFile: File) : InfoParser<ProjectInfo>(infoFile) {
|
|||||||
val lastId = m.group(2)?.let { Integer.parseInt(it) } ?: firstId
|
val lastId = m.group(2)?.let { Integer.parseInt(it) } ?: firstId
|
||||||
steps += parseSteps(firstId, lastId)
|
steps += parseSteps(firstId, lastId)
|
||||||
}
|
}
|
||||||
else -> println(diagnosticMessage("Unknown op $op", line))
|
else -> error(diagnosticMessage("Unknown op $op", line))
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
@@ -186,11 +189,11 @@ class ModuleInfoParser(infoFile: File) : InfoParser<ModuleInfo>(infoFile) {
|
|||||||
val mop = matcher3.group(1)
|
val mop = matcher3.group(1)
|
||||||
val cmd = matcher3.group(2)
|
val cmd = matcher3.group(2)
|
||||||
when (mop) {
|
when (mop) {
|
||||||
"U" -> {
|
MODIFICATION_UPDATE -> {
|
||||||
val (from, to) = cmd.split("->")
|
val (from, to) = cmd.split("->")
|
||||||
modifications.add(ModuleInfo.Modification.Update(from.trim(), to.trim()))
|
modifications.add(ModuleInfo.Modification.Update(from.trim(), to.trim()))
|
||||||
}
|
}
|
||||||
"D" -> modifications.add(ModuleInfo.Modification.Delete(cmd.trim()))
|
MODIFICATION_DELETE -> modifications.add(ModuleInfo.Modification.Delete(cmd.trim()))
|
||||||
else -> error("Unknown modification $line")
|
else -> error("Unknown modification $line")
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
@@ -204,7 +207,8 @@ class ModuleInfoParser(infoFile: File) : InfoParser<ModuleInfo>(infoFile) {
|
|||||||
|
|
||||||
private fun parseSteps(firstId: Int, lastId: Int): List<ModuleInfo.ModuleStep> {
|
private fun parseSteps(firstId: Int, lastId: Int): List<ModuleInfo.ModuleStep> {
|
||||||
val expectedFileStats = mutableMapOf<String, Set<String>>()
|
val expectedFileStats = mutableMapOf<String, Set<String>>()
|
||||||
val dependencies = mutableSetOf<String>()
|
val regularDependencies = mutableSetOf<String>()
|
||||||
|
val friendDependencies = mutableSetOf<String>()
|
||||||
val modifications = mutableListOf<ModuleInfo.Modification>()
|
val modifications = mutableListOf<ModuleInfo.Modification>()
|
||||||
|
|
||||||
loop { line ->
|
loop { line ->
|
||||||
@@ -223,15 +227,24 @@ class ModuleInfoParser(infoFile: File) : InfoParser<ModuleInfo>(infoFile) {
|
|||||||
expectedFileStats[expectedState.str] = getOpArgs().toSet()
|
expectedFileStats[expectedState.str] = getOpArgs().toSet()
|
||||||
} else {
|
} else {
|
||||||
when (op) {
|
when (op) {
|
||||||
"dependencies" -> getOpArgs().forEach { dependencies.add(it) }
|
DEPENDENCIES -> getOpArgs().forEach { regularDependencies += it }
|
||||||
"modifications" -> modifications.addAll(parseModifications())
|
FRIENDS -> getOpArgs().forEach { friendDependencies += it }
|
||||||
else -> println(diagnosticMessage("Unknown op $op", line))
|
MODIFICATIONS -> modifications += parseModifications()
|
||||||
|
else -> error(diagnosticMessage("Unknown op $op", line))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(friendDependencies - regularDependencies)
|
||||||
|
.takeIf(Set<String>::isNotEmpty)
|
||||||
|
?.let { error("Misconfiguration: There are friend modules that are not listed as regular dependencies: $it") }
|
||||||
|
|
||||||
|
val dependencies = regularDependencies.map { regularDependency ->
|
||||||
|
ModuleInfo.Dependency(regularDependency, regularDependency in friendDependencies)
|
||||||
|
}
|
||||||
|
|
||||||
return (firstId..lastId).map {
|
return (firstId..lastId).map {
|
||||||
ModuleInfo.ModuleStep(
|
ModuleInfo.ModuleStep(
|
||||||
id = it,
|
id = it,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
private const val BOX_FUNCTION_NAME = "box"
|
private const val BOX_FUNCTION_NAME = "box"
|
||||||
private const val STDLIB_ALIAS = "stdlib"
|
private const val STDLIB_ALIAS = "stdlib"
|
||||||
|
|
||||||
private val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
||||||
private val STDLIB_KLIB = File(System.getProperty("kotlin.js.stdlib.klib.path") ?: error("Please set stdlib path")).canonicalPath
|
private val STDLIB_KLIB = File(System.getProperty("kotlin.js.stdlib.klib.path") ?: error("Please set stdlib path")).canonicalPath
|
||||||
|
|
||||||
private val KT_FILE_IGNORE_PATTERN = Regex("^.*\\..+\\.kt$")
|
private val KT_FILE_IGNORE_PATTERN = Regex("^.*\\..+\\.kt$")
|
||||||
@@ -139,7 +139,9 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
modification.execute(moduleTestDir, moduleSourceDir) { deletedFiles.add(it.name) }
|
modification.execute(moduleTestDir, moduleSourceDir) { deletedFiles.add(it.name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val dependencies = moduleStep.dependencies.mapTo(mutableListOf(File(STDLIB_KLIB))) { resolveModuleArtifact(it, buildDir) }
|
val dependencies = moduleStep.dependencies.mapTo(mutableListOf(File(STDLIB_KLIB))) {
|
||||||
|
resolveModuleArtifact(it.moduleName, buildDir)
|
||||||
|
}
|
||||||
val outputKlibFile = resolveModuleArtifact(module, buildDir)
|
val outputKlibFile = resolveModuleArtifact(module, buildDir)
|
||||||
val configuration = createConfiguration(module, projStep.language)
|
val configuration = createConfiguration(module, projStep.language)
|
||||||
buildArtifact(configuration, module, moduleSourceDir, dependencies, outputKlibFile)
|
buildArtifact(configuration, module, moduleSourceDir, dependencies, outputKlibFile)
|
||||||
|
|||||||
@@ -71,11 +71,11 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
|||||||
override val buildDir: File get() = this@AbstractJsKLibABITestCase.buildDir
|
override val buildDir: File get() = this@AbstractJsKLibABITestCase.buildDir
|
||||||
override val stdlibFile: File get() = File("libraries/stdlib/js-ir/build/classes/kotlin/js/main").absoluteFile
|
override val stdlibFile: File get() = File("libraries/stdlib/js-ir/build/classes/kotlin/js/main").absoluteFile
|
||||||
|
|
||||||
override fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection<File>, klibFile: File) =
|
override fun buildKlib(moduleName: String, moduleSourceDir: File, dependencies: KlibABITestUtils.Dependencies, klibFile: File) =
|
||||||
this@AbstractJsKLibABITestCase.buildKlib(moduleName, moduleSourceDir, moduleDependencies, klibFile)
|
this@AbstractJsKLibABITestCase.buildKlib(moduleName, moduleSourceDir, dependencies, klibFile)
|
||||||
|
|
||||||
override fun buildBinaryAndRun(mainModuleKlibFile: File, allDependencies: Collection<File>) =
|
override fun buildBinaryAndRun(mainModuleKlibFile: File, dependencies: KlibABITestUtils.Dependencies) =
|
||||||
this@AbstractJsKLibABITestCase.buildBinaryAndRun(mainModuleKlibFile, allDependencies)
|
this@AbstractJsKLibABITestCase.buildBinaryAndRun(mainModuleKlibFile, dependencies)
|
||||||
|
|
||||||
override fun onNonEmptyBuildDirectory(directory: File) {
|
override fun onNonEmptyBuildDirectory(directory: File) {
|
||||||
directory.listFiles()?.forEach(File::deleteRecursively)
|
directory.listFiles()?.forEach(File::deleteRecursively)
|
||||||
@@ -103,7 +103,7 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
|||||||
// The entry point to generated test classes.
|
// The entry point to generated test classes.
|
||||||
fun doTest(testPath: String) = KlibABITestUtils.runTest(JsTestConfiguration(testPath))
|
fun doTest(testPath: String) = KlibABITestUtils.runTest(JsTestConfiguration(testPath))
|
||||||
|
|
||||||
private fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection<File>, klibFile: File) {
|
private fun buildKlib(moduleName: String, moduleSourceDir: File, dependencies: KlibABITestUtils.Dependencies, klibFile: File) {
|
||||||
val ktFiles = environment.createPsiFiles(moduleSourceDir)
|
val ktFiles = environment.createPsiFiles(moduleSourceDir)
|
||||||
|
|
||||||
val config = environment.configuration.copy()
|
val config = environment.configuration.copy()
|
||||||
@@ -113,15 +113,15 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
|||||||
environment.project,
|
environment.project,
|
||||||
ktFiles,
|
ktFiles,
|
||||||
config,
|
config,
|
||||||
moduleDependencies.map { it.path },
|
dependencies.regularDependencies.map { it.path },
|
||||||
emptyList(), // TODO
|
dependencies.friendDependencies.map { it.path },
|
||||||
AnalyzerWithCompilerReport(config)
|
AnalyzerWithCompilerReport(config)
|
||||||
)
|
)
|
||||||
|
|
||||||
generateKLib(sourceModule, IrFactoryImpl, klibFile.path, nopack = false, jsOutputName = moduleName)
|
generateKLib(sourceModule, IrFactoryImpl, klibFile.path, nopack = false, jsOutputName = moduleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildBinaryAndRun(mainModuleKlibFile: File, libraries: Collection<File>) {
|
private fun buildBinaryAndRun(mainModuleKlibFile: File, allDependencies: KlibABITestUtils.Dependencies) {
|
||||||
val configuration = environment.configuration.copy()
|
val configuration = environment.configuration.copy()
|
||||||
|
|
||||||
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
||||||
@@ -130,12 +130,12 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
|||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
||||||
|
|
||||||
val compilationOutputs = if (useIncrementalCompiler)
|
val compilationOutputs = if (useIncrementalCompiler)
|
||||||
buildBinaryWithIC(configuration, mainModuleKlibFile, libraries)
|
buildBinaryWithIC(configuration, mainModuleKlibFile, allDependencies)
|
||||||
else
|
else
|
||||||
buildBinaryNoIC(configuration, mainModuleKlibFile, libraries)
|
buildBinaryNoIC(configuration, mainModuleKlibFile, allDependencies)
|
||||||
|
|
||||||
val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() }
|
val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() }
|
||||||
val binaries = ArrayList<File>(libraries.size)
|
val binaries = ArrayList<File>(allDependencies.regularDependencies.size)
|
||||||
|
|
||||||
for ((name, code) in compilationOutputs.dependencies) {
|
for ((name, code) in compilationOutputs.dependencies) {
|
||||||
val depBinary = binariesDir.binJsFile(name)
|
val depBinary = binariesDir.binJsFile(name)
|
||||||
@@ -154,14 +154,15 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
|||||||
private fun buildBinaryWithIC(
|
private fun buildBinaryWithIC(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
mainModuleKlibFile: File,
|
mainModuleKlibFile: File,
|
||||||
libraries: Collection<File>
|
allDependencies: KlibABITestUtils.Dependencies
|
||||||
): CompilationOutputs {
|
): CompilationOutputs {
|
||||||
fun cacheDir(library: File): File = buildDir.resolve("libs-cache").resolve(library.name).apply { mkdirs() }
|
fun cacheDir(library: File): File = buildDir.resolve("libs-cache").resolve(library.name).apply { mkdirs() }
|
||||||
|
|
||||||
|
// TODO: what about friend dependencies?
|
||||||
val cacheUpdater = CacheUpdater(
|
val cacheUpdater = CacheUpdater(
|
||||||
mainModule = mainModuleKlibFile.absolutePath,
|
mainModule = mainModuleKlibFile.absolutePath,
|
||||||
allModules = libraries.map { it.absolutePath },
|
allModules = allDependencies.regularDependencies.map { it.path },
|
||||||
icCachePaths = libraries.map { cacheDir(it).absolutePath },
|
icCachePaths = allDependencies.regularDependencies.map { cacheDir(it).path },
|
||||||
compilerConfiguration = configuration,
|
compilerConfiguration = configuration,
|
||||||
irFactory = { IrFactoryImplForJsIC(WholeWorldStageController()) },
|
irFactory = { IrFactoryImplForJsIC(WholeWorldStageController()) },
|
||||||
mainArguments = null,
|
mainArguments = null,
|
||||||
@@ -186,10 +187,16 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
|||||||
private fun buildBinaryNoIC(
|
private fun buildBinaryNoIC(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
mainModuleKlibFile: File,
|
mainModuleKlibFile: File,
|
||||||
libraries: Collection<File>
|
allDependencies: KlibABITestUtils.Dependencies
|
||||||
): CompilationOutputs {
|
): CompilationOutputs {
|
||||||
val klib = MainModule.Klib(mainModuleKlibFile.path)
|
val klib = MainModule.Klib(mainModuleKlibFile.path)
|
||||||
val moduleStructure = ModulesStructure(environment.project, klib, configuration, libraries.map { it.path }, emptyList())
|
val moduleStructure = ModulesStructure(
|
||||||
|
environment.project,
|
||||||
|
klib,
|
||||||
|
configuration,
|
||||||
|
allDependencies.regularDependencies.map { it.path },
|
||||||
|
allDependencies.friendDependencies.map { it.path }
|
||||||
|
)
|
||||||
|
|
||||||
val ir = compile(
|
val ir = compile(
|
||||||
moduleStructure,
|
moduleStructure,
|
||||||
|
|||||||
+21
-14
@@ -23,18 +23,18 @@ import java.io.File
|
|||||||
|
|
||||||
@Tag("klib-abi")
|
@Tag("klib-abi")
|
||||||
abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
||||||
private val producedKlibs = linkedMapOf<KLIB, Collection<File>>() // IMPORTANT: The order makes sense!
|
private val producedKlibs = linkedMapOf<KLIB, KlibABITestUtils.Dependencies>() // IMPORTANT: The order makes sense!
|
||||||
|
|
||||||
private inner class NativeTestConfiguration(testPath: String) : KlibABITestUtils.TestConfiguration {
|
private inner class NativeTestConfiguration(testPath: String) : KlibABITestUtils.TestConfiguration {
|
||||||
override val testDir = getAbsoluteFile(testPath)
|
override val testDir = getAbsoluteFile(testPath)
|
||||||
override val buildDir get() = this@AbstractNativeKlibABITest.buildDir
|
override val buildDir get() = this@AbstractNativeKlibABITest.buildDir
|
||||||
override val stdlibFile get() = this@AbstractNativeKlibABITest.stdlibFile
|
override val stdlibFile get() = this@AbstractNativeKlibABITest.stdlibFile
|
||||||
|
|
||||||
override fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection<File>, klibFile: File) =
|
override fun buildKlib(moduleName: String, moduleSourceDir: File, dependencies: KlibABITestUtils.Dependencies, klibFile: File) =
|
||||||
this@AbstractNativeKlibABITest.buildKlib(moduleName, moduleSourceDir, moduleDependencies, klibFile)
|
this@AbstractNativeKlibABITest.buildKlib(moduleName, moduleSourceDir, dependencies, klibFile)
|
||||||
|
|
||||||
override fun buildBinaryAndRun(mainModuleKlibFile: File, allDependencies: Collection<File>) =
|
override fun buildBinaryAndRun(mainModuleKlibFile: File, dependencies: KlibABITestUtils.Dependencies) =
|
||||||
this@AbstractNativeKlibABITest.buildBinaryAndRun(allDependencies)
|
this@AbstractNativeKlibABITest.buildBinaryAndRun(dependencies)
|
||||||
|
|
||||||
override fun onNonEmptyBuildDirectory(directory: File) = backupDirectoryContents(directory)
|
override fun onNonEmptyBuildDirectory(directory: File) = backupDirectoryContents(directory)
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
|||||||
// The entry point to generated test classes.
|
// The entry point to generated test classes.
|
||||||
protected fun runTest(@TestDataFile testPath: String) = KlibABITestUtils.runTest(NativeTestConfiguration(testPath))
|
protected fun runTest(@TestDataFile testPath: String) = KlibABITestUtils.runTest(NativeTestConfiguration(testPath))
|
||||||
|
|
||||||
private fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection<File>, klibFile: File) {
|
private fun buildKlib(moduleName: String, moduleSourceDir: File, dependencies: KlibABITestUtils.Dependencies, klibFile: File) {
|
||||||
val module = createModule(moduleName)
|
val module = createModule(moduleName)
|
||||||
moduleSourceDir.walk()
|
moduleSourceDir.walk()
|
||||||
.filter { file -> file.isFile && file.extension == "kt" }
|
.filter { file -> file.isFile && file.extension == "kt" }
|
||||||
@@ -57,16 +57,16 @@ abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
|||||||
settings = testRunSettings,
|
settings = testRunSettings,
|
||||||
freeCompilerArgs = testCase.freeCompilerArgs,
|
freeCompilerArgs = testCase.freeCompilerArgs,
|
||||||
sourceModules = testCase.modules,
|
sourceModules = testCase.modules,
|
||||||
dependencies = createLibraryDependencies(moduleDependencies),
|
dependencies = createLibraryDependencies(dependencies),
|
||||||
expectedArtifact = klibArtifact
|
expectedArtifact = klibArtifact
|
||||||
)
|
)
|
||||||
|
|
||||||
compilation.result.assertSuccess() // <-- trigger compilation
|
compilation.result.assertSuccess() // <-- trigger compilation
|
||||||
|
|
||||||
producedKlibs[klibArtifact] = moduleDependencies // Remember the artifact with its dependencies.
|
producedKlibs[klibArtifact] = dependencies // Remember the artifact with its dependencies.
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildBinaryAndRun(allDependencies: Collection<File>) {
|
private fun buildBinaryAndRun(allDependencies: KlibABITestUtils.Dependencies) {
|
||||||
val cacheDependencies = if (staticCacheRequiredForEveryLibrary) {
|
val cacheDependencies = if (staticCacheRequiredForEveryLibrary) {
|
||||||
producedKlibs.map { (klibArtifact, moduleDependencies) ->
|
producedKlibs.map { (klibArtifact, moduleDependencies) ->
|
||||||
buildCacheForKlib(moduleDependencies, klibArtifact)
|
buildCacheForKlib(moduleDependencies, klibArtifact)
|
||||||
@@ -102,7 +102,7 @@ abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
|||||||
runExecutableAndVerify(testCase, executable) // <-- run executable and verify
|
runExecutableAndVerify(testCase, executable) // <-- run executable and verify
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildCacheForKlib(moduleDependencies: Collection<File>, klibArtifact: KLIB) {
|
private fun buildCacheForKlib(moduleDependencies: KlibABITestUtils.Dependencies, klibArtifact: KLIB) {
|
||||||
val compilation = StaticCacheCompilation(
|
val compilation = StaticCacheCompilation(
|
||||||
settings = testRunSettings,
|
settings = testRunSettings,
|
||||||
freeCompilerArgs = COMPILER_ARGS_FOR_STATIC_CACHE_AND_EXECUTABLE,
|
freeCompilerArgs = COMPILER_ARGS_FOR_STATIC_CACHE_AND_EXECUTABLE,
|
||||||
@@ -133,13 +133,20 @@ abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
|||||||
initialize(null)
|
initialize(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLibraryDependencies(klibFiles: Iterable<File>): Iterable<TestCompilationDependency<KLIB>> =
|
private fun createLibraryDependencies(dependencies: KlibABITestUtils.Dependencies): Iterable<TestCompilationDependency<KLIB>> =
|
||||||
klibFiles.map { klibFile -> KLIB(klibFile).toDependency() }
|
with(dependencies) {
|
||||||
|
regularDependencies.map { KLIB(it).toDependency() } + friendDependencies.map { KLIB(it).toFriendDependency() }
|
||||||
|
}
|
||||||
|
|
||||||
private fun createLibraryCacheDependencies(klibFiles: Iterable<File>): Iterable<TestCompilationDependency<KLIBStaticCache>> =
|
private fun createLibraryCacheDependencies(dependencies: KlibABITestUtils.Dependencies): Iterable<TestCompilationDependency<KLIBStaticCache>> =
|
||||||
klibFiles.mapNotNull { klibFile -> if (klibFile != stdlibFile) KLIB(klibFile).toStaticCacheArtifact().toDependency() else null }
|
with(dependencies) {
|
||||||
|
regularDependencies.mapNotNull { klibFile ->
|
||||||
|
if (klibFile != stdlibFile) KLIB(klibFile).toStaticCacheArtifact().toDependency() else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun KLIB.toDependency() = ExistingDependency(this, Library)
|
private fun KLIB.toDependency() = ExistingDependency(this, Library)
|
||||||
|
private fun KLIB.toFriendDependency() = ExistingDependency(this, TestCompilationDependencyType.FriendLibrary)
|
||||||
private fun KLIBStaticCache.toDependency() = ExistingDependency(this, TestCompilationDependencyType.LibraryStaticCache)
|
private fun KLIBStaticCache.toDependency() = ExistingDependency(this, TestCompilationDependencyType.LibraryStaticCache)
|
||||||
|
|
||||||
private fun KLIB.toStaticCacheArtifact() = KLIBStaticCache(
|
private fun KLIB.toStaticCacheArtifact() = KLIBStaticCache(
|
||||||
|
|||||||
Reference in New Issue
Block a user