Support target templates in bytecode tests

Avoid test data duplication
This commit is contained in:
Mikhael Bogdanov
2019-07-16 09:15:31 +02:00
parent de1e27c584
commit 496765f41e
46 changed files with 250 additions and 679 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.TestJdkKind
import org.junit.Assert
import java.io.File
@@ -30,7 +31,7 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
} else {
val expected = readExpectedOccurrences(wholeFile.path)
val actual = generateToText("helpers/")
checkGeneratedTextAgainstExpectedOccurrences(actual, expected)
checkGeneratedTextAgainstExpectedOccurrences(actual, expected, getBackend())
}
}
@@ -45,25 +46,28 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
assertTextWasGenerated(expectedOutputFile, generated)
val generatedText = generated[expectedOutputFile]!!
val expectedOccurrences = expectedOccurrencesByOutputFile[expectedOutputFile]!!
checkGeneratedTextAgainstExpectedOccurrences(generatedText, expectedOccurrences)
checkGeneratedTextAgainstExpectedOccurrences(generatedText, expectedOccurrences, getBackend())
}
}
protected fun readExpectedOccurrences(filename: String): List<OccurrenceInfo> {
val result = ArrayList<OccurrenceInfo>()
val lines = File(filename).readLines().dropLastWhile(String::isEmpty)
var backend = TargetBackend.ANY
for (line in lines) {
if (line.contains(JVM_TEMPLATES)) backend = TargetBackend.JVM
else if (line.contains(JVM_IR_TEMPLATES)) backend = TargetBackend.JVM_IR
val matcher = EXPECTED_OCCURRENCES_PATTERN.matcher(line)
if (matcher.matches()) {
result.add(parseOccurrenceInfo(matcher))
result.add(parseOccurrenceInfo(matcher, backend))
}
}
return result
}
class OccurrenceInfo constructor(private val numberOfOccurrences: Int, private val needle: String) {
class OccurrenceInfo constructor(private val numberOfOccurrences: Int, private val needle: String, val backend: TargetBackend) {
fun getActualOccurrence(text: String): String? {
val actualCount = StringUtil.findMatches(text, Pattern.compile("($needle)")).size
return "$actualCount $needle"
@@ -88,13 +92,29 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
return kotlinFiles > 1
}
fun checkGeneratedTextAgainstExpectedOccurrences(text: String, expectedOccurrences: List<OccurrenceInfo>) {
fun checkGeneratedTextAgainstExpectedOccurrences(text: String, expectedOccurrences: List<OccurrenceInfo>, currentBackend: TargetBackend) {
val expected = StringBuilder()
val actual = StringBuilder()
var lastBackend = TargetBackend.ANY
for (info in expectedOccurrences) {
if (lastBackend != info.backend) {
when (info.backend) {
TargetBackend.JVM -> JVM_TEMPLATES
TargetBackend.JVM_IR -> JVM_IR_TEMPLATES
else -> error("Common part should be first one: ${expectedOccurrences.joinToString("\n")}")
}.also {
actual.append("\n$it\n")
expected.append("\n$it\n")
}
lastBackend = info.backend
}
expected.append(info).append("\n")
actual.append(info.getActualOccurrence(text)).append("\n")
if (info.backend == TargetBackend.ANY || info.backend == currentBackend) {
actual.append(info.getActualOccurrence(text)).append("\n")
} else {
actual.append(info).append("\n")
}
}
try {
@@ -117,9 +137,17 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
}
}
private const val JVM_TEMPLATES = "// JVM_TEMPLATES"
private const val JVM_IR_TEMPLATES = "// JVM_IR_TEMPLATES"
private fun readExpectedOccurrencesForMultiFileTest(file: TestFile, occurrenceMap: MutableMap<String, List<OccurrenceInfo>>) {
var currentOccurrenceInfos: MutableList<OccurrenceInfo>? = null
var backend = TargetBackend.ANY
for (line in file.content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
if (line.contains(JVM_TEMPLATES)) backend = TargetBackend.JVM
else if (line.contains(JVM_IR_TEMPLATES)) backend = TargetBackend.JVM_IR
val atOutputFileMatcher = AT_OUTPUT_FILE_PATTERN.matcher(line)
if (atOutputFileMatcher.matches()) {
val outputFileName = atOutputFileMatcher.group(1)
@@ -135,16 +163,20 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
if (currentOccurrenceInfos == null) {
throw AssertionError("${file.name}: Should specify output file with '// @<OUTPUT_FILE_NAME>:' before expectations")
}
val occurrenceInfo = parseOccurrenceInfo(expectedOccurrencesMatcher)
val occurrenceInfo = parseOccurrenceInfo(expectedOccurrencesMatcher, backend)
currentOccurrenceInfos.add(occurrenceInfo)
}
}
}
private fun parseOccurrenceInfo(matcher: Matcher): OccurrenceInfo {
private fun parseOccurrenceInfo(matcher: Matcher, backend: TargetBackend): OccurrenceInfo {
val numberOfOccurrences = Integer.parseInt(matcher.group(1))
val needle = matcher.group(2)
return OccurrenceInfo(numberOfOccurrences, needle)
return OccurrenceInfo(numberOfOccurrences, needle, backend)
}
}
protected open fun getBackend(): TargetBackend {
return TargetBackend.JVM
}
}
@@ -23,10 +23,7 @@ import kotlin.sequences.SequencesKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.test.CompilerTestUtil;
import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestJdkKind;
import org.jetbrains.kotlin.test.*;
import java.io.File;
import java.util.Collections;
@@ -62,6 +59,6 @@ public abstract class AbstractTopLevelMembersInvocationTest extends AbstractByte
List<OccurrenceInfo> expected = readExpectedOccurrences(KotlinTestUtils.getTestDataPathBase() + "/codegen/" + sourceFiles.get(0));
String actual = generateToText();
Companion.checkGeneratedTextAgainstExpectedOccurrences(actual, expected);
Companion.checkGeneratedTextAgainstExpectedOccurrences(actual, expected, TargetBackend.ANY);
}
}
@@ -8,7 +8,12 @@ package org.jetbrains.kotlin.codegen.ir
import org.jetbrains.kotlin.codegen.AbstractBytecodeTextTest
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.test.TargetBackend
abstract class AbstractIrBytecodeTextTest : AbstractBytecodeTextTest() {
override fun updateConfiguration(configuration: CompilerConfiguration) = configuration.put(JVMConfigurationKeys.IR, true)
override fun getBackend(): TargetBackend {
return TargetBackend.JVM_IR
}
}