Test infra: adapt blackbox test runner to work with non-psi sources

This commit is contained in:
Ilya Chernikov
2022-02-19 20:35:29 +03:00
committed by teamcity
parent 2044754628
commit 25e9de286d
11 changed files with 78 additions and 34 deletions
@@ -327,7 +327,7 @@ object FirKotlinToJvmBytecodeCompiler {
generationState.beforeCompile()
generationState.oldBEInitTrace(ktFiles)
codegenFactory.generateModuleInFrontendIRMode(
generationState, ktFiles, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components)
generationState, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components)
) {
performanceManager?.notifyIRLoweringFinished()
performanceManager?.notifyIRGenerationStarted()
@@ -241,7 +241,7 @@ fun generateCodeFromIr(
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, emptyList() /* !! */, input.irModuleFragment, input.symbolTable, input.extensions,
generationState, input.irModuleFragment, input.symbolTable, input.extensions,
FirJvmBackendExtension(input.firSession, input.components)
) {
performanceManager?.notifyIRLoweringFinished()
@@ -8,7 +8,10 @@ package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.analyzer.hasJdkCapability
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.backend.common.phaser.then
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
import org.jetbrains.kotlin.backend.jvm.ir.getIoFile
@@ -59,7 +62,6 @@ open class JvmIrCodegenFactory(
) : CodegenFactory {
data class JvmIrBackendInput(
val irModuleFragment: IrModuleFragment,
val ktFiles: List<KtFile>,
val symbolTable: SymbolTable,
val phaseConfig: PhaseConfig?,
val irProviders: List<IrProvider>,
@@ -215,7 +217,6 @@ open class JvmIrCodegenFactory(
}
return JvmIrBackendInput(
irModuleFragment,
input.files.toList(),
symbolTable,
phaseConfig,
irProviders,
@@ -250,7 +251,7 @@ open class JvmIrCodegenFactory(
}
override fun invokeLowerings(state: GenerationState, input: CodegenFactory.BackendInput): CodegenFactory.CodegenInput {
val (irModuleFragment, _, symbolTable, customPhaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) =
val (irModuleFragment, symbolTable, customPhaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) =
input as JvmIrBackendInput
val irSerializer = if (
state.configuration.get(JVMConfigurationKeys.SERIALIZE_IR, JvmSerializeIrMode.NONE) != JvmSerializeIrMode.NONE
@@ -289,7 +290,6 @@ open class JvmIrCodegenFactory(
fun generateModuleInFrontendIRMode(
state: GenerationState,
ktFiles: List<KtFile>,
irModuleFragment: IrModuleFragment,
symbolTable: SymbolTable,
extensions: JvmGeneratorExtensionsImpl,
@@ -299,10 +299,7 @@ open class JvmIrCodegenFactory(
val irProviders = configureBuiltInsAndGenerateIrProvidersInFrontendIRMode(irModuleFragment, symbolTable, extensions)
generateModule(
state,
JvmIrBackendInput(
irModuleFragment, ktFiles, symbolTable, phaseConfig, irProviders, extensions, backendExtension,
notifyCodegenStart
)
JvmIrBackendInput(irModuleFragment, symbolTable, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart)
)
}
@@ -10,6 +10,7 @@ dependencies {
testApi(project(":compiler:cli"))
testImplementation(project(":compiler:ir.tree.impl"))
testImplementation(project(":compiler:backend.jvm.entrypoint"))
testImplementation(project(":compiler:backend.jvm.lower"))
testImplementation(intellijCore())
testCompileOnly(project(":kotlin-reflect-api"))
@@ -9,10 +9,12 @@ import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.DefaultCodegenFactory
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.model.ArtifactKinds
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.SourceFileInfo
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
@@ -42,6 +44,9 @@ class ClassicJvmBackendFacade(
KotlinCodegenFacade.compileCorrectFiles(psiFiles, generationState, DefaultCodegenFactory)
javaCompilerFacade.compileJavaFiles(module, configuration, generationState.factory)
return BinaryArtifacts.Jvm(generationState.factory, psiFiles)
return BinaryArtifacts.Jvm(
generationState.factory,
psiFiles.map { SourceFileInfo(it, JvmFileClassUtil.getFileClassInfoNoResolve(it)) }
)
}
}
@@ -9,6 +9,7 @@ import junit.framework.TestCase
import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberDeclarationsToGenerate
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.getFileClassInfoNoResolve
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.TestJdkKind
@@ -31,7 +32,7 @@ import org.jetbrains.kotlin.test.services.jvm.compiledClassesManager
import org.jetbrains.kotlin.test.services.jvm.jvmBoxMainClassProvider
import org.jetbrains.kotlin.test.services.runtimeClasspathProviders
import org.jetbrains.kotlin.test.services.sourceProviders.MainFunctionForBlackBoxTestsSourceProvider
import org.jetbrains.kotlin.test.services.sourceProviders.MainFunctionForBlackBoxTestsSourceProvider.Companion.containsBoxMethod
import org.jetbrains.kotlin.test.services.sourceProviders.MainFunctionForBlackBoxTestsSourceProvider.Companion.fileContainsBoxMethod
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf
@@ -55,15 +56,15 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
}
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
val ktFiles = info.ktFiles.ifEmpty { return }
val fileInfos = info.fileInfos.ifEmpty { return }
val reportProblems = !testServices.codegenSuppressionChecker.failuresInModuleAreIgnored(module)
val classLoader = createAndVerifyClassLoader(module, info.classFileFactory, reportProblems)
try {
for (ktFile in ktFiles) {
if (containsBoxMethod(ktFile.text)) {
for (fileInfo in fileInfos) {
if (fileContainsBoxMethod(fileInfo.file)) {
boxMethodFound = true
callBoxMethodAndCheckResultWithCleanup(
ktFile,
fileInfo.info,
module,
info.classFileFactory,
classLoader,
@@ -79,7 +80,7 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
}
private fun callBoxMethodAndCheckResultWithCleanup(
ktFile: KtFile,
fileInfo: JvmFileClassInfo,
module: TestModule,
classFileFactory: ClassFileFactory,
classLoader: URLClassLoader,
@@ -87,7 +88,7 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
reportProblems: Boolean
) {
try {
callBoxMethodAndCheckResult(ktFile, module, classFileFactory, classLoader, unexpectedBehaviour)
callBoxMethodAndCheckResult(fileInfo, module, classFileFactory, classLoader, unexpectedBehaviour)
} catch (e: Throwable) {
if (reportProblems) {
try {
@@ -106,11 +107,11 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
}
private fun findClassAndMethodToExecute(
ktFile: KtFile,
fileInfo: JvmFileClassInfo,
classLoader: URLClassLoader,
classFileFactory: ClassFileFactory
): Pair<Class<*>, Method> {
val className = ktFile.getFacadeFqName() ?: error("Class<*> for ${ktFile.name} not found")
val className = fileInfo.facadeClassFqName.asString()
val clazz = try {
classLoader.getGeneratedClass(className)
} catch (e: LinkageError) {
@@ -121,7 +122,7 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
}
private fun callBoxMethodAndCheckResult(
ktFile: KtFile,
fileInfo: JvmFileClassInfo,
module: TestModule,
classFileFactory: ClassFileFactory,
classLoader: URLClassLoader,
@@ -132,7 +133,7 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
module,
classFileFactory,
classLoader,
findClassAndMethodToExecute(ktFile, classLoader, classFileFactory).first
findClassAndMethodToExecute(fileInfo, classLoader, classFileFactory).first
)
} else {
val jdkKind = module.directives.singleOrZeroValue(JDK_KIND)
@@ -141,7 +142,7 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
} else {
runBoxInCurrentProcess(
classLoader,
findClassAndMethodToExecute(ktFile, classLoader, classFileFactory).second
findClassAndMethodToExecute(fileInfo, classLoader, classFileFactory).second
)
}
}
@@ -6,13 +6,22 @@
package org.jetbrains.kotlin.test.backend.ir
import org.jetbrains.kotlin.backend.common.BackendException
import org.jetbrains.kotlin.backend.jvm.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.lower.getFileClassInfoFromIrFile
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.ir.PsiIrFileEntry
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.backend.classic.JavaCompilerFacade
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.model.ArtifactKinds
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.SourceFileInfo
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import java.io.File
class JvmIrBackendFacade(
testServices: TestServices
@@ -39,6 +48,29 @@ class JvmIrBackendFacade(
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
javaCompilerFacade.compileJavaFiles(module, configuration, state.factory)
return BinaryArtifacts.Jvm(state.factory, inputArtifact.backendInput.ktFiles)
fun sourceFileInfos(irFile: IrFile, allowNestedMultifileFacades: Boolean): List<SourceFileInfo<*>> =
when (val fileEntry = irFile.fileEntry) {
is PsiIrFileEntry -> {
listOf(SourceFileInfo(fileEntry.psiFile, JvmFileClassUtil.getFileClassInfoNoResolve(fileEntry.psiFile as KtFile)))
}
is NaiveSourceBasedFileEntryImpl -> {
val file = File(fileEntry.name)
listOf(SourceFileInfo(file, getFileClassInfoFromIrFile(irFile, file.name)))
}
is MultifileFacadeFileEntry -> {
if (!allowNestedMultifileFacades) error("nested multi-file facades are not allowed")
else fileEntry.partFiles.flatMap { sourceFileInfos(it, allowNestedMultifileFacades = false) }
}
else -> {
error("unknown kind of file entry: $fileEntry")
}
}
return BinaryArtifacts.Jvm(
state.factory,
inputArtifact.backendInput.irModuleFragment.files.flatMap {
sourceFileInfos(it, allowNestedMultifileFacades = true)
}
)
}
}
@@ -76,7 +76,6 @@ class Fir2IrResultsConverter(
codegenFactory,
JvmIrCodegenFactory.JvmIrBackendInput(
irModuleFragment,
ktFiles,
symbolTable,
phaseConfig,
irProviders,
@@ -6,18 +6,18 @@
package org.jetbrains.kotlin.test.model
import org.jetbrains.kotlin.codegen.ClassFileFactory
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
import org.jetbrains.kotlin.ir.backend.js.CompilerResult
import org.jetbrains.kotlin.js.backend.ast.JsProgram
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.ir.backend.js.LoweredIr
import org.jetbrains.kotlin.js.facade.TranslationResult
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
class SourceFileInfo<F>(
val file: F,
val info: JvmFileClassInfo
)
object BinaryArtifacts {
class Jvm(val classFileFactory: ClassFileFactory, val ktFiles: Collection<KtFile>) : ResultingArtifact.Binary<Jvm>() {
class Jvm(val classFileFactory: ClassFileFactory, val fileInfos: Collection<SourceFileInfo<*>>) : ResultingArtifact.Binary<Jvm>() {
override val kind: BinaryKind<Jvm>
get() = ArtifactKinds.Jvm
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.test.services.sourceProviders
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.REQUIRES_SEPARATE_PROCESS
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JDK_KIND
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.AdditionalSourceProvider
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.temporaryDirectoryManager
import java.io.File
open class MainFunctionForBlackBoxTestsSourceProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
companion object {
@@ -37,6 +39,13 @@ open class MainFunctionForBlackBoxTestsSourceProvider(testServices: TestServices
return containsBoxMethod(file.originalContent)
}
fun <T> fileContainsBoxMethod(file: T): Boolean =
when (file) {
is PsiFile -> containsBoxMethod(file.text)
is File -> containsBoxMethod(file.readText())
else -> error("Unknown file type: $file")
}
fun containsBoxMethod(fileContent: String): Boolean {
return START_BOX_METHOD_REGEX.containsMatchIn(fileContent) ||
MIDDLE_BOX_METHOD_REGEX.containsMatchIn(fileContent) ||
@@ -134,7 +134,7 @@ object GenerationUtils {
generationState.beforeCompile()
generationState.oldBEInitTrace(files)
codegenFactory.generateModuleInFrontendIRMode(
generationState, files, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components),
generationState, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components),
) {}
generationState.factory.done()