From 6ea1d92841d39f33e028b69d90ab2ccef25fa5f9 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 25 Jun 2019 15:53:02 +0200 Subject: [PATCH] Implement main-kts test with command-line compiler --- .../kotlin-main-kts-test/build.gradle.kts | 5 +- .../kotlin/mainKts/test/mainKtsIT.kt | 94 +++++++++++++++++++ .../kotlin/mainKts/test/mainKtsTest.kt | 18 ++-- 3 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsIT.kt diff --git a/libraries/tools/kotlin-main-kts-test/build.gradle.kts b/libraries/tools/kotlin-main-kts-test/build.gradle.kts index 98bfe00eff4..e8ea6022ce1 100644 --- a/libraries/tools/kotlin-main-kts-test/build.gradle.kts +++ b/libraries/tools/kotlin-main-kts-test/build.gradle.kts @@ -25,4 +25,7 @@ sourceSets { "test" { projectDefault() } } -projectTest(parallel = true) +projectTest(parallel = true) { + dependsOn(":dist", ":kotlin-main-kts:dist") + workingDir = rootDir +} diff --git a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsIT.kt b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsIT.kt new file mode 100644 index 00000000000..b9b43928f06 --- /dev/null +++ b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsIT.kt @@ -0,0 +1,94 @@ +/* + * 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.mainKts.test + +import junit.framework.Assert.* +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 = emptyList(), + expectedExitCode: Int = 0, + workDirectory: File? = null + ) { + val executableName = "kotlinc" + val executableFileName = if (System.getProperty("os.name").startsWith("windows")) "$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> { + val out = ArrayList() + 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(10000, TimeUnit.MILLISECONDS) + + try { + if (process.isAlive) { + process.destroyForcibly() + fail("Process terminated forcibly") + } + stdoutThread.join(100) + assertFalse("stdout thread not finished", stdoutThread.isAlive) + assertNull(stdoutException.value) + assertFalse("stderr thread not finished", stderrThread.isAlive) + assertNull(stderrException.value) + assertEquals(expectedOutPatterns.size, processOut.size) + for (i in 0 until expectedOutPatterns.size) { + val expectedPattern = expectedOutPatterns[i] + val actualLine = processOut[i] + 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!")) + } +} diff --git a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt index 4ba7bdcd250..a9870426463 100644 --- a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt +++ b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt @@ -32,11 +32,13 @@ fun evalFile(scriptFile: File): ResultWithDiagnostics { return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), scriptDefinition, evaluationEnv) } +const val TEST_DATA_ROOT = "libraries/tools/kotlin-main-kts-test/testData" + class MainKtsTest { @Test fun testResolveJunit() { - val res = evalFile(File("testData/hello-resolve-junit.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/hello-resolve-junit.main.kts")) assertSucceeded(res) } @@ -46,34 +48,34 @@ class MainKtsTest { // TODO: 1. find non-default but non-pom dependency suitable for an example to test resolving // TODO: 2. implement proper handling of pom-typed dependencies (e.g. consider to reimplement it on aether as in JarRepositoryManager (from IDEA)) fun testResolveWithArtifactType() { - val res = evalFile(File("testData/resolve-moneta.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/resolve-moneta.main.kts")) assertSucceeded(res) } @Test fun testResolveJunitDynamicVer() { - val errRes = evalFile(File("testData/hello-resolve-junit-dynver-error.main.kts")) + val errRes = evalFile(File("$TEST_DATA_ROOT/hello-resolve-junit-dynver-error.main.kts")) assertFailed("Unresolved reference: assertThrows", errRes) - val res = evalFile(File("testData/hello-resolve-junit-dynver.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/hello-resolve-junit-dynver.main.kts")) assertSucceeded(res) } @Test fun testUnresolvedJunit() { - val res = evalFile(File("testData/hello-unresolved-junit.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/hello-unresolved-junit.main.kts")) assertFailed("Unresolved reference: junit", res) } @Test fun testResolveError() { - val res = evalFile(File("testData/hello-resolve-error.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/hello-resolve-error.main.kts")) assertFailed("Unrecognized set of arguments to ivy resolver: abracadabra", res) } @Test fun testResolveLog4jAndDocopt() { - val res = evalFile(File("testData/resolve-log4j-and-docopt.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/resolve-log4j-and-docopt.main.kts")) assertSucceeded(res) } @@ -81,7 +83,7 @@ class MainKtsTest { fun testImport() { val out = captureOut { - val res = evalFile(File("testData/import-test.main.kts")) + val res = evalFile(File("$TEST_DATA_ROOT/import-test.main.kts")) assertSucceeded(res) }.lines()