[Test] Add single service for checking that codegen test is ingored
This approach is better than manual check for `IGNORE_BACKEND` directive because it also tracks `IGNORE_BACKEND_FIR` directive and reduces duplicating code
This commit is contained in:
committed by
teamcityserver
parent
c8386ad1c7
commit
6f0bf766f2
+49
-37
@@ -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<DirectivesContainer>
|
||||
get() = listOf(CodegenTestDirectives)
|
||||
|
||||
override val additionalServices: List<ServiceRegistrationData>
|
||||
get() = listOf(service(::SuppressionChecker.bind(customIgnoreDirective)))
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override fun suppressIfNeeded(failedAssertions: List<WrappedException>): List<WrappedException> {
|
||||
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<TargetBackend>,
|
||||
targetBackends: List<TargetBackend>,
|
||||
failedAssertions: List<WrappedException>
|
||||
): List<WrappedException> {
|
||||
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<WrappedException>,
|
||||
directive: ValueDirective<TargetBackend>,
|
||||
@@ -81,4 +58,39 @@ class BlackBoxCodegenSuppressor(
|
||||
listOf(AssertionError(message).wrap())
|
||||
}
|
||||
}
|
||||
|
||||
class SuppressionChecker(val testServices: TestServices, val customIgnoreDirective: ValueDirective<TargetBackend>?) : TestService {
|
||||
fun extractIgnoreDirective(module: TestModule): ValueDirective<TargetBackend>? {
|
||||
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<TargetBackend>): 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()
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+2
-1
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user