Improve multi-file test framework in CodegenTestCase

Instead of inheriting from KotlinMultiFileTestWithJava, invoke
KotlinTestUtils.createTestFiles directly. This helps to avoid constructing
unnecessary environment (createEnvironment() was called in setUp, but codegen
tests ignored the created environment because it's not possible to do
generically in codegen tests; the environment kind depends on the source file
usually)
This commit is contained in:
Alexander Udalov
2016-02-29 11:50:49 +03:00
parent 4b96a8131b
commit 0b26e749f6
7 changed files with 61 additions and 42 deletions
@@ -54,6 +54,7 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KotlinTestWithEn
@Override @Override
protected KotlinCoreEnvironment createEnvironment() throws Exception { protected KotlinCoreEnvironment createEnvironment() throws Exception {
// TODO: do not create temporary directory for tests without Java sources
javaFilesDir = KotlinTestUtils.tmpDir("java-files"); javaFilesDir = KotlinTestUtils.tmpDir("java-files");
CompilerConfiguration configuration = KotlinTestUtils.compilerConfigurationForTests( CompilerConfiguration configuration = KotlinTestUtils.compilerConfigurationForTests(
getConfigurationKind(), getConfigurationKind(),
@@ -93,11 +94,6 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KotlinTestWithEn
return false; return false;
} }
@NotNull
protected final File getJavaFilesDir() {
return javaFilesDir;
}
protected void doTest(String filePath) throws Exception { protected void doTest(String filePath) throws Exception {
File file = new File(filePath); File file = new File(filePath);
@@ -45,16 +45,15 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.codegen.CodegenTestUtil.compileJava; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.compileJava;
public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
@Override @Override
protected void doMultiFileTest(File file, Map<String, ModuleAndDependencies> modules, List<TestFile> files) throws Exception { protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) throws Exception {
if (files.size() == 1) { if (files.size() == 1) {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
blackBoxFileByFullPath(file.getPath()); blackBoxFileByFullPath(wholeFile.getPath());
} }
else { else {
doTestMultiFile(files); doTestMultiFile(files);
@@ -16,14 +16,11 @@
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
import java.io.File import java.io.File
abstract class AbstractBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest() { abstract class AbstractBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest() {
override fun doMultiFileTest( override fun doMultiFileTest(file: File, files: List<TestFile>, javaFilesDir: File?) {
file: File, modules: Map<String, KotlinMultiFileTestWithJava<Void, TestFile>.ModuleAndDependencies>, files: List<TestFile>
) {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL) createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL)
loadMultiFiles(files) loadMultiFiles(files)
blackBox() blackBox()
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import kotlin.text.Charsets; import kotlin.text.Charsets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
@@ -36,15 +37,15 @@ public abstract class AbstractBytecodeTextTest extends CodegenTestCase {
private static final Pattern EXPECTED_OCCURRENCES_PATTERN = Pattern.compile("^\\s*//\\s*(\\d+)\\s*(.*)$"); private static final Pattern EXPECTED_OCCURRENCES_PATTERN = Pattern.compile("^\\s*//\\s*(\\d+)\\s*(.*)$");
@Override @Override
protected void doMultiFileTest(File file, Map<String, ModuleAndDependencies> modules, List<TestFile> files) throws Exception { protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, getJavaFilesDir()); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, javaFilesDir);
loadMultiFiles(files); loadMultiFiles(files);
if (isMultiFileTest(files)) { if (isMultiFileTest(files)) {
doTestMultiFile(files); doTestMultiFile(files);
} }
else { else {
List<OccurrenceInfo> expected = readExpectedOccurrences(file.getPath()); List<OccurrenceInfo> expected = readExpectedOccurrences(wholeFile.getPath());
String actual = generateToText(); String actual = generateToText();
checkGeneratedTextAgainstExpectedOccurrences(actual, expected); checkGeneratedTextAgainstExpectedOccurrences(actual, expected);
} }
@@ -16,14 +16,11 @@
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import java.io.File import java.io.File
abstract class AbstractCompileKotlinAgainstInlineKotlinTest : AbstractCompileKotlinAgainstKotlinTest() { abstract class AbstractCompileKotlinAgainstInlineKotlinTest : AbstractCompileKotlinAgainstKotlinTest() {
override fun doMultiFileTest( override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
file: File, modules: Map<String, KotlinMultiFileTestWithJava<Void, TestFile>.ModuleAndDependencies>, files: List<TestFile>
) {
val kotlinFiles = files.filter { it.name.endsWith(".kt") } val kotlinFiles = files.filter { it.name.endsWith(".kt") }
assert(kotlinFiles.size == 2) { "There should be exactly two files in this test" } assert(kotlinFiles.size == 2) { "There should be exactly two files in this test" }
@@ -20,6 +20,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Disposer;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.common.modules.ModuleBuilder; import org.jetbrains.kotlin.cli.common.modules.ModuleBuilder;
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
@@ -39,7 +40,6 @@ import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.List; import java.util.List;
import java.util.Map;
public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTestCase { public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTestCase {
private File tmpdir; private File tmpdir;
@@ -57,7 +57,7 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
} }
@Override @Override
protected void doMultiFileTest(File file, Map<String, ModuleAndDependencies> modules, List<TestFile> files) throws Exception { protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) throws Exception {
// Note that it may be beneficial to improve this test to handle many files, compiling them successively against all previous // Note that it may be beneficial to improve this test to handle many files, compiling them successively against all previous
assert files.size() == 2 : "There should be exactly two files in this test"; assert files.size() == 2 : "There should be exactly two files in this test";
TestFile fileA = files.get(0); TestFile fileA = files.get(0);
@@ -17,14 +17,17 @@
package org.jetbrains.kotlin.codegen; package org.jetbrains.kotlin.codegen;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.testFramework.TestDataFile; import com.intellij.testFramework.TestDataFile;
import com.intellij.util.SmartList; import com.intellij.testFramework.UsefulTestCase;
import kotlin.collections.ArraysKt;
import kotlin.io.FilesKt;
import kotlin.text.Charsets; import kotlin.text.Charsets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFile;
import org.jetbrains.kotlin.checkers.CheckerTestUtil; import org.jetbrains.kotlin.checkers.CheckerTestUtil;
import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
@@ -63,7 +66,7 @@ import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
import static org.jetbrains.kotlin.test.KotlinTestUtils.compilerConfigurationForTests; import static org.jetbrains.kotlin.test.KotlinTestUtils.compilerConfigurationForTests;
import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar; import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar;
public abstract class CodegenTestCase extends KotlinMultiFileTestWithJava<Void, CodegenTestCase.TestFile> { public abstract class CodegenTestCase extends UsefulTestCase {
private static final String DEFAULT_TEST_FILE_NAME = "a_test"; private static final String DEFAULT_TEST_FILE_NAME = "a_test";
protected KotlinCoreEnvironment myEnvironment; protected KotlinCoreEnvironment myEnvironment;
@@ -72,19 +75,22 @@ public abstract class CodegenTestCase extends KotlinMultiFileTestWithJava<Void,
protected GeneratedClassLoader initializedClassLoader; protected GeneratedClassLoader initializedClassLoader;
protected ConfigurationKind configurationKind; protected ConfigurationKind configurationKind;
final protected void createEnvironmentWithMockJdkAndIdeaAnnotations(@NotNull ConfigurationKind configurationKind, File... javaSourceRoot) { protected final void createEnvironmentWithMockJdkAndIdeaAnnotations(
@NotNull ConfigurationKind configurationKind,
@Nullable File... javaSourceRoots
) {
if (myEnvironment != null) { if (myEnvironment != null) {
throw new IllegalStateException("must not set up myEnvironment twice"); throw new IllegalStateException("must not set up myEnvironment twice");
} }
CompilerConfiguration configuration = CompilerConfiguration configuration = compilerConfigurationForTests(
compilerConfigurationForTests(configurationKind, TestJdkKind.MOCK_JDK, configurationKind, TestJdkKind.MOCK_JDK, Collections.singletonList(getAnnotationsJar()),
Collections.singletonList(getAnnotationsJar()), new SmartList<File>(javaSourceRoot)); ArraysKt.filterNotNull(javaSourceRoots)
);
myEnvironment = KotlinCoreEnvironment.createForTests( myEnvironment = KotlinCoreEnvironment.createForTests(
getTestRootDisposable(), getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES
configuration, );
EnvironmentConfigFiles.JVM_CONFIG_FILES);
} }
@Override @Override
@@ -373,19 +379,42 @@ public abstract class CodegenTestCase extends KotlinMultiFileTestWithJava<Void,
} }
} }
@Override protected void doTest(String filePath) throws Exception {
protected Void createTestModule(@NotNull String name) { File file = new File(filePath);
// TODO: support multi-module codegen tests String expectedText = KotlinTestUtils.doLoadFile(file);
throw new UnsupportedOperationException("Multi-module codegen tests are not yet supported"); final Ref<File> javaFilesDir = Ref.create();
List<TestFile> testFiles =
KotlinTestUtils.createTestFiles(file.getName(), expectedText, new KotlinTestUtils.TestFileFactoryNoModules<TestFile>() {
@NotNull
@Override
public TestFile create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives) {
if (fileName.endsWith(".java")) {
if (javaFilesDir.isNull()) {
try {
javaFilesDir.set(KotlinTestUtils.tmpDir("java-files"));
}
catch (IOException e) {
throw ExceptionUtilsKt.rethrow(e);
}
}
writeSourceFile(fileName, text, javaFilesDir.get());
}
return new TestFile(fileName, text);
}
private void writeSourceFile(@NotNull String fileName, @NotNull String content, @NotNull File targetDir) {
File file = new File(targetDir, fileName);
KotlinTestUtils.mkdirs(file.getParentFile());
FilesKt.writeText(file, content, Charsets.UTF_8);
}
});
doMultiFileTest(file, testFiles, javaFilesDir.get());
} }
@Override protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) throws Exception {
protected TestFile createTestFile(Void module, String fileName, String text, Map<String, String> directives) {
return new TestFile(fileName, text);
}
@Override
protected void doMultiFileTest(File file, Map<String, ModuleAndDependencies> modules, List<TestFile> files) throws Exception {
throw new UnsupportedOperationException("Multi-file test cases are not supported in this test"); throw new UnsupportedOperationException("Multi-file test cases are not supported in this test");
} }
} }