Add possibility to dump and test IR after execution of given lowering

This commit is contained in:
Ivan Kylchik
2021-06-29 14:27:31 +03:00
committed by TeamCityServer
parent 330f15ff7d
commit 88aa71b0aa
4 changed files with 74 additions and 1 deletions
@@ -0,0 +1,42 @@
/*
* 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.test.backend.handlers
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.createTempDirectory
class PhasedIrDumpHandler(testServices: TestServices) : JvmBinaryArtifactHandler(testServices) {
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
if (CodegenTestDirectives.DUMP_IR_FOR_GIVEN_PHASES !in module.directives) return
val dumpDirectory = testServices.createTempDirectory(DUMPED_IR_FOLDER_NAME)
val dumpFiles = dumpDirectory.resolve(module.name).listFiles() ?: return
val testFile = module.files.first()
val testDirectory = testFile.originalFile.parentFile
val visitedFiles = mutableListOf<String>()
for (actualFile in dumpFiles) {
val expectedFileName = testFile.originalFile.nameWithoutExtension + actualFile.name.removeRange(0, 2)
visitedFiles += expectedFileName
assertions.assertEqualsToFile(testDirectory.resolve(expectedFileName), actualFile.readText())
}
// check that all expected files has their actual counterpart
val remainFiles = testDirectory
.listFiles { _, name -> name.startsWith("${testFile.originalFile.nameWithoutExtension}_") }
?.filter { it.name !in visitedFiles } ?: return
assertions.assertTrue(remainFiles.isEmpty()) {
"There are some files in test directory (${remainFiles.joinToString { it.name }}) that don't have actual dump"
}
}
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
companion object {
const val DUMPED_IR_FOLDER_NAME = "dumped_ir"
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.test.directives
import org.jetbrains.kotlin.backend.common.phaser.AnyNamedPhase
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.handlers.*
import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade
@@ -116,6 +117,11 @@ object CodegenTestDirectives : SimpleDirectivesContainer() {
description = "Skips check pretty kt IR dump (disables ${IrPrettyKotlinDumpHandler::class})"
)
val DUMP_IR_FOR_GIVEN_PHASES by valueDirective<AnyNamedPhase>(
description = "Dumps backend IR after given lowerings (enables ${PhasedIrDumpHandler::class})",
parser = { error("Cannot parse value $it for \"DUMP_IR_FOR_GIVEN_PHASES\" directive. All arguments must be specified via code in test system") }
)
val TREAT_AS_ONE_FILE by directive(
description = "Treat bytecode from all files as one in ${BytecodeTextHandler::class}"
)
@@ -7,6 +7,9 @@ package org.jetbrains.kotlin.test.services.configuration
import com.intellij.openapi.util.SystemInfo
import com.intellij.psi.PsiJavaModule.MODULE_INFO_FILE
import org.jetbrains.kotlin.backend.common.phaser.AnyNamedPhase
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.jvmPhases
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.jvm.addModularRootIfNotNull
@@ -23,6 +26,8 @@ import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.MockLibraryUtil.compileJavaFilesLibraryToJar
import org.jetbrains.kotlin.test.TestJavacVersion
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.backend.handlers.PhasedIrDumpHandler
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.ALL_JAVA_AS_BINARY
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.ASSERTIONS_MODE
@@ -44,6 +49,7 @@ import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.NO_UNIFIE
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.PARAMETERS_METADATA
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.directives.model.ValueDirective
import org.jetbrains.kotlin.test.model.DependencyDescription
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.TestFile
@@ -247,6 +253,10 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
if (LanguageSettingsDirectives.ALLOW_KOTLIN_PACKAGE in module.directives) {
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, true)
}
if (CodegenTestDirectives.DUMP_IR_FOR_GIVEN_PHASES in module.directives) {
configuration.putCustomPhaseConfigWithEnabledDump(module)
}
}
private fun addJavaSourceRootsByJavaModules(configuration: CompilerConfiguration, moduleInfoFiles: List<TestFile>) {
@@ -348,6 +358,19 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
}
}
private fun CompilerConfiguration.putCustomPhaseConfigWithEnabledDump(module: TestModule) {
val dumpDirectory = testServices.createTempDirectory(PhasedIrDumpHandler.DUMPED_IR_FOLDER_NAME)
val phases = module.directives[CodegenTestDirectives.DUMP_IR_FOR_GIVEN_PHASES].toSet()
if (phases.isNotEmpty()) {
val phaseConfig = PhaseConfig(
jvmPhases,
toDumpStateAfter = phases,
dumpToDirectory = dumpDirectory.absolutePath
)
put(CLIConfigurationKeys.PHASE_CONFIG, phaseConfig)
}
}
private fun CompilerConfiguration.registerModuleDependencies(module: TestModule) {
addJvmClasspathRoots(module.allDependencies.filter { it.kind == DependencyKind.Binary }.toFileList())
@@ -13,16 +13,18 @@ import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File
class TemporaryDirectoryManagerImpl(testServices: TestServices) : TemporaryDirectoryManager(testServices) {
private val cache = mutableMapOf<String, File>()
private val rootTempDir: File = run {
val testInfo = testServices.testInfo
KtTestUtil.tmpDirForTest(testInfo.className, testInfo.methodName)
}
override fun createTempDirectory(name: String): File {
return KtTestUtil.tmpDir(rootTempDir, name)
return cache.getOrPut(name) { KtTestUtil.tmpDir(rootTempDir, name) }
}
override fun cleanupTemporaryDirectories() {
cache.clear()
FileUtil.delete(rootTempDir)
}
}