Extract some functions from test class into base class

To be used in other tests which will be subclasses of
AbstractKotlinCompilerIntegrationTest
This commit is contained in:
Alexander Udalov
2017-05-26 12:40:47 +03:00
parent 69efb81a12
commit 0c8ca5f930
2 changed files with 153 additions and 116 deletions
@@ -0,0 +1,146 @@
/*
* 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.
*/
package org.jetbrains.kotlin.jvm.compiler
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.io.ZipUtil
import org.jetbrains.kotlin.cli.AbstractCliTest
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import java.io.File
import java.util.regex.Pattern
import java.util.zip.ZipOutputStream
abstract class AbstractKotlinCompilerIntegrationTest : TestCaseWithTmpdir() {
protected abstract val testDataPath: String
protected val testDataDirectory: File
get() = File(testDataPath, getTestName(true))
protected fun getTestDataFileWithExtension(extension: String): File {
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]
*/
protected fun compileLibrary(
libraryName: String,
destination: File = File(tmpdir, "$libraryName.jar"),
additionalOptions: List<String> = emptyList(),
vararg extraClassPath: File
): File {
val javaFiles = FileUtil.findFilesByMask(JAVA_FILES, File(testDataDirectory, libraryName))
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
}
/**
* 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"
*/
protected 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 {
return AbstractCliTest.getNormalizedCompilerOutput(output.first, output.second, testDataDirectory.path)
.replace(FileUtil.toSystemIndependentName(tmpdir.absolutePath), "\$TMP_DIR\$")
}
protected fun compileKotlin(
fileName: String,
output: File,
classpath: List<File> = emptyList(),
compiler: CLICompiler<*> = K2JVMCompiler(),
additionalOptions: List<String> = emptyList(),
expectedFileName: String? = "output.txt"
): Pair<String, ExitCode> {
val args = mutableListOf<String>()
val sourceFile = File(testDataDirectory, fileName)
assert(sourceFile.exists()) { "Source file does not exist: ${sourceFile.absolutePath}" }
args.add(sourceFile.path)
if (compiler is K2JSCompiler) {
if (classpath.isNotEmpty()) {
args.add("-libraries")
args.add(classpath.joinToString(File.pathSeparator))
}
args.add("-output")
args.add(output.path)
args.add("-meta-info")
}
else if (compiler is K2JVMCompiler) {
if (classpath.isNotEmpty()) {
args.add("-classpath")
args.add(classpath.joinToString(File.pathSeparator))
}
args.add("-d")
args.add(output.path)
}
else {
throw UnsupportedOperationException(compiler.toString())
}
args.addAll(additionalOptions)
val result = AbstractCliTest.executeCompilerGrabOutput(compiler, args)
if (expectedFileName != null) {
KotlinTestUtils.assertEqualsToFile(File(testDataDirectory, expectedFileName), normalizeOutput(result))
}
return result
}
companion object {
private val KOTLIN_FILES = Pattern.compile(".*\\.kt$")
private val JAVA_FILES = Pattern.compile(".*\\.java$")
}
}
@@ -17,11 +17,8 @@
package org.jetbrains.kotlin.jvm.compiler
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.io.ZipUtil
import org.jetbrains.kotlin.cli.AbstractCliTest
import org.jetbrains.kotlin.cli.WrongBytecodeVersionTest
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
@@ -38,7 +35,10 @@ import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isObject
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import org.jetbrains.kotlin.test.*
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile
import org.jetbrains.kotlin.utils.JsMetadataVersion
import org.jetbrains.org.objectweb.asm.ClassReader
@@ -48,74 +48,12 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import java.io.File
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.regex.Pattern
import java.util.zip.ZipOutputStream
import kotlin.experimental.xor
class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
private val testDataDirectory: File
get() = File(TEST_DATA_PATH, getTestName(true))
private fun getTestDataFileWithExtension(extension: String): File {
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(
libraryName: String,
destination: File = File(tmpdir, "$libraryName.jar"),
additionalOptions: List<String> = emptyList(),
vararg extraClassPath: File
): File {
val javaFiles = FileUtil.findFilesByMask(JAVA_FILES, File(testDataDirectory, libraryName))
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
}
/**
* 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 {
return AbstractCliTest.getNormalizedCompilerOutput(output.first, output.second, testDataDirectory.path)
.replace(FileUtil.toSystemIndependentName(tmpdir.absolutePath), "\$TMP_DIR\$")
}
class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegrationTest() {
override val testDataPath: String
get() = "compiler/testData/compileKotlinAgainstCustomBinaries/"
private fun doTestWithTxt(vararg extraClassPath: File) {
validateAndCompareDescriptorWithFile(
@@ -144,49 +82,6 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
private fun analyzeAndGetAllDescriptors(vararg extraClassPath: File): Collection<DeclarationDescriptor> =
DescriptorUtils.getAllDescriptors(analyzeFileToPackageView(*extraClassPath).memberScope)
private fun compileKotlin(
fileName: String,
output: File,
classpath: List<File> = emptyList(),
compiler: CLICompiler<*> = K2JVMCompiler(),
additionalOptions: List<String> = emptyList(),
expectedFileName: String? = "output.txt"
): Pair<String, ExitCode> {
val args = mutableListOf<String>()
val sourceFile = File(testDataDirectory, fileName)
assert(sourceFile.exists()) { "Source file does not exist: ${sourceFile.absolutePath}" }
args.add(sourceFile.path)
if (compiler is K2JSCompiler) {
if (classpath.isNotEmpty()) {
args.add("-libraries")
args.add(classpath.joinToString(File.pathSeparator))
}
args.add("-output")
args.add(output.path)
args.add("-meta-info")
}
else if (compiler is K2JVMCompiler) {
if (classpath.isNotEmpty()) {
args.add("-classpath")
args.add(classpath.joinToString(File.pathSeparator))
}
args.add("-d")
args.add(output.path)
}
else {
throw UnsupportedOperationException(compiler.toString())
}
args.addAll(additionalOptions)
val result = AbstractCliTest.executeCompilerGrabOutput(compiler, args)
if (expectedFileName != null) {
KotlinTestUtils.assertEqualsToFile(File(testDataDirectory, expectedFileName), normalizeOutput(result))
}
return result
}
private fun doTestBrokenLibrary(libraryName: String, vararg pathsToDelete: String) {
// 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
@@ -490,10 +385,6 @@ class CompileKotlinAgainstCustomBinariesTest : TestCaseWithTmpdir() {
}
companion object {
private val TEST_DATA_PATH = "compiler/testData/compileKotlinAgainstCustomBinaries/"
private val KOTLIN_FILES = Pattern.compile(".*\\.kt$")
private val JAVA_FILES = Pattern.compile(".*\\.java$")
private fun copyJarFileWithoutEntry(jarPath: File, vararg entriesToDelete: String): File =
transformJar(jarPath, { _, bytes -> bytes }, entriesToDelete.toSet())