Reformat and cleanup most JVM codegen test classes

This commit is contained in:
Alexander Udalov
2019-03-29 14:56:35 +01:00
parent 23a214710b
commit 7fdb9c990e
43 changed files with 491 additions and 580 deletions
@@ -33,9 +33,9 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
@Override
protected void doMultiFileTest(
@NotNull File wholeFile,
@NotNull List<TestFile> files,
@Nullable File javaFilesDir
@NotNull File wholeFile,
@NotNull List<TestFile> files,
@Nullable File javaFilesDir
) throws Exception {
boolean isIgnored = IGNORE_EXPECTED_FAILURES && InTextDirectivesUtils.isIgnoredTarget(getBackend(), wholeFile);
@@ -24,8 +24,7 @@ abstract class AbstractBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest()
try {
InlineTestUtil.checkNoCallsToInline(initializedClassLoader.allGeneratedFiles.filterClassFiles(), myFiles.psiFiles)
SMAPTestUtil.checkSMAP(files, generateClassesInFile().getClassFiles(), false)
}
catch (e: Throwable) {
} catch (e: Throwable) {
println(generateToText())
throw e
}
@@ -34,7 +34,7 @@ abstract class AbstractBytecodeListingTest : CodegenTestCase() {
}
private fun isWithSignatures(wholeFile: File): Boolean =
WITH_SIGNATURES.containsMatchIn(wholeFile.readText())
WITH_SIGNATURES.containsMatchIn(wholeFile.readText())
companion object {
private val WITH_SIGNATURES = Regex.fromLiteral("// WITH_SIGNATURES")
@@ -132,13 +132,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
}
}.toString()
override fun visitMethod(
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
if (!filter.shouldWriteMethod(access, name, desc)) {
return null
}
@@ -176,7 +170,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
}.joinToString()
val signatureIfRequired = if (withSignatures) "<$signature> " else ""
declarationsInsideClass.add(
Declaration("${signatureIfRequired}method $name($parameterWithAnnotations): $returnType", methodAnnotations)
Declaration("${signatureIfRequired}method $name($parameterWithAnnotations): $returnType", methodAnnotations)
)
super.visitEnd()
}
@@ -218,14 +212,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
return super.visitAnnotation(desc, visible)
}
override fun visit(
version: Int,
access: Int,
name: String,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<out String>?) {
className = name
classAccess = access
classSignature = signature
@@ -5,12 +5,10 @@
package org.jetbrains.kotlin.codegen
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.utils.rethrow
import org.junit.Assert
import java.io.File
import java.util.*
@@ -18,24 +16,25 @@ import java.util.regex.Matcher
import java.util.regex.Pattern
abstract class AbstractBytecodeTextTest : CodegenTestCase() {
@Throws(Exception::class)
override fun doMultiFileTest(wholeFile: File, files: List<CodegenTestCase.TestFile>, javaFilesDir: File?) {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, files, TestJdkKind.MOCK_JDK, javaFilesDir)
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
createEnvironmentWithMockJdkAndIdeaAnnotations(
ConfigurationKind.ALL,
files,
TestJdkKind.MOCK_JDK,
*listOfNotNull(javaFilesDir).toTypedArray()
)
loadMultiFiles(files)
if (isMultiFileTest(files) && !InTextDirectivesUtils.isDirectiveDefined(wholeFile.readText(), "TREAT_AS_ONE_FILE")) {
doTestMultiFile(files)
}
else {
} else {
val expected = readExpectedOccurrences(wholeFile.path)
val actual = generateToText("helpers/")
checkGeneratedTextAgainstExpectedOccurrences(actual, expected)
}
}
@Throws(Exception::class)
private fun doTestMultiFile(files: List<CodegenTestCase.TestFile>) {
private fun doTestMultiFile(files: List<TestFile>) {
val expectedOccurrencesByOutputFile = LinkedHashMap<String, List<OccurrenceInfo>>()
for (file in files) {
readExpectedOccurrencesForMultiFileTest(file, expectedOccurrencesByOutputFile)
@@ -50,10 +49,9 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
}
}
@Throws(Exception::class)
protected fun readExpectedOccurrences(filename: String): List<OccurrenceInfo> {
val result = ArrayList<OccurrenceInfo>()
val lines = FileUtil.loadFile(File(filename), Charsets.UTF_8.name(), true).split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val lines = File(filename).readLines().dropLastWhile(String::isEmpty)
for (line in lines) {
val matcher = EXPECTED_OCCURRENCES_PATTERN.matcher(line)
@@ -80,7 +78,7 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
private val AT_OUTPUT_FILE_PATTERN = Pattern.compile("^\\s*//\\s*@(.*):$")
private val EXPECTED_OCCURRENCES_PATTERN = Pattern.compile("^\\s*//\\s*(\\d+)\\s*(.*)$")
private fun isMultiFileTest(files: List<CodegenTestCase.TestFile>): Boolean {
private fun isMultiFileTest(files: List<TestFile>): Boolean {
var kotlinFiles = 0
for (file in files) {
if (file.name.endsWith(".kt")) {
@@ -90,8 +88,7 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
return kotlinFiles > 1
}
fun checkGeneratedTextAgainstExpectedOccurrences(text: String,
expectedOccurrences: List<OccurrenceInfo>) {
fun checkGeneratedTextAgainstExpectedOccurrences(text: String, expectedOccurrences: List<OccurrenceInfo>) {
val expected = StringBuilder()
val actual = StringBuilder()
@@ -102,10 +99,9 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
try {
Assert.assertEquals(text, expected.toString(), actual.toString())
}
catch (e: Throwable) {
} catch (e: Throwable) {
println(text)
throw rethrow(e)
throw e
}
}
@@ -121,27 +117,23 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
}
}
private fun readExpectedOccurrencesForMultiFileTest(
file: CodegenTestCase.TestFile,
occurrenceMap: MutableMap<String, List<OccurrenceInfo>>) {
private fun readExpectedOccurrencesForMultiFileTest(file: TestFile, occurrenceMap: MutableMap<String, List<OccurrenceInfo>>) {
var currentOccurrenceInfos: MutableList<OccurrenceInfo>? = null
for (line in file.content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
val atOutputFileMatcher = AT_OUTPUT_FILE_PATTERN.matcher(line)
if (atOutputFileMatcher.matches()) {
val outputFileName = atOutputFileMatcher.group(1)
if (occurrenceMap.containsKey(outputFileName)) {
throw AssertionError(
file.name + ": Expected occurrences for output file " + outputFileName + " were already provided")
throw AssertionError("${file.name}: Expected occurrences for output file $outputFileName were already provided")
}
currentOccurrenceInfos = ArrayList<OccurrenceInfo>()
occurrenceMap.put(outputFileName, currentOccurrenceInfos)
currentOccurrenceInfos = ArrayList()
occurrenceMap[outputFileName] = currentOccurrenceInfos
}
val expectedOccurrencesMatcher = EXPECTED_OCCURRENCES_PATTERN.matcher(line)
if (expectedOccurrencesMatcher.matches()) {
if (currentOccurrenceInfos == null) {
throw AssertionError(
file.name + ": Should specify output file with '// @<OUTPUT_FILE_NAME>:' before expectations")
throw AssertionError("${file.name}: Should specify output file with '// @<OUTPUT_FILE_NAME>:' before expectations")
}
val occurrenceInfo = parseOccurrenceInfo(expectedOccurrencesMatcher)
currentOccurrenceInfos.add(occurrenceInfo)
@@ -26,8 +26,7 @@ abstract class AbstractCompileKotlinAgainstInlineKotlinTest : AbstractCompileKot
val sourceFiles = factory1.inputFiles + factory2.inputFiles
InlineTestUtil.checkNoCallsToInline(allGeneratedFiles.filterClassFiles(), sourceFiles)
SMAPTestUtil.checkSMAP(files, allGeneratedFiles.filterClassFiles(), true)
}
catch (e: Throwable) {
} catch (e: Throwable) {
println("FIRST:\n\n${factory1.createText()}\n\nSECOND:\n\n${factory2.createText()}")
throw e
}
@@ -49,13 +49,13 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
}
@Override
protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) throws Exception {
protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) {
assert javaFilesDir == null : ".java files are not supported yet in this test";
doTwoFileTest(files);
}
@NotNull
protected Pair<ClassFileFactory, ClassFileFactory> doTwoFileTest(@NotNull List<TestFile> files) throws Exception {
protected Pair<ClassFileFactory, ClassFileFactory> doTwoFileTest(@NotNull List<TestFile> files) {
// Note that it may be beneficial to improve this test to handle many files, compiling them successively against all previous
assert files.size() == 2 || (files.size() == 3 && files.get(2).name.equals("CoroutineUtil.kt")) : "There should be exactly two files in this test";
TestFile fileA = files.get(0);
@@ -17,7 +17,7 @@ abstract class AbstractDumpDeclarationsTest : CodegenTestCase() {
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
val expectedResult = KotlinTestUtils.replaceExtension(wholeFile, "json")
dumpToFile = KotlinTestUtils.tmpDirForTest(this).resolve(name + ".json")
dumpToFile = KotlinTestUtils.tmpDirForTest(this).resolve("$name.json")
compile(files, null)
classFileFactory.generationState.destroy()
KotlinTestUtils.assertEqualsToFile(expectedResult, dumpToFile.readText()) {
@@ -34,10 +34,10 @@ abstract class AbstractLightAnalysisModeTest : CodegenTestCase() {
}
val fullTxt = compileWithFullAnalysis(files, javaFilesDir)
.replace("final enum class", "enum class")
.replace("final enum class", "enum class")
val liteTxt = compileWithLightAnalysis(wholeFile, files, javaFilesDir)
.replace("@synthetic.kotlin.jvm.GeneratedByJvmOverloads ", "")
.replace("@synthetic.kotlin.jvm.GeneratedByJvmOverloads ", "")
assertEquals(fullTxt, liteTxt)
}
@@ -53,7 +53,7 @@ abstract class AbstractLightAnalysisModeTest : CodegenTestCase() {
assert(!relativePath.startsWith(".."))
val configuration = createConfiguration(
configurationKind, getJdkKind(files), listOf(getAnnotationsJar()), javaFilesDir?.let(::listOf).orEmpty(), files
configurationKind, getJdkKind(files), listOf(getAnnotationsJar()), javaFilesDir?.let(::listOf).orEmpty(), files
)
val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
AnalysisHandlerExtension.registerExtension(environment.project, PartialAnalysisHandlerExtension())
@@ -65,14 +65,14 @@ abstract class AbstractLightAnalysisModeTest : CodegenTestCase() {
}
protected fun compileWithFullAnalysis(
files: List<TestFile>,
javaSourceDir: File?
files: List<TestFile>,
javaSourceDir: File?
): String {
compile(files, javaSourceDir)
classFileFactory.getClassFiles()
val classInternalNames = classFileFactory.generationState.bindingContext
.getSliceContents(CodegenBinding.ASM_TYPE).map { it.value.internalName to it.key }.toMap()
.getSliceContents(CodegenBinding.ASM_TYPE).map { it.value.internalName to it.key }.toMap()
return BytecodeListingTextCollectingVisitor.getText(classFileFactory, object : ListAnalysisFilter() {
override fun shouldWriteClass(access: Int, name: String): Boolean {
@@ -29,7 +29,7 @@ import kotlin.collections.ArrayList
abstract class AbstractLineNumberTest : CodegenTestCase() {
override fun doMultiFileTest(
wholeFile: File, files: MutableList<CodegenTestCase.TestFile>, javaFilesDir: File?
wholeFile: File, files: MutableList<TestFile>, javaFilesDir: File?
) {
val isCustomTest = wholeFile.parentFile.name.equals("custom", ignoreCase = true)
if (!isCustomTest) {
@@ -159,7 +159,7 @@ abstract class AbstractLineNumberTest : CodegenTestCase() {
private val TEST_LINE_NUMBER_PATTERN = Pattern.compile("^.*test.$LINE_NUMBER_FUN\\(\\).*$")
private fun createLineNumberDeclaration() =
CodegenTestCase.TestFile(
TestFile(
"$LINE_NUMBER_FUN.kt",
"package test;\n\npublic fun $LINE_NUMBER_FUN(): Int = 0\n"
)
@@ -21,13 +21,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.TestJdkKind;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.List;
import static org.jetbrains.kotlin.script.ScriptTestUtilKt.loadScriptingPlugin;
@@ -56,7 +56,6 @@ import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -82,7 +81,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
private static final String DEFAULT_TEST_FILE_NAME = "a_test";
private static final String DEFAULT_JVM_TARGET_FOR_TEST = "kotlin.test.default.jvm.target";
private static final String JAVA_COMPILATION_TARGET = "kotlin.test.java.compilation.target";
public static final String RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT = "kotlin.test.box.in.separate.process.port";
private static final String RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT = "kotlin.test.box.in.separate.process.port";
protected KotlinCoreEnvironment myEnvironment;
protected CodegenTestFiles myFiles;
@@ -90,7 +89,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
protected GeneratedClassLoader initializedClassLoader;
protected File javaClassesOutputDirectory = null;
protected List<File> additionalDependencies = null;
protected String coroutinesPackage;
protected String coroutinesPackage = "";
protected ConfigurationKind configurationKind = ConfigurationKind.JDK_ONLY;
private final String defaultJvmTarget = System.getProperty(DEFAULT_JVM_TARGET_FOR_TEST);
@@ -99,7 +98,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
protected final void createEnvironmentWithMockJdkAndIdeaAnnotations(
@NotNull ConfigurationKind configurationKind,
@Nullable File... javaSourceRoots
@NotNull File... javaSourceRoots
) {
createEnvironmentWithMockJdkAndIdeaAnnotations(configurationKind, Collections.emptyList(), TestJdkKind.MOCK_JDK, javaSourceRoots);
}
@@ -118,7 +117,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
@NotNull ConfigurationKind configurationKind,
@NotNull List<TestFile> testFilesWithConfigurationDirectives,
@NotNull TestJdkKind testJdkKind,
@Nullable File... javaSourceRoots
@NotNull File... javaSourceRoots
) {
if (myEnvironment != null) {
throw new IllegalStateException("must not set up myEnvironment twice");
@@ -161,7 +160,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
updateConfigurationByDirectivesInTestFiles(testFilesWithConfigurationDirectives, configuration, "");
}
protected static void updateConfigurationByDirectivesInTestFiles(
private static void updateConfigurationByDirectivesInTestFiles(
@NotNull List<TestFile> testFilesWithConfigurationDirectives,
@NotNull CompilerConfiguration configuration,
@NotNull String coroutinesPackage
@@ -306,12 +305,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
}
}
@Override
protected void setUp() throws Exception {
coroutinesPackage = "";
super.setUp();
}
@Override
protected void tearDown() throws Exception {
myFiles = null;
@@ -343,7 +336,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
assert myFiles == null : "Should not initialize myFiles twice";
myFiles = CodegenTestFiles.create(file.getName(), content, myEnvironment.getProject());
return content;
} catch (IOException e) {
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@@ -512,44 +506,46 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
}
@NotNull
protected ClassFileFactory generateClassesInFile(boolean reportProblems) {
if (classFileFactory == null) {
try {
GenerationState generationState = GenerationUtils.compileFiles(
myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(),
new NoScopeRecordCliBindingTrace()
);
classFileFactory = generationState.getFactory();
private ClassFileFactory generateClassesInFile(boolean reportProblems) {
if (classFileFactory != null) return classFileFactory;
if (verifyWithDex() && DxChecker.RUN_DX_CHECKER) {
DxChecker.check(classFileFactory);
}
try {
GenerationState generationState = GenerationUtils.compileFiles(
myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(),
new NoScopeRecordCliBindingTrace()
);
classFileFactory = generationState.getFactory();
if (verifyWithDex() && DxChecker.RUN_DX_CHECKER) {
DxChecker.check(classFileFactory);
}
catch (TestsCompiletimeError e) {
if (reportProblems) {
e.getOriginal().printStackTrace();
System.err.println("Generating instructions as text...");
try {
if (classFileFactory == null) {
System.err.println("Cannot generate text: exception was thrown during generation");
}
else {
System.err.println(classFileFactory.createText());
}
}
catch (TestsCompiletimeError e) {
if (reportProblems) {
e.getOriginal().printStackTrace();
System.err.println("Generating instructions as text...");
try {
if (classFileFactory == null) {
System.err.println("Cannot generate text: exception was thrown during generation");
}
catch (Throwable e1) {
System.err.println("Exception thrown while trying to generate text, the actual exception follows:");
e1.printStackTrace();
System.err.println("-----------------------------------------------------------------------------");
else {
System.err.println(classFileFactory.createText());
}
System.err.println("See exceptions above");
} else {
System.err.println("Compilation failure");
}
throw e;
} catch (Throwable e) {
throw new TestsCompilerError(e);
catch (Throwable e1) {
System.err.println("Exception thrown while trying to generate text, the actual exception follows:");
e1.printStackTrace();
System.err.println("-----------------------------------------------------------------------------");
}
System.err.println("See exceptions above");
}
else {
System.err.println("Compilation failure");
}
throw e;
}
catch (Throwable e) {
throw new TestsCompilerError(e);
}
return classFileFactory;
}
@@ -558,7 +554,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
return true;
}
protected static boolean verifyAllFilesWithAsm(ClassFileFactory factory, ClassLoader loader, boolean reportProblems) {
private static boolean verifyAllFilesWithAsm(ClassFileFactory factory, ClassLoader loader, boolean reportProblems) {
boolean noErrors = true;
for (OutputFile file : ClassFileUtilsKt.getClassFiles(factory)) {
noErrors &= verifyWithAsm(file, loader, reportProblems);
@@ -607,7 +603,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
Class<?> aClass = generateFacadeClass();
try {
return findTheOnlyMethod(aClass);
} catch (Error e) {
}
catch (Error e) {
System.out.println(generateToText());
throw e;
}
@@ -618,22 +615,11 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
return findDeclaredMethodByName(generateFacadeClass(), name);
}
@NotNull
@SuppressWarnings("unchecked")
public Class<? extends Annotation> loadAnnotationClassQuietly(@NotNull String fqName) {
try {
return (Class<? extends Annotation>) initializedClassLoader.loadClass(fqName);
}
catch (ClassNotFoundException e) {
throw ExceptionUtilsKt.rethrow(e);
}
}
protected void updateConfiguration(@NotNull CompilerConfiguration configuration) {
}
protected ClassBuilderFactory getClassBuilderFactory(){
protected ClassBuilderFactory getClassBuilderFactory() {
return ClassBuilderFactories.TEST;
}
@@ -641,7 +627,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
}
protected void setCustomDefaultJvmTarget(CompilerConfiguration configuration) {
private void setCustomDefaultJvmTarget(CompilerConfiguration configuration) {
JvmTarget target = configuration.get(JVMConfigurationKeys.JVM_TARGET);
if (target == null && defaultJvmTarget != null) {
JvmTarget value = JvmTarget.fromString(defaultJvmTarget);
@@ -663,8 +649,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
boolean reportProblems
) {
configurationKind = extractConfigurationKind(files);
boolean loadAndroidAnnotations = files.stream().anyMatch(it ->
InTextDirectivesUtils.isDirectiveDefined(it.content, "ANDROID_ANNOTATIONS")
boolean loadAndroidAnnotations = files.stream().anyMatch(
it -> InTextDirectivesUtils.isDirectiveDefined(it.content, "ANDROID_ANNOTATIONS")
);
List<String> javacOptions = extractJavacOptions(files);
@@ -744,7 +730,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
return javacOptions;
}
protected void updateJavacOptions(List<String> javacOptions) {
private void updateJavacOptions(List<String> javacOptions) {
if (javaCompilationTarget != null && !javacOptions.contains("-target")) {
javacOptions.add("-source");
javacOptions.add(javaCompilationTarget);
@@ -832,9 +818,9 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
}
protected void doMultiFileTest(
@NotNull File wholeFile,
@NotNull List<TestFile> files,
@Nullable File javaFilesDir
@NotNull File wholeFile,
@NotNull List<TestFile> files,
@Nullable File javaFilesDir
) throws Exception {
throw new UnsupportedOperationException("Multi-file test cases are not supported in this test");
}
@@ -843,7 +829,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
throws IOException, InvocationTargetException, IllegalAccessException {
Class<?> aClass = getGeneratedClass(classLoader, className);
Method method = getBoxMethodOrNull(aClass);
assertTrue("Can't find box method in " + aClass,method != null);
assertNotNull("Can't find box method in " + aClass, method);
callBoxMethodAndCheckResult(classLoader, aClass, method);
}
@@ -876,7 +862,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
List<URL> classPath = extractUrls(classLoader);
if (classLoader instanceof GeneratedClassLoader) {
File outDir = KotlinTestUtils.tmpDirForTest(this);
SimpleOutputFileCollection currentOutput = new SimpleOutputFileCollection(((GeneratedClassLoader) classLoader).getAllGeneratedFiles());
SimpleOutputFileCollection currentOutput =
new SimpleOutputFileCollection(((GeneratedClassLoader) classLoader).getAllGeneratedFiles());
writeAllTo(currentOutput, outDir);
classPath.add(0, outDir.toURI().toURL());
}
@@ -127,7 +127,8 @@ public class CodegenTestFiles {
String[] values = valueString.split(" ");
scriptParameterValues.add(values);
} else {
}
else {
scriptParameterValues.add(ArrayUtil.EMPTY_STRING_ARRAY);
}
}
@@ -39,15 +39,17 @@ import java.util.List;
import static org.junit.Assert.assertTrue;
public class CodegenTestUtil {
private CodegenTestUtil() {}
private CodegenTestUtil() {
}
@NotNull
public static ClassFileFactory generateFiles(@NotNull KotlinCoreEnvironment environment, @NotNull CodegenTestFiles files) {
return GenerationUtils.compileFiles(files.getPsiFiles(), environment).getFactory();
}
public static void assertThrows(@NotNull Method foo, @NotNull Class<? extends Throwable> exceptionClass,
@Nullable Object instance, @NotNull Object... args) throws IllegalAccessException {
public static void assertThrows(
@NotNull Method foo, @NotNull Class<? extends Throwable> exceptionClass, @Nullable Object instance, @NotNull Object... args
) throws IllegalAccessException {
boolean caught = false;
try {
foo.invoke(instance, args);
@@ -46,10 +46,6 @@ object GenerationUtils {
writeAllTo(output)
}
@JvmStatic
fun compileFile(ktFile: KtFile, environment: KotlinCoreEnvironment): ClassFileFactory =
compileFiles(listOf(ktFile), environment).factory
@JvmStatic
@JvmOverloads
fun compileFiles(
@@ -35,7 +35,7 @@ object InlineTestUtil {
fun checkNoCallsToInline(outputFiles: Iterable<OutputFile>, sourceFiles: List<KtFile>) {
val inlineInfo = obtainInlineInfo(outputFiles)
val inlineMethods = inlineInfo.inlineMethods
assert(!inlineMethods.isEmpty()) { "There are no inline methods" }
assert(inlineMethods.isNotEmpty()) { "There are no inline methods" }
val notInlinedCalls = checkInlineMethodNotInvoked(outputFiles, inlineMethods)
assert(notInlinedCalls.isEmpty()) { "All inline methods should be inlined but:\n" + notInlinedCalls.joinToString("\n") }
@@ -48,7 +48,7 @@ object InlineTestUtil {
val notInlinedParameters = checkParametersInlined(outputFiles, inlineInfo, sourceFiles)
assert(notInlinedParameters.isEmpty()) {
"All inline parameters should be inlined but:\n${notInlinedParameters.joinToString("\n")}\n" +
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive"
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive"
}
}
}
@@ -61,7 +61,9 @@ object InlineTestUtil {
val inlineFunctions = inlineFunctionsJvmNames(binaryClass.classHeader)
val classVisitor = object : ClassVisitorWithName() {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
override fun visitMethod(
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
): MethodVisitor? {
if (name + desc in inlineFunctions) {
inlineMethods.add(MethodInfo(className, name, desc))
}
@@ -70,7 +72,7 @@ object InlineTestUtil {
}
ClassReader(file.asByteArray()).accept(classVisitor, 0)
binaryClasses.put(classVisitor.className, binaryClass)
binaryClasses[classVisitor.className] = binaryClass
}
return InlineInfo(inlineMethods, binaryClasses)
@@ -84,9 +86,11 @@ object InlineTestUtil {
//if inline function creates anonymous object then do not try to check that all lambdas are inlined
val classVisitor = object : ClassVisitorWithName() {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
override fun visitMethod(
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
): MethodVisitor? {
if (name + desc in inlineFunctions) {
return object: MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
return object : MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
override fun onAnonymousConstructorCallOrSingletonAccess(owner: String) {
doLambdaInliningCheck = false
}
@@ -126,7 +130,9 @@ object InlineTestUtil {
return null
}
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
override fun visitMethod(
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
): MethodVisitor? {
if (skipMethodsOfThisClass) {
return null
}
@@ -160,11 +166,13 @@ object InlineTestUtil {
return notInlined
}
private fun checkParametersInlined(outputFiles: Iterable<OutputFile>, inlineInfo: InlineInfo, sourceFiles: List<KtFile>): ArrayList<NotInlinedParameter> {
private fun checkParametersInlined(
outputFiles: Iterable<OutputFile>, inlineInfo: InlineInfo, sourceFiles: List<KtFile>
): ArrayList<NotInlinedParameter> {
val skipMethods =
sourceFiles.flatMap {
InTextDirectivesUtils.findLinesWithPrefixesRemoved(it.text, "// SKIP_INLINE_CHECK_IN: ")
}.toSet()
sourceFiles.flatMap {
InTextDirectivesUtils.findLinesWithPrefixesRemoved(it.text, "// SKIP_INLINE_CHECK_IN: ")
}.toSet()
val inlinedMethods = inlineInfo.inlineMethods
val notInlinedParameters = ArrayList<NotInlinedParameter>()
@@ -172,7 +180,9 @@ object InlineTestUtil {
if (!isClassOrPackagePartKind(loadBinaryClass(file))) continue
ClassReader(file.asByteArray()).accept(object : ClassVisitorWithName() {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
override fun visitMethod(
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
): MethodVisitor? {
val declaration = MethodInfo(className, name, desc)
//do not check anonymous object creation in inline functions and in package facades
@@ -184,7 +194,7 @@ object InlineTestUtil {
return null
}
return object: MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
return object : MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
override fun onAnonymousConstructorCallOrSingletonAccess(owner: String) {
val fromCall = MethodInfo(className, this.name, this.desc)
notInlinedParameters.add(NotInlinedParameter(owner, fromCall))
@@ -201,29 +211,27 @@ object InlineTestUtil {
if (classInternalName.startsWith("kotlin/jvm/internal/"))
return true
return isClassOrPackagePartKind(inlineInfo.binaryClasses[classInternalName]!!)
return isClassOrPackagePartKind(inlineInfo.binaryClasses.getValue(classInternalName))
}
private fun isClassOrPackagePartKind(klass: KotlinJvmBinaryClass): Boolean {
return klass.classHeader.kind == KotlinClassHeader.Kind.CLASS && !klass.classId.isLocal
|| klass.classHeader.kind == KotlinClassHeader.Kind.FILE_FACADE /*single file facade equals to package part*/
|| klass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
|| klass.classHeader.kind == KotlinClassHeader.Kind.FILE_FACADE /*single file facade equals to package part*/
|| klass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
}
private fun loadBinaryClass(file: OutputFile): KotlinJvmBinaryClass {
val klass = FileBasedKotlinClass.create(file.asByteArray()) {
className, classVersion, classHeader, innerClasses ->
private fun loadBinaryClass(file: OutputFile): KotlinJvmBinaryClass =
FileBasedKotlinClass.create<FileBasedKotlinClass>(file.asByteArray()) { className, classVersion, classHeader, innerClasses ->
object : FileBasedKotlinClass(className, classVersion, classHeader, innerClasses) {
override val location: String
get() = throw UnsupportedOperationException()
override fun getFileContents(): ByteArray = throw UnsupportedOperationException()
override fun hashCode(): Int = throw UnsupportedOperationException()
override fun equals(other: Any?): Boolean = throw UnsupportedOperationException()
override fun toString(): String = throw UnsupportedOperationException()
}
}!!
return klass
}
private class InlineInfo(val inlineMethods: Set<MethodInfo>, val binaryClasses: Map<String, KotlinJvmBinaryClass>)
@@ -242,9 +250,11 @@ object InlineTestUtil {
}
}
private abstract class MethodNodeWithAnonymousObjectCheck(val inlineInfo: InlineInfo, access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?) : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) {
private abstract class MethodNodeWithAnonymousObjectCheck(
val inlineInfo: InlineInfo, access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
) : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) {
private fun isInlineParameterLikeOwner(owner: String) =
"$" in owner && !isTopLevelOrInnerOrPackageClass(owner, inlineInfo)
"$" in owner && !isTopLevelOrInnerOrPackageClass(owner, inlineInfo)
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
if ("<init>" == name && isInlineParameterLikeOwner(owner)) {
@@ -41,7 +41,7 @@ object SMAPTestUtil {
}
}, 0)
SMAPAndFile.SMAPAndFile(debugInfo, outputFile.sourceFiles.single(), outputFile.relativePath)
SMAPAndFile(debugInfo, outputFile.sourceFiles.single(), outputFile.relativePath)
}
}
@@ -61,7 +61,10 @@ object SMAPTestUtil {
}
private fun checkExtension(file: CodegenTestCase.TestFile, separateCompilation: Boolean) =
file.name.run { endsWith(".smap") || if (separateCompilation) endsWith(".smap-separate-compilation") else endsWith(".smap-nonseparate-compilation") }
file.name.run {
endsWith(".smap") ||
if (separateCompilation) endsWith(".smap-separate-compilation") else endsWith(".smap-nonseparate-compilation")
}
fun checkSMAP(inputFiles: List<CodegenTestCase.TestFile>, outputFiles: Iterable<OutputFile>, separateCompilation: Boolean) {
if (!GENERATE_SMAP) return
@@ -71,15 +74,15 @@ object SMAPTestUtil {
val compiledData = compiledSmaps.groupBy {
it.sourceFile
}.map {
val smap = it.value.sortedByDescending { it.outputFile }.mapNotNull { it.smap }.joinToString("\n")
val smap = it.value.sortedByDescending(SMAPAndFile::outputFile).mapNotNull(SMAPAndFile::smap).joinToString("\n")
SMAPAndFile(if (smap.isNotEmpty()) smap else null, it.key, "NOT_SORTED")
}.associateBy { it.sourceFile }
for (source in sourceData) {
val ktFileName = "/" + source.sourceFile.
replace(".smap-nonseparate-compilation", ".kt").
replace(".smap-separate-compilation", ".kt").
replace(".smap", ".kt")
val ktFileName = "/" + source.sourceFile
.replace(".smap-nonseparate-compilation", ".kt")
.replace(".smap-separate-compilation", ".kt")
.replace(".smap", ".kt")
val data = compiledData[ktFileName]
Assert.assertEquals("Smap data differs for $ktFileName", normalize(source.smap), normalize(data?.smap))
}
@@ -90,37 +93,32 @@ object SMAPTestUtil {
private fun checkNoConflictMappings(compiledSmap: List<SMAPAndFile>?) {
if (compiledSmap == null) return
compiledSmap.mapNotNull { it.smap }.forEach {
val smap = SMAPParser.parse(it)
val conflictingLines = smap.fileMappings.flatMap {
fileMapping ->
fileMapping.lineMappings.flatMap {
lineMapping: RangeMapping ->
compiledSmap.mapNotNull(SMAPAndFile::smap).forEach { smapString ->
val smap = SMAPParser.parse(smapString)
val conflictingLines = smap.fileMappings.flatMap { fileMapping ->
fileMapping.lineMappings.flatMap { lineMapping: RangeMapping ->
lineMapping.toRange.keysToMap { lineMapping }.entries
}
}.groupBy { it.key }.entries.filter { it.value.size != 1 }
Assert.assertTrue(
conflictingLines.joinToString(separator = "\n") {
"Conflicting mapping for line ${it.key} in ${it.value.joinToString { it.toString() }} "
},
conflictingLines.isEmpty()
conflictingLines.joinToString(separator = "\n") {
"Conflicting mapping for line ${it.key} in ${it.value.joinToString(transform = Any::toString)}"
},
conflictingLines.isEmpty()
)
}
}
private fun normalize(text: String?) =
text?.let { StringUtil.convertLineSeparators(it.trim()) }
text?.let { StringUtil.convertLineSeparators(it.trim()) }
private class SMAPAndFile(val smap: String?, val sourceFile: String, val outputFile: String) {
companion object {
fun SMAPAndFile(smap: String?, sourceFile: File, outputFile: String) =
SMAPAndFile(smap, getPath(sourceFile), outputFile)
constructor(smap: String?, sourceFile: File, outputFile: String) : this(smap, getPath(sourceFile), outputFile)
fun getPath(file: File): String {
return getPath(file.canonicalPath)
}
companion object {
fun getPath(file: File): String =
getPath(file.canonicalPath)
fun getPath(canonicalPath: String): String {
//There are some problems with disk name on windows cause LightVirtualFile return it without disk name
@@ -20,6 +20,6 @@ import org.jetbrains.kotlin.codegen.AbstractBlackBoxCodegenTest
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
abstract class AbstractIrBlackBoxInlineCodegenTest: AbstractBlackBoxCodegenTest() {
abstract class AbstractIrBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest() {
override fun updateConfiguration(configuration: CompilerConfiguration) = configuration.put(JVMConfigurationKeys.IR, true)
}
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.codegen
import junit.framework.TestCase
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.utils.rethrow
import java.lang.reflect.Method
import java.net.URL
import java.net.URLClassLoader
@@ -28,17 +25,13 @@ fun clearReflectionCache(classLoader: ClassLoader) {
val klass = classLoader.loadClass(JvmAbi.REFLECTION_FACTORY_IMPL.asSingleFqName().asString())
val method = klass.getDeclaredMethod("clearCaches")
method.invoke(null)
}
catch (e: ClassNotFoundException) {
} catch (e: ClassNotFoundException) {
// This is OK for a test without kotlin-reflect in the dependencies
}
}
fun ClassLoader?.extractUrls(): List<URL> {
return (this as? URLClassLoader)?.let {
it.urLs.toList() + it.parent.extractUrls()
} ?: emptyList()
}
}
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.script.loadScriptingPlugin
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContextOrStlib
import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.InTextDirectivesUtils
@@ -25,6 +24,7 @@ import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.implicitReceivers
import kotlin.script.experimental.api.providedProperties
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
private lateinit var scriptDefinitions: List<String>
@@ -56,14 +56,14 @@ abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
scriptDefinitions = InTextDirectivesUtils.findListWithPrefixes(content, "KOTLIN_SCRIPT_DEFINITION:")
if (scriptDefinitions.isNotEmpty()) {
additionalDependencies =
scriptCompilationClasspathFromContextOrStlib("tests-common", "kotlin-stdlib") +
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
with(PathUtil.kotlinPathsForDistDirectory) {
arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
).mapNotNull { File(libPath, it).takeIf { it.exists() } }
}
scriptCompilationClasspathFromContextOrStdlib("tests-common", "kotlin-stdlib") +
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
with(PathUtil.kotlinPathsForDistDirectory) {
arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
).mapNotNull { File(libPath, it).takeIf(File::exists) }
}
}
createEnvironmentWithMockJdkAndIdeaAnnotations(configurationKind, files, TestJdkKind.FULL_JDK)
@@ -71,7 +71,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(getDeprecatedAnnotationFromList(srcClassMethod.getParameterAnnotations()[0]));
}
public void testAnnotationForParamInInstanceFunction() throws NoSuchFieldException, NoSuchMethodException {
public void testAnnotationForParamInInstanceFunction() throws NoSuchMethodException {
loadText("class A() { fun x(@[java.lang.Deprecated] i: Int) {}}");
Class<?> aClass = generateClass("A");
Method x = aClass.getMethod("x", int.class);
@@ -81,7 +81,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testAnnotationForParamInInstanceExtensionFunction() throws NoSuchFieldException, NoSuchMethodException {
public void testAnnotationForParamInInstanceExtensionFunction() throws NoSuchMethodException {
loadText("class A() { fun String.x(@[java.lang.Deprecated] i: Int) {}}");
Class<?> aClass = generateClass("A");
Method x = aClass.getMethod("x", String.class, int.class);
@@ -91,7 +91,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testParamInConstructor() throws NoSuchFieldException, NoSuchMethodException {
public void testParamInConstructor() throws NoSuchMethodException {
loadText("class A (@[java.lang.Deprecated] x: Int) {}");
Class<?> aClass = generateClass("A");
Constructor constructor = aClass.getDeclaredConstructor(int.class);
@@ -101,7 +101,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testParamInEnumConstructor() throws NoSuchFieldException, NoSuchMethodException {
public void testParamInEnumConstructor() throws NoSuchMethodException {
loadText("enum class E(@[java.lang.Deprecated] p: String)");
Class<?> klass = generateClass("E");
Constructor constructor = klass.getDeclaredConstructor(String.class, int.class, String.class);
@@ -111,7 +111,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testParamInInnerConstructor() throws NoSuchFieldException, NoSuchMethodException {
public void testParamInInnerConstructor() throws NoSuchMethodException {
loadText("class Outer { inner class Inner(@[java.lang.Deprecated] x: Int) }");
Class<?> outer = generateClass("Outer");
Class<?> inner = outer.getDeclaredClasses()[0];
@@ -134,7 +134,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
}
public void testAnnotationWithParamForParamInFunction() throws Exception {
loadText("import java.lang.annotation.*\n" +
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
@@ -162,7 +162,7 @@ public class AnnotationGenTest extends CodegenTestCase {
}
}
return null;
}
}
public void testConstructor() throws NoSuchFieldException, NoSuchMethodException {
loadText("class A @[java.lang.Deprecated] constructor() {}");
@@ -196,14 +196,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertEquals("java.lang.annotation.Annotation", interfaces[0].getName());
}
public void testAnnotationClassWithStringProperty()
throws
NoSuchFieldException,
NoSuchMethodException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
InvocationTargetException {
public void testAnnotationClassWithStringProperty() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
loadText("import java.lang.annotation.*\n" +
"" +
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
@@ -231,13 +224,7 @@ public class AnnotationGenTest extends CodegenTestCase {
}
public void testAnnotationClassWithAnnotationProperty()
throws
NoSuchFieldException,
NoSuchMethodException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
InvocationTargetException {
throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
loadText("import java.lang.annotation.*\n" +
"" +
"annotation class C(val c: String)\n" +
@@ -270,13 +257,7 @@ public class AnnotationGenTest extends CodegenTestCase {
}
public void testAnnotationClassWithStringArrayProperty()
throws
NoSuchFieldException,
NoSuchMethodException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
InvocationTargetException {
throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
loadText("import java.lang.annotation.*\n" +
"" +
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: Array<String>)\n" +
@@ -301,18 +282,11 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(bClassAnnotation);
Object invoke = methods[0].invoke(bClassAnnotation);
assertEquals("239", ((String[])invoke)[0]);
assertEquals("932", ((String[])invoke)[1]);
assertEquals("239", ((String[]) invoke)[0]);
assertEquals("932", ((String[]) invoke)[1]);
}
public void testAnnotationClassWithIntArrayProperty()
throws
NoSuchFieldException,
NoSuchMethodException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
InvocationTargetException {
public void testAnnotationClassWithIntArrayProperty() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
loadText("import java.lang.annotation.*\n" +
"" +
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: IntArray)\n" +
@@ -337,18 +311,11 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(bClassAnnotation);
Object invoke = methods[0].invoke(bClassAnnotation);
assertEquals(239, ((int[])invoke)[0]);
assertEquals(932, ((int[])invoke)[1]);
assertEquals(239, ((int[]) invoke)[0]);
assertEquals(932, ((int[]) invoke)[1]);
}
public void testAnnotationClassWithEnumArrayProperty()
throws
NoSuchFieldException,
NoSuchMethodException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
InvocationTargetException {
public void testAnnotationClassWithEnumArrayProperty() {
loadText("import java.lang.annotation.*\n" +
"" +
"@java.lang.annotation.Target(ElementType.TYPE, ElementType.METHOD) annotation class A");
@@ -363,13 +330,7 @@ public class AnnotationGenTest extends CodegenTestCase {
}
public void testAnnotationClassWithAnnotationArrayProperty()
throws
NoSuchFieldException,
NoSuchMethodException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
InvocationTargetException {
throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
loadText("import java.lang.annotation.*\n" +
"import java.lang.annotation.Retention\n" +
"" +
@@ -388,7 +349,7 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(bClassAnnotation);
Object invoke = methods[0].invoke(bClassAnnotation);
Retention[] invoke1 = (Retention[])invoke;
Retention[] invoke1 = (Retention[]) invoke;
assertEquals(2, invoke1.length);
assertEquals(invoke1[0].value(), RetentionPolicy.RUNTIME);
assertEquals(invoke1[1].value(), RetentionPolicy.SOURCE);
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.backend.common.bridges.Bridge
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
import org.jetbrains.kotlin.backend.common.bridges.generateBridges
import org.jetbrains.kotlin.utils.DFS
import java.util.*
import kotlin.test.assertEquals
class BridgeTest : TestCase() {
@@ -91,14 +90,14 @@ class BridgeTest : TestCase() {
return result
}
val vertices = edges.flatMapTo(HashSet<Fun>()) { pair -> listOf(pair.first, pair.second) }
val vertices = edges.flatMapTo(HashSet()) { pair -> listOf(pair.first, pair.second) }
for (vertex in vertices) {
val directConcreteSuperFunctions = vertex.overriddenFunctions.filter { !it.isAbstract }
assert(directConcreteSuperFunctions.size <= 1) {
"Incorrect test data: function $vertex has more than one direct concrete super-function: ${vertex.overriddenFunctions}\n" +
"This is not allowed because only classes can contain implementations (concrete functions), and having more than one " +
"concrete super-function means having more than one superclass, which is prohibited in Kotlin"
"This is not allowed because only classes can contain implementations (concrete functions), and having more than " +
"one concrete super-function means having more than one superclass, which is prohibited in Kotlin"
}
if (vertex.isDeclaration) continue
@@ -120,7 +119,7 @@ class BridgeTest : TestCase() {
}
assert(concreteDeclarations.size == 1) {
"Incorrect test data: concrete fake override vertex $vertex has more than one concrete super-declaration: " +
"$concreteDeclarations"
"$concreteDeclarations"
}
}
}
@@ -130,7 +129,7 @@ class BridgeTest : TestCase() {
val actualBridges = generateBridges(function, ::Meth)
assert(actualBridges.firstOrNull { it.from == it.to } == null) {
"A bridge invoking itself was generated, which makes no sense, since it will result in StackOverflowError" +
" once called: $actualBridges"
" once called: $actualBridges"
}
assertEquals(expectedBridges, actualBridges, "Expected and actual bridge sets differ for function $function")
}
@@ -537,9 +536,11 @@ class BridgeTest : TestCase() {
val h = v("-D8")
val i = v("-D9")
val j = v("+F0")
graph(d to a, d to b, d to c,
g to d, g to e, g to f,
j to g, j to h, j to i)
graph(
d to a, d to b, d to c,
g to d, g to e, g to f,
j to g, j to h, j to i
)
doTest(d, setOf(bridge(b, a), bridge(c, a)))
doTest(g, setOf(bridge(e, a), bridge(f, a)))
doTest(j, setOf(bridge(h, a), bridge(i, a)))
@@ -68,7 +68,7 @@ public class ControlStructuresTest extends CodegenTestCase {
public void testCompareToNull() throws Exception {
loadText("fun foo(a: String?, b: String?): Boolean = a == null && b !== null && null == a && null !== b");
String text = generateToText();
assertTrue(!text.contains("java/lang/Object.equals"));
assertFalse(text.contains("java/lang/Object.equals"));
Method main = generateFunction();
assertEquals(true, main.invoke(null, null, "lala"));
assertEquals(false, main.invoke(null, null, null));
@@ -22,29 +22,35 @@ import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
class CustomBytecodeTextTest : AbstractBytecodeTextTest() {
fun testEnumMapping() {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL)
myFiles = CodegenTestFiles.create("whenMappingOrder.kt", """
enum class MyEnum {
ENTRY1, ENTRY2, ENTRY3, ENTRY4
}
fun f(e: MyEnum) {
when (e) {
MyEnum.ENTRY4 -> {}
MyEnum.ENTRY3 -> {}
MyEnum.ENTRY2 -> {}
MyEnum.ENTRY1 -> {}
myFiles = CodegenTestFiles.create(
"whenMappingOrder.kt",
"""
enum class MyEnum {
ENTRY1, ENTRY2, ENTRY3, ENTRY4
}
}
""", myEnvironment.project)
fun f(e: MyEnum) {
when (e) {
MyEnum.ENTRY4 -> {}
MyEnum.ENTRY3 -> {}
MyEnum.ENTRY2 -> {}
MyEnum.ENTRY1 -> {}
}
}
""",
myEnvironment.project
)
val text = generateToText()
val getstatics = text.lines().filter { it.contains("GETSTATIC MyEnum.") }.map { it.trim() }
KtUsefulTestCase.assertOrderedEquals("actual bytecode:\n" + text, listOf(
KtUsefulTestCase.assertOrderedEquals(
"actual bytecode:\n$text", listOf(
"GETSTATIC MyEnum.${'$'}VALUES : [LMyEnum;",
"GETSTATIC MyEnum.ENTRY4 : LMyEnum;",
"GETSTATIC MyEnum.ENTRY3 : LMyEnum;",
"GETSTATIC MyEnum.ENTRY2 : LMyEnum;",
"GETSTATIC MyEnum.ENTRY1 : LMyEnum;"
), getstatics)
), getstatics
)
}
}
}
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.script.loadScriptingPlugin
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContextOrStlib
import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.TestJdkKind
@@ -19,9 +18,10 @@ import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_COMPILER_IMPL_JAR
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_JVM_JAR
import java.io.File
import java.lang.reflect.Constructor
import kotlin.reflect.KClass
import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
class CustomScriptCodegenTest : CodegenTestCase() {
@@ -46,14 +46,14 @@ class CustomScriptCodegenTest : CodegenTestCase() {
}
additionalDependencies =
scriptCompilationClasspathFromContextOrStlib("tests-common", "kotlin-stdlib") +
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
with(PathUtil.kotlinPathsForDistDirectory) {
arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
).mapNotNull { File(libPath, it).also { assertTrue("$it not found", it.exists()) } }
}
scriptCompilationClasspathFromContextOrStdlib("tests-common", "kotlin-stdlib") +
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
with(PathUtil.kotlinPathsForDistDirectory) {
arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
).mapNotNull { jarName -> File(libPath, jarName).also { assertTrue("$it not found", it.exists()) } }
}
val configuration = createConfiguration(
ConfigurationKind.ALL,
@@ -75,7 +75,6 @@ class CustomScriptCodegenTest : CodegenTestCase() {
testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES
)
}
}
@Suppress("UNCHECKED_CAST")
@@ -83,7 +82,7 @@ private fun Class<*>.safeGetAnnotation(ann: KClass<out Annotation>): Annotation?
getAnnotation(classLoader.loadClass(ann.qualifiedName) as Class<Annotation>)
@Suppress("UNCHECKED_CAST")
private fun java.lang.reflect.Constructor<*>.safeGetAnnotation(ann: KClass<out Annotation>): Annotation? =
private fun Constructor<*>.safeGetAnnotation(ann: KClass<out Annotation>): Annotation? =
getAnnotation(this.declaringClass.classLoader.loadClass(ann.qualifiedName) as Class<Annotation>)
@Target(AnnotationTarget.CLASS)
@@ -96,6 +95,5 @@ annotation class MyScriptConstructorAnnotation
@Suppress("unused")
@KotlinScript
@MyScriptClassAnnotation()
@MyScriptClassAnnotation
abstract class TestScriptWithAnnotatedBaseClass @MyScriptConstructorAnnotation constructor()
@@ -55,7 +55,8 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, disableCallAssertions);
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, disableParamAssertions);
myEnvironment = KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
myEnvironment =
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
myFiles = null;
}
@@ -87,7 +88,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
doTestCallAssertions(true);
}
public void testNoAssertionsForKotlinFromSource() throws Exception {
public void testNoAssertionsForKotlinFromSource() {
setUpEnvironment(false, true);
loadFiles(getPrefix() + "/noAssertionsForKotlin.kt", getPrefix() + "/noAssertionsForKotlinMain.kt");
@@ -95,7 +96,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
assertNoIntrinsicsMethodIsCalledInMyClasses(true);
}
public void testNoAssertionsForKotlinFromBinary() throws Exception {
public void testNoAssertionsForKotlinFromBinary() {
setUpEnvironment(false, true);
loadSource("noAssertionsForKotlin.kt");
OutputFileCollection outputFiles = generateClassesInFile();
@@ -116,7 +117,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
generateFunction().invoke(null);
}
public void testDoNotGenerateParamAssertions() throws Exception {
public void testDoNotGenerateParamAssertions() {
setUpEnvironment(true, true);
loadSource("doNotGenerateParamAssertions.kt");
@@ -124,7 +125,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
assertNoIntrinsicsMethodIsCalled("A", true);
}
public void testNoParamAssertionForPrivateMethod() throws Exception {
public void testNoParamAssertionForPrivateMethod() {
setUpEnvironment(true, false);
loadSource("noAssertionForPrivateMethod.kt");
@@ -116,8 +116,6 @@ public class InnerClassInfoGenTest extends CodegenTestCase {
extractAndCompareInnerClasses("A$bar$1", bar);
}
private void checkAccess(@NotNull String outerName, @NotNull String innerName, int accessFlags) {
String name = outerName + "$" + innerName;
InnerClassAttribute attribute = CollectionsKt.single(extractInnerClasses(name), value -> innerName.equals(value.innerName));
@@ -18,7 +18,7 @@ import java.util.concurrent.TimeUnit
class Java9CodegenTest : AbstractBlackBoxCodegenTest() {
override fun setUp() {
super.setUp()
val fileName = KotlinTestUtils.getTestDataPathBase() + "/codegen/" + getPrefix() + "/" + getTestName(true) + ".kt"
val fileName = KotlinTestUtils.getTestDataPathBase() + "/codegen/" + prefix + "/" + getTestName(true) + ".kt"
val testFile = TestFile(fileName, File(fileName).readText())
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.NO_KOTLIN_REFLECT, listOf(testFile), TestJdkKind.FULL_JDK_9)
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import java.lang.annotation.Annotation;
import java.util.Collection;
@@ -32,7 +33,7 @@ import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_FQ_NAME
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_VERSION_FIELD_NAME;
public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
public static final FqName PACKAGE_NAME = new FqName("test");
private static final FqName PACKAGE_NAME = new FqName("test");
@Override
protected void setUp() throws Exception {
@@ -124,7 +125,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
List<OutputFile> output = generateClassesInFile().asList();
Collection<OutputFile> files = CollectionsKt.filter(output, file -> file.getRelativePath().contains(classFilePart));
assertFalse("No files with \"" + classFilePart + "\" in the name are found: " + output, files.isEmpty());
assertTrue("Exactly one file with \"" + classFilePart + "\" in the name should be found: " + files, files.size() == 1);
assertEquals("Exactly one file with \"" + classFilePart + "\" in the name should be found: " + files, 1, files.size());
String path = files.iterator().next().getRelativePath();
String fqName = path.substring(0, path.length() - ".class".length()).replace('/', '.');
@@ -144,4 +145,15 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
assertTrue("Annotation " + annotationFqName + " is written with an unsupported format",
new JvmMetadataVersion(version).isCompatible());
}
@NotNull
@SuppressWarnings("unchecked")
private Class<? extends Annotation> loadAnnotationClassQuietly(@NotNull String fqName) {
try {
return (Class<? extends Annotation>) initializedClassLoader.loadClass(fqName);
}
catch (ClassNotFoundException e) {
throw ExceptionUtilsKt.rethrow(e);
}
}
}
@@ -24,111 +24,126 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.*
class MethodOrderTest: CodegenTestCase() {
class MethodOrderTest : CodegenTestCase() {
fun testDelegatedMethod() {
doTest(
"""
interface Trait {
fun f0()
fun f4()
fun f3()
fun f2()
fun f1()
fun f5()
}
"""
interface Trait {
fun f0()
fun f4()
fun f3()
fun f2()
fun f1()
fun f5()
}
val delegate: Trait = throw Error()
val delegate: Trait = throw Error()
val obj = object : Trait by delegate {
override fun f3() { }
}
""",
"\$obj$1",
listOf("f3()V", "<init>()V", "f0()V", "f1()V", "f2()V", "f4()V", "f5()V")
val obj = object : Trait by delegate {
override fun f3() { }
}
""",
"\$obj$1",
listOf("f3()V", "<init>()V", "f0()V", "f1()V", "f2()V", "f4()V", "f5()V")
)
}
fun testLambdaClosureOrdering() {
doTest(
"""
class Klass {
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
{ a + b + c + d + e + this@f + this@Klass }()
}
"""
class Klass {
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
{ a + b + c + d + e + this@f + this@Klass }()
}
""",
"\$f$1",
listOf("invoke()Ljava/lang/Object;", "invoke()Ljava/lang/String;", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
}
""",
"\$f$1",
listOf(
"invoke()Ljava/lang/Object;",
"invoke()Ljava/lang/String;",
"<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V"
)
)
}
fun testAnonymousObjectClosureOrdering() {
doTest(
"""
class Klass {
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
object : Runnable {
override fun run() {
a + b + c + d + e + this@f + this@Klass
}
}.run()
}
"""
class Klass {
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
object : Runnable {
override fun run() {
a + b + c + d + e + this@f + this@Klass
}
}.run()
}
""",
"\$f$1",
listOf("run()V", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
}
""",
"\$f$1",
listOf("run()V", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
)
}
fun testMemberAccessor() {
doTest(
"""
class Outer(private val a: Int, private var b: String) {
private fun c() {
}
"""
class Outer(private val a: Int, private var b: String) {
private fun c() {
}
inner class Inner() {
init {
b = b + a
c()
}
inner class Inner() {
init {
b = b + a
c()
}
}
""",
"Outer",
listOf(
"c()V",
"<init>(ILjava/lang/String;)V",
"access\$getB\$p(LOuter;)Ljava/lang/String;",
"access\$setB\$p(LOuter;Ljava/lang/String;)V",
"access\$getA\$p(LOuter;)I",
"access\$c(LOuter;)V"
)
}
""",
"Outer",
listOf(
"c()V",
"<init>(ILjava/lang/String;)V",
"access\$getB\$p(LOuter;)Ljava/lang/String;",
"access\$setB\$p(LOuter;Ljava/lang/String;)V",
"access\$getA\$p(LOuter;)I",
"access\$c(LOuter;)V"
)
)
}
fun testDeterministicDefaultMethodImplOrder() {
doTest(
"""
interface Base<K, V> {
fun getSize(): Int = 5
fun size(): Int = getSize()
fun getKeys(): Int = 4
fun keySet() = getKeys()
fun getEntries(): Int = 3
fun entrySet() = getEntries()
fun getValues(): Int = 2
fun values() = getValues()
"""
interface Base<K, V> {
fun getSize(): Int = 5
fun size(): Int = getSize()
fun getKeys(): Int = 4
fun keySet() = getKeys()
fun getEntries(): Int = 3
fun entrySet() = getEntries()
fun getValues(): Int = 2
fun values() = getValues()
fun removeEldestEntry(eldest: Any?): Boolean
}
fun removeEldestEntry(eldest: Any?): Boolean
}
class MinMap<K, V> : Base<K, V> {
override fun removeEldestEntry(eldest: Any?) = true
}
""",
"MinMap",
listOf("removeEldestEntry(Ljava/lang/Object;)Z", "<init>()V", "getSize()I", "size()I", "getKeys()I", "keySet()I", "getEntries()I", "entrySet()I", "getValues()I", "values()I")
class MinMap<K, V> : Base<K, V> {
override fun removeEldestEntry(eldest: Any?) = true
}
""",
"MinMap",
listOf(
"removeEldestEntry(Ljava/lang/Object;)Z",
"<init>()V",
"getSize()I",
"size()I",
"getKeys()I",
"keySet()I",
"getEntries()I",
"entrySet()I",
"getValues()I",
"values()I"
)
)
}
@@ -169,7 +184,13 @@ class MethodOrderTest: CodegenTestCase() {
val methodNames = ArrayList<String>()
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
override fun visitMethod(
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? {
methodNames.add(name + desc)
return null
}
@@ -41,110 +41,110 @@ public class OuterClassGenTest extends CodegenTestCase {
return "outerClassInfo";
}
public void testClass() throws Exception {
public void testClass() {
doTest("foo.Foo", "outerClassInfo");
}
public void testClassObject() throws Exception {
public void testClassObject() {
doTest("foo.Foo$" + SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString(), "outerClassInfo");
}
public void testInnerClass() throws Exception {
public void testInnerClass() {
doTest("foo.Foo$InnerClass", "outerClassInfo");
}
public void testInnerObject() throws Exception {
public void testInnerObject() {
doTest("foo.Foo$InnerObject", "outerClassInfo");
}
public void testLocalClassInFunction() throws Exception {
public void testLocalClassInFunction() {
doTest("foo.Foo$foo$LocalClass", "foo.Foo$1LocalClass", "outerClassInfo");
}
public void testLocalObjectInFunction() throws Exception {
public void testLocalObjectInFunction() {
doTest("foo.Foo$foo$LocalObject", "foo.Foo$1LocalObject", "outerClassInfo");
}
public void testObjectInPackageClass() throws Exception {
public void testObjectInPackageClass() {
doTest("foo.PackageInnerObject", "outerClassInfo");
}
public void testLambdaInNoInlineFun() throws Exception {
public void testLambdaInNoInlineFun() {
doTest("foo.Foo$foo$1", "foo.Foo$1Lambda", "outerClassInfo");
}
public void testLambdaInConstructor() throws Exception {
public void testLambdaInConstructor() {
doTest("foo.Foo$s$1", "foo.Foo$1LambdaInConstructor", "outerClassInfo");
}
public void testObjectLiteralInPackageClass() throws Exception {
public void testObjectLiteralInPackageClass() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/OuterClassInfo", null, null);
doCustomTest("foo/OuterClassInfoKt\\$packageObjectLiteral\\$1", expectedInfo, "outerClassInfo");
}
public void testLocalClassInTopLevelFunction() throws Exception {
public void testLocalClassInTopLevelFunction() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/OuterClassInfo", "packageMethod", "(Lfoo/Foo;)V");
doCustomTest("foo/OuterClassInfoKt\\$packageMethod\\$PackageLocalClass", expectedInfo, "outerClassInfo");
}
public void testLocalObjectInTopLevelFunction() throws Exception {
public void testLocalObjectInTopLevelFunction() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/OuterClassInfo", "packageMethod", "(Lfoo/Foo;)V");
doCustomTest("foo/OuterClassInfoKt\\$packageMethod\\$PackageLocalObject", expectedInfo, "outerClassInfo");
}
public void testLocalObjectInInlineFunction() throws Exception {
public void testLocalObjectInInlineFunction() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Foo", "inlineFoo", "(Lkotlin/jvm/functions/Function0;)V");
doCustomTest("foo/Foo\\$inlineFoo\\$localObject\\$1", expectedInfo, "inlineObject");
}
public void testLocalObjectInlined() throws Exception {
public void testLocalObjectInlined() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "callToInline", "()V");
doCustomTest("foo/Bar\\$callToInline\\$\\$inlined\\$inlineFoo\\$1", expectedInfo, "inlineObject");
}
public void testLocalObjectInInlineLambda() throws Exception {
public void testLocalObjectInInlineLambda() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "objectInInlineLambda", "()V");
doCustomTest("foo/Bar\\$objectInInlineLambda\\$\\$inlined\\$simpleFoo\\$lambda\\$1", expectedInfo, "inlineObject");
}
public void testLocalObjectInLambdaInlinedIntoObject() throws Exception {
public void testLocalObjectInLambdaInlinedIntoObject() {
OuterClassInfo intoObjectInfo = new OuterClassInfo("foo/Bar", "objectInLambdaInlinedIntoObject", "()V");
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineObject");
}
public void testLocalObjectInLambdaInlinedIntoObject2() throws Exception {
public void testLocalObjectInLambdaInlinedIntoObject2() {
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "run", "()V");
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1\\$lambda\\$1",
objectInLambda, "inlineObject");
}
public void testLambdaInInlineFunction() throws Exception {
public void testLambdaInInlineFunction() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Foo", "inlineFoo", "(Lkotlin/jvm/functions/Function0;)V");
doCustomTest("foo/Foo\\$inlineFoo\\$1", expectedInfo, "inlineLambda");
}
public void testLambdaInlined() throws Exception {
public void testLambdaInlined() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "callToInline", "()V");
doCustomTest("foo/Bar\\$callToInline\\$\\$inlined\\$inlineFoo\\$1", expectedInfo, "inlineLambda");
}
public void testLambdaInInlineLambda() throws Exception {
public void testLambdaInInlineLambda() {
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "objectInInlineLambda", "()V");
doCustomTest("foo/Bar\\$objectInInlineLambda\\$\\$inlined\\$simpleFoo\\$lambda\\$1", expectedInfo, "inlineLambda");
}
public void testLambdaInLambdaInlinedIntoObject() throws Exception {
public void testLambdaInLambdaInlinedIntoObject() {
OuterClassInfo intoObjectInfo = new OuterClassInfo("foo/Bar", "objectInLambdaInlinedIntoObject", "()V");
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineLambda");
}
public void testLambdaInLambdaInlinedIntoObject2() throws Exception {
public void testLambdaInLambdaInlinedIntoObject2() {
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "invoke", "()V");
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1\\$lambda\\$1",
objectInLambda, "inlineLambda");
}
private void doTest(@NotNull String classFqName, @NotNull String testDataFile) throws Exception {
private void doTest(@NotNull String classFqName, @NotNull String testDataFile) {
doTest(classFqName, classFqName, testDataFile);
}
@@ -154,7 +154,7 @@ public class OuterClassGenTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
}
private void doTest(@NotNull String classFqName, @NotNull String javaClassName, @NotNull String testDataFile) throws Exception {
private void doTest(@NotNull String classFqName, @NotNull String javaClassName, @NotNull String testDataFile) {
File javaOut = CodegenTestUtil.compileJava(
Collections.singletonList(KotlinTestUtils.getTestDataPathBase() + "/codegen/" + getPrefix() + "/" + testDataFile + ".java"),
Collections.emptyList(),
@@ -176,14 +176,10 @@ public class OuterClassGenTest extends CodegenTestCase {
) {
ClassReader kotlinReader = getKotlinClassReader(internalNameRegexp, testDataFile);
OuterClassInfo kotlinInfo = readOuterClassInfo(kotlinReader);
assertNotNull(kotlinInfo);
String message = "Error in enclosingMethodInfo info for class: " + kotlinReader.getClassName();
if (kotlinInfo == null) {
assertNull(expectedInfo.getOwner());
}
else {
assertTrue(message + "\n" + kotlinInfo.getOwner() + " doesn't start with " + expectedInfo.getOwner(),
kotlinInfo.getOwner().startsWith(expectedInfo.getOwner()));
}
assertTrue(message + "\n" + kotlinInfo.getOwner() + " doesn't start with " + expectedInfo.getOwner(),
kotlinInfo.getOwner().startsWith(expectedInfo.getOwner()));
assertEquals(message, expectedInfo.getMethodName(), kotlinInfo.getMethodName());
assertEquals(message, expectedInfo.getMethodDesc(), kotlinInfo.getMethodDesc());
}
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.codegen
data class OuterClassInfo(
val owner: String,
val methodName: String?,
val methodDesc: String?
val owner: String,
val methodName: String?,
val methodDesc: String?
)
@@ -171,6 +171,7 @@ public class PackageGenTest extends CodegenTestCase {
assertEquals("beer", result.toString());
}
@SuppressWarnings("StringOperationCanBeSimplified")
public void testJavaEquals() throws Exception {
loadText("fun foo(s1: String, s2: String) = s1 == s2");
Method main = generateFunction();
@@ -178,6 +179,7 @@ public class PackageGenTest extends CodegenTestCase {
assertEquals(Boolean.FALSE, main.invoke(null, new String("kotlin"), new String("ceylon")));
}
@SuppressWarnings("StringOperationCanBeSimplified")
public void testJavaNotEquals() throws Exception {
loadText("fun foo(s1: String, s2: String) = s1 != s2");
Method main = generateFunction();
@@ -200,6 +202,7 @@ public class PackageGenTest extends CodegenTestCase {
assertEquals(Boolean.FALSE, main.invoke(null, "kotlin"));
}
@SuppressWarnings("StringOperationCanBeSimplified")
public void testTripleEq() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 === s2");
Method main = generateFunction();
@@ -209,6 +212,7 @@ public class PackageGenTest extends CodegenTestCase {
assertEquals(Boolean.FALSE, main.invoke(null, s1, s2));
}
@SuppressWarnings("StringOperationCanBeSimplified")
public void testTripleNotEq() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 !== s2");
Method main = generateFunction();
@@ -301,7 +305,7 @@ public class PackageGenTest extends CodegenTestCase {
assertEquals(610, c.gridx);
}
public void testIncrementAsLastOperation() throws Exception {
public void testIncrementAsLastOperation() {
loadText("fun foo() { var a = 0; a++; }");
generateFunction(); // make sure we're not falling off end of code
}
@@ -440,7 +444,7 @@ public class PackageGenTest extends CodegenTestCase {
public void testExplicitCallOfBooleanNotIntrinsic() throws Exception {
loadText("fun foo(a: Boolean) = a.not()");
Method main = generateFunction();
assertEquals(false, ((Boolean) main.invoke(null, true)).booleanValue());
assertFalse(((Boolean) main.invoke(null, true)).booleanValue());
}
public void testAppendArrayToString() throws Exception {
@@ -89,22 +89,22 @@ public class PrimitiveTypesTest extends CodegenTestCase {
public void testShort() throws Exception {
binOpTest("fun foo(a: Short, b: Short): Int = a + b",
Short.valueOf((short) 32767), Short.valueOf((short) 32767), 65534);
Short.valueOf((short) 32767), Short.valueOf((short) 32767), 65534);
}
public void testShortCmp() throws Exception {
binOpTest("fun foo(a: Short, b: Short): Boolean = a == b",
Short.valueOf((short) 32767), Short.valueOf((short) 32767), true);
Short.valueOf((short) 32767), Short.valueOf((short) 32767), true);
}
public void testByte() throws Exception {
binOpTest("fun foo(a: Byte, b: Byte): Int = a + b",
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 254);
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 254);
}
public void testByteCmp() throws Exception {
binOpTest("fun foo(a: Byte, b: Byte): Int = if (a == b) 1 else 0",
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 1);
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 1);
}
public void testByteLess() throws Exception {
@@ -39,18 +39,18 @@ class ReflectionClassLoaderTest : CodegenTestCase() {
}
fun testSimpleDifferentClassLoaders() {
loadFile(prefix + "/differentClassLoaders.kt")
loadFile("$prefix/differentClassLoaders.kt")
doTest(
createClassLoader(),
createClassLoader()
createClassLoader(),
createClassLoader()
)
}
fun testClassLoaderWithNonTrivialEqualsAndHashCode() {
// Check that class loaders do not participate as keys in hash maps (use identity hash maps instead)
loadFile(prefix + "/differentClassLoaders.kt")
loadFile("$prefix/differentClassLoaders.kt")
class BrokenEqualsClassLoader(parent: ClassLoader) : ClassLoader(parent) {
override fun equals(other: Any?) = true
@@ -58,23 +58,23 @@ class ReflectionClassLoaderTest : CodegenTestCase() {
}
doTest(
BrokenEqualsClassLoader(createClassLoader()),
BrokenEqualsClassLoader(createClassLoader())
BrokenEqualsClassLoader(createClassLoader()),
BrokenEqualsClassLoader(createClassLoader())
)
}
fun testParentFirst() {
// Check that for a child class loader, a class reference would be the same as for his parent
loadFile(prefix + "/parentFirst.kt")
loadFile("$prefix/parentFirst.kt")
class ChildClassLoader(parent: ClassLoader) : ClassLoader(parent)
val parent = createClassLoader()
doTest(
parent,
ChildClassLoader(parent)
parent,
ChildClassLoader(parent)
)
}
}
@@ -46,16 +46,16 @@ class ScriptGenTest : CodegenTestCase() {
override fun setUp() {
super.setUp()
additionalDependencies =
System.getenv("PROJECT_CLASSES_DIRS")?.split(File.pathSeparator)?.map { File(it) }
System.getenv("PROJECT_CLASSES_DIRS")?.split(File.pathSeparator)?.map { File(it) }
?: listOf(
"compiler/build/classes/kotlin/test",
"build/compiler/classes/kotlin/test",
"out/test/compiler.test",
"out/test/compiler_test"
)
.mapNotNull { File(it).canonicalFile.takeIf { it.isDirectory } }
.takeIf { it.isNotEmpty() }
?: throw IllegalStateException("Unable to get classes output dirs, set PROJECT_CLASSES_DIRS environment variable")
.mapNotNull { File(it).canonicalFile.takeIf(File::isDirectory) }
.takeIf { it.isNotEmpty() }
?: throw IllegalStateException("Unable to get classes output dirs, set PROJECT_CLASSES_DIRS environment variable")
}
fun testLanguage() {
@@ -136,7 +136,9 @@ class ScriptGenTest : CodegenTestCase() {
}
}
@Suppress("unused")
@ScriptTemplateDefinition(
scriptFilePattern =".*\\.lang\\.kts",
resolver = TestKotlinScriptDependenciesResolver::class)
scriptFilePattern = ".*\\.lang\\.kts",
resolver = TestKotlinScriptDependenciesResolver::class
)
abstract class ScriptWithIntParam(val num: Int)
@@ -25,6 +25,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
public class SourceInfoGenTest extends CodegenTestCase {
private static final String TEST_FOLDER = "sourceInfo/";
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -50,7 +51,6 @@ public class SourceInfoGenTest extends CodegenTestCase {
public void visitSource(String source, String debug) {
producer[0] = source;
}
}, 0);
return producer[0];
}
@@ -23,11 +23,13 @@ import java.io.FileInputStream
import java.util.zip.ZipInputStream
class TestStdlibWithDxTest {
@Test fun testRuntimeWithDx() {
@Test
fun testRuntimeWithDx() {
doTest(ForTestCompileRuntime.runtimeJarForTests())
}
@Test fun testReflectWithDx() {
@Test
fun testReflectWithDx() {
doTest(ForTestCompileRuntime.reflectJarForTests())
}
@@ -34,56 +34,56 @@ public class VarArgTest extends CodegenTestCase {
loadText("fun test(vararg ts: String) = ts");
Method main = generateFunction();
String[] args = {"mama", "papa"};
assertTrue(args == main.invoke(null, new Object[]{ args } ));
assertSame(args, main.invoke(null, new Object[] {args}));
}
public void testIntArray() throws InvocationTargetException, IllegalAccessException {
loadText("fun test(vararg ts: Int) = ts");
Method main = generateFunction();
int[] args = {3, 4};
assertTrue(args == main.invoke(null, new Object[]{ args }));
assertSame(args, main.invoke(null, new Object[] {args}));
}
public void testIntArrayKotlinNoArgs() throws InvocationTargetException, IllegalAccessException {
loadText("fun test() = testf(); fun testf(vararg ts: Int) = ts");
Method main = generateFunction("test");
Object res = main.invoke(null);
assertTrue(((int[])res).length == 0);
assertEquals(0, ((int[]) res).length);
}
public void testIntArrayKotlin() throws InvocationTargetException, IllegalAccessException {
loadText("fun test() = testf(239, 7); fun testf(vararg ts: Int) = ts");
Method main = generateFunction("test");
Object res = main.invoke(null);
assertTrue(((int[])res).length == 2);
assertTrue(((int[])res)[0] == 239);
assertTrue(((int[])res)[1] == 7);
assertEquals(2, ((int[]) res).length);
assertEquals(239, ((int[]) res)[0]);
assertEquals(7, ((int[]) res)[1]);
}
public void testNullableIntArrayKotlin() throws InvocationTargetException, IllegalAccessException {
loadText("fun test() = testf(239.toByte(), 7.toByte()); fun testf(vararg ts: Byte?) = ts");
Method main = generateFunction("test");
Object res = main.invoke(null);
assertTrue(((Byte[])res).length == 2);
assertTrue(((Byte[])res)[0] == (byte)239);
assertTrue(((Byte[])res)[1] == 7);
assertEquals(2, ((Byte[]) res).length);
assertEquals((byte) ((Byte[]) res)[0], (byte) 239);
assertEquals(7, (byte) ((Byte[]) res)[1]);
}
public void testIntArrayKotlinObj() throws InvocationTargetException, IllegalAccessException {
loadText("fun test() = testf(\"239\"); fun testf(vararg ts: String) = ts");
Method main = generateFunction("test");
Object res = main.invoke(null);
assertTrue(((String[])res).length == 1);
assertTrue(((String[])res)[0].equals("239"));
assertEquals(1, ((String[]) res).length);
assertEquals("239", ((String[]) res)[0]);
}
public void testArrayT() throws InvocationTargetException, IllegalAccessException {
loadText("fun test() = _array(2, 4); fun <T> _array(vararg elements : T) = elements");
Method main = generateFunction("test");
Object res = main.invoke(null);
assertTrue(((Integer[])res).length == 2);
assertTrue(((Integer[])res)[0].equals(2));
assertTrue(((Integer[])res)[1].equals(4));
assertEquals(2, ((Integer[]) res).length);
assertEquals(2, (int) ((Integer[]) res)[0]);
assertEquals(4, (int) ((Integer[]) res)[1]);
}
public void testArrayAsVararg() throws InvocationTargetException, IllegalAccessException {
@@ -91,7 +91,7 @@ public class VarArgTest extends CodegenTestCase {
Method main = generateFunction("test");
String[] args = {"mama", "papa"};
String[] result = (String []) main.invoke(null, new Object[] {args});
assertTrue(args != result);
assertNotSame(args, result);
assertTrue(Arrays.equals(args, result));
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2019 JetBrains s.r.o. 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.android.parcel
@@ -37,11 +26,11 @@ import java.util.concurrent.TimeUnit
abstract class AbstractParcelBoxTest : CodegenTestCase() {
protected companion object {
val BASE_DIR = "plugins/android-extensions/android-extensions-compiler/testData/parcel/box"
const val BASE_DIR = "plugins/android-extensions/android-extensions-compiler/testData/parcel/box"
val LIBRARY_KT = File(File(BASE_DIR).parentFile, "boxLib.kt")
private val JUNIT_GENERATED_TEST_CLASS_BYTES by lazy { constructSyntheticTestClass() }
private val JUNIT_GENERATED_TEST_CLASS_FQNAME = "test.JunitTest"
private const val JUNIT_GENERATED_TEST_CLASS_FQNAME = "test.JunitTest"
private fun constructSyntheticTestClass(): ByteArray {
return with(ClassWriter(COMPUTE_MAXS or COMPUTE_FRAMES)) {
@@ -104,12 +93,12 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
}
override fun doTest(filePath: String) {
super.doTest(File(BASE_DIR, filePath + ".kt").absolutePath)
super.doTest(File(BASE_DIR, "$filePath.kt").absolutePath)
}
private val androidPluginPath: String by lazy {
System.getProperty("ideaSdk.androidPlugin.path")?.takeIf { File(it).isDirectory }
?: throw RuntimeException("Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location")
?: throw RuntimeException("Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location")
}
private fun getClasspathForTest(): List<File> {
@@ -117,10 +106,10 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
val layoutLibJars = listOf(File(androidPluginPath, "layoutlib.jar"), File(androidPluginPath, "layoutlib-api.jar"))
val robolectricClasspath = System.getProperty("robolectric.classpath")
?: throw RuntimeException("Unable to get a valid classpath from 'robolectric.classpath' property, please set it accordingly")
?: throw RuntimeException("Unable to get a valid classpath from 'robolectric.classpath' property, please set it accordingly")
val robolectricJars = robolectricClasspath.split(File.pathSeparator)
.map { File(it) }
.sortedBy { it.nameWithoutExtension }
.map { File(it) }
.sortedBy { it.nameWithoutExtension }
val junitCoreResourceName = JUnitCore::class.java.name.replace('.', '/') + ".class"
val junitJar = File(JUnitCore::class.java.classLoader.getResource(junitCoreResourceName).file.substringBeforeLast('!'))
@@ -151,12 +140,12 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
classFileFactory.getClassFiles().forEach { writeClass(it.relativePath, it.asByteArray()) }
val process = ProcessBuilder(
javaExe.absolutePath,
"-ea",
"-classpath",
(libraryClasspath + dirForTestClasses).joinToString(File.pathSeparator),
JUnitCore::class.java.name,
JUNIT_GENERATED_TEST_CLASS_FQNAME
javaExe.absolutePath,
"-ea",
"-classpath",
(libraryClasspath + dirForTestClasses).joinToString(File.pathSeparator),
JUnitCore::class.java.name,
JUNIT_GENERATED_TEST_CLASS_FQNAME
).inheritIO().start()
process.waitFor(3, TimeUnit.MINUTES)
@@ -175,4 +164,4 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
addAndroidExtensionsRuntimeLibrary(environment)
environment.updateClasspath(listOf(JvmClasspathRoot(File(androidPluginPath, "layoutlib.jar"))))
}
}
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2019 JetBrains s.r.o. 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.android.parcel
@@ -28,7 +17,9 @@ abstract class AbstractParcelBytecodeListingTest : AbstractAsmLikeInstructionLis
AndroidComponentRegistrar.registerParcelExtensions(environment.project)
addAndroidExtensionsRuntimeLibrary(environment)
val androidPluginPath = System.getProperty("ideaSdk.androidPlugin.path")?.takeIf { File(it).isDirectory }
?: throw RuntimeException("Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location")
?: throw RuntimeException(
"Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location"
)
environment.updateClasspath(listOf(JvmClasspathRoot(File(androidPluginPath, "layoutlib.jar"))))
}
}
}
@@ -1,24 +1,12 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2019 JetBrains s.r.o. 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.android.synthetic.test
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.ArrayUtil
import com.intellij.util.Processor
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.codegen.AbstractBlackBoxCodegenTest
import org.jetbrains.kotlin.codegen.CodegenTestFiles
@@ -28,7 +16,6 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind
import java.io.File
import java.net.URL
import java.util.*
import java.util.regex.Pattern
abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
@@ -42,7 +29,9 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
}
private fun createEnvironmentForConfiguration(configuration: CompilerConfiguration, path: String) {
val layoutPaths = File(path).listFiles { it -> it.name.startsWith("layout") && it.isDirectory }!!.map { "$path${it.name}/" }
val layoutPaths = File(path)
.listFiles { file -> file.name.startsWith("layout") && file.isDirectory }!!
.map { "$path${it.name}/" }
myEnvironment = createTestEnvironment(configuration, layoutPaths)
}
@@ -63,11 +52,12 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
}
private fun getFakeFiles(path: String): Collection<String> {
return FileUtil.findFilesByMask(Pattern.compile("^Fake.*\\.kt$"), File(path.replace(getTestName(true), ""))).map { relativePath(it) }
return FileUtil.findFilesByMask(Pattern.compile("^Fake.*\\.kt$"), File(path.replace(getTestName(true), "")))
.map { relativePath(it) }
}
private fun needsInvocationTest(path: String): Boolean {
return !FileUtil.findFilesByMask(Pattern.compile("^0.kt$"), File(path)).isEmpty()
return FileUtil.findFilesByMask(Pattern.compile("^0.kt$"), File(path)).isNotEmpty()
}
override fun codegenTestBasePath(): String {
@@ -76,35 +66,33 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
private fun doMultiFileTest(path: String, additionalFiles: Collection<String>? = null) {
val files = mutableListOf<String>()
FileUtil.processFilesRecursively(File(path), object : Processor<File> {
override fun process(file: File?): Boolean {
when (file!!.name) {
"1.kt" -> {
if (additionalFiles == null) files.add(relativePath(file))
}
"0.kt" -> {
if (additionalFiles != null) files.add(relativePath(file))
}
else -> {
if (file.name.endsWith(".kt")) files.add(relativePath(file))
}
FileUtil.processFilesRecursively(File(path)) { file ->
when (file!!.name) {
"1.kt" -> {
if (additionalFiles == null) files.add(relativePath(file))
}
"0.kt" -> {
if (additionalFiles != null) files.add(relativePath(file))
}
else -> {
if (file.name.endsWith(".kt")) files.add(relativePath(file))
}
return true
}
})
true
}
for (file in File("plugins/android-extensions/android-extensions-runtime/src").walk()) {
if (file.extension == "kt") files += relativePath(file.absoluteFile)
}
Collections.sort(files)
files.sort()
if (additionalFiles != null) {
files.addAll(additionalFiles)
}
myFiles = CodegenTestFiles.create(
myEnvironment!!.project,
ArrayUtil.toStringArray(files),
KotlinTestUtils.getHomeDirectory() + "/plugins/android-extensions/android-extensions-compiler/testData"
myEnvironment!!.project,
ArrayUtil.toStringArray(files),
KotlinTestUtils.getHomeDirectory() + "/plugins/android-extensions/android-extensions-compiler/testData"
)
blackBox(true)
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2019 JetBrains s.r.o. 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.android.synthetic.test
@@ -41,20 +30,20 @@ abstract class AbstractAndroidSyntheticPropertyDescriptorTest : KtUsefulTestCase
val analysisResult = JvmResolveUtil.analyzeAndCheckForErrors(listOf(), env)
val fragmentProvider =
ext.getPackageFragmentProvider(
project, analysisResult.moduleDescriptor, LockBasedStorageManager.NO_LOCKS,
KotlinTestUtils.DUMMY_EXCEPTION_ON_ERROR_TRACE, null, LookupTracker.DO_NOTHING
) as AndroidSyntheticPackageFragmentProvider
ext.getPackageFragmentProvider(
project, analysisResult.moduleDescriptor, LockBasedStorageManager.NO_LOCKS,
KotlinTestUtils.DUMMY_EXCEPTION_ON_ERROR_TRACE, null, LookupTracker.DO_NOTHING
) as AndroidSyntheticPackageFragmentProvider
val renderer = DescriptorRenderer.COMPACT_WITH_MODIFIERS
val expected = fragmentProvider.packages.values
.map { it() }
.sortedBy { it.fqName.asString() }
.joinToString(separator = "\n\n\n") {
val descriptors = it.getMemberScope().getContributedDescriptors()
.joinToString(separator = "\n\n\n") { packageFragment ->
val descriptors = packageFragment.getMemberScope().getContributedDescriptors()
.sortedWith(MemberComparator.INSTANCE)
.map { " " + renderer.render(it) }.joinToString("\n")
it.fqName.asString() + (if (descriptors.isNotEmpty()) "\n\n" + descriptors else "")
.joinToString("\n") { " " + renderer.render(it) }
packageFragment.fqName.asString() + (if (descriptors.isNotEmpty()) "\n\n" + descriptors else "")
}
KotlinTestUtils.assertEqualsToFile(File(path, "result.txt"), expected)
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2019 JetBrains s.r.o. 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.android.synthetic.test
@@ -35,8 +24,6 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
@@ -52,7 +39,9 @@ fun KtUsefulTestCase.createTestEnvironment(configuration: CompilerConfiguration,
ExpressionCodegenExtension.registerExtension(project, CliAndroidExtensionsExpressionCodegenExtension(true, CacheImplementation.DEFAULT))
StorageComponentContainerContributor.registerExtension(project, AndroidExtensionPropertiesComponentContainerContributor())
ClassBuilderInterceptorExtension.registerExtension(project, CliAndroidOnDestroyClassBuilderInterceptorExtension(CacheImplementation.DEFAULT))
ClassBuilderInterceptorExtension.registerExtension(
project, CliAndroidOnDestroyClassBuilderInterceptorExtension(CacheImplementation.DEFAULT)
)
PackageFragmentProviderExtension.registerExtension(project, CliAndroidPackageFragmentProviderExtension(true))
addAndroidExtensionsRuntimeLibrary(myEnvironment)
@@ -68,5 +57,7 @@ fun addAndroidExtensionsRuntimeLibrary(environment: KotlinCoreEnvironment) {
}
fun getResPaths(path: String): List<String> {
return File(path).listFiles { it -> it.name.startsWith("res") && it.isDirectory }!!.map { "$path${it.name}/" }
}
return File(path)
.listFiles { file -> file.name.startsWith("res") && file.isDirectory }!!
.map { "$path${it.name}/" }
}