diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/BlackBoxCodegenSuppressor.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/BlackBoxCodegenSuppressor.kt index 3a7705b90bd..6ddf3df8a95 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/BlackBoxCodegenSuppressor.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/BlackBoxCodegenSuppressor.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.test.backend import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.WrappedException +import org.jetbrains.kotlin.test.bind import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_BACKEND import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_BACKEND_FIR @@ -14,11 +15,8 @@ import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.directives.model.ValueDirective import org.jetbrains.kotlin.test.model.AfterAnalysisChecker import org.jetbrains.kotlin.test.model.FrontendKinds -import org.jetbrains.kotlin.test.services.TestModuleStructure -import org.jetbrains.kotlin.test.services.TestServices -import org.jetbrains.kotlin.test.services.defaultsProvider -import org.jetbrains.kotlin.test.services.moduleStructure -import org.jetbrains.kotlin.test.util.joinToArrayString +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.* class BlackBoxCodegenSuppressor( testServices: TestServices, @@ -27,43 +25,22 @@ class BlackBoxCodegenSuppressor( override val directiveContainers: List get() = listOf(CodegenTestDirectives) + override val additionalServices: List + get() = listOf(service(::SuppressionChecker.bind(customIgnoreDirective))) + @OptIn(ExperimentalStdlibApi::class) override fun suppressIfNeeded(failedAssertions: List): List { + if (failedAssertions.isEmpty()) return failedAssertions + + val suppressionChecker = testServices.codegenSuppressionChecker val moduleStructure = testServices.moduleStructure - val targetBackends = buildList { - testServices.defaultsProvider.defaultTargetBackend?.let { - add(it) - return@buildList - } - moduleStructure.modules.mapNotNullTo(this) { it.targetBackend } - } - val ignoreDirective = when (moduleStructure.modules.map { it.frontendKind }.first()) { - FrontendKinds.ClassicFrontend -> customIgnoreDirective ?: IGNORE_BACKEND - FrontendKinds.FIR -> IGNORE_BACKEND_FIR - else -> return failedAssertions - } - return processIgnoreBackend(moduleStructure, ignoreDirective, targetBackends, failedAssertions) + val ignoreDirective = suppressionChecker.extractIgnoreDirective(moduleStructure.modules.first()) ?: return failedAssertions + val suppressionResult = moduleStructure.modules.map { suppressionChecker.failuresInModuleAreIgnored(it, ignoreDirective) } + .firstOrNull { it.testMuted } ?: return failedAssertions + val additionalMessage = suppressionResult.matchedBackend?.let { "for $it" } ?: "" + return processAssertions(failedAssertions, ignoreDirective, additionalMessage) } - private fun processIgnoreBackend( - moduleStructure: TestModuleStructure, - directive: ValueDirective, - targetBackends: List, - failedAssertions: List - ): List { - val ignoredBackends = moduleStructure.allDirectives[directive] - if (ignoredBackends.isEmpty()) return failedAssertions - val matchedBackend = ignoredBackends.intersect(targetBackends) - if (ignoredBackends.contains(TargetBackend.ANY)) { - return processAssertions(failedAssertions, directive) - } - if (matchedBackend.isNotEmpty()) { - return processAssertions(failedAssertions, directive, "for ${matchedBackend.joinToArrayString()}") - } - return failedAssertions - } - - private fun processAssertions( failedAssertions: List, directive: ValueDirective, @@ -81,4 +58,39 @@ class BlackBoxCodegenSuppressor( listOf(AssertionError(message).wrap()) } } + + class SuppressionChecker(val testServices: TestServices, val customIgnoreDirective: ValueDirective?) : TestService { + fun extractIgnoreDirective(module: TestModule): ValueDirective? { + return when (module.frontendKind) { + FrontendKinds.ClassicFrontend -> customIgnoreDirective ?: IGNORE_BACKEND + FrontendKinds.FIR -> IGNORE_BACKEND_FIR + else -> null + } + } + + fun failuresInModuleAreIgnored(module: TestModule): Boolean { + val ignoreDirective = extractIgnoreDirective(module) ?: return false + return failuresInModuleAreIgnored(module, ignoreDirective).testMuted + } + + fun failuresInModuleAreIgnored(module: TestModule, ignoreDirective: ValueDirective): SuppressionResult { + val ignoredBackends = module.directives[ignoreDirective] + + val targetBackend = testServices.defaultsProvider.defaultTargetBackend ?: module.targetBackend + return when { + ignoredBackends.isEmpty() -> SuppressionResult.NO_MUTE + targetBackend in ignoredBackends -> SuppressionResult(true, targetBackend) + TargetBackend.ANY in ignoredBackends -> SuppressionResult(true, null) + else -> SuppressionResult.NO_MUTE + } + } + + data class SuppressionResult(val testMuted: Boolean, val matchedBackend: TargetBackend?) { + companion object { + val NO_MUTE = SuppressionResult(false, null) + } + } + } } + +val TestServices.codegenSuppressionChecker: BlackBoxCodegenSuppressor.SuppressionChecker by TestServices.testServiceAccessor() diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/BytecodeTextHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/BytecodeTextHandler.kt index 843cd258da1..58da74e0edc 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/BytecodeTextHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/BytecodeTextHandler.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.test.backend.handlers import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.test.TargetBackend +import org.jetbrains.kotlin.test.backend.codegenSuppressionChecker import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.CHECK_BYTECODE_TEXT import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.TREAT_AS_ONE_FILE @@ -31,7 +32,7 @@ class BytecodeTextHandler(testServices: TestServices, private val shouldEnableEx if (shouldEnableExplicitly && CHECK_BYTECODE_TEXT !in module.directives) return val targetBackend = module.targetBackend!! - val isIgnored = targetBackend in module.directives[CodegenTestDirectives.IGNORE_BACKEND] + val isIgnored = testServices.codegenSuppressionChecker.failuresInModuleAreIgnored(module) val files = module.files.filter { it.isKtFile } if (files.size > 1 && TREAT_AS_ONE_FILE !in module.directives) { processMultiFileTest(files, info, targetBackend, !isIgnored) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/DxCheckerHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/DxCheckerHandler.kt index ed13d1e197a..c8f0db3e3d5 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/DxCheckerHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/DxCheckerHandler.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.backend.handlers import org.jetbrains.kotlin.codegen.D8Checker import org.jetbrains.kotlin.codegen.getClassFiles import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil +import org.jetbrains.kotlin.test.backend.codegenSuppressionChecker import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_DEXING import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.RUN_DEX_CHECKER @@ -28,7 +29,7 @@ class DxCheckerHandler(testServices: TestServices) : JvmBinaryArtifactHandler(te D8Checker.check(info.classFileFactory) } catch (e: Throwable) { if (!GeneratorsFileUtil.isTeamCityBuild && - module.targetBackend !in module.directives[CodegenTestDirectives.IGNORE_BACKEND] + !testServices.codegenSuppressionChecker.failuresInModuleAreIgnored(module) ) { try { val javaDir = compiledClassesManager.getCompiledJavaDirForModule(module) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBoxRunner.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBoxRunner.kt index f7cf735539e..67dca99eb55 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBoxRunner.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBoxRunner.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.getFileClassInfoNoResolve import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.TestJdkKind +import org.jetbrains.kotlin.test.backend.codegenSuppressionChecker import org.jetbrains.kotlin.test.clientserver.TestProxy import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.ATTACH_DEBUGGER @@ -53,7 +54,7 @@ class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(testSe override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) { val ktFiles = info.classFileFactory.inputFiles.ifEmpty { return } - val reportProblems = module.targetBackend !in module.directives[CodegenTestDirectives.IGNORE_BACKEND] + val reportProblems = !testServices.codegenSuppressionChecker.failuresInModuleAreIgnored(module) val classLoader = createAndVerifyClassLoader(module, info.classFileFactory, reportProblems) try { for (ktFile in ktFiles) {