[Tests] Introduce replacing source transformer

This commit is contained in:
Evgeniy.Zhelenskiy
2021-12-07 02:48:30 +03:00
parent 38ff3f5a24
commit cb4ec932d7
18 changed files with 80 additions and 42 deletions
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.ResultingArtifact
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
import org.jetbrains.kotlin.test.runners.TransformersFunctions.Android
import org.jetbrains.kotlin.test.utils.TransformersFunctions.Android
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.test.runners.codegen;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.runners.TransformersFunctions;
import org.jetbrains.kotlin.test.utils.TransformersFunctions;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -51,7 +51,7 @@ class GlobalMetadataInfoHandler(
infos += codeMetaInfos
}
fun compareAllMetaDataInfos(expectedTransformer: ((String) -> String)?) {
fun compareAllMetaDataInfos() {
// TODO: adapt to multiple testdata files
val moduleStructure = testServices.moduleStructure
val builder = StringBuilder()
@@ -66,18 +66,15 @@ class GlobalMetadataInfoHandler(
codeMetaInfos,
testServices.sourceFileProvider.getContentOfSourceFile(file)
)
builder.append(fileBuilder.stripAdditionalEmptyLines(file))
val reverseTransformers = testServices.sourceFileProvider.preprocessors.filterIsInstance<ReversibleSourceFilePreprocessor>()
val initialFileContent = fileBuilder.stripAdditionalEmptyLines(file).toString()
val actualFileContent =
reverseTransformers.foldRight(initialFileContent) { transformer, source -> transformer.revert(file, source) }
builder.append(actualFileContent)
}
}
val actualText = builder.toString()
val expectedFile = moduleStructure.originalTestDataFiles.single()
if (expectedTransformer != null) {
val expectedContent = expectedFile.readText().let(expectedTransformer)
val message = "Actual data differs from transformed content of file $expectedFile"
testServices.assertions.assertEquals(expectedContent, actualText) { message }
} else {
testServices.assertions.assertEqualsToFile(expectedFile, actualText)
}
testServices.assertions.assertEqualsToFile(moduleStructure.originalTestDataFiles.single(), actualText)
}
private fun StringBuilder.stripAdditionalEmptyLines(file: TestFile): CharSequence {
@@ -1,6 +1,6 @@
// WITH_STDLIB
// WORKS_WHEN_VALUE_CLASS
// !LANGUAGE: +ValueClasses
// LANGUAGE: +ValueClasses
OPTIONAL_JVM_INLINE_ANNOTATION
value class Result<T>(val a: Any?)
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.test.runners.codegen;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.runners.TransformersFunctions;
import org.jetbrains.kotlin.test.utils.TransformersFunctions;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.test.runners.codegen;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.runners.TransformersFunctions;
import org.jetbrains.kotlin.test.utils.TransformersFunctions;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.preprocessors.MetaInfosCleanupPreprocessor
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.impl.TemporaryDirectoryManagerImpl
import org.jetbrains.kotlin.test.utils.ReplacingSourceTransformer
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.FlexibleTypeImpl
import org.junit.jupiter.api.BeforeEach
@@ -81,18 +82,17 @@ abstract class AbstractKotlinCompilerTest {
testRunner(filePath, configuration).runTest(filePath)
}
@JvmOverloads
open fun runTest(
@TestDataFile filePath: String,
actualContentModifier: (String) -> String,
expectedContentModifier: ((String) -> String)? = actualContentModifier
contentModifier: ReplacingSourceTransformer,
) {
class SourceTransformer(testServices: TestServices) : SourceFilePreprocessor(testServices) {
override fun process(file: TestFile, content: String): String = content.let(actualContentModifier)
class SourceTransformer(testServices: TestServices) : ReversibleSourceFilePreprocessor(testServices) {
override fun process(file: TestFile, content: String): String = contentModifier.invokeForTestFile(file, content)
override fun revert(file: TestFile, actualContent: String): String = contentModifier.revertForFile(file, actualContent)
}
testRunner(filePath) {
configuration.let { it() } // property configuration, not method
useSourcePreprocessor({ SourceTransformer(it) })
}.runTest(filePath, expectedFileTransformer = expectedContentModifier)
configuration.invoke(this)
useSourcePreprocessor(::SourceTransformer)
}.runTest(filePath)
}
}
@@ -0,0 +1,33 @@
/*
* 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.utils
import org.jetbrains.kotlin.test.model.TestFile
import java.util.function.Function
class ReplacingSourceTransformer(val from: String, val to: String) : Function<String, String>, (String) -> String {
init {
require(from.isNotEmpty()) { "Cannot replace empty string" }
require(from.lines().size == 1) { "Multiline text cannot be replaced yet" }
require(to.lines().size == from.lines().size) { "Number of lines cannot change" }
}
private val replacements: MutableMap<String?, List<List<String>>> = mutableMapOf()
fun invokeForTestFile(testFile: TestFile?, source: String): String {
val value = source.lines().map { it.split(from) }
replacements[testFile?.relativePath] = value
return value.joinToString("\n") { it.joinToString(to) }
}
fun revertForFile(testFile: TestFile?, actual: String): String = actual.lines().mapIndexed { index, line ->
val partition = replacements[testFile?.relativePath]?.elementAtOrNull(index) ?: return@mapIndexed line
if (partition.joinToString(to) == line) partition.joinToString(from) else line
}.joinToString("\n")
override fun apply(source: String): String = invokeForTestFile(null, source)
override fun invoke(source: String): String = invokeForTestFile(null, source)
}
@@ -3,7 +3,7 @@
* 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
package org.jetbrains.kotlin.test.utils
import java.io.File
@@ -126,7 +126,7 @@ private class TestGeneratorImplInstance(
for (clazz in testClassModels.flatMapTo(mutableSetOf()) { classModel -> classModel.imports }) {
val realName = when (clazz) {
TransformingTestMethodModel.TransformerFunctionsClassPlaceHolder::class.java ->
"org.jetbrains.kotlin.test.runners.TransformersFunctions"
"org.jetbrains.kotlin.test.utils.TransformersFunctions"
else -> clazz.name
}
p.println("import $realName;")
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.runners.TransformersFunctions;
import org.jetbrains.kotlin.test.utils.TransformersFunctions;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;