From 88aa71b0aacf9d225188d2939a4e6c827c4c34c5 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Tue, 29 Jun 2021 14:27:31 +0300 Subject: [PATCH] Add possibility to dump and test IR after execution of given lowering --- .../backend/handlers/PhasedIrDumpHandler.kt | 42 +++++++++++++++++++ .../test/directives/CodegenTestDirectives.kt | 6 +++ .../JvmEnvironmentConfigurator.kt | 23 ++++++++++ .../impl/TemporaryDirectoryManagerImpl.kt | 4 +- 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/PhasedIrDumpHandler.kt diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/PhasedIrDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/PhasedIrDumpHandler.kt new file mode 100644 index 00000000000..a7b6d9ff6ff --- /dev/null +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/PhasedIrDumpHandler.kt @@ -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() + 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" + } +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/CodegenTestDirectives.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/CodegenTestDirectives.kt index 4389040b40d..2a871a6ab59 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/CodegenTestDirectives.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/CodegenTestDirectives.kt @@ -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( + 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}" ) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt index 848e1f92412..7faf3506ce0 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt @@ -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) { @@ -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()) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/TemporaryDirectoryManagerImpl.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/TemporaryDirectoryManagerImpl.kt index b08c6928499..d023376bcdf 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/TemporaryDirectoryManagerImpl.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/TemporaryDirectoryManagerImpl.kt @@ -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() 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) } }