[Native][tests] W/A: Generate test suites for included KLIB with tests

Relates to KT-51375
This commit is contained in:
Dmitriy Dolovov
2022-02-18 11:29:27 +03:00
parent f635e450df
commit 0bc6885b2c
3 changed files with 167 additions and 79 deletions
@@ -97,6 +97,7 @@ abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
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,
options = StaticCacheCompilation.Options.Regular,
dependencies = createLibraryCacheDependencies(moduleDependencies) + klibArtifact.toDependency(), dependencies = createLibraryCacheDependencies(moduleDependencies) + klibArtifact.toDependency(),
expectedArtifact = klibArtifact.toStaticCacheArtifact() expectedArtifact = klibArtifact.toStaticCacheArtifact()
) )
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.konan.blackboxtest.support.compilation
import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.konan.blackboxtest.support.* import org.jetbrains.kotlin.konan.blackboxtest.support.*
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.* import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.*
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.ExecutableCompilation.Companion.applyTestRunnerSpecificArgs
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.ExecutableCompilation.Companion.assertTestDumpFileNotEmptyIfExists
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.* import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationDependencyType.* import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationDependencyType.*
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.* import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
@@ -16,6 +18,7 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.util.buildArgs
import org.jetbrains.kotlin.konan.blackboxtest.support.util.flatMapToSet import org.jetbrains.kotlin.konan.blackboxtest.support.util.flatMapToSet
import org.jetbrains.kotlin.konan.blackboxtest.support.util.mapToSet import org.jetbrains.kotlin.konan.blackboxtest.support.util.mapToSet
import org.jetbrains.kotlin.konan.properties.resolvablePropertyList import org.jetbrains.kotlin.konan.properties.resolvablePropertyList
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
import java.io.File import java.io.File
@@ -29,14 +32,14 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
private val classLoader: KotlinNativeClassLoader, private val classLoader: KotlinNativeClassLoader,
private val optimizationMode: OptimizationMode, private val optimizationMode: OptimizationMode,
protected val freeCompilerArgs: TestCompilerArgs, protected val freeCompilerArgs: TestCompilerArgs,
protected val dependencies: Iterable<TestCompilationDependency<*>>, protected val dependencies: CategorizedDependencies,
protected val expectedArtifact: A protected val expectedArtifact: A
) : TestCompilation<A>() { ) : TestCompilation<A>() {
protected abstract val sourceModules: Collection<TestModule> protected abstract val sourceModules: Collection<TestModule>
// Runs the compiler and memorizes the result on property access. // Runs the compiler and memorizes the result on property access.
final override val result: TestCompilationResult<out A> by lazy { final override val result: TestCompilationResult<out A> by lazy {
val failures = dependencies.collectFailures() val failures = dependencies.failures
if (failures.isNotEmpty()) if (failures.isNotEmpty())
TestCompilationResult.DependencyFailures(causes = failures) TestCompilationResult.DependencyFailures(causes = failures)
else else
@@ -65,6 +68,8 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
addFlattenedTwice(sourceModules, { it.files }) { it.location.path } addFlattenedTwice(sourceModules, { it.files }) { it.location.path }
} }
protected open fun postCompileCheck() = Unit
private fun doCompile(): TestCompilationResult.ImmediateResult<out A> { private fun doCompile(): TestCompilationResult.ImmediateResult<out A> {
val compilerArgs = buildArgs { val compilerArgs = buildArgs {
applyCommonArgs() applyCommonArgs()
@@ -100,39 +105,10 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
expectedArtifact.logFile.writeText(loggedCompilerCall.toString()) expectedArtifact.logFile.writeText(loggedCompilerCall.toString())
postCompileCheck()
return result return result
} }
companion object {
private fun Iterable<TestCompilationDependency<*>>.collectFailures() = flatMapToSet { dependency ->
when (val result = (dependency as? TestCompilation<*>)?.result) {
is TestCompilationResult.Failure -> listOf(result)
is TestCompilationResult.DependencyFailures -> result.causes
is TestCompilationResult.Success -> emptyList()
null -> emptyList()
}
}
@JvmStatic
protected inline fun <reified A : TestCompilationArtifact, reified T : TestCompilationDependencyType<A>> Iterable<TestCompilationDependency<*>>.collectArtifacts(): List<A> {
val concreteDependencyType = T::class.objectInstance
val dependencyTypeMatcher: (TestCompilationDependencyType<*>) -> Boolean = if (concreteDependencyType != null) {
{ it == concreteDependencyType }
} else {
{ it.canYield(A::class.java) }
}
return mapNotNull { dependency -> if (dependencyTypeMatcher(dependency.type)) dependency.artifact as A else null }
}
@JvmStatic
protected val Iterable<TestCompilationDependency<*>>.cachedLibraries: List<KLIBStaticCache>
get() = collectArtifacts<KLIBStaticCache, LibraryStaticCache>()
@JvmStatic
protected val Iterable<KLIBStaticCache>.uniqueCacheDirs: Set<File>
get() = mapToSet { (libraryCacheDir, _) -> libraryCacheDir } // Avoid repeating the same directory more than once.
}
} }
internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>( internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
@@ -146,7 +122,7 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
private val gcScheduler: GCScheduler, private val gcScheduler: GCScheduler,
freeCompilerArgs: TestCompilerArgs, freeCompilerArgs: TestCompilerArgs,
override val sourceModules: Collection<TestModule>, override val sourceModules: Collection<TestModule>,
dependencies: Iterable<TestCompilationDependency<*>>, dependencies: CategorizedDependencies,
expectedArtifact: A expectedArtifact: A
) : BasicCompilation<A>( ) : BasicCompilation<A>(
targets = targets, targets = targets,
@@ -172,12 +148,6 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
} }
add(dependencies.includedLibraries) { include -> "-Xinclude=${include.path}" } add(dependencies.includedLibraries) { include -> "-Xinclude=${include.path}" }
} }
companion object {
private val Iterable<TestCompilationDependency<*>>.libraries get() = collectArtifacts<KLIB, Library>()
private val Iterable<TestCompilationDependency<*>>.friends get() = collectArtifacts<KLIB, FriendLibrary>()
private val Iterable<TestCompilationDependency<*>>.includedLibraries get() = collectArtifacts<KLIB, IncludedLibrary>()
}
} }
internal class LibraryCompilation( internal class LibraryCompilation(
@@ -197,7 +167,7 @@ internal class LibraryCompilation(
gcScheduler = settings.get(), gcScheduler = settings.get(),
freeCompilerArgs = freeCompilerArgs, freeCompilerArgs = freeCompilerArgs,
sourceModules = sourceModules, sourceModules = sourceModules,
dependencies = dependencies, dependencies = CategorizedDependencies(dependencies),
expectedArtifact = expectedArtifact expectedArtifact = expectedArtifact
) { ) {
override fun applySpecificArgs(argsBuilder: ArgsBuilder) = with(argsBuilder) { override fun applySpecificArgs(argsBuilder: ArgsBuilder) = with(argsBuilder) {
@@ -227,7 +197,7 @@ internal class ExecutableCompilation(
gcScheduler = settings.get(), gcScheduler = settings.get(),
freeCompilerArgs = freeCompilerArgs, freeCompilerArgs = freeCompilerArgs,
sourceModules = sourceModules, sourceModules = sourceModules,
dependencies = dependencies, dependencies = CategorizedDependencies(dependencies),
expectedArtifact = expectedArtifact expectedArtifact = expectedArtifact
) { ) {
private val cacheMode: CacheMode = settings.get() private val cacheMode: CacheMode = settings.get()
@@ -240,13 +210,20 @@ internal class ExecutableCompilation(
when (extras) { when (extras) {
is NoTestRunnerExtras -> add("-entry", extras.entryPoint) is NoTestRunnerExtras -> add("-entry", extras.entryPoint)
is WithTestRunnerExtras -> { is WithTestRunnerExtras -> {
val testRunnerArg = when (extras.runnerType) { val testDumpFile: File? = if (sourceModules.isEmpty()
TestRunnerType.DEFAULT -> "-generate-test-runner" && dependencies.includedLibraries.isNotEmpty()
TestRunnerType.WORKER -> "-generate-worker-test-runner" && cacheMode.staticCacheRequiredForEveryLibrary
TestRunnerType.NO_EXIT -> "-generate-no-exit-test-runner" ) {
// If there are no source modules passed to the compiler, but there is an included library with the static cache, then
// this should be two-stage test mode: Test functions are already stored in the included library, and they should
// already have been dumped during generation of library's static cache.
null // No, don't need to dump tests.
} else {
expectedArtifact.testDumpFile // Yes, need to dump tests.
} }
add(testRunnerArg)
add("-Xdump-tests-to=${expectedArtifact.testDumpFile}") applyTestRunnerSpecificArgs(extras, testDumpFile)
} }
} }
super.applySpecificArgs(argsBuilder) super.applySpecificArgs(argsBuilder)
@@ -255,13 +232,38 @@ internal class ExecutableCompilation(
override fun applyDependencies(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) { override fun applyDependencies(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) {
super.applyDependencies(argsBuilder) super.applyDependencies(argsBuilder)
cacheMode.staticCacheRootDir?.let { cacheRootDir -> add("-Xcache-directory=$cacheRootDir") } cacheMode.staticCacheRootDir?.let { cacheRootDir -> add("-Xcache-directory=$cacheRootDir") }
add(dependencies.cachedLibraries.uniqueCacheDirs) { libraryCacheDir -> "-Xcache-directory=${libraryCacheDir.path}" } add(dependencies.uniqueCacheDirs) { libraryCacheDir -> "-Xcache-directory=${libraryCacheDir.path}" }
}
override fun postCompileCheck() {
expectedArtifact.assertTestDumpFileNotEmptyIfExists()
}
companion object {
internal fun ArgsBuilder.applyTestRunnerSpecificArgs(extras: WithTestRunnerExtras, testDumpFile: File?) {
val testRunnerArg = when (extras.runnerType) {
TestRunnerType.DEFAULT -> "-generate-test-runner"
TestRunnerType.WORKER -> "-generate-worker-test-runner"
TestRunnerType.NO_EXIT -> "-generate-no-exit-test-runner"
}
add(testRunnerArg)
testDumpFile?.let { add("-Xdump-tests-to=$it") }
}
internal fun Executable.assertTestDumpFileNotEmptyIfExists() {
if (testDumpFile.exists()) {
testDumpFile.useLines { lines ->
assertTrue(lines.filter(String::isNotBlank).any()) { "Test dump file is empty: $testDumpFile" }
}
}
}
} }
} }
internal class StaticCacheCompilation( internal class StaticCacheCompilation(
settings: Settings, settings: Settings,
freeCompilerArgs: TestCompilerArgs, freeCompilerArgs: TestCompilerArgs,
private val options: Options,
dependencies: Iterable<TestCompilationDependency<*>>, dependencies: Iterable<TestCompilationDependency<*>>,
expectedArtifact: KLIBStaticCache expectedArtifact: KLIBStaticCache
) : BasicCompilation<KLIBStaticCache>( ) : BasicCompilation<KLIBStaticCache>(
@@ -270,9 +272,14 @@ internal class StaticCacheCompilation(
classLoader = settings.get(), classLoader = settings.get(),
optimizationMode = settings.get(), optimizationMode = settings.get(),
freeCompilerArgs = freeCompilerArgs, freeCompilerArgs = freeCompilerArgs,
dependencies = dependencies, dependencies = CategorizedDependencies(dependencies),
expectedArtifact = expectedArtifact expectedArtifact = expectedArtifact
) { ) {
sealed interface Options {
object Regular : Options
class ForIncludedLibraryWithTests(val expectedExecutableArtifact: Executable, val extras: WithTestRunnerExtras) : Options
}
override val sourceModules get() = emptyList<TestModule>() override val sourceModules get() = emptyList<TestModule>()
private val cacheRootDir: File = run { private val cacheRootDir: File = run {
@@ -283,6 +290,14 @@ internal class StaticCacheCompilation(
override fun applySpecificArgs(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) { override fun applySpecificArgs(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) {
add("-produce", "static_cache") add("-produce", "static_cache")
when (options) {
is Options.Regular -> Unit /* Nothing to do. */
is Options.ForIncludedLibraryWithTests -> {
applyTestRunnerSpecificArgs(options.extras, options.expectedExecutableArtifact.testDumpFile)
add("-Xinclude=${dependencies.libraryToCache.path}")
}
}
// The following line adds "-Xembed-bitcode-marker" for certain iOS device targets: // The following line adds "-Xembed-bitcode-marker" for certain iOS device targets:
add(home.properties.resolvablePropertyList("additionalCacheFlags", targets.testTarget.visibleName)) add(home.properties.resolvablePropertyList("additionalCacheFlags", targets.testTarget.visibleName))
add( add(
@@ -293,17 +308,51 @@ internal class StaticCacheCompilation(
} }
override fun applyDependencies(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) { override fun applyDependencies(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) {
val cachedLibraries = dependencies.cachedLibraries addFlattened(dependencies.cachedLibraries) { (_, library) -> listOf("-l", library.path) }
addFlattened(cachedLibraries) { (_, library) -> listOf("-l", library.path) } add(dependencies.uniqueCacheDirs) { libraryCacheDir -> "-Xcache-directory=${libraryCacheDir.path}" }
add(cachedLibraries.uniqueCacheDirs) { libraryCacheDir -> "-Xcache-directory=${libraryCacheDir.path}" }
} }
companion object { override fun postCompileCheck() {
private val Iterable<TestCompilationDependency<*>>.libraryToCache: KLIB (options as? Options.ForIncludedLibraryWithTests)?.expectedExecutableArtifact?.assertTestDumpFileNotEmptyIfExists()
get() { }
val libraries = collectArtifacts<KLIB, TestCompilationDependencyType<KLIB>>() }
return libraries.singleOrNull()
?: fail { "Only one library is expected as input for ${StaticCacheCompilation::class.java}, found: $libraries" } internal class CategorizedDependencies(uncategorizedDependencies: Iterable<TestCompilationDependency<*>>) {
} val failures: Set<TestCompilationResult.Failure> by lazy {
uncategorizedDependencies.flatMapToSet { dependency ->
when (val result = (dependency as? TestCompilation<*>)?.result) {
is TestCompilationResult.Failure -> listOf(result)
is TestCompilationResult.DependencyFailures -> result.causes
is TestCompilationResult.Success -> emptyList()
null -> emptyList()
}
}
}
val libraries: List<KLIB> by lazy { uncategorizedDependencies.collectArtifacts<KLIB, Library>() }
val friends: List<KLIB> by lazy { uncategorizedDependencies.collectArtifacts<KLIB, FriendLibrary>() }
val includedLibraries: List<KLIB> by lazy { uncategorizedDependencies.collectArtifacts<KLIB, IncludedLibrary>() }
val cachedLibraries: List<KLIBStaticCache> by lazy { uncategorizedDependencies.collectArtifacts<KLIBStaticCache, LibraryStaticCache>() }
val libraryToCache: KLIB by lazy {
val libraries = uncategorizedDependencies.collectArtifacts<KLIB, TestCompilationDependencyType<KLIB>>()
libraries.singleOrNull<KLIB>()
?: fail { "Only one library is expected as input for ${StaticCacheCompilation::class.java}, found: $libraries" }
}
val uniqueCacheDirs: Set<File> by lazy {
cachedLibraries.mapToSet { (libraryCacheDir, _) -> libraryCacheDir } // Avoid repeating the same directory more than once.
}
private inline fun <reified A : TestCompilationArtifact, reified T : TestCompilationDependencyType<A>> Iterable<TestCompilationDependency<*>>.collectArtifacts(): List<A> {
val concreteDependencyType = T::class.objectInstance
val dependencyTypeMatcher: (TestCompilationDependencyType<*>) -> Boolean = if (concreteDependencyType != null) {
{ it == concreteDependencyType }
} else {
{ it.canYield(A::class.java) }
}
return mapNotNull { dependency -> if (dependencyTypeMatcher(dependency.type)) dependency.artifact as A else null }
} }
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.konan.blackboxtest.support.compilation
import org.jetbrains.kotlin.konan.blackboxtest.support.PackageName import org.jetbrains.kotlin.konan.blackboxtest.support.PackageName
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.*
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilerArgs import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilerArgs
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allDependencies import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allDependencies
@@ -29,7 +30,7 @@ internal class TestCompilationFactory {
// A pair of compilations for a KLIB itself and for its static cache that are created together. // A pair of compilations for a KLIB itself and for its static cache that are created together.
private data class KlibCompilations(val klib: TestCompilation<KLIB>, val staticCache: TestCompilation<KLIBStaticCache>?) private data class KlibCompilations(val klib: TestCompilation<KLIB>, val staticCache: TestCompilation<KLIBStaticCache>?)
private data class SourceBasedCompilationDependencies( private data class CompilationDependencies(
private val klibDependencies: List<CompiledDependency<KLIB>>, private val klibDependencies: List<CompiledDependency<KLIB>>,
private val staticCacheDependencies: List<CompiledDependency<KLIBStaticCache>> private val staticCacheDependencies: List<CompiledDependency<KLIBStaticCache>>
) { ) {
@@ -52,6 +53,31 @@ internal class TestCompilationFactory {
(klibDependencies.asSequence() + staticCacheDependencies + listOfNotNull(includedKlib, includedKlibStaticCache)).asIterable() (klibDependencies.asSequence() + staticCacheDependencies + listOfNotNull(includedKlib, includedKlibStaticCache)).asIterable()
} }
private sealed interface ProduceStaticCache {
object No : ProduceStaticCache
sealed class Yes(val options: StaticCacheCompilation.Options) : ProduceStaticCache {
object Regular : Yes(StaticCacheCompilation.Options.Regular)
class ForIncludedKlibWithTests(options: StaticCacheCompilation.Options.ForIncludedLibraryWithTests) : Yes(options)
}
companion object {
fun decideForRegularKlib(settings: Settings): ProduceStaticCache =
if (settings.get<CacheMode>().staticCacheRequiredForEveryLibrary) Yes.Regular else No
fun decideForIncludedKlib(settings: Settings, expectedExecutableArtifact: Executable, extras: Extras): ProduceStaticCache =
if (!settings.get<CacheMode>().staticCacheRequiredForEveryLibrary)
No
else
when (extras) {
is NoTestRunnerExtras -> Yes.Regular
is WithTestRunnerExtras -> Yes.ForIncludedKlibWithTests(
StaticCacheCompilation.Options.ForIncludedLibraryWithTests(expectedExecutableArtifact, extras)
)
}
}
}
fun testCasesToExecutable(testCases: Collection<TestCase>, settings: Settings): TestCompilation<Executable> { fun testCasesToExecutable(testCases: Collection<TestCase>, settings: Settings): TestCompilation<Executable> {
val rootModules = testCases.flatMapToSet { testCase -> testCase.rootModules } val rootModules = testCases.flatMapToSet { testCase -> testCase.rootModules }
val cacheKey = ExecutableCacheKey(rootModules) val cacheKey = ExecutableCacheKey(rootModules)
@@ -75,7 +101,8 @@ internal class TestCompilationFactory {
} }
TestMode.TWO_STAGE_MULTI_MODULE -> { TestMode.TWO_STAGE_MULTI_MODULE -> {
// Compile root modules to KLIB. Pass this KLIB as included dependency to executable compilation. // Compile root modules to KLIB. Pass this KLIB as included dependency to executable compilation.
val klibCompilations = modulesToKlib(rootModules, freeCompilerArgs, settings) val produceStaticCache = ProduceStaticCache.decideForIncludedKlib(settings, executableArtifact, extras)
val klibCompilations = modulesToKlib(rootModules, freeCompilerArgs, produceStaticCache, settings)
sourceModulesToCompileExecutable = emptySet() // No sources. sourceModulesToCompileExecutable = emptySet() // No sources.
@@ -99,7 +126,12 @@ internal class TestCompilationFactory {
} }
} }
private fun modulesToKlib(sourceModules: Set<TestModule>, freeCompilerArgs: TestCompilerArgs, settings: Settings): KlibCompilations { private fun modulesToKlib(
sourceModules: Set<TestModule>,
freeCompilerArgs: TestCompilerArgs,
produceStaticCache: ProduceStaticCache,
settings: Settings
): KlibCompilations {
val cacheKey = KlibCacheKey(sourceModules, freeCompilerArgs) val cacheKey = KlibCacheKey(sourceModules, freeCompilerArgs)
// Fast pass. // Fast pass.
@@ -109,10 +141,13 @@ internal class TestCompilationFactory {
val dependencies = collectDependencies(sourceModules, freeCompilerArgs, settings) val dependencies = collectDependencies(sourceModules, freeCompilerArgs, settings)
val klibArtifact = KLIB(settings.artifactFileForKlib(sourceModules, freeCompilerArgs)) val klibArtifact = KLIB(settings.artifactFileForKlib(sourceModules, freeCompilerArgs))
val staticCacheArtifact: KLIBStaticCache? = if (settings.get<CacheMode>().staticCacheRequiredForEveryLibrary) val staticCacheArtifactAndOptions: Pair<KLIBStaticCache, StaticCacheCompilation.Options>? = when (produceStaticCache) {
KLIBStaticCache(cacheDir = klibArtifact.cacheDirForStaticCache(), klib = klibArtifact) is ProduceStaticCache.No -> null // No artifact means no static cache should be compiled.
else is ProduceStaticCache.Yes -> KLIBStaticCache(
null // No artifact means no static cache should be compiled. cacheDir = klibArtifact.cacheDirForStaticCache(),
klib = klibArtifact
) to produceStaticCache.options
}
return cachedKlibCompilations.computeIfAbsent(cacheKey) { return cachedKlibCompilations.computeIfAbsent(cacheKey) {
val klibCompilation = LibraryCompilation( val klibCompilation = LibraryCompilation(
@@ -123,15 +158,16 @@ internal class TestCompilationFactory {
expectedArtifact = klibArtifact expectedArtifact = klibArtifact
) )
val staticCacheCompilation: StaticCacheCompilation? = if (staticCacheArtifact != null) { val staticCacheCompilation: StaticCacheCompilation? =
StaticCacheCompilation( staticCacheArtifactAndOptions?.let { (staticCacheArtifact, staticCacheOptions) ->
settings = settings, StaticCacheCompilation(
freeCompilerArgs = freeCompilerArgs, settings = settings,
dependencies = dependencies.forStaticCache(klibCompilation.asKlibDependency(type = /* does not matter in fact*/ Library)), freeCompilerArgs = freeCompilerArgs,
expectedArtifact = staticCacheArtifact options = staticCacheOptions,
) dependencies = dependencies.forStaticCache(klibCompilation.asKlibDependency(type = /* does not matter in fact*/ Library)),
} else expectedArtifact = staticCacheArtifact
null )
}
KlibCompilations(klibCompilation, staticCacheCompilation) KlibCompilations(klibCompilation, staticCacheCompilation)
} }
@@ -141,13 +177,15 @@ internal class TestCompilationFactory {
sourceModules: Set<TestModule>, sourceModules: Set<TestModule>,
freeCompilerArgs: TestCompilerArgs, freeCompilerArgs: TestCompilerArgs,
settings: Settings settings: Settings
): SourceBasedCompilationDependencies { ): CompilationDependencies {
val klibDependencies = mutableListOf<CompiledDependency<KLIB>>() val klibDependencies = mutableListOf<CompiledDependency<KLIB>>()
val staticCacheDependencies = mutableListOf<CompiledDependency<KLIBStaticCache>>() val staticCacheDependencies = mutableListOf<CompiledDependency<KLIBStaticCache>>()
val produceStaticCache = ProduceStaticCache.decideForRegularKlib(settings)
fun <T : TestCompilationDependencyType<KLIB>> Set<TestModule>.collectDependencies(type: T) = fun <T : TestCompilationDependencyType<KLIB>> Set<TestModule>.collectDependencies(type: T) =
forEach { dependencyModule: TestModule -> forEach { dependencyModule: TestModule ->
val klibCompilations = modulesToKlib(setOf(dependencyModule), freeCompilerArgs, settings) val klibCompilations = modulesToKlib(setOf(dependencyModule), freeCompilerArgs, produceStaticCache, settings)
klibDependencies += klibCompilations.klib.asKlibDependency(type) klibDependencies += klibCompilations.klib.asKlibDependency(type)
if (type == Library || type == IncludedLibrary) if (type == Library || type == IncludedLibrary)
@@ -157,7 +195,7 @@ internal class TestCompilationFactory {
sourceModules.allDependencies().collectDependencies(Library) sourceModules.allDependencies().collectDependencies(Library)
sourceModules.allFriends().collectDependencies(FriendLibrary) sourceModules.allFriends().collectDependencies(FriendLibrary)
return SourceBasedCompilationDependencies(klibDependencies, staticCacheDependencies) return CompilationDependencies(klibDependencies, staticCacheDependencies)
} }
companion object { companion object {