Refactor CompileKotlinAgainstCustomBinariesTest

Combine compileLibrary and compileJava into a universal compileLibrary
which compiles both .java and .kt files, either to a directory or to a
.jar file. Also introduce compileJsLibrary for JS only
This commit is contained in:
Alexander Udalov
2017-05-25 19:52:43 +03:00
parent dae414854d
commit da0ecc6cf7
2 changed files with 77 additions and 74 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.jvm.compiler package org.jetbrains.kotlin.jvm.compiler
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.io.ZipUtil
import org.jetbrains.kotlin.cli.AbstractCliTest import org.jetbrains.kotlin.cli.AbstractCliTest
import org.jetbrains.kotlin.cli.WrongBytecodeVersionTest import org.jetbrains.kotlin.cli.WrongBytecodeVersionTest
import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.CLICompiler
@@ -59,18 +60,58 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
return File(testDataDirectory, "${getTestName(true)}.$extension") return File(testDataDirectory, "${getTestName(true)}.$extension")
} }
/**
* Compiles all sources (.java and .kt) under the directory named [libraryName] to [destination].
* [destination] should be either a path to the directory under [tmpdir], or a path to the resulting .jar file (also under [tmpdir]).
* Kotlin sources are compiled first, and there should be no errors or warnings. Java sources are compiled next.
*
* @return [destination]
*/
private fun compileLibrary( private fun compileLibrary(
sourcePath: String, libraryName: String,
compiler: CLICompiler<*> = K2JVMCompiler(), destination: File = File(tmpdir, "$libraryName.jar"),
destination: File = File(tmpdir, "$sourcePath.jar"),
additionalOptions: List<String> = emptyList(), additionalOptions: List<String> = emptyList(),
vararg extraClassPath: File vararg extraClassPath: File
): File { ): File {
val output = compileKotlin(sourcePath, destination, extraClassPath.toList(), compiler, additionalOptions, expectedFileName = null) val javaFiles = FileUtil.findFilesByMask(JAVA_FILES, File(testDataDirectory, libraryName))
assertEquals(normalizeOutput("" to ExitCode.OK), normalizeOutput(output)) val kotlinFiles = FileUtil.findFilesByMask(KOTLIN_FILES, File(testDataDirectory, libraryName))
assert(javaFiles.isNotEmpty() || kotlinFiles.isNotEmpty()) { "There should be either .kt or .java files in the directory" }
val isJar = destination.name.endsWith(".jar")
val outputDir = if (isJar) File(tmpdir, "output-$libraryName") else destination
if (kotlinFiles.isNotEmpty()) {
val output = compileKotlin(libraryName, outputDir, extraClassPath.toList(), K2JVMCompiler(), additionalOptions, expectedFileName = null)
assertEquals(normalizeOutput("" to ExitCode.OK), normalizeOutput(output))
}
if (javaFiles.isNotEmpty()) {
outputDir.mkdirs()
KotlinTestUtils.compileJavaFiles(javaFiles, listOf("-d", outputDir.path))
}
if (isJar) {
destination.delete()
ZipOutputStream(destination.outputStream()).use { zip ->
ZipUtil.addDirToZipRecursively(zip, destination, outputDir, "", null, null)
}
}
return destination return destination
} }
/**
* Compiles all .kt sources under the directory named [libraryName] to a file named "[libraryName].js" in [tmpdir]
*
* @return the path to the corresponding .meta.js file, i.e. "[libraryName].meta.js"
*/
private fun compileJsLibrary(libraryName: String): File {
val destination = File(tmpdir, "$libraryName.js")
val output = compileKotlin(libraryName, destination, compiler = K2JSCompiler(), expectedFileName = null)
assertEquals(normalizeOutput("" to ExitCode.OK), normalizeOutput(output))
return File(tmpdir, "$libraryName.meta.js")
}
private fun normalizeOutput(output: Pair<String, ExitCode>): String { private fun normalizeOutput(output: Pair<String, ExitCode>): String {
return AbstractCliTest.getNormalizedCompilerOutput(output.first, output.second, testDataDirectory.path) return AbstractCliTest.getNormalizedCompilerOutput(output.first, output.second, testDataDirectory.path)
.replace(FileUtil.toSystemIndependentName(tmpdir.absolutePath), "\$TMP_DIR\$") .replace(FileUtil.toSystemIndependentName(tmpdir.absolutePath), "\$TMP_DIR\$")
@@ -103,14 +144,6 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
private fun analyzeAndGetAllDescriptors(vararg extraClassPath: File): Collection<DeclarationDescriptor> = private fun analyzeAndGetAllDescriptors(vararg extraClassPath: File): Collection<DeclarationDescriptor> =
DescriptorUtils.getAllDescriptors(analyzeFileToPackageView(*extraClassPath).memberScope) DescriptorUtils.getAllDescriptors(analyzeFileToPackageView(*extraClassPath).memberScope)
private fun compileJava(libraryDir: String): File {
val allJavaFiles = FileUtil.findFilesByMask(JAVA_FILES, File(testDataDirectory, libraryDir))
val result = File(tmpdir, libraryDir)
assert(result.mkdirs()) { "Could not create directory: $result" }
KotlinTestUtils.compileJavaFiles(allJavaFiles, listOf("-d", result.path))
return result
}
private fun compileKotlin( private fun compileKotlin(
fileName: String, fileName: String,
output: File, output: File,
@@ -154,15 +187,9 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
return result return result
} }
private fun doTestBrokenJavaLibrary(libraryName: String, vararg pathsToDelete: String) { private fun doTestBrokenLibrary(libraryName: String, vararg pathsToDelete: String) {
// This function compiles a Java library, then deletes one class file and attempts to compile a Kotlin source against // This function compiles a library, then deletes one class file and attempts to compile a Kotlin source against
// this broken library. The expected result is an error message from the compiler // this broken library. The expected result is an error message from the compiler
val library = deletePaths(compileJava(libraryName), *pathsToDelete)
compileKotlin("source.kt", tmpdir, listOf(library))
}
private fun doTestBrokenKotlinLibrary(libraryName: String, vararg pathsToDelete: String) {
// Analogous to doTestBrokenJavaLibrary, but with a Kotlin library compiled to a JAR file
val library = copyJarFileWithoutEntry(compileLibrary(libraryName), *pathsToDelete) val library = copyJarFileWithoutEntry(compileLibrary(libraryName), *pathsToDelete)
compileKotlin("source.kt", tmpdir, listOf(library)) compileKotlin("source.kt", tmpdir, listOf(library))
} }
@@ -186,9 +213,8 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
} }
private fun doTestKotlinLibraryWithWrongMetadataVersionJs(libraryName: String, vararg additionalOptions: String) { private fun doTestKotlinLibraryWithWrongMetadataVersionJs(libraryName: String, vararg additionalOptions: String) {
compileLibrary(libraryName, K2JSCompiler(), File(tmpdir, "library.js"), emptyList()) val library = compileJsLibrary(libraryName)
val library = File(tmpdir, "library.meta.js")
library.writeText(library.readText(Charsets.UTF_8).replace( library.writeText(library.readText(Charsets.UTF_8).replace(
"(" + JsMetadataVersion.INSTANCE.toInteger() + ", ", "(" + JsMetadataVersion.INSTANCE.toInteger() + ", ",
"(" + JsMetadataVersion(42, 0, 0).toInteger() + ", " "(" + JsMetadataVersion(42, 0, 0).toInteger() + ", "
@@ -200,16 +226,18 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
private fun doTestPreReleaseKotlinLibrary( private fun doTestPreReleaseKotlinLibrary(
compiler: CLICompiler<*>, compiler: CLICompiler<*>,
libraryName: String, libraryName: String,
destination: File,
result: File,
usageDestination: File, usageDestination: File,
vararg additionalOptions: String vararg additionalOptions: String
) { ) {
// Compiles the library with the "pre-release" flag, then compiles a usage of this library in the release mode // Compiles the library with the "pre-release" flag, then compiles a usage of this library in the release mode
try { val result = try {
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true") System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true")
compileLibrary(libraryName, compiler, destination) when (compiler) {
is K2JSCompiler -> compileJsLibrary(libraryName)
is K2JVMCompiler -> compileLibrary(libraryName)
else -> throw UnsupportedOperationException(compiler.toString())
}
} }
finally { finally {
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY) System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY)
@@ -227,9 +255,7 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
fun testRawTypes() { fun testRawTypes() {
val libraryOutput = compileJava("library") compileKotlin("main.kt", tmpdir, listOf(compileLibrary("library")))
compileKotlin("library", libraryOutput, listOf(libraryOutput))
compileKotlin("main.kt", tmpdir, listOf(libraryOutput))
} }
fun testDuplicateObjectInBinaryAndSources() { fun testDuplicateObjectInBinaryAndSources() {
@@ -259,8 +285,8 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
// This test checks that there are no PARAMETER_NAME_CHANGED_ON_OVERRIDE or DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES // This test checks that there are no PARAMETER_NAME_CHANGED_ON_OVERRIDE or DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES
// warnings when subclassing in Kotlin from Java binaries (in case when no parameter names are available for Java classes) // warnings when subclassing in Kotlin from Java binaries (in case when no parameter names are available for Java classes)
val libraryOutput = compileJava("library") val library = compileLibrary("library")
val environment = createEnvironment(listOf(libraryOutput)) val environment = createEnvironment(listOf(library))
val ktFile = KotlinTestUtils.loadJetFile(environment.project, getTestDataFileWithExtension("kt")) val ktFile = KotlinTestUtils.loadJetFile(environment.project, getTestDataFileWithExtension("kt"))
val result = JvmResolveUtil.analyze(ktFile, environment) val result = JvmResolveUtil.analyze(ktFile, environment)
@@ -275,23 +301,23 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
} }
fun testIncompleteHierarchyInJava() { fun testIncompleteHierarchyInJava() {
doTestBrokenJavaLibrary("library", "test/Super.class") doTestBrokenLibrary("library", "test/Super.class")
} }
fun testIncompleteHierarchyInKotlin() { fun testIncompleteHierarchyInKotlin() {
doTestBrokenKotlinLibrary("library", "test/Super.class") doTestBrokenLibrary("library", "test/Super.class")
} }
fun testMissingDependencySimple() { fun testMissingDependencySimple() {
doTestBrokenKotlinLibrary("library", "a/A.class") doTestBrokenLibrary("library", "a/A.class")
} }
fun testMissingDependencyDifferentCases() { fun testMissingDependencyDifferentCases() {
doTestBrokenKotlinLibrary("library", "a/A.class") doTestBrokenLibrary("library", "a/A.class")
} }
fun testMissingDependencyNestedAnnotation() { fun testMissingDependencyNestedAnnotation() {
doTestBrokenKotlinLibrary("library", "a/A\$Anno.class") doTestBrokenLibrary("library", "a/A\$Anno.class")
} }
fun testMissingDependencyConflictingLibraries() { fun testMissingDependencyConflictingLibraries() {
@@ -303,48 +329,33 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
} }
fun testMissingDependencyJava() { fun testMissingDependencyJava() {
doTestBrokenJavaLibrary("library", "test/Bar.class") doTestBrokenLibrary("library", "test/Bar.class")
} }
fun testMissingDependencyJavaConflictingLibraries() { fun testMissingDependencyJavaConflictingLibraries() {
val library1 = deletePaths(compileJava("library1"), "test/A.class", "test/A\$Inner.class") val library1 = copyJarFileWithoutEntry(compileLibrary("library1"), "test/A.class", "test/A\$Inner.class")
val library2 = deletePaths(compileJava("library2"), "test/A.class", "test/A\$Inner.class") val library2 = copyJarFileWithoutEntry(compileLibrary("library2"), "test/A.class", "test/A\$Inner.class")
compileKotlin("source.kt", tmpdir, listOf(library1, library2)) compileKotlin("source.kt", tmpdir, listOf(library1, library2))
} }
fun testMissingDependencyJavaNestedAnnotation() { fun testMissingDependencyJavaNestedAnnotation() {
doTestBrokenJavaLibrary("library", "test/A\$Anno.class") doTestBrokenLibrary("library", "test/A\$Anno.class")
} }
fun testReleaseCompilerAgainstPreReleaseLibrary() { fun testReleaseCompilerAgainstPreReleaseLibrary() {
val destination = File(tmpdir, "library.jar") doTestPreReleaseKotlinLibrary(K2JVMCompiler(), "library", tmpdir)
doTestPreReleaseKotlinLibrary(K2JVMCompiler(), "library", destination, destination, tmpdir)
} }
fun testReleaseCompilerAgainstPreReleaseLibraryJs() { fun testReleaseCompilerAgainstPreReleaseLibraryJs() {
doTestPreReleaseKotlinLibrary( doTestPreReleaseKotlinLibrary(K2JSCompiler(), "library", File(tmpdir, "usage.js"))
K2JSCompiler(), "library",
File(tmpdir, "library.js"), File(tmpdir, "library.meta.js"),
File(tmpdir, "usage.js")
)
} }
fun testReleaseCompilerAgainstPreReleaseLibrarySkipVersionCheck() { fun testReleaseCompilerAgainstPreReleaseLibrarySkipVersionCheck() {
val destination = File(tmpdir, "library.jar") doTestPreReleaseKotlinLibrary(K2JVMCompiler(), "library", tmpdir, "-Xskip-metadata-version-check")
doTestPreReleaseKotlinLibrary(
K2JVMCompiler(), "library",
destination, destination, tmpdir,
"-Xskip-metadata-version-check"
)
} }
fun testReleaseCompilerAgainstPreReleaseLibraryJsSkipVersionCheck() { fun testReleaseCompilerAgainstPreReleaseLibraryJsSkipVersionCheck() {
doTestPreReleaseKotlinLibrary( doTestPreReleaseKotlinLibrary(K2JSCompiler(), "library", File(tmpdir, "usage.js"), "-Xskip-metadata-version-check")
K2JSCompiler(), "library",
File(tmpdir, "library.js"), File(tmpdir, "library.meta.js"),
File(tmpdir, "usage.js"),
"-Xskip-metadata-version-check"
)
} }
fun testWrongMetadataVersion() { fun testWrongMetadataVersion() {
@@ -439,25 +450,24 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
fun testProhibitNestedClassesByDollarName() { fun testProhibitNestedClassesByDollarName() {
val library = compileLibrary("library") val library = compileLibrary("library")
val javaLibraryOutput = compileJava("library") compileKotlin("main.kt", tmpdir, listOf(library))
compileKotlin("main.kt", tmpdir, listOf(javaLibraryOutput, library))
} }
fun testTypeAliasesAreInvisibleInCompatibilityMode() { fun testTypeAliasesAreInvisibleInCompatibilityMode() {
val library = compileLibrary("typeAliases.kt") val library = compileLibrary("library")
compileKotlin("main.kt", tmpdir, listOf(library), K2JVMCompiler(), listOf("-language-version", "1.0")) compileKotlin("main.kt", tmpdir, listOf(library), K2JVMCompiler(), listOf("-language-version", "1.0"))
} }
fun testInnerClassPackageConflict() { fun testInnerClassPackageConflict() {
val output = compileJava("library") val output = compileLibrary("library", destination = File(tmpdir, "library"))
File(testDataDirectory, "library/test/Foo/x.txt").copyTo(File(output, "test/Foo/x.txt")) File(testDataDirectory, "library/test/Foo/x.txt").copyTo(File(output, "test/Foo/x.txt"))
MockLibraryUtil.createJarFile(tmpdir, output, null, "library", false) MockLibraryUtil.createJarFile(tmpdir, output, null, "library", false)
compileKotlin("source.kt", tmpdir, listOf(File(tmpdir, "library.jar"))) compileKotlin("source.kt", tmpdir, listOf(File(tmpdir, "library.jar")))
} }
fun testInnerClassPackageConflict2() { fun testInnerClassPackageConflict2() {
val library1 = compileJava("library1") val library1 = compileLibrary("library1", destination = File(tmpdir, "library1"))
val library2 = compileJava("library2") val library2 = compileLibrary("library2", destination = File(tmpdir, "library2"))
// Copy everything from library2 to library1 // Copy everything from library2 to library1
FileUtil.visitFiles(library2) { file -> FileUtil.visitFiles(library2) { file ->
@@ -481,6 +491,7 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
companion object { companion object {
private val TEST_DATA_PATH = "compiler/testData/compileKotlinAgainstCustomBinaries/" private val TEST_DATA_PATH = "compiler/testData/compileKotlinAgainstCustomBinaries/"
private val KOTLIN_FILES = Pattern.compile(".*\\.kt$")
private val JAVA_FILES = Pattern.compile(".*\\.java$") private val JAVA_FILES = Pattern.compile(".*\\.java$")
private fun copyJarFileWithoutEntry(jarPath: File, vararg entriesToDelete: String): File = private fun copyJarFileWithoutEntry(jarPath: File, vararg entriesToDelete: String): File =
@@ -512,13 +523,5 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
return outputFile return outputFile
} }
private fun deletePaths(library: File, vararg pathsToDelete: String): File {
for (pathToDelete in pathsToDelete) {
val fileToDelete = File(library, pathToDelete)
assert(fileToDelete.delete()) { "Can't delete $fileToDelete" }
}
return library
}
} }
} }