Introduce base class for codegen and diagnostic tests

Extract base TestFile and TestModule classes.
 Move coroutinePackage related logic to base class
This commit is contained in:
Mikhael Bogdanov
2020-02-20 17:01:07 +01:00
parent b031706ea9
commit a795c38eb7
29 changed files with 257 additions and 188 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.test.KotlinBaseTest
import java.io.File import java.io.File
import java.util.regex.Pattern import java.util.regex.Pattern
@@ -34,7 +35,7 @@ private data class OldPackageAndNew(val oldFqName: FqName, val newFqName: FqName
internal fun patchFilesAndAddTest( internal fun patchFilesAndAddTest(
testFile: File, testFile: File,
testFiles: List<CodegenTestCase.TestFile>, testFiles: List<KotlinBaseTest.TestFile>,
filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter
): FqName? { ): FqName? {
if (testFiles.any { it.name.endsWith(".java") }) { if (testFiles.any { it.name.endsWith(".java") }) {
@@ -36,26 +36,24 @@ abstract class AbstractFir2IrTextTest : AbstractIrTextTestCase() {
buildFragmentAndTestIt(wholeFile, testFiles) buildFragmentAndTestIt(wholeFile, testFiles)
} }
override fun doTest(filePath: String?) { override fun doTest(filePath: String) {
if (filePath != null) { val originalTextPath = filePath.replace(".kt", ".txt")
val originalTextPath = filePath.replace(".kt", ".txt") val firTextPath = filePath.replace(".kt", ".fir.txt")
val firTextPath = filePath.replace(".kt", ".fir.txt") val originalText = File(originalTextPath)
val originalText = File(originalTextPath) val firText = File(firTextPath)
val firText = File(firTextPath) if (originalText.exists() && firText.exists()) {
if (originalText.exists() && firText.exists()) { val originalLines = originalText.readLines()
val originalLines = originalText.readLines() val firLines = firText.readLines()
val firLines = firText.readLines() TestCase.assertFalse(
TestCase.assertFalse( "Dumps via FIR & via old FE are the same. Please delete .fir.txt dump and add // FIR_IDENTICAL to test source",
"Dumps via FIR & via old FE are the same. Please delete .fir.txt dump and add // FIR_IDENTICAL to test source", firLines.withIndex().all { (index, line) ->
firLines.withIndex().all { (index, line) -> val trimmed = line.trim()
val trimmed = line.trim() val originalTrimmed = originalLines.getOrNull(index)?.trim()
val originalTrimmed = originalLines.getOrNull(index)?.trim() trimmed.isEmpty() && originalTrimmed?.isEmpty() != false || trimmed == originalTrimmed
trimmed.isEmpty() && originalTrimmed?.isEmpty() != false || trimmed == originalTrimmed } && originalLines.withIndex().all { (index, line) ->
} && originalLines.withIndex().all { (index, line) -> index < firLines.size || line.trim().isEmpty()
index < firLines.size || line.trim().isEmpty() }
} )
)
}
} }
super.doTest(filePath) super.doTest(filePath)
} }
@@ -102,7 +102,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
val content = javaLines.joinToString(separator = "\n") val content = javaLines.joinToString(separator = "\n")
if (InTextDirectivesUtils.isDirectiveDefined(content, "SKIP_IN_FIR_TEST")) return if (InTextDirectivesUtils.isDirectiveDefined(content, "SKIP_IN_FIR_TEST")) return
val srcFiles = TestFiles.createTestFiles<Void, File>( val srcFiles = TestFiles.createTestFiles(
javaFile.name, FileUtil.loadFile(javaFile, true), javaFile.name, FileUtil.loadFile(javaFile, true),
object : TestFiles.TestFileFactoryNoModules<File>() { object : TestFiles.TestFileFactoryNoModules<File>() {
override fun create(fileName: String, text: String, directives: Map<String, String>): File { override fun create(fileName: String, text: String, directives: Map<String, String>): File {
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.asJava
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -29,12 +30,12 @@ import org.jetbrains.kotlin.util.KotlinFrontEndException
import org.junit.Assert import org.junit.Assert
import java.io.File import java.io.File
abstract class AbstractCompilerLightClassTest : KotlinMultiFileTestWithJava<Void, Void>() { abstract class AbstractCompilerLightClassTest : KotlinMultiFileTestWithJava<KotlinBaseTest.TestModule, KotlinBaseTest.TestFile>() {
override fun getConfigurationKind(): ConfigurationKind = ConfigurationKind.ALL override fun getConfigurationKind(): ConfigurationKind = ConfigurationKind.ALL
override fun isKotlinSourceRootNeeded(): Boolean = true override fun isKotlinSourceRootNeeded(): Boolean = true
override fun doMultiFileTest(file: File, modules: MutableMap<String, ModuleAndDependencies>, files: MutableList<Void>) { override fun doMultiFileTest(file: File, files: List<TestFile>) {
val environment = createEnvironment(file) val environment = createEnvironment(file)
val expectedFile = KotlinTestUtils.replaceExtension(file, "java") val expectedFile = KotlinTestUtils.replaceExtension(file, "java")
val allowFrontendExceptions = InTextDirectivesUtils.isDirectiveDefined(file.readText(), "// ALLOW_FRONTEND_EXCEPTION") val allowFrontendExceptions = InTextDirectivesUtils.isDirectiveDefined(file.readText(), "// ALLOW_FRONTEND_EXCEPTION")
@@ -47,9 +48,18 @@ abstract class AbstractCompilerLightClassTest : KotlinMultiFileTestWithJava<Void
) )
} }
override fun createTestModule(name: String): Void? = null override fun createTestModule(
name: String,
dependencies: MutableList<String>,
friends: MutableList<String>
): TestModule? = null
override fun createTestFile(module: Void?, fileName: String, text: String, directives: Map<String, String>): Void? = null override fun createTestFile(
module: TestModule?,
fileName: String,
text: String,
directives: Map<String, String>
): TestFile? = null
companion object { companion object {
fun findLightClass(allowFrontendExceptions: Boolean, environment: KotlinCoreEnvironment, fqname: String): PsiClass? { fun findLightClass(allowFrontendExceptions: Boolean, environment: KotlinCoreEnvironment, fqname: String): PsiClass? {
@@ -59,6 +59,7 @@ import org.jetbrains.kotlin.storage.ExceptionTracker
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.DescriptorValidator import org.jetbrains.kotlin.test.util.DescriptorValidator
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
@@ -191,7 +192,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
val actualText = StringBuilder() val actualText = StringBuilder()
for (testFile in files) { for (testFile in files) {
val module = testFile.module val module: KotlinBaseTest.TestModule? = testFile.module
val isCommonModule = modules[module]!!.platform.isCommon() val isCommonModule = modules[module]!!.platform.isCommon()
val implementingModules = val implementingModules =
if (!isCommonModule) emptyList() if (!isCommonModule) emptyList()
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.test.util.trimTrailingWhitespacesAndAddNewlineAtEOF import org.jetbrains.kotlin.test.util.trimTrailingWhitespacesAndAddNewlineAtEOF
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.junit.Assert import org.junit.Assert
@@ -74,26 +75,24 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
super.tearDown() super.tearDown()
} }
override fun createTestModule(name: String): TestModule = override fun createTestModule(
TestModule(name) name: String,
dependencies: List<String>,
friends: List<String>
): TestModule =
TestModule(name, dependencies, friends)
override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile = override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile =
TestFile(module, fileName, text, directives) TestFile(module, fileName, text, directives)
override fun doMultiFileTest( override fun doMultiFileTest(
file: File, wholeFile: File,
modules: @JvmSuppressWildcards Map<String, ModuleAndDependencies>, files: List<TestFile>
testFiles: List<TestFile>
) { ) {
for (moduleAndDependencies in modules.values) { environment = createEnvironment(wholeFile)
moduleAndDependencies.module.getDependencies().addAll(moduleAndDependencies.dependencies.map { name ->
modules[name]?.module ?: error("Dependency not found: $name for module ${moduleAndDependencies.module.name}")
})
}
environment = createEnvironment(file) analyzeAndCheck(wholeFile, files)
analyzeAndCheck(file, testFiles)
} }
protected abstract fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) protected abstract fun analyzeAndCheck(testDataFile: File, files: List<TestFile>)
@@ -122,16 +121,9 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
return ktFiles return ktFiles
} }
class TestModule(val name: String) : Comparable<TestModule> { class TestModule(name: String, dependencies: List<String>, friends: List<String>) :
KotlinBaseTest.TestModule(name, dependencies, friends) {
lateinit var languageVersionSettings: LanguageVersionSettings lateinit var languageVersionSettings: LanguageVersionSettings
private val dependencies = ArrayList<TestModule>()
fun getDependencies(): MutableList<TestModule> = dependencies
override fun compareTo(other: TestModule): Int = name.compareTo(other.name)
override fun toString(): String = name
} }
inner class TestFile( inner class TestFile(
@@ -139,7 +131,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
val fileName: String, val fileName: String,
textWithMarkers: String, textWithMarkers: String,
val directives: Map<String, String> val directives: Map<String, String>
) { ) : KotlinBaseTest.TestFile(fileName, textWithMarkers) {
val diagnosedRanges: MutableList<DiagnosedRange> = mutableListOf() val diagnosedRanges: MutableList<DiagnosedRange> = mutableListOf()
private val diagnosedRangesToDiagnosticNames: MutableMap<IntRange, MutableSet<String>> = mutableMapOf() private val diagnosedRangesToDiagnosticNames: MutableMap<IntRange, MutableSet<String>> = mutableMapOf()
val actualDiagnostics: MutableList<ActualDiagnostic> = mutableListOf() val actualDiagnostics: MutableList<ActualDiagnostic> = mutableListOf()
@@ -18,17 +18,16 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.parsing.KotlinParserDefinition; import org.jetbrains.kotlin.parsing.KotlinParserDefinition;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase; import org.jetbrains.kotlin.test.KotlinBaseTest;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
import static org.jetbrains.kotlin.script.ScriptTestUtilKt.loadScriptingPlugin; import static org.jetbrains.kotlin.script.ScriptTestUtilKt.loadScriptingPlugin;
public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase { public abstract class KotlinMultiFileTestWithJava<M extends KotlinBaseTest.TestModule, F extends KotlinBaseTest.TestFile> extends KotlinBaseTest<F> {
protected File javaFilesDir; protected File javaFilesDir;
private File kotlinSourceRoot; private File kotlinSourceRoot;
protected String coroutinesPackage;
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
@@ -38,7 +37,6 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
if (isKotlinSourceRootNeeded()) { if (isKotlinSourceRootNeeded()) {
kotlinSourceRoot = KotlinTestUtils.tmpDir("kotlin-src"); kotlinSourceRoot = KotlinTestUtils.tmpDir("kotlin-src");
} }
coroutinesPackage = "";
} }
public class ModuleAndDependencies { public class ModuleAndDependencies {
@@ -54,10 +52,16 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
} }
@NotNull @NotNull
protected Boolean isScriptingNeeded(@NotNull File file) { private static Boolean isScriptingNeeded(@NotNull File file) {
return file.getName().endsWith(KotlinParserDefinition.STD_SCRIPT_EXT); return file.getName().endsWith(KotlinParserDefinition.STD_SCRIPT_EXT);
} }
@Override
@NotNull
public List<F> createTestFilesFromFile(@NotNull File file, String expectedText) {
return createTestFiles(file, expectedText, new HashMap<>());
}
@NotNull @NotNull
protected KotlinCoreEnvironment createEnvironment(@NotNull File file) { protected KotlinCoreEnvironment createEnvironment(@NotNull File file) {
CompilerConfiguration configuration = KotlinTestUtils.newConfiguration( CompilerConfiguration configuration = KotlinTestUtils.newConfiguration(
@@ -142,35 +146,20 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
return new File(filePath); return new File(filePath);
} }
protected void doTest(String filePath) throws Exception { @Override
protected void doTest(@NotNull String filePath) throws Exception {
File file = createTestFileFromPath(filePath); File file = createTestFileFromPath(filePath);
String expectedText = KotlinTestUtils.doLoadFile(file); String expectedText = KotlinTestUtils.doLoadFile(file);
//TODO: move to proper tests
if (InTextDirectivesUtils.isDirectiveDefined(expectedText, "// SKIP_JAVAC")) return; if (InTextDirectivesUtils.isDirectiveDefined(expectedText, "// SKIP_JAVAC")) return;
Map<String, ModuleAndDependencies> modules = new HashMap<>(); super.doTest(file.getPath());
List<F> testFiles = createTestFiles(file, expectedText, modules);
doMultiFileTest(file, modules, testFiles);
} }
protected void doTestWithCoroutinesPackageReplacement(String filePath, String coroutinesPackage) throws Exception { protected abstract M createTestModule(@NotNull String name, List<String> dependencies, List<String> friends);
File file = new File(filePath);
String expectedText = KotlinTestUtils.doLoadFile(file);
expectedText = expectedText.replace("COROUTINES_PACKAGE", coroutinesPackage);
this.coroutinesPackage = coroutinesPackage;
Map<String, ModuleAndDependencies> modules = new HashMap<>();
List<F> testFiles = createTestFiles(file, expectedText, modules);
doMultiFileTest(file, modules, testFiles);
}
protected abstract M createTestModule(@NotNull String name);
protected abstract F createTestFile(M module, String fileName, String text, Map<String, String> directives); protected abstract F createTestFile(M module, String fileName, String text, Map<String, String> directives);
protected abstract void doMultiFileTest(File file, Map<String, ModuleAndDependencies> modules, List<F> files) throws Exception;
protected List<F> createTestFiles(File file, String expectedText, Map<String, ModuleAndDependencies> modules) { protected List<F> createTestFiles(File file, String expectedText, Map<String, ModuleAndDependencies> modules) {
return TestFiles.createTestFiles(file.getName(), expectedText, new TestFiles.TestFileFactory<M, F>() { return TestFiles.createTestFiles(file.getName(), expectedText, new TestFiles.TestFileFactory<M, F>() {
@Override @Override
@@ -193,7 +182,7 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
@Override @Override
public M createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends) { public M createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends) {
M module = createTestModule(name); M module = createTestModule(name, dependencies, friends);
ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies, friends)); ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies, friends));
assert oldValue == null : "Module " + name + " declared more than once"; assert oldValue == null : "Module " + name + " declared more than once";
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import java.io.File import java.io.File
abstract class AbstractBlackBoxAgainstJavaCodegenTest : AbstractBlackBoxCodegenTest() { abstract class AbstractBlackBoxAgainstJavaCodegenTest : AbstractBlackBoxCodegenTest() {
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>) { override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
javaClassesOutputDirectory = writeJavaFiles(files)!!.let { directory -> javaClassesOutputDirectory = writeJavaFiles(files)!!.let { directory ->
CodegenTestUtil.compileJava(CodegenTestUtil.findJavaSourcesInDirectory(directory), emptyList(), extractJavacOptions(files)) CodegenTestUtil.compileJava(CodegenTestUtil.findJavaSourcesInDirectory(directory), emptyList(), extractJavacOptions(files))
} }
@@ -59,9 +59,9 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
@Override @Override
protected void doMultiFileTest( protected void doMultiFileTest(
@NotNull File wholeFile, @NotNull File wholeFile,
@NotNull List<TestFile> files @NotNull List<? extends TestFile> files
) throws Exception { ) throws Exception {
doMultiFileTest(wholeFile, files, false); doMultiFileTest(wholeFile, (List<TestFile>)files, false);
} }
private void doBytecodeListingTest(@NotNull File wholeFile) throws Exception { private void doBytecodeListingTest(@NotNull File wholeFile) throws Exception {
@@ -49,9 +49,9 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
} }
@Override @Override
protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files) { protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<? extends TestFile> files) {
boolean isIgnored = InTextDirectivesUtils.isIgnoredTarget(getBackend(), wholeFile); boolean isIgnored = InTextDirectivesUtils.isIgnoredTarget(getBackend(), wholeFile);
doTwoFileTest(files, !isIgnored); doTwoFileTest((List<TestFile>) files, !isIgnored);
} }
@NotNull @NotNull
@@ -29,7 +29,7 @@ abstract class AbstractKapt3BuilderModeBytecodeShapeTest : CodegenTestCase() {
} }
} }
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>) { override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
compile(files) compile(files)
val txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".txt") val txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".txt")
KotlinTestUtils.assertEqualsToFile(txtFile, BytecodeListingTextCollectingVisitor.getText(classFileFactory)) KotlinTestUtils.assertEqualsToFile(txtFile, BytecodeListingTextCollectingVisitor.getText(classFileFactory))
@@ -28,12 +28,9 @@ import kotlin.collections.ArrayList
abstract class AbstractLineNumberTest : CodegenTestCase() { abstract class AbstractLineNumberTest : CodegenTestCase() {
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>) { override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
val isCustomTest = wholeFile.parentFile.name.equals("custom", ignoreCase = true) val isCustomTest = wholeFile.parentFile.name.equals("custom", ignoreCase = true)
if (!isCustomTest) { compile(if (!isCustomTest) files + createLineNumberDeclaration() else files)
files.add(createLineNumberDeclaration())
}
compile(files)
val psiFile = myFiles.psiFiles.single { file -> file.name == wholeFile.name } val psiFile = myFiles.psiFiles.single { file -> file.name == wholeFile.name }
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.TestsCompiletimeError;
import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFile;
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection; import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection;
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings; import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
import org.jetbrains.kotlin.test.KotlinBaseTest;
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil; import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.output.OutputUtilsKt; import org.jetbrains.kotlin.cli.common.output.OutputUtilsKt;
@@ -41,7 +42,6 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider;
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper; import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper;
import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.clientserver.TestProxy; import org.jetbrains.kotlin.test.clientserver.TestProxy;
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.tree.ClassNode; import org.jetbrains.org.objectweb.asm.tree.ClassNode;
@@ -74,7 +74,7 @@ import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getBoxMethodOrNull; import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getBoxMethodOrNull;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass; import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass;
public abstract class CodegenTestCase extends KtUsefulTestCase { public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.TestFile> {
private static final String DEFAULT_TEST_FILE_NAME = "a_test"; private static final String DEFAULT_TEST_FILE_NAME = "a_test";
private static final String DEFAULT_JVM_TARGET = System.getProperty("kotlin.test.default.jvm.target"); private static final String DEFAULT_JVM_TARGET = System.getProperty("kotlin.test.default.jvm.target");
public static final String BOX_IN_SEPARATE_PROCESS_PORT = System.getProperty("kotlin.test.box.in.separate.process.port"); public static final String BOX_IN_SEPARATE_PROCESS_PORT = System.getProperty("kotlin.test.box.in.separate.process.port");
@@ -778,37 +778,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
return TargetBackend.JVM; return TargetBackend.JVM;
} }
public static class TestFile implements Comparable<TestFile> { @Override
public final String name; protected void doTest(@NotNull String filePath) throws Exception {
public final String content;
public TestFile(@NotNull String name, @NotNull String content) {
this.name = name;
this.content = content;
}
@Override
public int compareTo(@NotNull TestFile o) {
return name.compareTo(o.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof TestFile && ((TestFile) obj).name.equals(name);
}
@Override
public String toString() {
return name;
}
}
protected void doTest(String filePath) throws Exception {
File file = new File(filePath); File file = new File(filePath);
String expectedText = KotlinTestUtils.doLoadFile(file); String expectedText = KotlinTestUtils.doLoadFile(file);
@@ -816,18 +787,20 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
expectedText = expectedText.replace("COROUTINES_PACKAGE", coroutinesPackage); expectedText = expectedText.replace("COROUTINES_PACKAGE", coroutinesPackage);
} }
List<TestFile> testFiles = createTestFiles(file, expectedText); List<TestFile> testFiles = createTestFilesFromFile(file, expectedText);
doMultiFileTest(file, testFiles); doMultiFileTest(file, testFiles);
} }
protected void doTestWithCoroutinesPackageReplacement(String filePath, String packageName) throws Exception { @Override
protected void doTestWithCoroutinesPackageReplacement(@NotNull String filePath, @NotNull String packageName) throws Exception {
this.coroutinesPackage = packageName; this.coroutinesPackage = packageName;
doTest(filePath); doTest(filePath);
} }
@Override
@NotNull @NotNull
private List<TestFile> createTestFiles(File file, String expectedText) { protected List<TestFile> createTestFilesFromFile(File file, String expectedText) {
List testFiles = TestFiles.createTestFiles(file.getName(), expectedText, new TestFiles.TestFileFactoryNoModules<TestFile>() { List testFiles = TestFiles.createTestFiles(file.getName(), expectedText, new TestFiles.TestFileFactoryNoModules<TestFile>() {
@NotNull @NotNull
@Override @Override
@@ -880,13 +853,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
return dir; return dir;
} }
protected void doMultiFileTest(
@NotNull File wholeFile,
@NotNull List<TestFile> files
) throws Exception {
throw new UnsupportedOperationException("Multi-file test cases are not supported in this test");
}
protected void callBoxMethodAndCheckResult(URLClassLoader classLoader, String className) protected void callBoxMethodAndCheckResult(URLClassLoader classLoader, String className)
throws IOException, InvocationTargetException, IllegalAccessException { throws IOException, InvocationTargetException, IllegalAccessException {
Class<?> aClass = getGeneratedClass(classLoader, className); Class<?> aClass = getGeneratedClass(classLoader, className);
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.inline.GENERATE_SMAP
import org.jetbrains.kotlin.codegen.inline.RangeMapping import org.jetbrains.kotlin.codegen.inline.RangeMapping
import org.jetbrains.kotlin.codegen.inline.SMAPParser import org.jetbrains.kotlin.codegen.inline.SMAPParser
import org.jetbrains.kotlin.codegen.inline.toRange import org.jetbrains.kotlin.codegen.inline.toRange
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.utils.keysToMap import org.jetbrains.kotlin.utils.keysToMap
import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.ClassVisitor
@@ -45,7 +46,7 @@ object SMAPTestUtil {
} }
} }
private fun extractSmapFromTestDataFile(file: CodegenTestCase.TestFile, separateCompilation: Boolean): SMAPAndFile? { private fun extractSmapFromTestDataFile(file: KotlinBaseTest.TestFile, separateCompilation: Boolean): SMAPAndFile? {
if (!checkExtension(file, separateCompilation)) return null if (!checkExtension(file, separateCompilation)) return null
val content = buildString { val content = buildString {
@@ -60,13 +61,13 @@ object SMAPTestUtil {
return SMAPAndFile(if (content.isNotEmpty()) content else null, SMAPAndFile.getPath(file.name), "NOT_SORTED") return SMAPAndFile(if (content.isNotEmpty()) content else null, SMAPAndFile.getPath(file.name), "NOT_SORTED")
} }
private fun checkExtension(file: CodegenTestCase.TestFile, separateCompilation: Boolean) = private fun checkExtension(file: KotlinBaseTest.TestFile, separateCompilation: Boolean) =
file.name.run { file.name.run {
endsWith(".smap") || endsWith(".smap") ||
if (separateCompilation) endsWith(".smap-separate-compilation") else endsWith(".smap-nonseparate-compilation") if (separateCompilation) endsWith(".smap-separate-compilation") else endsWith(".smap-nonseparate-compilation")
} }
fun checkSMAP(inputFiles: List<CodegenTestCase.TestFile>, outputFiles: Iterable<OutputFile>, separateCompilation: Boolean) { fun checkSMAP(inputFiles: List<KotlinBaseTest.TestFile>, outputFiles: Iterable<OutputFile>, separateCompilation: Boolean) {
if (!GENERATE_SMAP) return if (!GENERATE_SMAP) return
val sourceData = inputFiles.mapNotNull { extractSmapFromTestDataFile(it, separateCompilation) } val sourceData = inputFiles.mapNotNull { extractSmapFromTestDataFile(it, separateCompilation) }
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.defaultConstructor; package org.jetbrains.kotlin.codegen.defaultConstructor;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.CodegenTestCase; import org.jetbrains.kotlin.codegen.CodegenTestCase;
import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.ConfigurationKind;
@@ -35,7 +36,7 @@ public abstract class AbstractDefaultArgumentsReflectionTest extends CodegenTest
} }
@Override @Override
protected void doTest(String path) throws IOException { protected void doTest(@NotNull String path) throws IOException {
loadFileByFullPath(path); loadFileByFullPath(path);
File file = new File(path); File file = new File(path);
@@ -55,8 +55,8 @@ import static org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPref
public abstract class AbstractWriteFlagsTest extends CodegenTestCase { public abstract class AbstractWriteFlagsTest extends CodegenTestCase {
@Override @Override
protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files) throws Exception { protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<? extends TestFile> files) throws Exception {
compile(files); compile((List<TestFile>)files);
String fileText = FileUtil.loadFile(wholeFile, true); String fileText = FileUtil.loadFile(wholeFile, true);
@@ -15,7 +15,7 @@ import java.util.*
import java.util.regex.MatchResult import java.util.regex.MatchResult
abstract class AbstractWriteSignatureTest : CodegenTestCase() { abstract class AbstractWriteSignatureTest : CodegenTestCase() {
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>) { override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
val isIgnored = InTextDirectivesUtils.isIgnoredTarget(backend, wholeFile) val isIgnored = InTextDirectivesUtils.isIgnoredTarget(backend, wholeFile)
compile(files) compile(files)
try { try {
@@ -0,0 +1,84 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import java.io.File
import java.util.*
abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase() {
@JvmField
protected var coroutinesPackage: String = ""
@Throws(Exception::class)
override fun setUp() {
coroutinesPackage = ""
super.setUp()
}
@Throws(java.lang.Exception::class)
protected open fun doTestWithCoroutinesPackageReplacement(filePath: String, coroutinesPackage: String) {
this.coroutinesPackage = coroutinesPackage
doTest(filePath)
}
@Throws(java.lang.Exception::class)
protected open fun doTest(filePath: String) {
val file = File(filePath)
var expectedText = KotlinTestUtils.doLoadFile(file)
if (coroutinesPackage.isNotEmpty()) {
expectedText = expectedText.replace("COROUTINES_PACKAGE", coroutinesPackage)
}
doMultiFileTest(file, createTestFilesFromFile(file, expectedText))
}
protected abstract fun createTestFilesFromFile(file: File, expectedText: String?): List<F>
@Throws(java.lang.Exception::class)
protected open fun doMultiFileTest(
wholeFile: File,
files: List<F>
) {
throw UnsupportedOperationException("Multi-file test cases are not supported in this test")
}
open class TestFile(@JvmField val name: String, @JvmField val content: String) : Comparable<TestFile> {
override operator fun compareTo(other: TestFile): Int {
return name.compareTo(other.name)
}
override fun hashCode(): Int {
return name.hashCode()
}
override fun equals(other: Any?): Boolean {
return other is TestFile && other.name == name
}
override fun toString(): String {
return name
}
}
open class TestModule(
@JvmField val name: String,
@JvmField val dependenciesSymbols: List<String>,
@JvmField val friendsSymbols: List<String>
) : Comparable<TestModule> {
private val dependencies = ArrayList<TestModule>()
private val friends = ArrayList<TestModule>()
fun getDependencies(): MutableList<TestModule> = dependencies
fun getFriends(): MutableList<TestModule> = friends
override fun compareTo(other: TestModule): Int = name.compareTo(other.name)
override fun toString(): String = name
}
}
@@ -11,10 +11,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.TestHelperGeneratorKt; import org.jetbrains.kotlin.TestHelperGeneratorKt;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isDirectiveDefined; import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isDirectiveDefined;
@@ -37,20 +39,20 @@ public class TestFiles {
private static final Pattern LINE_SEPARATOR_PATTERN = Pattern.compile("\\r\\n|\\r|\\n"); private static final Pattern LINE_SEPARATOR_PATTERN = Pattern.compile("\\r\\n|\\r|\\n");
@NotNull @NotNull
public static <M, F> List<F> createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory<M, F> factory) { public static <M extends KotlinBaseTest.TestModule, F> List<F> createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory<M, F> factory) {
return createTestFiles(testFileName, expectedText, factory, false, ""); return createTestFiles(testFileName, expectedText, factory, false, "");
} }
@NotNull @NotNull
public static <M, F> List<F> createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory<M, F> factory, String coroutinesPackage) { public static <M extends KotlinBaseTest.TestModule, F> List<F> createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory<M, F> factory, String coroutinesPackage) {
return createTestFiles(testFileName, expectedText, factory, false, coroutinesPackage); return createTestFiles(testFileName, expectedText, factory, false, coroutinesPackage);
} }
@NotNull @NotNull
public static <M, F> List<F> createTestFiles(String testFileName, String expectedText, TestFileFactory<M, F> factory, public static <M extends KotlinBaseTest.TestModule, F> List<F> createTestFiles(String testFileName, String expectedText, TestFileFactory<M , F> factory,
boolean preserveLocations, String coroutinesPackage) { boolean preserveLocations, String coroutinesPackage) {
Map<String, String> directives = KotlinTestUtils.parseDirectives(expectedText); Map<String, String> directives = KotlinTestUtils.parseDirectives(expectedText);
Map<String, M> modules = new HashMap<>();
List<F> testFiles = Lists.newArrayList(); List<F> testFiles = Lists.newArrayList();
Matcher matcher = FILE_OR_MODULE_PATTERN.matcher(expectedText); Matcher matcher = FILE_OR_MODULE_PATTERN.matcher(expectedText);
boolean hasModules = false; boolean hasModules = false;
@@ -71,6 +73,8 @@ public class TestFiles {
moduleName = moduleName.trim(); moduleName = moduleName.trim();
hasModules = true; hasModules = true;
module = factory.createModule(moduleName, parseModuleList(moduleDependencies), parseModuleList(moduleFriends)); module = factory.createModule(moduleName, parseModuleList(moduleDependencies), parseModuleList(moduleFriends));
M oldValue = modules.put(moduleName, module);
assert oldValue == null : "Module with name " + moduleName + " already present in file";
} }
String fileName = matcher.group(4); String fileName = matcher.group(4);
@@ -101,6 +105,10 @@ public class TestFiles {
if (isDirectiveDefined(expectedText, "WITH_COROUTINES")) { if (isDirectiveDefined(expectedText, "WITH_COROUTINES")) {
M supportModule = hasModules ? factory.createModule("support", Collections.emptyList(), Collections.emptyList()) : null; M supportModule = hasModules ? factory.createModule("support", Collections.emptyList(), Collections.emptyList()) : null;
if (supportModule != null) {
M oldValue = modules.put(supportModule.name, supportModule);
assert oldValue == null : "Module with name " + supportModule.name + " already present in file";
}
boolean isReleaseCoroutines = boolean isReleaseCoroutines =
!coroutinesPackage.contains("experimental") && !coroutinesPackage.contains("experimental") &&
@@ -119,6 +127,23 @@ public class TestFiles {
)); ));
} }
for (M module : modules.values()) {
if (module != null) {
module.getDependencies().addAll(module.dependenciesSymbols.stream().map(name -> {
M dep = modules.get(name);
assert dep != null : "Dependency not found:" + name + "for module " + module.name;
return dep;
}).collect(Collectors.toList()));
module.getFriends().addAll(module.friendsSymbols.stream().map(name -> {
M dep = modules.get(name);
assert dep != null : "Dependency not found:" + name + "for module " + module.name;
return dep;
}).collect(Collectors.toList()));
}
}
return testFiles; return testFiles;
} }
@@ -152,10 +177,10 @@ public class TestFiles {
M createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends); M createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends);
} }
public static abstract class TestFileFactoryNoModules<F> implements TestFileFactory<Void, F> { public static abstract class TestFileFactoryNoModules<F> implements TestFileFactory<KotlinBaseTest.TestModule, F> {
@Override @Override
public final F createFile( public final F createFile(
@Nullable Void module, @Nullable KotlinBaseTest.TestModule module,
@NotNull String fileName, @NotNull String fileName,
@NotNull String text, @NotNull String text,
@NotNull Map<String, String> directives @NotNull Map<String, String> directives
@@ -167,7 +192,7 @@ public class TestFiles {
public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives); public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives);
@Override @Override
public Void createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends) { public KotlinBaseTest.TestModule createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends) {
return null; return null;
} }
} }
@@ -27,24 +27,22 @@ abstract class AbstractBlackBoxCodegenTestSpec : AbstractBlackBoxCodegenTest() {
private fun addPackageDirectiveToHelperFile(helperContent: String, packageName: String?) = private fun addPackageDirectiveToHelperFile(helperContent: String, packageName: String?) =
helperContent.replace(HELPERS_PACKAGE_VARIABLE, if (packageName == null) "" else "package $packageName") helperContent.replace(HELPERS_PACKAGE_VARIABLE, if (packageName == null) "" else "package $packageName")
private fun includeHelpers(wholeFile: File, files: MutableList<TestFile>, specTest: AbstractSpecTest) { private fun includeHelpers(wholeFile: File, files: List<TestFile>, specTest: AbstractSpecTest): List<TestFile> {
if (specTest.helpers == null) return if (specTest.helpers == null) return files
val fileContent = FileUtil.loadFile(wholeFile, true) val fileContent = FileUtil.loadFile(wholeFile, true)
val packageName = packagePattern.matcher(fileContent).let { val packageName = packagePattern.matcher(fileContent).let {
if (it.find()) it.group("packageName") else null if (it.find()) it.group("packageName") else null
} }
specTest.helpers.forEach { return files + specTest.helpers.map {
val filename = "$it.kt" val filename = "$it.kt"
val helperContent = FileUtil.loadFile(File("$HELPERS_PATH/$filename"), true) val helperContent = FileUtil.loadFile(File("$HELPERS_PATH/$filename"), true)
files.add( TestFile(filename, addPackageDirectiveToHelperFile(helperContent, packageName))
TestFile(filename, addPackageDirectiveToHelperFile(helperContent, packageName))
)
} }
} }
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>) { override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
val (specTest, testLinkedType) = CommonParser.parseSpecTest( val (specTest, testLinkedType) = CommonParser.parseSpecTest(
wholeFile.canonicalPath, wholeFile.canonicalPath,
mapOf("main.kt" to FileUtil.loadFile(wholeFile, true)) mapOf("main.kt" to FileUtil.loadFile(wholeFile, true))
@@ -60,9 +58,9 @@ abstract class AbstractBlackBoxCodegenTestSpec : AbstractBlackBoxCodegenTest() {
println(specTest) println(specTest)
includeHelpers(wholeFile, files, specTest) val filesWithHelpers = includeHelpers(wholeFile, files, specTest)
val runTest = { super.doMultiFileTest(wholeFile, files, specTest.unexpectedBehavior) } val runTest = { super.doMultiFileTest(wholeFile, filesWithHelpers, specTest.unexpectedBehavior) }
if (specTest.exception == null) { if (specTest.exception == null) {
runTest() runTest()
@@ -48,7 +48,7 @@ abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
loadScriptingPlugin(configuration) loadScriptingPlugin(configuration)
} }
override fun doMultiFileTest(wholeFile: File, files: MutableList<TestFile>) { override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
if (files.size > 1) { if (files.size > 1) {
throw UnsupportedOperationException("Multiple files are not yet supported in this test") throw UnsupportedOperationException("Multiple files are not yet supported in this test")
} }
@@ -5,20 +5,28 @@
package org.jetbrains.kotlin.visualizer package org.jetbrains.kotlin.visualizer
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.TestJdkKind
import java.io.File import java.io.File
abstract class AbstractVisualizer : KotlinMultiFileTestWithJava<Void?, Void?>() { abstract class AbstractVisualizer : KotlinMultiFileTestWithJava<KotlinBaseTest.TestModule?, KotlinBaseTest.TestFile>() {
lateinit var replacement: Pair<String, String> lateinit var replacement: Pair<String, String>
override fun createTestModule(name: String): Void? = null override fun createTestModule(
name: String,
dependencies: MutableList<String>,
friends: MutableList<String>
): TestModule? = null
override fun createTestFile(module: Void?, fileName: String?, text: String?, directives: MutableMap<String, String>?): Void? = null
override fun doMultiFileTest(file: File, modules: MutableMap<String, ModuleAndDependencies>?, files: MutableList<Void?>) { override fun createTestFile(module: TestModule?, fileName: String?, text: String?, directives: MutableMap<String, String>?): TestFile? =
null
override fun doMultiFileTest(file: File, files: List<TestFile>) {
val environment = createEnvironment(file) val environment = createEnvironment(file)
doVisualizerTest(file, environment) doVisualizerTest(file, environment)
} }
@@ -22,7 +22,6 @@ import com.sun.jdi.ObjectReference
import org.jetbrains.eval4j.ObjectValue import org.jetbrains.eval4j.ObjectValue
import org.jetbrains.eval4j.Value import org.jetbrains.eval4j.Value
import org.jetbrains.eval4j.jdi.asValue import org.jetbrains.eval4j.jdi.asValue
import org.jetbrains.kotlin.codegen.CodegenTestCase.TestFile
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferences import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferences
@@ -32,6 +31,7 @@ import org.jetbrains.kotlin.idea.debugger.test.util.SteppingInstruction
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findLinesWithPrefixesRemoved import org.jetbrains.kotlin.test.InTextDirectivesUtils.findLinesWithPrefixesRemoved
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes
import org.jetbrains.kotlin.test.KotlinBaseTest
import java.io.File import java.io.File
import javax.swing.tree.TreeNode import javax.swing.tree.TreeNode
@@ -254,7 +254,7 @@ abstract class AbstractKotlinEvaluateExpressionTest : KotlinDescriptorTestCaseWi
return this.toString() return this.toString()
} }
private fun loadExpressions(testFile: TestFile): List<CodeFragment> { private fun loadExpressions(testFile: KotlinBaseTest.TestFile): List<CodeFragment> {
val directives = findLinesWithPrefixesRemoved(testFile.content, "// EXPRESSION: ") val directives = findLinesWithPrefixesRemoved(testFile.content, "// EXPRESSION: ")
val expected = findLinesWithPrefixesRemoved(testFile.content, "// RESULT: ") val expected = findLinesWithPrefixesRemoved(testFile.content, "// RESULT: ")
assert(directives.size == expected.size) { "Sizes of test directives are different" } assert(directives.size == expected.size) { "Sizes of test directives are different" }
@@ -276,7 +276,7 @@ abstract class AbstractKotlinEvaluateExpressionTest : KotlinDescriptorTestCaseWi
return codeFragments return codeFragments
} }
private fun loadDebugLabels(testFile: TestFile): List<DebugLabel> { private fun loadDebugLabels(testFile: KotlinBaseTest.TestFile): List<DebugLabel> {
return findLinesWithPrefixesRemoved(testFile.content, "// DEBUG_LABEL: ") return findLinesWithPrefixesRemoved(testFile.content, "// DEBUG_LABEL: ")
.map { text -> .map { text ->
val labelParts = text.split("=") val labelParts = text.split("=")
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
import org.jetbrains.kotlin.cli.common.output.writeAllTo import org.jetbrains.kotlin.cli.common.output.writeAllTo
import org.jetbrains.kotlin.cli.jvm.compiler.findMainClass import org.jetbrains.kotlin.cli.jvm.compiler.findMainClass
import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenTestCase.TestFile
import org.jetbrains.kotlin.codegen.CodegenTestUtil import org.jetbrains.kotlin.codegen.CodegenTestUtil
import org.jetbrains.kotlin.codegen.DefaultCodegenFactory import org.jetbrains.kotlin.codegen.DefaultCodegenFactory
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.KotlinBaseTest.TestFile
import org.jetbrains.kotlin.test.MockLibraryUtil import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import java.io.File import java.io.File
@@ -21,7 +21,6 @@ import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.testFramework.EdtTestUtil import com.intellij.testFramework.EdtTestUtil
import com.intellij.xdebugger.XDebugSession import com.intellij.xdebugger.XDebugSession
import org.jetbrains.kotlin.codegen.CodegenTestCase.TestFile
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
@@ -31,6 +30,7 @@ import org.jetbrains.kotlin.idea.debugger.test.util.KotlinOutputChecker
import org.jetbrains.kotlin.idea.debugger.test.util.LogPropagator import org.jetbrains.kotlin.idea.debugger.test.util.LogPropagator
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.test.KotlinBaseTest.TestFile
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestMetadata import org.jetbrains.kotlin.test.TestMetadata
import org.jetbrains.kotlin.test.isIgnoredInDatabaseWithLog import org.jetbrains.kotlin.test.isIgnoredInDatabaseWithLog
@@ -125,7 +125,7 @@ abstract class KotlinDescriptorTestCase : DescriptorTestCase() {
} }
private fun createTestFiles(wholeFile: File, wholeFileContents: String): TestFiles { private fun createTestFiles(wholeFile: File, wholeFileContents: String): TestFiles {
val testFiles = org.jetbrains.kotlin.test.TestFiles.createTestFiles<Void, TestFile>( val testFiles = org.jetbrains.kotlin.test.TestFiles.createTestFiles(
wholeFile.name, wholeFile.name,
wholeFileContents, wholeFileContents,
object : org.jetbrains.kotlin.test.TestFiles.TestFileFactoryNoModules<TestFile>() { object : org.jetbrains.kotlin.test.TestFiles.TestFileFactoryNoModules<TestFile>() {
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.idea.debugger.test.util package org.jetbrains.kotlin.idea.debugger.test.util
import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.test.KotlinBaseTest.TestFile
enum class SteppingInstructionKind(val directiveName: String) { enum class SteppingInstructionKind(val directiveName: String) {
StepInto("STEP_INTO"), StepInto("STEP_INTO"),
@@ -19,11 +19,11 @@ enum class SteppingInstructionKind(val directiveName: String) {
class SteppingInstruction(val kind: SteppingInstructionKind, val arg: Int) { class SteppingInstruction(val kind: SteppingInstructionKind, val arg: Int) {
companion object { companion object {
fun parse(file: CodegenTestCase.TestFile): List<SteppingInstruction> { fun parse(file: TestFile): List<SteppingInstruction> {
return parse(file, Companion::parseLine) return parse(file, Companion::parseLine)
} }
fun parseSingle(file: CodegenTestCase.TestFile, kind: SteppingInstructionKind): SteppingInstruction? { fun parseSingle(file: TestFile, kind: SteppingInstructionKind): SteppingInstruction? {
val instructions = parse(file) { line -> parseKind(line, kind) } val instructions = parse(file) { line -> parseKind(line, kind) }
if (instructions.size > 1) { if (instructions.size > 1) {
error("Several instructions found for kind $kind") error("Several instructions found for kind $kind")
@@ -32,7 +32,7 @@ class SteppingInstruction(val kind: SteppingInstructionKind, val arg: Int) {
return instructions.singleOrNull() return instructions.singleOrNull()
} }
private fun parse(file: CodegenTestCase.TestFile, processor: (String) -> SteppingInstruction?): List<SteppingInstruction> { private fun parse(file: TestFile, processor: (String) -> SteppingInstruction?): List<SteppingInstruction> {
return file.content.lineSequence() return file.content.lineSequence()
.map { it.trimStart() } .map { it.trimStart() }
.filter { it.startsWith("// ") } .filter { it.startsWith("// ") }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.js.test.utils.LineOutputToStringVisitor
import org.jetbrains.kotlin.js.util.TextOutputImpl import org.jetbrains.kotlin.js.util.TextOutputImpl
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
import org.jetbrains.kotlin.test.TestFiles import org.jetbrains.kotlin.test.TestFiles
@@ -51,7 +52,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
.map { it.module }.distinct() .map { it.module }.distinct()
.associateBy { it.name } .associateBy { it.name }
val orderedModules = DFS.topologicalOrder(modules.values) { module -> module.dependencies.mapNotNull { modules[it] } } val orderedModules = DFS.topologicalOrder(modules.values) { module -> module.dependenciesSymbols.mapNotNull { modules[it] } }
orderedModules.asReversed().forEach { module -> orderedModules.asReversed().forEach { module ->
val baseOutputPath = module.outputFileName(file) val baseOutputPath = module.outputFileName(file)
@@ -110,7 +111,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES) KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
private fun createConfig(module: TestModule, inputFile: File, modules: Map<String, TestModule>): JsConfig { private fun createConfig(module: TestModule, inputFile: File, modules: Map<String, TestModule>): JsConfig {
val dependencies = module.dependencies val dependencies = module.dependenciesSymbols
.mapNotNull { modules[it]?.outputFileName(inputFile) } .mapNotNull { modules[it]?.outputFileName(inputFile) }
.map { "$it.meta.js" } .map { "$it.meta.js" }
@@ -137,7 +138,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
private inner class TestFileFactoryImpl : TestFiles.TestFileFactory<TestModule, TestFile>, Closeable { private inner class TestFileFactoryImpl : TestFiles.TestFileFactory<TestModule, TestFile>, Closeable {
private val tmpDir = KotlinTestUtils.tmpDir("js-tests") private val tmpDir = KotlinTestUtils.tmpDir("js-tests")
private val defaultModule = TestModule(BasicBoxTest.TEST_MODULE, emptyList()) private val defaultModule = TestModule(BasicBoxTest.TEST_MODULE, emptyList(), emptyList())
override fun createFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile? { override fun createFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile? {
val currentModule = module ?: defaultModule val currentModule = module ?: defaultModule
@@ -146,11 +147,10 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
KotlinTestUtils.mkdirs(temporaryFile.parentFile) KotlinTestUtils.mkdirs(temporaryFile.parentFile)
temporaryFile.writeText(text, Charsets.UTF_8) temporaryFile.writeText(text, Charsets.UTF_8)
return TestFile(temporaryFile.absolutePath, text, currentModule)
return TestFile(temporaryFile.absolutePath, currentModule)
} }
override fun createModule(name: String, dependencies: List<String>, friends: List<String>) = TestModule(name, dependencies) override fun createModule(name: String, dependencies: List<String>, friends: List<String>) = TestModule(name, dependencies, friends)
override fun close() { override fun close() {
FileUtil.delete(tmpDir) FileUtil.delete(tmpDir)
@@ -158,14 +158,14 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
} }
private class TestModule( private class TestModule(
val name: String, name: String,
dependencies: List<String> dependenciesSymbols: List<String>,
) { friendsSymbols: List<String>
val dependencies = dependencies.toMutableList() ): KotlinBaseTest.TestModule(name, dependenciesSymbols, friendsSymbols) {
val files = mutableListOf<TestFile>() val files = mutableListOf<TestFile>()
} }
private class TestFile(val fileName: String, val module: TestModule) { private class TestFile(val fileName: String, content: String, val module: TestModule) : KotlinBaseTest.TestFile(fileName, content) {
init { init {
module.files += this module.files += this
} }
@@ -141,10 +141,10 @@ abstract class BasicBoxTest(
.map { it.name to it }.toMap() .map { it.name to it }.toMap()
fun TestModule.allTransitiveDependencies(): Set<String> { fun TestModule.allTransitiveDependencies(): Set<String> {
return dependencies.toSet() + dependencies.flatMap { modules[it]!!.allTransitiveDependencies() } return dependenciesSymbols.toSet() + dependenciesSymbols.flatMap { modules[it]!!.allTransitiveDependencies() }
} }
val orderedModules = DFS.topologicalOrder(modules.values) { module -> module.dependencies.mapNotNull { modules[it] } } val orderedModules = DFS.topologicalOrder(modules.values) { module -> module.dependenciesSymbols.mapNotNull { modules[it] } }
val testPackage = if (runPlainBoxFunction) null else testFactory.testPackage val testPackage = if (runPlainBoxFunction) null else testFactory.testPackage
@@ -159,9 +159,9 @@ abstract class BasicBoxTest(
val mainModule = modules[mainModuleName] ?: error("No module with name \"$mainModuleName\"") val mainModule = modules[mainModuleName] ?: error("No module with name \"$mainModuleName\"")
val generatedJsFiles = orderedModules.asReversed().mapNotNull { module -> val generatedJsFiles = orderedModules.asReversed().mapNotNull { module ->
val dependencies = module.dependencies.map { modules[it]?.outputFileName(outputDir) + ".meta.js" } val dependencies = module.dependenciesSymbols.map { modules[it]?.outputFileName(outputDir) + ".meta.js" }
val allDependencies = module.allTransitiveDependencies().map { modules[it]?.outputFileName(outputDir) + ".meta.js" } val allDependencies = module.allTransitiveDependencies().map { modules[it]?.outputFileName(outputDir) + ".meta.js" }
val friends = module.friends.map { modules[it]?.outputFileName(outputDir) + ".meta.js" } val friends = module.friendsSymbols.map { modules[it]?.outputFileName(outputDir) + ".meta.js" }
val outputFileName = module.outputFileName(outputDir) + ".js" val outputFileName = module.outputFileName(outputDir) + ".js"
val dceOutputFileName = module.outputFileName(dceOutputDir) + ".js" val dceOutputFileName = module.outputFileName(dceOutputDir) + ".js"
@@ -863,12 +863,10 @@ abstract class BasicBoxTest(
} }
private class TestModule( private class TestModule(
val name: String, name: String,
dependencies: List<String>, dependencies: List<String>,
friends: List<String> friends: List<String>
) { ): KotlinBaseTest.TestModule(name, dependencies, friends) {
val dependencies = dependencies.toMutableList()
val friends = friends.toMutableList()
var moduleKind = ModuleKind.PLAIN var moduleKind = ModuleKind.PLAIN
var inliningDisabled = false var inliningDisabled = false
val files = mutableListOf<TestFile>() val files = mutableListOf<TestFile>()
@@ -323,7 +323,7 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
} }
abstract class AbstractKotlinKaptContextTest : AbstractKotlinKapt3Test() { abstract class AbstractKotlinKaptContextTest : AbstractKotlinKapt3Test() {
override fun doTest(filePath: String?) { override fun doTest(filePath: String) {
kaptFlags.add(KaptFlag.CORRECT_ERROR_TYPES) kaptFlags.add(KaptFlag.CORRECT_ERROR_TYPES)
kaptFlags.add(KaptFlag.STRICT) kaptFlags.add(KaptFlag.STRICT)
kaptFlags.add(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS) kaptFlags.add(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS)