a4730dd57e
Otherwise the test would invoke the "java" executable from PATH, which might not be 1.8, and that would cause some tests to fail because error messages are slightly different in newer Java versions.
358 lines
13 KiB
Kotlin
358 lines
13 KiB
Kotlin
/*
|
|
* Copyright 2010-2015 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.cli
|
|
|
|
import com.intellij.openapi.util.SystemInfo
|
|
import com.intellij.openapi.util.text.StringUtil
|
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
|
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
|
|
import org.jetbrains.kotlin.test.util.KtTestUtil
|
|
import org.jetbrains.kotlin.utils.PathUtil
|
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
|
import java.io.File
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
class LauncherScriptTest : TestCaseWithTmpdir() {
|
|
private fun runProcess(
|
|
executableName: String,
|
|
vararg args: String,
|
|
expectedStdout: String = "",
|
|
expectedStderr: String = "",
|
|
expectedExitCode: Int = 0,
|
|
workDirectory: File? = null,
|
|
environment: Map<String, String> = mapOf("JAVA_HOME" to KtTestUtil.getJdk8Home().absolutePath),
|
|
) {
|
|
val executableFileName = if (SystemInfo.isWindows) "$executableName.bat" else executableName
|
|
val launcherFile = File(PathUtil.kotlinPathsForDistDirectory.homePath, "bin/$executableFileName")
|
|
assertTrue("Launcher script not found, run dist task: ${launcherFile.absolutePath}", launcherFile.exists())
|
|
|
|
// For some reason, IntelliJ's ExecUtil screws quotes up on windows.
|
|
// So, use ProcessBuilder instead.
|
|
val pb = ProcessBuilder(
|
|
launcherFile.absolutePath,
|
|
// In cmd, `=` is delimiter, so we need to surround parameter with quotes.
|
|
*quoteIfNeeded(args)
|
|
)
|
|
pb.environment().putAll(environment)
|
|
pb.directory(workDirectory)
|
|
val process = pb.start()
|
|
val stdout =
|
|
AbstractCliTest.getNormalizedCompilerOutput(
|
|
StringUtil.convertLineSeparators(process.inputStream.bufferedReader().use { it.readText() }),
|
|
null, testDataDirectory
|
|
)
|
|
val stderr =
|
|
AbstractCliTest.getNormalizedCompilerOutput(
|
|
StringUtil.convertLineSeparators(process.errorStream.bufferedReader().use { it.readText() }),
|
|
null, testDataDirectory
|
|
).replace("Picked up [_A-Z]+:.*\n".toRegex(), "")
|
|
.replace("The system cannot find the file specified", "No such file or directory") // win -> unix
|
|
process.waitFor(10, TimeUnit.SECONDS)
|
|
val exitCode = process.exitValue()
|
|
try {
|
|
assertEquals(expectedStdout, stdout)
|
|
assertEquals(expectedStderr, stderr)
|
|
assertEquals(expectedExitCode, exitCode)
|
|
} catch (e: Throwable) {
|
|
System.err.println("exit code $exitCode")
|
|
System.err.println("=== STDOUT ===")
|
|
System.err.println(stdout)
|
|
System.err.println("=== STDERR ===")
|
|
System.err.println(stderr)
|
|
throw e
|
|
} finally {
|
|
process.destroy()
|
|
}
|
|
}
|
|
|
|
private fun quoteIfNeeded(args: Array<out String>): Array<String> =
|
|
if (SystemInfo.isWindows) args.map {
|
|
if (it.contains('=') || it.contains(" ") || it.contains(";") || it.contains(",")) "\"$it\"" else it
|
|
}.toTypedArray()
|
|
else args.cast()
|
|
|
|
private val testDataDirectory: String
|
|
get() = KtTestUtil.getTestDataPathBase() + "/launcher"
|
|
|
|
fun testKotlincSimple() {
|
|
runProcess(
|
|
"kotlinc",
|
|
"$testDataDirectory/helloWorld.kt",
|
|
"-d", tmpdir.path
|
|
)
|
|
}
|
|
|
|
fun testKotlincJvmSimple() {
|
|
runProcess(
|
|
"kotlinc-jvm",
|
|
"$testDataDirectory/helloWorld.kt",
|
|
"-d", tmpdir.path
|
|
)
|
|
}
|
|
|
|
fun testKotlincJvmScriptWithClassPathFromSysProp() {
|
|
runProcess(
|
|
"kotlinc-jvm",
|
|
"-script",
|
|
"$testDataDirectory/classPathPropTest.kts",
|
|
expectedStdout = "kotlin-compiler.jar\n"
|
|
)
|
|
}
|
|
|
|
fun testKotlinJvmContextClassLoader() {
|
|
val kotlinTestJar = File(PathUtil.kotlinPathsForDistDirectory.homePath, "lib/kotlin-test.jar")
|
|
assertTrue("kotlin-main-kts.jar not found, run dist task: ${kotlinTestJar.absolutePath}", kotlinTestJar.exists())
|
|
runProcess(
|
|
"kotlinc",
|
|
"-cp", kotlinTestJar.path,
|
|
"$testDataDirectory/contextClassLoaderTester.kt",
|
|
"-d", tmpdir.path
|
|
)
|
|
|
|
runProcess(
|
|
"kotlin",
|
|
"-cp", listOf(tmpdir.path, kotlinTestJar.path).joinToString(File.pathSeparator),
|
|
"ContextClassLoaderTester",
|
|
expectedStdout = "${kotlinTestJar.name}\n"
|
|
)
|
|
}
|
|
|
|
fun testKotlincJsSimple() {
|
|
runProcess(
|
|
"kotlinc-js",
|
|
"$testDataDirectory/emptyMain.kt",
|
|
"-output", File(tmpdir, "out.js").path
|
|
)
|
|
}
|
|
|
|
fun testKotlinNoReflect() {
|
|
runProcess(
|
|
"kotlinc",
|
|
"$testDataDirectory/reflectionUsage.kt",
|
|
"-d", tmpdir.path
|
|
)
|
|
|
|
runProcess(
|
|
"kotlin",
|
|
"-cp", tmpdir.path,
|
|
"-no-reflect",
|
|
"ReflectionUsageKt",
|
|
expectedStdout = "no reflection"
|
|
)
|
|
}
|
|
|
|
fun testDoNotAppendCurrentDirToNonEmptyClasspath() {
|
|
runProcess(
|
|
"kotlinc",
|
|
"$testDataDirectory/helloWorld.kt",
|
|
"-d", tmpdir.path
|
|
)
|
|
|
|
runProcess("kotlin", "test.HelloWorldKt", expectedStdout = "Hello!\n", workDirectory = tmpdir)
|
|
|
|
val emptyDir = KotlinTestUtils.tmpDirForTest(this)
|
|
runProcess(
|
|
"kotlin",
|
|
"-cp", emptyDir.path,
|
|
"test.HelloWorldKt",
|
|
expectedStderr = "error: could not find or load main class test.HelloWorldKt\n",
|
|
expectedExitCode = 1,
|
|
workDirectory = tmpdir
|
|
)
|
|
}
|
|
|
|
fun testRunnerExpression() {
|
|
runProcess(
|
|
"kotlin",
|
|
"-e",
|
|
"val x = 2; (args + listOf(2,1).map { (it * x).toString() }).joinToString()",
|
|
"--",
|
|
"a",
|
|
"b",
|
|
expectedStdout = "a, b, 4, 2\n"
|
|
)
|
|
}
|
|
|
|
fun testCommandlineProcessing() {
|
|
runProcess(
|
|
"kotlin",
|
|
"-e",
|
|
"println(args.joinToString())",
|
|
"-a",
|
|
"b",
|
|
expectedStdout = "-a, b\n"
|
|
)
|
|
runProcess(
|
|
"kotlin",
|
|
"-e",
|
|
"println(args.joinToString())",
|
|
"--",
|
|
"-e",
|
|
"b",
|
|
expectedStdout = "-e, b\n"
|
|
)
|
|
runProcess(
|
|
"kotlin",
|
|
"$testDataDirectory/printargs.kts",
|
|
"-a",
|
|
"b",
|
|
expectedStdout = "-a, b\n"
|
|
)
|
|
runProcess(
|
|
"kotlin",
|
|
"$testDataDirectory/printargs.kts",
|
|
"--",
|
|
"-a",
|
|
"b",
|
|
expectedStdout = "-a, b\n"
|
|
)
|
|
}
|
|
|
|
fun testLegacyAssert() {
|
|
runProcess(
|
|
"kotlinc",
|
|
"$testDataDirectory/legacyAssertDisabled.kt", "-Xassertions=legacy", "-d", tmpdir.path
|
|
)
|
|
|
|
runProcess("kotlin", "LegacyAssertDisabledKt", "-J-da:kotlin._Assertions", workDirectory = tmpdir)
|
|
|
|
runProcess(
|
|
"kotlinc",
|
|
"$testDataDirectory/legacyAssertEnabled.kt", "-Xassertions=legacy", "-d", tmpdir.path
|
|
)
|
|
|
|
runProcess("kotlin", "LegacyAssertEnabledKt", "-J-ea:kotlin._Assertions", workDirectory = tmpdir)
|
|
}
|
|
|
|
fun testScriptWithXArguments() {
|
|
runProcess(
|
|
"kotlin", "-Xno-inline", "$testDataDirectory/noInline.kts",
|
|
expectedExitCode = 3,
|
|
expectedStderr = """java.lang.IllegalAccessError: tried to access method kotlin.io.ConsoleKt.println(Ljava/lang/Object;)V from class NoInline
|
|
at NoInline.<init>(noInline.kts:1)
|
|
""")
|
|
runProcess("kotlin", "$testDataDirectory/noInline.kts", expectedStdout = "OK\n")
|
|
}
|
|
|
|
fun testNoStdLib() {
|
|
runProcess("kotlin", "-e", "println(42)", expectedStdout = "42\n")
|
|
runProcess(
|
|
"kotlin", "-no-stdlib", "-e", "println(42)",
|
|
expectedExitCode = 1,
|
|
expectedStderr = """error: unresolved reference: println (script.kts:1:1)
|
|
error: no script runtime was found in the classpath: class 'kotlin.script.templates.standard.ScriptTemplateWithArgs' not found. Please add kotlin-script-runtime.jar to the module dependencies. (script.kts:1:1)
|
|
script.kts:1:1: error: unresolved reference: println
|
|
println(42)
|
|
^
|
|
script.kts:1:1: error: no script runtime was found in the classpath: class 'kotlin.script.templates.standard.ScriptTemplateWithArgs' not found. Please add kotlin-script-runtime.jar to the module dependencies.
|
|
println(42)
|
|
^
|
|
"""
|
|
)
|
|
}
|
|
|
|
fun testProperty() {
|
|
runProcess("kotlinc", "$testDataDirectory/property.kt", "-d", tmpdir.path)
|
|
|
|
runProcess(
|
|
"kotlin", "PropertyKt", "-Dresult=OK",
|
|
workDirectory = tmpdir, expectedStdout = "OK\n"
|
|
)
|
|
}
|
|
|
|
fun testHowToRunExpression() {
|
|
runProcess(
|
|
"kotlin", "-howtorun", "jar", "-e", "println(args.joinToString())", "-a", "b",
|
|
expectedExitCode = 1, expectedStderr = "error: expression evaluation is not compatible with -howtorun argument jar\n"
|
|
)
|
|
runProcess(
|
|
"kotlin", "-howtorun", "script", "-e", "println(args.joinToString())", "-a", "b",
|
|
expectedStdout = "-a, b\n"
|
|
)
|
|
}
|
|
|
|
fun testHowToRunScript() {
|
|
runProcess(
|
|
"kotlin", "-howtorun", "classfile", "$testDataDirectory/printargs.kts", "--", "-a", "b",
|
|
expectedExitCode = 1, expectedStderr = "error: could not find or load main class \$TESTDATA_DIR\$/printargs.kts\n"
|
|
)
|
|
runProcess(
|
|
"kotlin", "-howtorun", "script", "$testDataDirectory/printargs.kts", "--", "-a", "b",
|
|
expectedStdout = "-a, b\n"
|
|
)
|
|
}
|
|
|
|
fun testHowToRunCustomScript() {
|
|
runProcess(
|
|
"kotlin", "$testDataDirectory/noInline.myscript",
|
|
expectedExitCode = 1, expectedStderr = "error: could not find or load main class \$TESTDATA_DIR\$/noInline.myscript\n"
|
|
)
|
|
runProcess(
|
|
"kotlin", "-howtorun", "script", "$testDataDirectory/noInline.myscript",
|
|
expectedExitCode = 1, expectedStderr = "error: unrecognized script type: noInline.myscript; Specify path to the script file as the first argument\n"
|
|
)
|
|
runProcess(
|
|
"kotlin", "-howtorun", ".kts", "$testDataDirectory/noInline.myscript",
|
|
expectedExitCode = 1, expectedStderr = """error: unresolved reference: CompilerOptions (noInline.myscript:1:7)
|
|
compiler/testData/launcher/noInline.myscript:1:7: error: unresolved reference: CompilerOptions
|
|
@file:CompilerOptions("-Xno-inline")
|
|
^
|
|
"""
|
|
)
|
|
runProcess(
|
|
"kotlin", "-howtorun", ".main.kts", "$testDataDirectory/noInline.myscript",
|
|
expectedExitCode = 3,
|
|
expectedStderr = """java.lang.IllegalAccessError: tried to access method kotlin.io.ConsoleKt.println(Ljava/lang/Object;)V from class NoInline_main
|
|
at NoInline_main.<init>(noInline.myscript:3)
|
|
""")
|
|
}
|
|
|
|
fun testHowToRunClassFile() {
|
|
runProcess("kotlinc", "$testDataDirectory/helloWorld.kt", "-d", tmpdir.path)
|
|
|
|
runProcess(
|
|
"kotlin", "-howtorun", "jar", "test.HelloWorldKt", workDirectory = tmpdir,
|
|
expectedExitCode = 1,
|
|
expectedStderr = "error: could not read manifest from test.HelloWorldKt: test.HelloWorldKt (No such file or directory)\n"
|
|
)
|
|
runProcess("kotlin", "-howtorun", "classfile", "test.HelloWorldKt", expectedStdout = "Hello!\n", workDirectory = tmpdir)
|
|
}
|
|
|
|
fun testKotlincJdk15() {
|
|
val jdk15 = mapOf("JAVA_HOME" to KtTestUtil.getJdk15Home().absolutePath)
|
|
runProcess(
|
|
"kotlinc", "$testDataDirectory/helloWorld.kt", "-d", tmpdir.path,
|
|
environment = jdk15,
|
|
)
|
|
|
|
runProcess(
|
|
"kotlin", "-e", "listOf('O'.toString() + 'K')",
|
|
expectedStdout = "[OK]\n", environment = jdk15,
|
|
)
|
|
}
|
|
|
|
fun testEmptyJArgument() {
|
|
runProcess(
|
|
"kotlinc",
|
|
"$testDataDirectory/helloWorld.kt",
|
|
"-d", tmpdir.path,
|
|
"-J", expectedStdout = "error: empty -J argument\n",
|
|
expectedExitCode = 1
|
|
)
|
|
}
|
|
}
|