From 30e51452b4db4128b11de22f05fb35762dcd4fdf Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Thu, 25 Nov 2021 12:53:49 +0300 Subject: [PATCH] [Native][tests] Refactoring: Rework Settings/GlobalSettings --- .../support/NativeBlackBoxTestSupport.kt | 88 +++++++++++-------- .../konan/blackboxtest/support/TestCase.kt | 1 + .../blackboxtest/support/TestCompiler.kt | 25 +++--- .../blackboxtest/support/TestRunProvider.kt | 15 ++-- .../support/group/ExtTestCaseGroupProvider.kt | 37 ++++---- .../group/StandardTestCaseGroupProvider.kt | 9 +- .../support/group/TestCaseGroupProviding.kt | 11 --- .../group/UseExtTestCaseGroupProvider.kt | 4 +- .../GlobalSettings.kt} | 65 ++++---------- .../blackboxtest/support/settings/Settings.kt | 23 +++++ .../blackboxtest/support/settings/TestMode.kt | 20 +++++ .../support/settings/TestSettings.kt | 17 ++++ 12 files changed, 178 insertions(+), 137 deletions(-) delete mode 100644 native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/TestCaseGroupProviding.kt rename native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/{TestEnvironment.kt => settings/GlobalSettings.kt} (58%) create mode 100644 native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/Settings.kt create mode 100644 native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestMode.kt create mode 100644 native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestSettings.kt diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt index 4c347fdabbc..1ccdfe036dd 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt @@ -6,9 +6,11 @@ package org.jetbrains.kotlin.konan.blackboxtest.support 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.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.test.TestMetadata import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEquals @@ -35,7 +37,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { enclosingTestInstance.onRunProviderSet() // Set the essential compiler property. - System.setProperty("kotlin.native.home", getOrCreateGlobalEnvironment().kotlinNativeHome.path) + System.setProperty("kotlin.native.home", getOrCreateGlobalSettings().kotlinNativeHome.path) } companion object { @@ -46,13 +48,14 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { val enclosingTestClass = enclosingTestClass 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(uniqueEnclosingClassDirName) .ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale generated sources. @@ -61,7 +64,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { .resolve("__shared_modules__") .ensureExistsAndIsEmptyDirectory() - val testBinariesDir = globalEnvironment.baseBuildDir + val testBinariesDir = globalSettings.baseBuildDir .resolve("bbtest.bin") .resolve(uniqueEnclosingClassDirName) .ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale artifacts. @@ -70,8 +73,8 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { .resolve("__shared_modules__") .ensureExistsAndIsEmptyDirectory() - val environment = TestEnvironment( - globalEnvironment = globalEnvironment, + val settings = Settings( + global = globalSettings, testRoots = testRoots, testSourcesDir = testSourcesDir, sharedSourcesDir = sharedSourcesDir, @@ -79,16 +82,16 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { sharedBinariesDir = sharedBinariesDir ) - val testCaseGroupProvider = requiredTestClass.createTestCaseGroupProvider(environment) + val testCaseGroupProvider = createTestCaseGroupProvider(settings, testSettings, testSettingsAnnotation) - TestRunProvider(environment, testCaseGroupProvider) + TestRunProvider(settings, testCaseGroupProvider) }.cast() } - private fun ExtensionContext.getOrCreateGlobalEnvironment(): GlobalTestEnvironment = - root.getStore(NAMESPACE).getOrComputeIfAbsent(GlobalTestEnvironment::class.java.sanitizedName) { + private fun ExtensionContext.getOrCreateGlobalSettings(): GlobalSettings = + root.getStore(NAMESPACE).getOrComputeIfAbsent(GlobalSettings::class.java.sanitizedName) { // Create with the default settings. - GlobalTestEnvironment() + GlobalSettings() }.cast() private val ExtensionContext.enclosingTestInstance: AbstractNativeBlackBoxTest @@ -97,9 +100,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { private val ExtensionContext.enclosingTestClass: Class<*> get() = generateSequence(requiredTestClass) { it.enclosingClass }.last() - private fun ExtensionContext.computeTestRoots(): TestRoots { - val enclosingTestClass = enclosingTestClass - + private fun computeTestRoots(enclosingTestClass: Class<*>): TestRoots { val testRoots: Set = when (val outermostTestMetadata = enclosingTestClass.getAnnotation(TestMetadata::class.java)) { null -> { enclosingTestClass.declaredClasses.mapNotNullToSet { nestedClass -> @@ -125,35 +126,48 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { return TestRoots(testRoots, baseDir) } - private fun Class<*>.createTestCaseGroupProvider(environment: TestEnvironment): TestCaseGroupProvider { - val (providerAnnotation, providerAnnotationClass, providerClass) = annotations.asSequence() - .mapNotNull { annotation -> - val annotationClass = annotation.annotationClass - val providerClass = annotationClass.findAnnotation()?.providerClass ?: return@mapNotNull null - Triple(annotation, annotationClass, providerClass) + private fun computeTestSettings(enclosingTestClass: Class<*>): Pair { + val findTestSettings: Class<*>.() -> Pair? = { + annotations.asSequence().mapNotNull { annotation -> + val testSettings = annotation.annotationClass.findAnnotation() ?: return@mapNotNull null + testSettings to annotation }.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. - providerClass.constructors.asSequence() - .forEach { c -> - val (p1, p2) = c.parameters.takeIf { it.size == 2 } ?: return@forEach - val provider = when { - p1.hasTypeOf() && p2.hasTypeOf(providerAnnotationClass) -> c.call(environment, providerAnnotation) - p1.hasTypeOf(providerAnnotationClass) && p2.hasTypeOf() -> c.call(providerAnnotation, environment) - else -> return@forEach + if (testSettingsAnnotation != null) { + val testSettingsAnnotationClass = testSettingsAnnotation.annotationClass + + testSettings.providerClass.constructors.asSequence() + .forEach { c -> + val (p1, p2) = c.parameters.takeIf { it.size == 2 } ?: return@forEach + @Suppress("Reformat") val provider = when { + p1.hasTypeOf() && p2.hasTypeOf(testSettingsAnnotationClass) -> c.call(settings, testSettingsAnnotation) + p1.hasTypeOf(testSettingsAnnotationClass) && p2.hasTypeOf() -> c.call(testSettingsAnnotation, settings) + else -> return@forEach + } + return provider.cast() } - return provider.cast() - } + } // Next, try to find a single-argument constructor. - providerClass.constructors.asSequence() + testSettings.providerClass.constructors.asSequence() .forEach { c -> val p = c.parameters.singleOrNull() ?: return@forEach - if (p.hasTypeOf()) return c.call(environment).cast() + if (p.hasTypeOf()) return c.call(settings).cast() } - fail { "No suitable constructor for $providerClass" } + fail { "No suitable constructor for ${testSettings.providerClass}" } } private inline fun KParameter.hasTypeOf(): Boolean = hasTypeOf(T::class) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCase.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCase.kt index 4bfabcc315d..6d263c7b7ac 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCase.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCase.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.konan.blackboxtest.support 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.storage.LockBasedStorageManager import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt index 163bbf5356d..7766004e215 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt @@ -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.TestModule.Companion.allDependencies 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.test.services.JUnit5Assertions.fail import java.io.* @@ -22,7 +23,7 @@ import kotlin.time.Duration import kotlin.time.ExperimentalTime import kotlin.time.measureTime -internal class TestCompilationFactory(private val environment: TestEnvironment) { +internal class TestCompilationFactory(private val settings: Settings) { private val cachedCompilations = ThreadSafeCache() private sealed interface TestCompilationCacheKey { @@ -46,7 +47,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) val entryPoint = testCases.singleOrNull()?.safeExtras()?.entryPoint TestCompilationImpl( - environment = environment, + settings = settings, freeCompilerArgs = freeCompilerArgs, sourceModules = rootModules, dependencies = TestCompilationDependencies(libraries = libraries, friends = friends), @@ -54,7 +55,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) specificCompilerArgs = { add("-produce", "program") 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") } } @@ -75,7 +76,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) return cachedCompilations.computeIfAbsent(cacheKey) { TestCompilationImpl( - environment = environment, + settings = settings, freeCompilerArgs = freeCompilerArgs, sourceModules = sourceModules, dependencies = TestCompilationDependencies(libraries = libraries, friends = friends), @@ -87,15 +88,15 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) private fun artifactFileForExecutable(modules: Set) = when (modules.size) { 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) = - singleModuleArtifactFile(module, environment.globalEnvironment.target.family.exeSuffix) + singleModuleArtifactFile(module, settings.global.target.family.exeSuffix) private fun artifactFileForKlib(module: TestModule, freeCompilerArgs: TestCompilerArgs) = when (module) { 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 { @@ -141,7 +142,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) } 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 outputDir.mkdirs() @@ -221,7 +222,7 @@ internal class TestCompilationDependencies( } private class TestCompilationImpl( - private val environment: TestEnvironment, + private val settings: Settings, private val freeCompilerArgs: TestCompilerArgs, private val sourceModules: Collection, private val dependencies: TestCompilationDependencies, @@ -241,8 +242,8 @@ private class TestCompilationImpl( add( "-enable-assertions", "-g", - "-target", environment.globalEnvironment.target.name, - "-repo", environment.globalEnvironment.kotlinNativeHome.resolve("klib").path, + "-target", settings.global.target.name, + "-repo", settings.global.kotlinNativeHome.resolve("klib").path, "-output", expectedArtifactFile.path, "-Xskip-prerelease-check", "-Xverify-ir", @@ -273,7 +274,7 @@ private class TestCompilationImpl( val (loggedCompilerCall: LoggedData, result: TestCompilationResult.ImmediateResult) = try { val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = callCompiler( compilerArgs = compilerArgs, - lazyKotlinNativeClassLoader = environment.globalEnvironment.lazyKotlinNativeClassLoader + lazyKotlinNativeClassLoader = settings.global.lazyKotlinNativeClassLoader ) val loggedCompilerCall = diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestRunProvider.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestRunProvider.kt index 07d2c88f401..a1c01b38ef7 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestRunProvider.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestRunProvider.kt @@ -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.runner.AbstractRunner 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.TreeNode import org.jetbrains.kotlin.konan.blackboxtest.support.util.buildTree @@ -24,10 +25,10 @@ import org.junit.jupiter.api.extension.ExtensionContext import java.io.File internal class TestRunProvider( - private val environment: TestEnvironment, + private val settings: Settings, private val testCaseGroupProvider: TestCaseGroupProvider ) : ExtensionContext.Store.CloseableResource { - private val compilationFactory = TestCompilationFactory(environment) + private val compilationFactory = TestCompilationFactory(settings) private val cachedCompilations = ThreadSafeCache() fun setProcessors(testDataFile: File, sourceTransformers: List<(String) -> String>) { @@ -114,7 +115,7 @@ internal class TestRunProvider( } private fun withTestExecutable(testDataFile: File, action: (TestCase, TestExecutable) -> T): T { - environment.assertNotDisposed() + settings.assertNotDisposed() val testDataDir = testDataFile.parentFile val testDataFileName = testDataFile.name @@ -173,19 +174,19 @@ internal class TestRunProvider( } // Currently, only local test runner is supported. - fun createRunner(testRun: TestRun): AbstractRunner<*> = when (val target = environment.globalEnvironment.target) { - environment.globalEnvironment.hostTarget -> LocalTestRunner(testRun, environment.globalEnvironment.executionTimeout) + fun createRunner(testRun: TestRun): AbstractRunner<*> = when (val target = settings.global.target) { + settings.global.hostTarget -> LocalTestRunner(testRun, settings.global.executionTimeout) else -> fail { """ Running at non-host target is not supported yet. Compilation target: $target - Host target: ${environment.globalEnvironment.hostTarget} + Host target: ${settings.global.hostTarget} """.trimIndent() } } override fun close() { - Disposer.dispose(environment) + Disposer.dispose(settings) } private sealed class TestCompilationCacheKey { diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/ExtTestCaseGroupProvider.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/ExtTestCaseGroupProvider.kt index bc2574c0bdb..b7f51d6088f 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/ExtTestCaseGroupProvider.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/ExtTestCaseGroupProvider.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.konan.blackboxtest.support.* 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.name.FqName import org.jetbrains.kotlin.name.Name @@ -37,8 +38,8 @@ import org.jetbrains.kotlin.utils.addIfNotNull import java.io.File internal class ExtTestCaseGroupProvider( - private val environment: TestEnvironment -) : TestCaseGroupProvider, TestDisposable(parentDisposable = environment) { + private val settings: Settings +) : TestCaseGroupProvider, TestDisposable(parentDisposable = settings) { private val sourceTransformers: MutableMap String>> = mutableMapOf() private val structureFactory = ExtTestDataFileStructureFactory(parentDisposable = this) private val sharedModules = ThreadSafeCache() @@ -58,7 +59,7 @@ internal class ExtTestCaseGroupProvider( testDataFiles.forEach { testDataFile -> val extTestDataFile = ExtTestDataFile( - environment, structureFactory, testDataFile, sourceTransformers[testDataFile.canonicalPath] ?: listOf() + settings, structureFactory, testDataFile, sourceTransformers[testDataFile.canonicalPath] ?: listOf() ) if (extTestDataFile.isRelevant) @@ -126,7 +127,7 @@ internal class ExtTestCaseGroupProvider( } private class ExtTestDataFile( - private val environment: TestEnvironment, + private val settings: Settings, structureFactory: ExtTestDataFileStructureFactory, private val testDataFile: File, 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 optInsForSourceCode = optIns subtract OPT_INS_PURELY_FOR_COMPILER val optInsForCompiler = optIns intersect OPT_INS_PURELY_FOR_COMPILER @@ -154,12 +155,12 @@ private class ExtTestDataFile( optInsForCompiler = optInsForCompiler, expectActualLinker = EXPECT_ACTUAL_LINKER_DIRECTIVE in structure.directives, generatedSourcesDir = computeGeneratedSourcesDir( - testDataBaseDir = environment.testRoots.baseDir, + testDataBaseDir = settings.testRoots.baseDir, testDataFile = testDataFile, - generatedSourcesBaseDir = environment.testSourcesDir + generatedSourcesBaseDir = settings.testSourcesDir ), nominalPackageName = computePackageName( - testDataBaseDir = environment.testRoots.baseDir, + testDataBaseDir = settings.testRoots.baseDir, testDataFile = testDataFile ) ) @@ -168,16 +169,16 @@ private class ExtTestDataFile( val isRelevant: Boolean = isCompatibleTarget(TargetBackend.NATIVE, testDataFile) // Checks TARGET_BACKEND/DONT_TARGET_EXACT_BACKEND directives. && !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 } && structure.directives[API_VERSION_DIRECTIVE] !in INCOMPATIBLE_API_VERSIONS && structure.directives[LANGUAGE_VERSION_DIRECTIVE] !in INCOMPATIBLE_LANGUAGE_VERSIONS private fun assembleFreeCompilerArgs(): TestCompilerArgs { val args = mutableListOf() - settings.languageSettings.sorted().mapTo(args) { "-XXLanguage:$it" } - settings.optInsForCompiler.sorted().mapTo(args) { "-Xopt-in=$it" } - if (settings.expectActualLinker) args += "-Xexpect-actual-linker" + testDataFileSettings.languageSettings.sorted().mapTo(args) { "-XXLanguage:$it" } + testDataFileSettings.optInsForCompiler.sorted().mapTo(args) { "-Xopt-in=$it" } + if (testDataFileSettings.expectActualLinker) args += "-Xexpect-actual-linker" return TestCompilerArgs(args) } @@ -274,7 +275,7 @@ private class ExtTestDataFile( private fun patchPackageNames(isStandaloneTest: Boolean) = with(structure) { if (isStandaloneTest) return // Don't patch packages for standalone tests. - val basePackageName = FqName(settings.nominalPackageName) + val basePackageName = FqName(testDataFileSettings.nominalPackageName) val oldPackageNames: Set = filesToTransform.mapToSet { it.packageFqName } val oldToNewPackageNameMapping: Map = oldPackageNames.associateWith { oldPackageName -> @@ -450,7 +451,7 @@ private class ExtTestDataFile( 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. - settings.optInsForSourceCode.mapTo(allFileLevelAnnotations, ::getAnnotationText) + testDataFileSettings.optInsForSourceCode.mapTo(allFileLevelAnnotations, ::getAnnotationText) // Now, collect file-level annotations already present in test files. filesToTransform.forEach { handler -> @@ -550,7 +551,7 @@ private class ExtTestDataFile( } if (!isStandaloneTest) { - append("package ").appendLine(settings.nominalPackageName) + append("package ").appendLine(testDataFileSettings.nominalPackageName) appendLine() } @@ -574,10 +575,10 @@ private class ExtTestDataFile( sharedModules: ThreadSafeCache ): TestCase = with(structure) { val modules = generateModules( - testCaseDir = settings.generatedSourcesDir, + testCaseDir = testDataFileSettings.generatedSourcesDir, findOrGenerateSharedModule = { moduleName: String, generator: SharedModuleGenerator -> sharedModules.computeIfAbsent(moduleName) { - generator(environment.sharedSourcesDir) + generator(settings.sharedSourcesDir) } } ) @@ -587,7 +588,7 @@ private class ExtTestDataFile( modules = modules, freeCompilerArgs = assembleFreeCompilerArgs(), origin = TestOrigin.SingleTestDataFile(testDataFile), - nominalPackageName = settings.nominalPackageName, + nominalPackageName = testDataFileSettings.nominalPackageName, expectedOutputDataFile = null, extras = WithTestRunnerExtras.EMPTY ) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/StandardTestCaseGroupProvider.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/StandardTestCaseGroupProvider.kt index 5079cfc401e..d4d0b2a9632 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/StandardTestCaseGroupProvider.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/StandardTestCaseGroupProvider.kt @@ -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.TestCase.NoTestRunnerExtras 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.ThreadSafeFactory 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 java.io.File -internal class StandardTestCaseGroupProvider(private val environment: TestEnvironment) : TestCaseGroupProvider { +internal class StandardTestCaseGroupProvider(private val settings: Settings) : TestCaseGroupProvider { val sourceTransformers: MutableMap String>> = mutableMapOf() // Load test cases in groups on demand. @@ -51,13 +52,13 @@ internal class StandardTestCaseGroupProvider(private val environment: TestEnviro private fun createTestCase(testDataFile: File): TestCase { val generatedSourcesDir = computeGeneratedSourcesDir( - testDataBaseDir = environment.testRoots.baseDir, + testDataBaseDir = settings.testRoots.baseDir, testDataFile = testDataFile, - generatedSourcesBaseDir = environment.testSourcesDir + generatedSourcesBaseDir = settings.testSourcesDir ) val nominalPackageName = computePackageName( - testDataBaseDir = environment.testRoots.baseDir, + testDataBaseDir = settings.testRoots.baseDir, testDataFile = testDataFile ) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/TestCaseGroupProviding.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/TestCaseGroupProviding.kt deleted file mode 100644 index a009ecfb03e..00000000000 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/TestCaseGroupProviding.kt +++ /dev/null @@ -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) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/UseExtTestCaseGroupProvider.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/UseExtTestCaseGroupProvider.kt index c06a76d3af0..e0ec361b76d 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/UseExtTestCaseGroupProvider.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/group/UseExtTestCaseGroupProvider.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.konan.blackboxtest.support.group +import org.jetbrains.kotlin.konan.blackboxtest.support.settings.TestSettings + @Target(AnnotationTarget.CLASS) -@TestCaseGroupProviding(ExtTestCaseGroupProvider::class) +@TestSettings(ExtTestCaseGroupProvider::class) annotation class UseExtTestCaseGroupProvider diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestEnvironment.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/GlobalSettings.kt similarity index 58% rename from native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestEnvironment.kt rename to native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/GlobalSettings.kt index 3d773efea43..be9744d008d 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestEnvironment.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/GlobalSettings.kt @@ -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. */ -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.KonanTarget -import org.jetbrains.kotlin.konan.blackboxtest.support.util.TestDisposable -import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail +import org.jetbrains.kotlin.test.services.JUnit5Assertions import java.io.File import java.net.URLClassLoader import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds -internal class TestEnvironment( - 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( +internal class GlobalSettings( val target: KonanTarget = HostManager.host, val kotlinNativeHome: File = defaultKotlinNativeHome, val lazyKotlinNativeClassLoader: Lazy = defaultKotlinNativeClassLoader, val testMode: TestMode = defaultTestMode, - val cacheSettings: TestCacheSettings = defaultCacheSettings, + val cacheSettings: CacheSettings = defaultCacheSettings, val executionTimeout: Duration = defaultExecutionTimeout, val baseBuildDir: File = projectBuildDir ) { val hostTarget: KonanTarget = HostManager.host fun getRootCacheDirectory(debuggable: Boolean): File? = - (cacheSettings as? TestCacheSettings.WithCache)?.getRootCacheDirectory(this, debuggable) + (cacheSettings as? CacheSettings.WithCache)?.getRootCacheDirectory(this, debuggable) companion object { 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. private val defaultKotlinNativeClassLoader: Lazy = lazy { @@ -48,7 +38,7 @@ internal class GlobalTestEnvironment( ?.split(':', ';') ?.map { File(it).toURI().toURL() } ?.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) } } @@ -56,7 +46,7 @@ internal class GlobalTestEnvironment( private val defaultTestMode: TestMode = run { 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 { appendLine("Unknown test mode name $testModeName.") 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 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 true - if (useCache) TestCacheSettings.WithCache else TestCacheSettings.WithoutCache + if (useCache) CacheSettings.WithCache else CacheSettings.WithoutCache } private val defaultExecutionTimeout: Duration = run { val executionTimeoutValue = System.getProperty(EXECUTION_TIMEOUT) if (executionTimeoutValue != null) { executionTimeoutValue.toLongOrNull()?.milliseconds - ?: fail { "Invalid value for $EXECUTION_TIMEOUT system property: $executionTimeoutValue" } + ?: JUnit5Assertions.fail { "Invalid value for $EXECUTION_TIMEOUT system property: $executionTimeoutValue" } } else DEFAULT_EXECUTION_TIMEOUT } 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 COMPILER_CLASSPATH = "kotlin.internal.native.test.compilerClasspath" @@ -100,30 +90,11 @@ internal class GlobalTestEnvironment( } } -internal class TestRoots( - val roots: Set, - val baseDir: File -) +internal sealed interface CacheSettings { + object WithoutCache : CacheSettings -// 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." - ) -} - -internal sealed interface TestCacheSettings { - object WithoutCache : TestCacheSettings - - object WithCache : TestCacheSettings { - fun getRootCacheDirectory(globalEnvironment: GlobalTestEnvironment, debuggable: Boolean): File? = with(globalEnvironment) { + object WithCache : CacheSettings { + fun getRootCacheDirectory(settings: GlobalSettings, debuggable: Boolean): File? = with(settings) { kotlinNativeHome.resolve("klib/cache").resolve(getCacheDirName(target, debuggable)).takeIf { it.exists() } } diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/Settings.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/Settings.kt new file mode 100644 index 00000000000..51ba83a226c --- /dev/null +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/Settings.kt @@ -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, + val baseDir: File +) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestMode.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestMode.kt new file mode 100644 index 00000000000..154c6ec4e9f --- /dev/null +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestMode.kt @@ -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." + ) +} diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestSettings.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestSettings.kt new file mode 100644 index 00000000000..4bd0c5a8952 --- /dev/null +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestSettings.kt @@ -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) { + companion object { + val DEFAULT = TestSettings(StandardTestCaseGroupProvider::class) + } +}