[Native][tests] Refactoring: Rework Settings/GlobalSettings
This commit is contained in:
+51
-37
@@ -6,9 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.konan.blackboxtest.support
|
package org.jetbrains.kotlin.konan.blackboxtest.support
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.AbstractNativeBlackBoxTest
|
import org.jetbrains.kotlin.konan.blackboxtest.AbstractNativeBlackBoxTest
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.group.StandardTestCaseGroupProvider
|
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProviding
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.GlobalSettings
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.TestRoots
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.TestSettings
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||||
import org.jetbrains.kotlin.test.TestMetadata
|
import org.jetbrains.kotlin.test.TestMetadata
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEquals
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEquals
|
||||||
@@ -35,7 +37,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
enclosingTestInstance.onRunProviderSet()
|
enclosingTestInstance.onRunProviderSet()
|
||||||
|
|
||||||
// Set the essential compiler property.
|
// Set the essential compiler property.
|
||||||
System.setProperty("kotlin.native.home", getOrCreateGlobalEnvironment().kotlinNativeHome.path)
|
System.setProperty("kotlin.native.home", getOrCreateGlobalSettings().kotlinNativeHome.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -46,13 +48,14 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
val enclosingTestClass = enclosingTestClass
|
val enclosingTestClass = enclosingTestClass
|
||||||
|
|
||||||
return root.getStore(NAMESPACE).getOrComputeIfAbsent(enclosingTestClass.sanitizedName) {
|
return root.getStore(NAMESPACE).getOrComputeIfAbsent(enclosingTestClass.sanitizedName) {
|
||||||
val globalEnvironment = getOrCreateGlobalEnvironment()
|
val globalSettings = getOrCreateGlobalSettings()
|
||||||
|
val (testSettings, testSettingsAnnotation) = computeTestSettings(enclosingTestClass)
|
||||||
|
|
||||||
val testRoots = computeTestRoots()
|
val testRoots = computeTestRoots(enclosingTestClass)
|
||||||
|
|
||||||
val uniqueEnclosingClassDirName = globalEnvironment.target.compressedName + "_" + enclosingTestClass.compressedSimpleName
|
val uniqueEnclosingClassDirName = globalSettings.target.compressedName + "_" + enclosingTestClass.compressedSimpleName
|
||||||
|
|
||||||
val testSourcesDir = globalEnvironment.baseBuildDir
|
val testSourcesDir = globalSettings.baseBuildDir
|
||||||
.resolve("bbtest.src")
|
.resolve("bbtest.src")
|
||||||
.resolve(uniqueEnclosingClassDirName)
|
.resolve(uniqueEnclosingClassDirName)
|
||||||
.ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale generated sources.
|
.ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale generated sources.
|
||||||
@@ -61,7 +64,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
.resolve("__shared_modules__")
|
.resolve("__shared_modules__")
|
||||||
.ensureExistsAndIsEmptyDirectory()
|
.ensureExistsAndIsEmptyDirectory()
|
||||||
|
|
||||||
val testBinariesDir = globalEnvironment.baseBuildDir
|
val testBinariesDir = globalSettings.baseBuildDir
|
||||||
.resolve("bbtest.bin")
|
.resolve("bbtest.bin")
|
||||||
.resolve(uniqueEnclosingClassDirName)
|
.resolve(uniqueEnclosingClassDirName)
|
||||||
.ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale artifacts.
|
.ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale artifacts.
|
||||||
@@ -70,8 +73,8 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
.resolve("__shared_modules__")
|
.resolve("__shared_modules__")
|
||||||
.ensureExistsAndIsEmptyDirectory()
|
.ensureExistsAndIsEmptyDirectory()
|
||||||
|
|
||||||
val environment = TestEnvironment(
|
val settings = Settings(
|
||||||
globalEnvironment = globalEnvironment,
|
global = globalSettings,
|
||||||
testRoots = testRoots,
|
testRoots = testRoots,
|
||||||
testSourcesDir = testSourcesDir,
|
testSourcesDir = testSourcesDir,
|
||||||
sharedSourcesDir = sharedSourcesDir,
|
sharedSourcesDir = sharedSourcesDir,
|
||||||
@@ -79,16 +82,16 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
sharedBinariesDir = sharedBinariesDir
|
sharedBinariesDir = sharedBinariesDir
|
||||||
)
|
)
|
||||||
|
|
||||||
val testCaseGroupProvider = requiredTestClass.createTestCaseGroupProvider(environment)
|
val testCaseGroupProvider = createTestCaseGroupProvider(settings, testSettings, testSettingsAnnotation)
|
||||||
|
|
||||||
TestRunProvider(environment, testCaseGroupProvider)
|
TestRunProvider(settings, testCaseGroupProvider)
|
||||||
}.cast()
|
}.cast()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ExtensionContext.getOrCreateGlobalEnvironment(): GlobalTestEnvironment =
|
private fun ExtensionContext.getOrCreateGlobalSettings(): GlobalSettings =
|
||||||
root.getStore(NAMESPACE).getOrComputeIfAbsent(GlobalTestEnvironment::class.java.sanitizedName) {
|
root.getStore(NAMESPACE).getOrComputeIfAbsent(GlobalSettings::class.java.sanitizedName) {
|
||||||
// Create with the default settings.
|
// Create with the default settings.
|
||||||
GlobalTestEnvironment()
|
GlobalSettings()
|
||||||
}.cast()
|
}.cast()
|
||||||
|
|
||||||
private val ExtensionContext.enclosingTestInstance: AbstractNativeBlackBoxTest
|
private val ExtensionContext.enclosingTestInstance: AbstractNativeBlackBoxTest
|
||||||
@@ -97,9 +100,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
private val ExtensionContext.enclosingTestClass: Class<*>
|
private val ExtensionContext.enclosingTestClass: Class<*>
|
||||||
get() = generateSequence(requiredTestClass) { it.enclosingClass }.last()
|
get() = generateSequence(requiredTestClass) { it.enclosingClass }.last()
|
||||||
|
|
||||||
private fun ExtensionContext.computeTestRoots(): TestRoots {
|
private fun computeTestRoots(enclosingTestClass: Class<*>): TestRoots {
|
||||||
val enclosingTestClass = enclosingTestClass
|
|
||||||
|
|
||||||
val testRoots: Set<File> = when (val outermostTestMetadata = enclosingTestClass.getAnnotation(TestMetadata::class.java)) {
|
val testRoots: Set<File> = when (val outermostTestMetadata = enclosingTestClass.getAnnotation(TestMetadata::class.java)) {
|
||||||
null -> {
|
null -> {
|
||||||
enclosingTestClass.declaredClasses.mapNotNullToSet { nestedClass ->
|
enclosingTestClass.declaredClasses.mapNotNullToSet { nestedClass ->
|
||||||
@@ -125,35 +126,48 @@ class NativeBlackBoxTestSupport : BeforeEachCallback {
|
|||||||
return TestRoots(testRoots, baseDir)
|
return TestRoots(testRoots, baseDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Class<*>.createTestCaseGroupProvider(environment: TestEnvironment): TestCaseGroupProvider {
|
private fun computeTestSettings(enclosingTestClass: Class<*>): Pair<TestSettings, Annotation?> {
|
||||||
val (providerAnnotation, providerAnnotationClass, providerClass) = annotations.asSequence()
|
val findTestSettings: Class<*>.() -> Pair<TestSettings, Annotation>? = {
|
||||||
.mapNotNull { annotation ->
|
annotations.asSequence().mapNotNull { annotation ->
|
||||||
val annotationClass = annotation.annotationClass
|
val testSettings = annotation.annotationClass.findAnnotation<TestSettings>() ?: return@mapNotNull null
|
||||||
val providerClass = annotationClass.findAnnotation<TestCaseGroupProviding>()?.providerClass ?: return@mapNotNull null
|
testSettings to annotation
|
||||||
Triple(annotation, annotationClass, providerClass)
|
|
||||||
}.firstOrNull()
|
}.firstOrNull()
|
||||||
?: return StandardTestCaseGroupProvider(environment) // Fallback if there is no annotation.
|
}
|
||||||
|
|
||||||
|
return enclosingTestClass.findTestSettings()
|
||||||
|
?: enclosingTestClass.declaredClasses.firstNotNullOfOrNull { it.findTestSettings() }
|
||||||
|
?: (TestSettings.DEFAULT to null) // Fallback if there is no annotation.
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTestCaseGroupProvider(
|
||||||
|
settings: Settings,
|
||||||
|
testSettings: TestSettings,
|
||||||
|
testSettingsAnnotation: Annotation?
|
||||||
|
): TestCaseGroupProvider {
|
||||||
// First, try to find two-argument constructor.
|
// First, try to find two-argument constructor.
|
||||||
providerClass.constructors.asSequence()
|
if (testSettingsAnnotation != null) {
|
||||||
.forEach { c ->
|
val testSettingsAnnotationClass = testSettingsAnnotation.annotationClass
|
||||||
val (p1, p2) = c.parameters.takeIf { it.size == 2 } ?: return@forEach
|
|
||||||
val provider = when {
|
testSettings.providerClass.constructors.asSequence()
|
||||||
p1.hasTypeOf<TestEnvironment>() && p2.hasTypeOf(providerAnnotationClass) -> c.call(environment, providerAnnotation)
|
.forEach { c ->
|
||||||
p1.hasTypeOf(providerAnnotationClass) && p2.hasTypeOf<TestEnvironment>() -> c.call(providerAnnotation, environment)
|
val (p1, p2) = c.parameters.takeIf { it.size == 2 } ?: return@forEach
|
||||||
else -> return@forEach
|
@Suppress("Reformat") val provider = when {
|
||||||
|
p1.hasTypeOf<Settings>() && p2.hasTypeOf(testSettingsAnnotationClass) -> c.call(settings, testSettingsAnnotation)
|
||||||
|
p1.hasTypeOf(testSettingsAnnotationClass) && p2.hasTypeOf<Settings>() -> c.call(testSettingsAnnotation, settings)
|
||||||
|
else -> return@forEach
|
||||||
|
}
|
||||||
|
return provider.cast()
|
||||||
}
|
}
|
||||||
return provider.cast()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Next, try to find a single-argument constructor.
|
// Next, try to find a single-argument constructor.
|
||||||
providerClass.constructors.asSequence()
|
testSettings.providerClass.constructors.asSequence()
|
||||||
.forEach { c ->
|
.forEach { c ->
|
||||||
val p = c.parameters.singleOrNull() ?: return@forEach
|
val p = c.parameters.singleOrNull() ?: return@forEach
|
||||||
if (p.hasTypeOf<TestEnvironment>()) return c.call(environment).cast()
|
if (p.hasTypeOf<Settings>()) return c.call(settings).cast()
|
||||||
}
|
}
|
||||||
|
|
||||||
fail { "No suitable constructor for $providerClass" }
|
fail { "No suitable constructor for ${testSettings.providerClass}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T : Any> KParameter.hasTypeOf(): Boolean = hasTypeOf(T::class)
|
private inline fun <reified T : Any> KParameter.hasTypeOf(): Boolean = hasTypeOf(T::class)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
package org.jetbrains.kotlin.konan.blackboxtest.support
|
package org.jetbrains.kotlin.konan.blackboxtest.support
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allDependencies
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allDependencies
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.TestMode
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue
|
||||||
|
|||||||
+13
-12
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilation.Companion
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilationResult.Companion.assertSuccess
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilationResult.Companion.assertSuccess
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allDependencies
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allDependencies
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allFriends
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule.Companion.allFriends
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
||||||
import java.io.*
|
import java.io.*
|
||||||
@@ -22,7 +23,7 @@ import kotlin.time.Duration
|
|||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.measureTime
|
import kotlin.time.measureTime
|
||||||
|
|
||||||
internal class TestCompilationFactory(private val environment: TestEnvironment) {
|
internal class TestCompilationFactory(private val settings: Settings) {
|
||||||
private val cachedCompilations = ThreadSafeCache<TestCompilationCacheKey, TestCompilation>()
|
private val cachedCompilations = ThreadSafeCache<TestCompilationCacheKey, TestCompilation>()
|
||||||
|
|
||||||
private sealed interface TestCompilationCacheKey {
|
private sealed interface TestCompilationCacheKey {
|
||||||
@@ -46,7 +47,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment)
|
|||||||
val entryPoint = testCases.singleOrNull()?.safeExtras<NoTestRunnerExtras>()?.entryPoint
|
val entryPoint = testCases.singleOrNull()?.safeExtras<NoTestRunnerExtras>()?.entryPoint
|
||||||
|
|
||||||
TestCompilationImpl(
|
TestCompilationImpl(
|
||||||
environment = environment,
|
settings = settings,
|
||||||
freeCompilerArgs = freeCompilerArgs,
|
freeCompilerArgs = freeCompilerArgs,
|
||||||
sourceModules = rootModules,
|
sourceModules = rootModules,
|
||||||
dependencies = TestCompilationDependencies(libraries = libraries, friends = friends),
|
dependencies = TestCompilationDependencies(libraries = libraries, friends = friends),
|
||||||
@@ -54,7 +55,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment)
|
|||||||
specificCompilerArgs = {
|
specificCompilerArgs = {
|
||||||
add("-produce", "program")
|
add("-produce", "program")
|
||||||
if (entryPoint != null) add("-entry", entryPoint) else add("-generate-test-runner")
|
if (entryPoint != null) add("-entry", entryPoint) else add("-generate-test-runner")
|
||||||
environment.globalEnvironment.getRootCacheDirectory(debuggable = true)?.let { rootCacheDir ->
|
settings.global.getRootCacheDirectory(debuggable = true)?.let { rootCacheDir ->
|
||||||
add("-Xcache-directory=$rootCacheDir")
|
add("-Xcache-directory=$rootCacheDir")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment)
|
|||||||
|
|
||||||
return cachedCompilations.computeIfAbsent(cacheKey) {
|
return cachedCompilations.computeIfAbsent(cacheKey) {
|
||||||
TestCompilationImpl(
|
TestCompilationImpl(
|
||||||
environment = environment,
|
settings = settings,
|
||||||
freeCompilerArgs = freeCompilerArgs,
|
freeCompilerArgs = freeCompilerArgs,
|
||||||
sourceModules = sourceModules,
|
sourceModules = sourceModules,
|
||||||
dependencies = TestCompilationDependencies(libraries = libraries, friends = friends),
|
dependencies = TestCompilationDependencies(libraries = libraries, friends = friends),
|
||||||
@@ -87,15 +88,15 @@ internal class TestCompilationFactory(private val environment: TestEnvironment)
|
|||||||
|
|
||||||
private fun artifactFileForExecutable(modules: Set<TestModule.Exclusive>) = when (modules.size) {
|
private fun artifactFileForExecutable(modules: Set<TestModule.Exclusive>) = when (modules.size) {
|
||||||
1 -> artifactFileForExecutable(modules.first())
|
1 -> artifactFileForExecutable(modules.first())
|
||||||
else -> multiModuleArtifactFile(modules, environment.globalEnvironment.target.family.exeSuffix)
|
else -> multiModuleArtifactFile(modules, settings.global.target.family.exeSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun artifactFileForExecutable(module: TestModule.Exclusive) =
|
private fun artifactFileForExecutable(module: TestModule.Exclusive) =
|
||||||
singleModuleArtifactFile(module, environment.globalEnvironment.target.family.exeSuffix)
|
singleModuleArtifactFile(module, settings.global.target.family.exeSuffix)
|
||||||
|
|
||||||
private fun artifactFileForKlib(module: TestModule, freeCompilerArgs: TestCompilerArgs) = when (module) {
|
private fun artifactFileForKlib(module: TestModule, freeCompilerArgs: TestCompilerArgs) = when (module) {
|
||||||
is TestModule.Exclusive -> singleModuleArtifactFile(module, "klib")
|
is TestModule.Exclusive -> singleModuleArtifactFile(module, "klib")
|
||||||
is TestModule.Shared -> environment.sharedBinariesDir.resolve("${module.name}-${prettyHash(freeCompilerArgs.hashCode())}.klib")
|
is TestModule.Shared -> settings.sharedBinariesDir.resolve("${module.name}-${prettyHash(freeCompilerArgs.hashCode())}.klib")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun singleModuleArtifactFile(module: TestModule.Exclusive, extension: String): File {
|
private fun singleModuleArtifactFile(module: TestModule.Exclusive, extension: String): File {
|
||||||
@@ -141,7 +142,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun artifactDirForPackageName(packageName: PackageFQN?): File {
|
private fun artifactDirForPackageName(packageName: PackageFQN?): File {
|
||||||
val baseDir = environment.testBinariesDir
|
val baseDir = settings.testBinariesDir
|
||||||
val outputDir = if (packageName != null) baseDir.resolve(packageName.compressedPackageName) else baseDir
|
val outputDir = if (packageName != null) baseDir.resolve(packageName.compressedPackageName) else baseDir
|
||||||
|
|
||||||
outputDir.mkdirs()
|
outputDir.mkdirs()
|
||||||
@@ -221,7 +222,7 @@ internal class TestCompilationDependencies(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class TestCompilationImpl(
|
private class TestCompilationImpl(
|
||||||
private val environment: TestEnvironment,
|
private val settings: Settings,
|
||||||
private val freeCompilerArgs: TestCompilerArgs,
|
private val freeCompilerArgs: TestCompilerArgs,
|
||||||
private val sourceModules: Collection<TestModule>,
|
private val sourceModules: Collection<TestModule>,
|
||||||
private val dependencies: TestCompilationDependencies,
|
private val dependencies: TestCompilationDependencies,
|
||||||
@@ -241,8 +242,8 @@ private class TestCompilationImpl(
|
|||||||
add(
|
add(
|
||||||
"-enable-assertions",
|
"-enable-assertions",
|
||||||
"-g",
|
"-g",
|
||||||
"-target", environment.globalEnvironment.target.name,
|
"-target", settings.global.target.name,
|
||||||
"-repo", environment.globalEnvironment.kotlinNativeHome.resolve("klib").path,
|
"-repo", settings.global.kotlinNativeHome.resolve("klib").path,
|
||||||
"-output", expectedArtifactFile.path,
|
"-output", expectedArtifactFile.path,
|
||||||
"-Xskip-prerelease-check",
|
"-Xskip-prerelease-check",
|
||||||
"-Xverify-ir",
|
"-Xverify-ir",
|
||||||
@@ -273,7 +274,7 @@ private class TestCompilationImpl(
|
|||||||
val (loggedCompilerCall: LoggedData, result: TestCompilationResult.ImmediateResult) = try {
|
val (loggedCompilerCall: LoggedData, result: TestCompilationResult.ImmediateResult) = try {
|
||||||
val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = callCompiler(
|
val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = callCompiler(
|
||||||
compilerArgs = compilerArgs,
|
compilerArgs = compilerArgs,
|
||||||
lazyKotlinNativeClassLoader = environment.globalEnvironment.lazyKotlinNativeClassLoader
|
lazyKotlinNativeClassLoader = settings.global.lazyKotlinNativeClassLoader
|
||||||
)
|
)
|
||||||
|
|
||||||
val loggedCompilerCall =
|
val loggedCompilerCall =
|
||||||
|
|||||||
+8
-7
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilationResult.Com
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.AbstractRunner
|
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.AbstractRunner
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.LocalTestRunner
|
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.LocalTestRunner
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.ThreadSafeCache
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.ThreadSafeCache
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.TreeNode
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.TreeNode
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.buildTree
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.buildTree
|
||||||
@@ -24,10 +25,10 @@ import org.junit.jupiter.api.extension.ExtensionContext
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class TestRunProvider(
|
internal class TestRunProvider(
|
||||||
private val environment: TestEnvironment,
|
private val settings: Settings,
|
||||||
private val testCaseGroupProvider: TestCaseGroupProvider
|
private val testCaseGroupProvider: TestCaseGroupProvider
|
||||||
) : ExtensionContext.Store.CloseableResource {
|
) : ExtensionContext.Store.CloseableResource {
|
||||||
private val compilationFactory = TestCompilationFactory(environment)
|
private val compilationFactory = TestCompilationFactory(settings)
|
||||||
private val cachedCompilations = ThreadSafeCache<TestCompilationCacheKey, TestCompilation>()
|
private val cachedCompilations = ThreadSafeCache<TestCompilationCacheKey, TestCompilation>()
|
||||||
|
|
||||||
fun setProcessors(testDataFile: File, sourceTransformers: List<(String) -> String>) {
|
fun setProcessors(testDataFile: File, sourceTransformers: List<(String) -> String>) {
|
||||||
@@ -114,7 +115,7 @@ internal class TestRunProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> withTestExecutable(testDataFile: File, action: (TestCase, TestExecutable) -> T): T {
|
private fun <T> withTestExecutable(testDataFile: File, action: (TestCase, TestExecutable) -> T): T {
|
||||||
environment.assertNotDisposed()
|
settings.assertNotDisposed()
|
||||||
|
|
||||||
val testDataDir = testDataFile.parentFile
|
val testDataDir = testDataFile.parentFile
|
||||||
val testDataFileName = testDataFile.name
|
val testDataFileName = testDataFile.name
|
||||||
@@ -173,19 +174,19 @@ internal class TestRunProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Currently, only local test runner is supported.
|
// Currently, only local test runner is supported.
|
||||||
fun createRunner(testRun: TestRun): AbstractRunner<*> = when (val target = environment.globalEnvironment.target) {
|
fun createRunner(testRun: TestRun): AbstractRunner<*> = when (val target = settings.global.target) {
|
||||||
environment.globalEnvironment.hostTarget -> LocalTestRunner(testRun, environment.globalEnvironment.executionTimeout)
|
settings.global.hostTarget -> LocalTestRunner(testRun, settings.global.executionTimeout)
|
||||||
else -> fail {
|
else -> fail {
|
||||||
"""
|
"""
|
||||||
Running at non-host target is not supported yet.
|
Running at non-host target is not supported yet.
|
||||||
Compilation target: $target
|
Compilation target: $target
|
||||||
Host target: ${environment.globalEnvironment.hostTarget}
|
Host target: ${settings.global.hostTarget}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
Disposer.dispose(environment)
|
Disposer.dispose(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class TestCompilationCacheKey {
|
private sealed class TestCompilationCacheKey {
|
||||||
|
|||||||
+19
-18
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.WithTestRunnerExtras
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.WithTestRunnerExtras
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -37,8 +38,8 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class ExtTestCaseGroupProvider(
|
internal class ExtTestCaseGroupProvider(
|
||||||
private val environment: TestEnvironment
|
private val settings: Settings
|
||||||
) : TestCaseGroupProvider, TestDisposable(parentDisposable = environment) {
|
) : TestCaseGroupProvider, TestDisposable(parentDisposable = settings) {
|
||||||
private val sourceTransformers: MutableMap<String, List<(String) -> String>> = mutableMapOf()
|
private val sourceTransformers: MutableMap<String, List<(String) -> String>> = mutableMapOf()
|
||||||
private val structureFactory = ExtTestDataFileStructureFactory(parentDisposable = this)
|
private val structureFactory = ExtTestDataFileStructureFactory(parentDisposable = this)
|
||||||
private val sharedModules = ThreadSafeCache<String, TestModule.Shared?>()
|
private val sharedModules = ThreadSafeCache<String, TestModule.Shared?>()
|
||||||
@@ -58,7 +59,7 @@ internal class ExtTestCaseGroupProvider(
|
|||||||
|
|
||||||
testDataFiles.forEach { testDataFile ->
|
testDataFiles.forEach { testDataFile ->
|
||||||
val extTestDataFile = ExtTestDataFile(
|
val extTestDataFile = ExtTestDataFile(
|
||||||
environment, structureFactory, testDataFile, sourceTransformers[testDataFile.canonicalPath] ?: listOf()
|
settings, structureFactory, testDataFile, sourceTransformers[testDataFile.canonicalPath] ?: listOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (extTestDataFile.isRelevant)
|
if (extTestDataFile.isRelevant)
|
||||||
@@ -126,7 +127,7 @@ internal class ExtTestCaseGroupProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ExtTestDataFile(
|
private class ExtTestDataFile(
|
||||||
private val environment: TestEnvironment,
|
private val settings: Settings,
|
||||||
structureFactory: ExtTestDataFileStructureFactory,
|
structureFactory: ExtTestDataFileStructureFactory,
|
||||||
private val testDataFile: File,
|
private val testDataFile: File,
|
||||||
sourceTransformers: List<(String) -> String>
|
sourceTransformers: List<(String) -> String>
|
||||||
@@ -139,7 +140,7 @@ private class ExtTestDataFile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val settings by lazy {
|
private val testDataFileSettings by lazy {
|
||||||
val optIns = structure.directives.multiValues(OPT_IN_DIRECTIVE)
|
val optIns = structure.directives.multiValues(OPT_IN_DIRECTIVE)
|
||||||
val optInsForSourceCode = optIns subtract OPT_INS_PURELY_FOR_COMPILER
|
val optInsForSourceCode = optIns subtract OPT_INS_PURELY_FOR_COMPILER
|
||||||
val optInsForCompiler = optIns intersect OPT_INS_PURELY_FOR_COMPILER
|
val optInsForCompiler = optIns intersect OPT_INS_PURELY_FOR_COMPILER
|
||||||
@@ -154,12 +155,12 @@ private class ExtTestDataFile(
|
|||||||
optInsForCompiler = optInsForCompiler,
|
optInsForCompiler = optInsForCompiler,
|
||||||
expectActualLinker = EXPECT_ACTUAL_LINKER_DIRECTIVE in structure.directives,
|
expectActualLinker = EXPECT_ACTUAL_LINKER_DIRECTIVE in structure.directives,
|
||||||
generatedSourcesDir = computeGeneratedSourcesDir(
|
generatedSourcesDir = computeGeneratedSourcesDir(
|
||||||
testDataBaseDir = environment.testRoots.baseDir,
|
testDataBaseDir = settings.testRoots.baseDir,
|
||||||
testDataFile = testDataFile,
|
testDataFile = testDataFile,
|
||||||
generatedSourcesBaseDir = environment.testSourcesDir
|
generatedSourcesBaseDir = settings.testSourcesDir
|
||||||
),
|
),
|
||||||
nominalPackageName = computePackageName(
|
nominalPackageName = computePackageName(
|
||||||
testDataBaseDir = environment.testRoots.baseDir,
|
testDataBaseDir = settings.testRoots.baseDir,
|
||||||
testDataFile = testDataFile
|
testDataFile = testDataFile
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -168,16 +169,16 @@ private class ExtTestDataFile(
|
|||||||
val isRelevant: Boolean =
|
val isRelevant: Boolean =
|
||||||
isCompatibleTarget(TargetBackend.NATIVE, testDataFile) // Checks TARGET_BACKEND/DONT_TARGET_EXACT_BACKEND directives.
|
isCompatibleTarget(TargetBackend.NATIVE, testDataFile) // Checks TARGET_BACKEND/DONT_TARGET_EXACT_BACKEND directives.
|
||||||
&& !isIgnoredTarget(TargetBackend.NATIVE, testDataFile) // Checks IGNORE_BACKEND directive.
|
&& !isIgnoredTarget(TargetBackend.NATIVE, testDataFile) // Checks IGNORE_BACKEND directive.
|
||||||
&& settings.languageSettings.none { it in INCOMPATIBLE_LANGUAGE_SETTINGS }
|
&& testDataFileSettings.languageSettings.none { it in INCOMPATIBLE_LANGUAGE_SETTINGS }
|
||||||
&& INCOMPATIBLE_DIRECTIVES.none { it in structure.directives }
|
&& INCOMPATIBLE_DIRECTIVES.none { it in structure.directives }
|
||||||
&& structure.directives[API_VERSION_DIRECTIVE] !in INCOMPATIBLE_API_VERSIONS
|
&& structure.directives[API_VERSION_DIRECTIVE] !in INCOMPATIBLE_API_VERSIONS
|
||||||
&& structure.directives[LANGUAGE_VERSION_DIRECTIVE] !in INCOMPATIBLE_LANGUAGE_VERSIONS
|
&& structure.directives[LANGUAGE_VERSION_DIRECTIVE] !in INCOMPATIBLE_LANGUAGE_VERSIONS
|
||||||
|
|
||||||
private fun assembleFreeCompilerArgs(): TestCompilerArgs {
|
private fun assembleFreeCompilerArgs(): TestCompilerArgs {
|
||||||
val args = mutableListOf<String>()
|
val args = mutableListOf<String>()
|
||||||
settings.languageSettings.sorted().mapTo(args) { "-XXLanguage:$it" }
|
testDataFileSettings.languageSettings.sorted().mapTo(args) { "-XXLanguage:$it" }
|
||||||
settings.optInsForCompiler.sorted().mapTo(args) { "-Xopt-in=$it" }
|
testDataFileSettings.optInsForCompiler.sorted().mapTo(args) { "-Xopt-in=$it" }
|
||||||
if (settings.expectActualLinker) args += "-Xexpect-actual-linker"
|
if (testDataFileSettings.expectActualLinker) args += "-Xexpect-actual-linker"
|
||||||
return TestCompilerArgs(args)
|
return TestCompilerArgs(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +275,7 @@ private class ExtTestDataFile(
|
|||||||
private fun patchPackageNames(isStandaloneTest: Boolean) = with(structure) {
|
private fun patchPackageNames(isStandaloneTest: Boolean) = with(structure) {
|
||||||
if (isStandaloneTest) return // Don't patch packages for standalone tests.
|
if (isStandaloneTest) return // Don't patch packages for standalone tests.
|
||||||
|
|
||||||
val basePackageName = FqName(settings.nominalPackageName)
|
val basePackageName = FqName(testDataFileSettings.nominalPackageName)
|
||||||
|
|
||||||
val oldPackageNames: Set<FqName> = filesToTransform.mapToSet { it.packageFqName }
|
val oldPackageNames: Set<FqName> = filesToTransform.mapToSet { it.packageFqName }
|
||||||
val oldToNewPackageNameMapping: Map<FqName, FqName> = oldPackageNames.associateWith { oldPackageName ->
|
val oldToNewPackageNameMapping: Map<FqName, FqName> = oldPackageNames.associateWith { oldPackageName ->
|
||||||
@@ -450,7 +451,7 @@ private class ExtTestDataFile(
|
|||||||
fun getAnnotationText(fullyQualifiedName: String) = "@file:${OPT_IN_ANNOTATION_NAME.asString()}($fullyQualifiedName::class)"
|
fun getAnnotationText(fullyQualifiedName: String) = "@file:${OPT_IN_ANNOTATION_NAME.asString()}($fullyQualifiedName::class)"
|
||||||
|
|
||||||
// Every OptIn specified in test directive should be represented as a file-level annotation.
|
// Every OptIn specified in test directive should be represented as a file-level annotation.
|
||||||
settings.optInsForSourceCode.mapTo(allFileLevelAnnotations, ::getAnnotationText)
|
testDataFileSettings.optInsForSourceCode.mapTo(allFileLevelAnnotations, ::getAnnotationText)
|
||||||
|
|
||||||
// Now, collect file-level annotations already present in test files.
|
// Now, collect file-level annotations already present in test files.
|
||||||
filesToTransform.forEach { handler ->
|
filesToTransform.forEach { handler ->
|
||||||
@@ -550,7 +551,7 @@ private class ExtTestDataFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isStandaloneTest) {
|
if (!isStandaloneTest) {
|
||||||
append("package ").appendLine(settings.nominalPackageName)
|
append("package ").appendLine(testDataFileSettings.nominalPackageName)
|
||||||
appendLine()
|
appendLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,10 +575,10 @@ private class ExtTestDataFile(
|
|||||||
sharedModules: ThreadSafeCache<String, TestModule.Shared?>
|
sharedModules: ThreadSafeCache<String, TestModule.Shared?>
|
||||||
): TestCase = with(structure) {
|
): TestCase = with(structure) {
|
||||||
val modules = generateModules(
|
val modules = generateModules(
|
||||||
testCaseDir = settings.generatedSourcesDir,
|
testCaseDir = testDataFileSettings.generatedSourcesDir,
|
||||||
findOrGenerateSharedModule = { moduleName: String, generator: SharedModuleGenerator ->
|
findOrGenerateSharedModule = { moduleName: String, generator: SharedModuleGenerator ->
|
||||||
sharedModules.computeIfAbsent(moduleName) {
|
sharedModules.computeIfAbsent(moduleName) {
|
||||||
generator(environment.sharedSourcesDir)
|
generator(settings.sharedSourcesDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -587,7 +588,7 @@ private class ExtTestDataFile(
|
|||||||
modules = modules,
|
modules = modules,
|
||||||
freeCompilerArgs = assembleFreeCompilerArgs(),
|
freeCompilerArgs = assembleFreeCompilerArgs(),
|
||||||
origin = TestOrigin.SingleTestDataFile(testDataFile),
|
origin = TestOrigin.SingleTestDataFile(testDataFile),
|
||||||
nominalPackageName = settings.nominalPackageName,
|
nominalPackageName = testDataFileSettings.nominalPackageName,
|
||||||
expectedOutputDataFile = null,
|
expectedOutputDataFile = null,
|
||||||
extras = WithTestRunnerExtras.EMPTY
|
extras = WithTestRunnerExtras.EMPTY
|
||||||
)
|
)
|
||||||
|
|||||||
+5
-4
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.konan.blackboxtest.support.group
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.NoTestRunnerExtras
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.NoTestRunnerExtras
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.WithTestRunnerExtras
|
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase.WithTestRunnerExtras
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.DEFAULT_FILE_NAME
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.DEFAULT_FILE_NAME
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.ThreadSafeFactory
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.ThreadSafeFactory
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.computeGeneratedSourcesDir
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.computeGeneratedSourcesDir
|
||||||
@@ -22,7 +23,7 @@ import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
|||||||
import org.jetbrains.kotlin.test.services.impl.RegisteredDirectivesParser
|
import org.jetbrains.kotlin.test.services.impl.RegisteredDirectivesParser
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class StandardTestCaseGroupProvider(private val environment: TestEnvironment) : TestCaseGroupProvider {
|
internal class StandardTestCaseGroupProvider(private val settings: Settings) : TestCaseGroupProvider {
|
||||||
val sourceTransformers: MutableMap<String, List<(String) -> String>> = mutableMapOf()
|
val sourceTransformers: MutableMap<String, List<(String) -> String>> = mutableMapOf()
|
||||||
|
|
||||||
// Load test cases in groups on demand.
|
// Load test cases in groups on demand.
|
||||||
@@ -51,13 +52,13 @@ internal class StandardTestCaseGroupProvider(private val environment: TestEnviro
|
|||||||
|
|
||||||
private fun createTestCase(testDataFile: File): TestCase {
|
private fun createTestCase(testDataFile: File): TestCase {
|
||||||
val generatedSourcesDir = computeGeneratedSourcesDir(
|
val generatedSourcesDir = computeGeneratedSourcesDir(
|
||||||
testDataBaseDir = environment.testRoots.baseDir,
|
testDataBaseDir = settings.testRoots.baseDir,
|
||||||
testDataFile = testDataFile,
|
testDataFile = testDataFile,
|
||||||
generatedSourcesBaseDir = environment.testSourcesDir
|
generatedSourcesBaseDir = settings.testSourcesDir
|
||||||
)
|
)
|
||||||
|
|
||||||
val nominalPackageName = computePackageName(
|
val nominalPackageName = computePackageName(
|
||||||
testDataBaseDir = environment.testRoots.baseDir,
|
testDataBaseDir = settings.testRoots.baseDir,
|
||||||
testDataFile = testDataFile
|
testDataFile = testDataFile
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.konan.blackboxtest.support.group
|
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
|
||||||
internal annotation class TestCaseGroupProviding(val providerClass: KClass<out TestCaseGroupProvider>)
|
|
||||||
+3
-1
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.konan.blackboxtest.support.group
|
package org.jetbrains.kotlin.konan.blackboxtest.support.group
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.TestSettings
|
||||||
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@TestCaseGroupProviding(ExtTestCaseGroupProvider::class)
|
@TestSettings(ExtTestCaseGroupProvider::class)
|
||||||
annotation class UseExtTestCaseGroupProvider
|
annotation class UseExtTestCaseGroupProvider
|
||||||
|
|||||||
+18
-47
@@ -3,44 +3,34 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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.konan.blackboxtest.support
|
package org.jetbrains.kotlin.konan.blackboxtest.support.settings
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.TestDisposable
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.seconds
|
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal class TestEnvironment(
|
internal class GlobalSettings(
|
||||||
val globalEnvironment: GlobalTestEnvironment,
|
|
||||||
val testRoots: TestRoots, // The directories with original sources (aka testData).
|
|
||||||
val testSourcesDir: File, // The directory with generated (preprocessed) test sources.
|
|
||||||
val sharedSourcesDir: File, // The directory with the sources of the shared modules (i.e. the modules that are widely used in multiple tests).
|
|
||||||
val testBinariesDir: File, // The directory with compiled test binaries (klibs) and executable files).
|
|
||||||
val sharedBinariesDir: File // The directory with compiled shared modules (klibs).
|
|
||||||
) : TestDisposable(parentDisposable = null)
|
|
||||||
|
|
||||||
internal class GlobalTestEnvironment(
|
|
||||||
val target: KonanTarget = HostManager.host,
|
val target: KonanTarget = HostManager.host,
|
||||||
val kotlinNativeHome: File = defaultKotlinNativeHome,
|
val kotlinNativeHome: File = defaultKotlinNativeHome,
|
||||||
val lazyKotlinNativeClassLoader: Lazy<ClassLoader> = defaultKotlinNativeClassLoader,
|
val lazyKotlinNativeClassLoader: Lazy<ClassLoader> = defaultKotlinNativeClassLoader,
|
||||||
val testMode: TestMode = defaultTestMode,
|
val testMode: TestMode = defaultTestMode,
|
||||||
val cacheSettings: TestCacheSettings = defaultCacheSettings,
|
val cacheSettings: CacheSettings = defaultCacheSettings,
|
||||||
val executionTimeout: Duration = defaultExecutionTimeout,
|
val executionTimeout: Duration = defaultExecutionTimeout,
|
||||||
val baseBuildDir: File = projectBuildDir
|
val baseBuildDir: File = projectBuildDir
|
||||||
) {
|
) {
|
||||||
val hostTarget: KonanTarget = HostManager.host
|
val hostTarget: KonanTarget = HostManager.host
|
||||||
|
|
||||||
fun getRootCacheDirectory(debuggable: Boolean): File? =
|
fun getRootCacheDirectory(debuggable: Boolean): File? =
|
||||||
(cacheSettings as? TestCacheSettings.WithCache)?.getRootCacheDirectory(this, debuggable)
|
(cacheSettings as? CacheSettings.WithCache)?.getRootCacheDirectory(this, debuggable)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val defaultKotlinNativeHome: File
|
private val defaultKotlinNativeHome: File
|
||||||
get() = System.getProperty(KOTLIN_NATIVE_HOME)?.let(::File) ?: fail { "Non-specified $KOTLIN_NATIVE_HOME system property" }
|
get() = System.getProperty(KOTLIN_NATIVE_HOME)?.let(::File) ?: JUnit5Assertions.fail { "Non-specified $KOTLIN_NATIVE_HOME system property" }
|
||||||
|
|
||||||
// Use isolated cached class loader.
|
// Use isolated cached class loader.
|
||||||
private val defaultKotlinNativeClassLoader: Lazy<ClassLoader> = lazy {
|
private val defaultKotlinNativeClassLoader: Lazy<ClassLoader> = lazy {
|
||||||
@@ -48,7 +38,7 @@ internal class GlobalTestEnvironment(
|
|||||||
?.split(':', ';')
|
?.split(':', ';')
|
||||||
?.map { File(it).toURI().toURL() }
|
?.map { File(it).toURI().toURL() }
|
||||||
?.toTypedArray()
|
?.toTypedArray()
|
||||||
?: fail { "Non-specified $COMPILER_CLASSPATH system property" }
|
?: JUnit5Assertions.fail { "Non-specified $COMPILER_CLASSPATH system property" }
|
||||||
|
|
||||||
URLClassLoader(nativeClassPath, /* no parent class loader */ null).apply { setDefaultAssertionStatus(true) }
|
URLClassLoader(nativeClassPath, /* no parent class loader */ null).apply { setDefaultAssertionStatus(true) }
|
||||||
}
|
}
|
||||||
@@ -56,7 +46,7 @@ internal class GlobalTestEnvironment(
|
|||||||
private val defaultTestMode: TestMode = run {
|
private val defaultTestMode: TestMode = run {
|
||||||
val testModeName = System.getProperty(TEST_MODE) ?: return@run TestMode.WITH_MODULES
|
val testModeName = System.getProperty(TEST_MODE) ?: return@run TestMode.WITH_MODULES
|
||||||
|
|
||||||
TestMode.values().firstOrNull { it.name == testModeName } ?: fail {
|
TestMode.values().firstOrNull { it.name == testModeName } ?: JUnit5Assertions.fail {
|
||||||
buildString {
|
buildString {
|
||||||
appendLine("Unknown test mode name $testModeName.")
|
appendLine("Unknown test mode name $testModeName.")
|
||||||
appendLine("One of the following test modes should be passed through $TEST_MODE system property:")
|
appendLine("One of the following test modes should be passed through $TEST_MODE system property:")
|
||||||
@@ -67,27 +57,27 @@ internal class GlobalTestEnvironment(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val defaultCacheSettings: TestCacheSettings = run {
|
private val defaultCacheSettings: CacheSettings = run {
|
||||||
val useCacheValue = System.getProperty(USE_CACHE)
|
val useCacheValue = System.getProperty(USE_CACHE)
|
||||||
val useCache = if (useCacheValue != null) {
|
val useCache = if (useCacheValue != null) {
|
||||||
useCacheValue.toBooleanStrictOrNull() ?: fail { "Invalid value for $USE_CACHE system property: $useCacheValue" }
|
useCacheValue.toBooleanStrictOrNull() ?: JUnit5Assertions.fail { "Invalid value for $USE_CACHE system property: $useCacheValue" }
|
||||||
} else
|
} else
|
||||||
true
|
true
|
||||||
|
|
||||||
if (useCache) TestCacheSettings.WithCache else TestCacheSettings.WithoutCache
|
if (useCache) CacheSettings.WithCache else CacheSettings.WithoutCache
|
||||||
}
|
}
|
||||||
|
|
||||||
private val defaultExecutionTimeout: Duration = run {
|
private val defaultExecutionTimeout: Duration = run {
|
||||||
val executionTimeoutValue = System.getProperty(EXECUTION_TIMEOUT)
|
val executionTimeoutValue = System.getProperty(EXECUTION_TIMEOUT)
|
||||||
if (executionTimeoutValue != null) {
|
if (executionTimeoutValue != null) {
|
||||||
executionTimeoutValue.toLongOrNull()?.milliseconds
|
executionTimeoutValue.toLongOrNull()?.milliseconds
|
||||||
?: fail { "Invalid value for $EXECUTION_TIMEOUT system property: $executionTimeoutValue" }
|
?: JUnit5Assertions.fail { "Invalid value for $EXECUTION_TIMEOUT system property: $executionTimeoutValue" }
|
||||||
} else
|
} else
|
||||||
DEFAULT_EXECUTION_TIMEOUT
|
DEFAULT_EXECUTION_TIMEOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
private val projectBuildDir: File
|
private val projectBuildDir: File
|
||||||
get() = System.getenv(PROJECT_BUILD_DIR)?.let(::File) ?: fail { "Non-specified $PROJECT_BUILD_DIR environment variable" }
|
get() = System.getenv(PROJECT_BUILD_DIR)?.let(::File) ?: JUnit5Assertions.fail { "Non-specified $PROJECT_BUILD_DIR environment variable" }
|
||||||
|
|
||||||
private const val KOTLIN_NATIVE_HOME = "kotlin.internal.native.test.nativeHome"
|
private const val KOTLIN_NATIVE_HOME = "kotlin.internal.native.test.nativeHome"
|
||||||
private const val COMPILER_CLASSPATH = "kotlin.internal.native.test.compilerClasspath"
|
private const val COMPILER_CLASSPATH = "kotlin.internal.native.test.compilerClasspath"
|
||||||
@@ -100,30 +90,11 @@ internal class GlobalTestEnvironment(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class TestRoots(
|
internal sealed interface CacheSettings {
|
||||||
val roots: Set<File>,
|
object WithoutCache : CacheSettings
|
||||||
val baseDir: File
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: in fact, only WITH_MODULES mode is supported now
|
object WithCache : CacheSettings {
|
||||||
internal enum class TestMode(val description: String) {
|
fun getRootCacheDirectory(settings: GlobalSettings, debuggable: Boolean): File? = with(settings) {
|
||||||
ONE_STAGE(
|
|
||||||
description = "Compile test files altogether without producing intermediate KLIBs."
|
|
||||||
),
|
|
||||||
TWO_STAGE(
|
|
||||||
description = "Compile test files altogether and produce an intermediate KLIB. Then produce a program from the KLIB using -Xinclude."
|
|
||||||
),
|
|
||||||
WITH_MODULES(
|
|
||||||
description = "Compile each test file as one or many modules (depending on MODULE directives declared in the file)." +
|
|
||||||
" Then link the KLIBs into the single executable file."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed interface TestCacheSettings {
|
|
||||||
object WithoutCache : TestCacheSettings
|
|
||||||
|
|
||||||
object WithCache : TestCacheSettings {
|
|
||||||
fun getRootCacheDirectory(globalEnvironment: GlobalTestEnvironment, debuggable: Boolean): File? = with(globalEnvironment) {
|
|
||||||
kotlinNativeHome.resolve("klib/cache").resolve(getCacheDirName(target, debuggable)).takeIf { it.exists() }
|
kotlinNativeHome.resolve("klib/cache").resolve(getCacheDirName(target, debuggable)).takeIf { it.exists() }
|
||||||
}
|
}
|
||||||
|
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.konan.blackboxtest.support.settings
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.TestDisposable
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class Settings(
|
||||||
|
val global: GlobalSettings,
|
||||||
|
val testRoots: TestRoots, // The directories with original sources (aka testData).
|
||||||
|
val testSourcesDir: File, // The directory with generated (preprocessed) test sources.
|
||||||
|
val sharedSourcesDir: File, // The directory with the sources of the shared modules (i.e. the modules that are widely used in multiple tests).
|
||||||
|
val testBinariesDir: File, // The directory with compiled test binaries (klibs) and executable files).
|
||||||
|
val sharedBinariesDir: File // The directory with compiled shared modules (klibs).
|
||||||
|
) : TestDisposable(parentDisposable = null)
|
||||||
|
|
||||||
|
internal class TestRoots(
|
||||||
|
val roots: Set<File>,
|
||||||
|
val baseDir: File
|
||||||
|
)
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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.konan.blackboxtest.support.settings
|
||||||
|
|
||||||
|
// TODO: in fact, only WITH_MODULES mode is supported now
|
||||||
|
internal enum class TestMode(val description: String) {
|
||||||
|
ONE_STAGE(
|
||||||
|
description = "Compile test files altogether without producing intermediate KLIBs."
|
||||||
|
),
|
||||||
|
TWO_STAGE(
|
||||||
|
description = "Compile test files altogether and produce an intermediate KLIB. Then produce a program from the KLIB using -Xinclude."
|
||||||
|
),
|
||||||
|
WITH_MODULES(
|
||||||
|
description = "Compile each test file as one or many modules (depending on MODULE directives declared in the file)." +
|
||||||
|
" Then link the KLIBs into the single executable file."
|
||||||
|
)
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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.konan.blackboxtest.support.settings
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.group.StandardTestCaseGroupProvider
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||||
|
internal annotation class TestSettings(val providerClass: KClass<out TestCaseGroupProvider>) {
|
||||||
|
companion object {
|
||||||
|
val DEFAULT = TestSettings(StandardTestCaseGroupProvider::class)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user