[Test] Migrate AbstractFirBlackBoxCodegenTest to new infrastructure

This commit is contained in:
Dmitriy Novozhilov
2020-12-30 12:15:52 +03:00
committed by TeamCityServer
parent af5a635f85
commit e3066a166e
11 changed files with 6976 additions and 2415 deletions
@@ -20,6 +20,7 @@ dependencies {
testApi(projectTests(":compiler:tests-common-new")) testApi(projectTests(":compiler:tests-common-new"))
testApi(project(":compiler:cli")) testApi(project(":compiler:cli"))
testApi(project(":compiler:fir:checkers")) testApi(project(":compiler:fir:checkers"))
testApi(project(":compiler:fir:fir-serialization"))
testApi(project(":compiler:fir:entrypoint")) testApi(project(":compiler:fir:entrypoint"))
testApi(project(":compiler:frontend")) testApi(project(":compiler:frontend"))
@@ -30,6 +31,8 @@ dependencies {
testCompileOnly(project(":kotlin-reflect-api")) testCompileOnly(project(":kotlin-reflect-api"))
testRuntimeOnly(project(":kotlin-reflect")) testRuntimeOnly(project(":kotlin-reflect"))
testRuntimeOnly(project(":core:descriptors.runtime")) testRuntimeOnly(project(":core:descriptors.runtime"))
testRuntimeOnly(androidDxJar())
testRuntimeOnly(project(":compiler:fir:fir2ir:jvm-backend"))
testImplementation(intellijCoreDep()) { includeJars("intellij-core") } testImplementation(intellijCoreDep()) { includeJars("intellij-core") }
testImplementation(intellijDep()) { testImplementation(intellijDep()) {
@@ -7,8 +7,13 @@ package org.jetbrains.kotlin.test.backend
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives 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
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer 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.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.TestServices
import org.jetbrains.kotlin.test.services.moduleStructure import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.test.util.joinToArrayString import org.jetbrains.kotlin.test.util.joinToArrayString
@@ -19,25 +24,42 @@ class BlackBoxCodegenSuppressor(testServices: TestServices) : AfterAnalysisCheck
override fun suppressIfNeeded(failedAssertions: List<AssertionError>): List<AssertionError> { override fun suppressIfNeeded(failedAssertions: List<AssertionError>): List<AssertionError> {
val moduleStructure = testServices.moduleStructure val moduleStructure = testServices.moduleStructure
val ignoredBackends = moduleStructure.modules.flatMap { it.directives[CodegenTestDirectives.IGNORE_BACKEND] } val targetBackends = moduleStructure.modules.mapNotNull { it.targetBackend }
if (ignoredBackends.isEmpty()) return failedAssertions return when (moduleStructure.modules.map { it.frontendKind }.first()) {
val targetBackends = moduleStructure.modules.map { it.targetBackend } FrontendKinds.ClassicFrontend -> processIgnoreBackend(moduleStructure, IGNORE_BACKEND, targetBackends, failedAssertions)
val matchedBackend = ignoredBackends.intersect(targetBackends) FrontendKinds.FIR -> processIgnoreBackend(moduleStructure, IGNORE_BACKEND_FIR, targetBackends, failedAssertions)
if (ignoredBackends.contains(TargetBackend.ANY)) { else -> failedAssertions
return processAssertions(failedAssertions)
} }
if (matchedBackend.isNotEmpty()) {
return processAssertions(failedAssertions, "for ${matchedBackend.joinToArrayString()}")
}
return failedAssertions
} }
private fun processAssertions(failedAssertions: List<AssertionError>, additionalMessage: String = ""): List<AssertionError> { private fun processIgnoreBackend(
moduleStructure: TestModuleStructure,
directive: ValueDirective<TargetBackend>,
targetBackends: List<TargetBackend>,
failedAssertions: List<AssertionError>
): List<AssertionError> {
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<AssertionError>,
directive: ValueDirective<TargetBackend>,
additionalMessage: String = ""
): List<AssertionError> {
return if (failedAssertions.isNotEmpty()) emptyList() return if (failedAssertions.isNotEmpty()) emptyList()
else { else {
val message = buildString { val message = buildString {
append("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive") append("Looks like this test can be unmuted. Remove ${directive.name} directive")
if (additionalMessage.isNotEmpty()) { if (additionalMessage.isNotEmpty()) {
append(" ") append(" ")
append(additionalMessage) append(additionalMessage)
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2020 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.test.backend.handlers
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderer
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_FIR_DIAGNOSTICS
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirAnalysisHandler
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
class NoFirCompilationErrorsHandler(testServices: TestServices) : FirAnalysisHandler(testServices) {
override val directivesContainers: List<DirectivesContainer>
get() = listOf(CodegenTestDirectives)
override fun processModule(module: TestModule, info: FirOutputArtifact) {
var hasError = false
val ignoreErrors = IGNORE_FIR_DIAGNOSTICS in module.directives
for ((firFile, diagnostics) in info.firAnalyzerFacade.runCheckers()) {
for (diagnostic in diagnostics) {
if (diagnostic.severity == Severity.ERROR) {
hasError = true
if (!ignoreErrors) {
val diagnosticText = FirDefaultErrorMessages.getRendererForDiagnostic(diagnostic).hackyRender(diagnostic)
val range = diagnostic.textRanges.first()
val locationText = firFile.source?.psi?.containingFile?.let { psiFile ->
PsiDiagnosticUtils.atLocation(psiFile, range)
} ?: "${firFile.name}:$range"
throw IllegalStateException("${diagnostic.factory.name}: $diagnosticText at $locationText")
}
}
}
}
if (!hasError && ignoreErrors) {
assertions.fail { "Test contains $IGNORE_FIR_DIAGNOSTICS directive but no errors was reported. Please remove directive" }
}
}
private fun FirDiagnosticRenderer<*>.hackyRender(diagnostic: FirDiagnostic<*>): String {
@Suppress("UNCHECKED_CAST")
val renderer = this as FirDiagnosticRenderer<FirDiagnostic<FirSourceElement>>
val castedDiagnostic = diagnostic as FirDiagnostic<FirSourceElement>
return renderer.render(castedDiagnostic)
}
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
}
@@ -13,6 +13,10 @@ object CodegenTestDirectives : SimpleDirectivesContainer() {
description = "Ignore failures of test on target backend" description = "Ignore failures of test on target backend"
) )
val IGNORE_BACKEND_FIR by enumDirective<TargetBackend>(
description = "Ignore specific backend if test uses FIR"
)
val JAVAC_OPTIONS by stringDirective( val JAVAC_OPTIONS by stringDirective(
description = "Specify javac options to compile java files" description = "Specify javac options to compile java files"
) )
@@ -35,4 +39,8 @@ object CodegenTestDirectives : SimpleDirectivesContainer() {
val IGNORE_DEXING by directive( val IGNORE_DEXING by directive(
description = "Ignore dex checkers" description = "Ignore dex checkers"
) )
val IGNORE_FIR_DIAGNOSTICS by directive(
description = "Run backend even FIR reported some diagnostics with ERROR severity"
)
} }
@@ -9,12 +9,18 @@ import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.classic.ClassicJvmBackendFacade import org.jetbrains.kotlin.test.backend.classic.ClassicJvmBackendFacade
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2ClassicBackendConverter import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2ClassicBackendConverter
import org.jetbrains.kotlin.test.model.BackendFacade import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
import org.jetbrains.kotlin.test.model.BinaryArtifacts import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter import org.jetbrains.kotlin.test.model.*
open class AbstractBlackBoxCodegenTest : AbstractJvmBlackBoxCodegenTestBase(TargetBackend.JVM) { open class AbstractBlackBoxCodegenTest : AbstractJvmBlackBoxCodegenTestBase<ClassicFrontendOutputArtifact>(
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<*, *>> FrontendKinds.ClassicFrontend,
TargetBackend.JVM
) {
override val frontendFacade: Constructor<FrontendFacade<ClassicFrontendOutputArtifact>>
get() = ::ClassicFrontendFacade
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<ClassicFrontendOutputArtifact, *>>
get() = ::ClassicFrontend2ClassicBackendConverter get() = ::ClassicFrontend2ClassicBackendConverter
override val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>> override val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>>
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2020 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.test.runners.codegen
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.USE_PSI_CLASS_FILES_READING
import org.jetbrains.kotlin.test.frontend.fir.Fir2IrResultsConverter
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.model.*
open class AbstractFirBlackBoxCodegenTest : AbstractJvmBlackBoxCodegenTestBase<FirOutputArtifact>(
FrontendKinds.FIR,
TargetBackend.JVM_IR
) {
override val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
get() = ::FirFrontendFacade
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<FirOutputArtifact, *>>
get() = ::Fir2IrResultsConverter
override val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>>
get() = ::JvmIrBackendFacade
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
with(builder) {
defaultDirectives {
// See KT-44152
-USE_PSI_CLASS_FILES_READING
}
}
}
}
@@ -9,12 +9,18 @@ import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2IrConverter import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2IrConverter
import org.jetbrains.kotlin.test.model.BackendFacade import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
import org.jetbrains.kotlin.test.model.BinaryArtifacts import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter import org.jetbrains.kotlin.test.model.*
open class AbstractIrBlackBoxCodegenTest : AbstractJvmBlackBoxCodegenTestBase(TargetBackend.JVM_IR) { open class AbstractIrBlackBoxCodegenTest : AbstractJvmBlackBoxCodegenTestBase<ClassicFrontendOutputArtifact>(
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<*, *>> FrontendKinds.ClassicFrontend,
TargetBackend.JVM_IR
) {
override val frontendFacade: Constructor<FrontendFacade<ClassicFrontendOutputArtifact>>
get() = ::ClassicFrontendFacade
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<ClassicFrontendOutputArtifact, *>>
get() = ::ClassicFrontend2IrConverter get() = ::ClassicFrontend2IrConverter
override val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>> override val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>>
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.test.backend.BlackBoxCodegenSuppressor
import org.jetbrains.kotlin.test.backend.handlers.* import org.jetbrains.kotlin.test.backend.handlers.*
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.RUN_DEX_CHECKER import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.RUN_DEX_CHECKER
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.REPORT_JVM_DIAGNOSTICS_ON_FRONTEND
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.USE_PSI_CLASS_FILES_READING import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.USE_PSI_CLASS_FILES_READING
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
import org.jetbrains.kotlin.test.model.* import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
@@ -23,22 +21,23 @@ import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsS
import org.jetbrains.kotlin.test.services.sourceProviders.CodegenHelpersSourceFilesProvider import org.jetbrains.kotlin.test.services.sourceProviders.CodegenHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider
abstract class AbstractJvmBlackBoxCodegenTestBase( abstract class AbstractJvmBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendOutput<R>>(
val targetFrontend: FrontendKind<R>,
targetBackend: TargetBackend targetBackend: TargetBackend
) : AbstractKotlinCompilerWithTargetBackendTest(targetBackend) { ) : AbstractKotlinCompilerWithTargetBackendTest(targetBackend) {
abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<*, *>> abstract val frontendFacade: Constructor<FrontendFacade<R>>
abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<R, *>>
abstract val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>> abstract val backendFacade: Constructor<BackendFacade<*, BinaryArtifacts.Jvm>>
override fun TestConfigurationBuilder.configuration() { override fun TestConfigurationBuilder.configuration() {
globalDefaults { globalDefaults {
frontend = FrontendKinds.ClassicFrontend frontend = targetFrontend
targetPlatform = JvmPlatforms.defaultJvmPlatform targetPlatform = JvmPlatforms.defaultJvmPlatform
dependencyKind = DependencyKind.Binary dependencyKind = DependencyKind.Binary
} }
defaultDirectives { defaultDirectives {
+USE_PSI_CLASS_FILES_READING +USE_PSI_CLASS_FILES_READING
+REPORT_JVM_DIAGNOSTICS_ON_FRONTEND
+RUN_DEX_CHECKER +RUN_DEX_CHECKER
} }
@@ -53,11 +52,15 @@ abstract class AbstractJvmBlackBoxCodegenTestBase(
::CodegenHelpersSourceFilesProvider, ::CodegenHelpersSourceFilesProvider,
) )
useFrontendFacades(::ClassicFrontendFacade) useFrontendFacades(frontendFacade)
useFrontend2BackendConverters(frontendToBackendConverter) useFrontend2BackendConverters(frontendToBackendConverter)
useBackendFacades(backendFacade) useBackendFacades(backendFacade)
useFrontendHandlers(::NoCompilationErrorsHandler) useFrontendHandlers(
::NoCompilationErrorsHandler,
::NoFirCompilationErrorsHandler,
)
useArtifactsHandlers( useArtifactsHandlers(
::JvmBoxRunner, ::JvmBoxRunner,
::NoJvmSpecificCompilationErrorsHandler, ::NoJvmSpecificCompilationErrorsHandler,
@@ -506,10 +506,6 @@ fun generateJUnit3CompilerTests(args: Array<String>) {
testRunnerMethodName = "runTestWithCustomIgnoreDirective", testRunnerMethodName = "runTestWithCustomIgnoreDirective",
additionalRunnerArguments = listOf("\"// IGNORE_BACKEND_FIR: \"") additionalRunnerArguments = listOf("\"// IGNORE_BACKEND_FIR: \"")
) { ) {
testClass<AbstractFirBlackBoxCodegenTest> {
model("codegen/box", targetBackend = TargetBackend.JVM_IR, excludeDirs = listOf("oldLanguageVersions"))
}
testClass<AbstractFirBlackBoxInlineCodegenTest> { testClass<AbstractFirBlackBoxInlineCodegenTest> {
model("codegen/boxInline", targetBackend = TargetBackend.JVM_IR, excludeDirs = listOf("oldLanguageVersions")) model("codegen/boxInline", targetBackend = TargetBackend.JVM_IR, excludeDirs = listOf("oldLanguageVersions"))
} }
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.generators.util.TestGeneratorUtil
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.runners.* import org.jetbrains.kotlin.test.runners.*
import org.jetbrains.kotlin.test.runners.codegen.AbstractBlackBoxCodegenTest import org.jetbrains.kotlin.test.runners.codegen.AbstractBlackBoxCodegenTest
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirBlackBoxCodegenTest
import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest
fun generateJUnit5CompilerTests(args: Array<String>) { fun generateJUnit5CompilerTests(args: Array<String>) {
@@ -72,6 +73,10 @@ fun generateJUnit5CompilerTests(args: Array<String>) {
model("diagnostics/tests", excludedPattern = excludedFirTestdataPattern) model("diagnostics/tests", excludedPattern = excludedFirTestdataPattern)
model("diagnostics/testsWithStdLib", excludedPattern = excludedFirTestdataPattern) model("diagnostics/testsWithStdLib", excludedPattern = excludedFirTestdataPattern)
} }
testClass<AbstractFirBlackBoxCodegenTest> {
model("codegen/box", excludeDirs = listOf("oldLanguageVersions"))
}
} }
testGroup("compiler/fir/analysis-tests/tests-gen", "compiler/fir/analysis-tests/testData") { testGroup("compiler/fir/analysis-tests/tests-gen", "compiler/fir/analysis-tests/testData") {