[minor] Rearrange test utils for easier reuse

This commit is contained in:
Ilya Chernikov
2019-08-27 11:29:43 +02:00
parent 947867286c
commit fda37eaaae
4 changed files with 174 additions and 131 deletions
@@ -5,93 +5,24 @@
package org.jetbrains.kotlin.mainKts.test
import junit.framework.Assert.*
import junit.framework.Assert
import org.jetbrains.kotlin.scripting.compiler.plugin.runWithK2JVMCompiler
import org.jetbrains.kotlin.scripting.compiler.plugin.runWithKotlinc
import org.junit.Test
import java.io.File
import java.io.InputStream
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
class MainKtsIT {
// TODO: partially copypasted from LauncherReplTest, consider extracting common parts to some (new) test util module
private fun runWithKotlinc(
scriptPath: String,
expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0,
workDirectory: File? = null
) {
val executableName = "kotlinc"
// TODO:
val executableFileName =
if (System.getProperty("os.name").contains("windows", ignoreCase = true)) "$executableName.bat" else executableName
val launcherFile = File("dist/kotlinc/bin/$executableFileName")
assertTrue("Launcher script not found, run dist task: ${launcherFile.absolutePath}", launcherFile.exists())
val mainKtsJar = File("dist/kotlinc/lib/kotlin-main-kts.jar")
assertTrue("kotlin-main-kts.jar not found, run dist task: ${mainKtsJar.absolutePath}", mainKtsJar.exists())
val processBuilder = ProcessBuilder(launcherFile.absolutePath, "-cp", mainKtsJar.absolutePath, "-script", scriptPath)
if (workDirectory != null) {
processBuilder.directory(workDirectory)
}
val process = processBuilder.start()
data class ExceptionContainer(
var value: Throwable? = null
)
fun InputStream.captureStream(): Triple<Thread, ExceptionContainer, ArrayList<String>> {
val out = ArrayList<String>()
val exceptionContainer = ExceptionContainer()
val thread = thread {
try {
reader().forEachLine {
out.add(it.trim())
}
} catch (e: Throwable) {
exceptionContainer.value = e
}
}
return Triple(thread, exceptionContainer, out)
}
val (stdoutThread, stdoutException, processOut) = process.inputStream.captureStream()
val (stderrThread, stderrException, processErr) = process.errorStream.captureStream()
process.waitFor(30000, TimeUnit.MILLISECONDS)
try {
if (process.isAlive) {
process.destroyForcibly()
fail("Process terminated forcibly")
}
stdoutThread.join(300)
assertFalse("stdout thread not finished", stdoutThread.isAlive)
assertNull(stdoutException.value)
stderrThread.join(300)
assertFalse("stderr thread not finished", stderrThread.isAlive)
assertNull(stderrException.value)
assertEquals(expectedOutPatterns.size, processOut.size)
for ((expectedPattern, actualLine) in expectedOutPatterns.zip(processOut)) {
assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"",
Regex(expectedPattern).matches(actualLine)
)
}
assertEquals(expectedExitCode, process.exitValue())
} catch (e: Throwable) {
println("OUT:\n${processOut.joinToString("\n")}")
println("ERR:\n${processErr.joinToString("\n")}")
throw e
}
}
@Test
fun testResolveJunit() {
runWithKotlinc("$TEST_DATA_ROOT/hello-resolve-junit.main.kts", listOf("Hello, World!"))
runWithKotlinc(
"$TEST_DATA_ROOT/hello-resolve-junit.main.kts", listOf("Hello, World!"),
classpath = listOf(
File("dist/kotlinc/lib/kotlin-main-kts.jar").also {
Assert.assertTrue("kotlin-main-kts.jar not found, run dist task: ${it.absolutePath}", it.exists())
}
)
)
}
@Test
@@ -54,5 +54,6 @@ javadocJar()
testsJar()
projectTest {
dependsOn(":dist")
workingDir = rootDir
}
@@ -5,13 +5,9 @@
package org.jetbrains.kotlin.scripting.compiler.plugin
import java.io.File
import junit.framework.Assert.*
import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import junit.framework.Assert
import org.junit.Test
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.io.File
class ScriptingWithCliCompilerTest {
@@ -24,58 +20,26 @@ class ScriptingWithCliCompilerTest {
runWithK2JVMCompiler("$TEST_DATA_DIR/integration/intResult.kts", listOf("10"))
}
@Test
fun testResultValueViaKotlinc() {
runWithKotlinc("$TEST_DATA_DIR/integration/intResult.kts", listOf("10"))
}
@Test
fun testStandardScriptWithDeps() {
runWithK2JVMCompiler("$TEST_DATA_DIR/integration/withDependencyOnCompileClassPath.kts", listOf("Hello from standard kts!"))
}
}
fun runWithK2JVMCompiler(
scriptPath: String,
expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0
) {
val mainKtsJar = File("dist/kotlinc/lib/kotlin-main-kts.jar")
assertTrue("kotlin-main-kts.jar not found, run dist task: ${mainKtsJar.absolutePath}", mainKtsJar.exists())
val (out, err, ret) = captureOutErrRet {
CLITool.doMainNoExit(
K2JVMCompiler(),
arrayOf("-kotlin-home", "dist/kotlinc", "-cp", mainKtsJar.absolutePath, "-script", scriptPath)
@Test
fun testStandardScriptWithDepsViaKotlinc() {
runWithKotlinc(
"$TEST_DATA_DIR/integration/withDependencyOnCompileClassPath.kts", listOf("Hello from standard kts!"),
classpath = listOf(
File("dist/kotlinc/lib/kotlin-main-kts.jar").also {
Assert.assertTrue("kotlin-main-kts.jar not found, run dist task: ${it.absolutePath}", it.exists())
}
)
)
}
try {
val outLines = out.lines()
assertEquals(expectedOutPatterns.size, outLines.size)
for ((expectedPattern, actualLine) in expectedOutPatterns.zip(outLines)) {
assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"",
Regex(expectedPattern).matches(actualLine)
)
}
assertEquals(expectedExitCode, ret.code)
} catch (e: Throwable) {
println("OUT:\n$out")
println("ERR:\n$err")
throw e
}
}
internal fun <T> captureOutErrRet(body: () -> T): Triple<String, String, T> {
val outStream = ByteArrayOutputStream()
val errStream = ByteArrayOutputStream()
val prevOut = System.out
val prevErr = System.err
System.setOut(PrintStream(outStream))
System.setErr(PrintStream(errStream))
val ret = try {
body()
} finally {
System.out.flush()
System.err.flush()
System.setOut(prevOut)
System.setErr(prevErr)
}
return Triple(outStream.toString().trim(), errStream.toString().trim(), ret)
}
@@ -0,0 +1,147 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.scripting.compiler.plugin
import junit.framework.Assert
import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.InputStream
import java.io.PrintStream
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
// TODO: partially copypasted from LauncherReplTest, consider extracting common parts to some (new) test util module
fun runWithKotlinc(
scriptPath: String,
expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0,
workDirectory: File? = null,
classpath: List<File> = emptyList()
) {
val executableName = "kotlinc"
// TODO:
val executableFileName =
if (System.getProperty("os.name").contains("windows", ignoreCase = true)) "$executableName.bat" else executableName
val launcherFile = File("dist/kotlinc/bin/$executableFileName")
Assert.assertTrue("Launcher script not found, run dist task: ${launcherFile.absolutePath}", launcherFile.exists())
val args = arrayListOf(launcherFile.absolutePath).apply {
if (classpath.isNotEmpty()) {
add("-cp")
add(classpath.joinToString(File.pathSeparator))
}
add("-script")
add(scriptPath)
}
val processBuilder = ProcessBuilder(args)
if (workDirectory != null) {
processBuilder.directory(workDirectory)
}
val process = processBuilder.start()
data class ExceptionContainer(
var value: Throwable? = null
)
fun InputStream.captureStream(): Triple<Thread, ExceptionContainer, ArrayList<String>> {
val out = ArrayList<String>()
val exceptionContainer = ExceptionContainer()
val thread = thread {
try {
reader().forEachLine {
out.add(it.trim())
}
} catch (e: Throwable) {
exceptionContainer.value = e
}
}
return Triple(thread, exceptionContainer, out)
}
val (stdoutThread, stdoutException, processOut) = process.inputStream.captureStream()
val (stderrThread, stderrException, processErr) = process.errorStream.captureStream()
process.waitFor(30000, TimeUnit.MILLISECONDS)
try {
if (process.isAlive) {
process.destroyForcibly()
Assert.fail("Process terminated forcibly")
}
stdoutThread.join(300)
Assert.assertFalse("stdout thread not finished", stdoutThread.isAlive)
Assert.assertNull(stdoutException.value)
stderrThread.join(300)
Assert.assertFalse("stderr thread not finished", stderrThread.isAlive)
Assert.assertNull(stderrException.value)
Assert.assertEquals(expectedOutPatterns.size, processOut.size)
for ((expectedPattern, actualLine) in expectedOutPatterns.zip(processOut)) {
Assert.assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"",
Regex(expectedPattern).matches(actualLine)
)
}
Assert.assertEquals(expectedExitCode, process.exitValue())
} catch (e: Throwable) {
println("OUT:\n${processOut.joinToString("\n")}")
println("ERR:\n${processErr.joinToString("\n")}")
throw e
}
}
fun runWithK2JVMCompiler(
scriptPath: String,
expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0
) {
val mainKtsJar = File("dist/kotlinc/lib/kotlin-main-kts.jar")
Assert.assertTrue("kotlin-main-kts.jar not found, run dist task: ${mainKtsJar.absolutePath}", mainKtsJar.exists())
val (out, err, ret) = captureOutErrRet {
CLITool.doMainNoExit(
K2JVMCompiler(),
arrayOf("-kotlin-home", "dist/kotlinc", "-cp", mainKtsJar.absolutePath, "-script", scriptPath)
)
}
try {
val outLines = out.lines()
Assert.assertEquals(expectedOutPatterns.size, outLines.size)
for ((expectedPattern, actualLine) in expectedOutPatterns.zip(outLines)) {
Assert.assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"",
Regex(expectedPattern).matches(actualLine)
)
}
Assert.assertEquals(expectedExitCode, ret.code)
} catch (e: Throwable) {
println("OUT:\n$out")
println("ERR:\n$err")
throw e
}
}
internal fun <T> captureOutErrRet(body: () -> T): Triple<String, String, T> {
val outStream = ByteArrayOutputStream()
val errStream = ByteArrayOutputStream()
val prevOut = System.out
val prevErr = System.err
System.setOut(PrintStream(outStream))
System.setErr(PrintStream(errStream))
val ret = try {
body()
} finally {
System.out.flush()
System.err.flush()
System.setOut(prevOut)
System.setErr(prevErr)
}
return Triple(outStream.toString().trim(), errStream.toString().trim(), ret)
}