Support -J<jvm-param> and "-Dname=value" in windows runner script

Otherwise, -J-ea has no effect on windows, which breaks assert tests.
Wrap parameters with delimeters in quotes.
 #KT-30211 Fixed
This commit is contained in:
Ilmir Usmanov
2020-04-15 15:24:12 +02:00
parent ec50b1c85e
commit 5ab55fbb57
3 changed files with 90 additions and 47 deletions
+21 -3
View File
@@ -27,9 +27,27 @@ if "%_JAVACMD%"=="" set _JAVACMD=java
rem We use the value of the JAVA_OPTS environment variable if defined rem We use the value of the JAVA_OPTS environment variable if defined
if "%JAVA_OPTS%"=="" set JAVA_OPTS=-Xmx256M -Xms32M if "%JAVA_OPTS%"=="" set JAVA_OPTS=-Xmx256M -Xms32M
if not "%_KOTLIN_RUNNER%"=="" ( rem Iterate through arguments and split them into java and kotlin ones
:loop
set _arg=%~1
if "%_arg%" == "" goto loopend
if "%_arg:~0,2%"=="-J" (
set JAVA_OPTS=%JAVA_OPTS% "%_arg:~2%"
) else (
if "%_arg:~0,2%"=="-D" (
set JAVA_OPTS=%JAVA_OPTS% "%_arg%"
) else (
set KOTLIN_OPTS=%KOTLIN_OPTS% "%_arg%"
)
)
shift
goto loop
:loopend
if "%_KOTLIN_RUNNER%"=="1" (
"%_JAVACMD%" %JAVA_OPTS% "-Dkotlin.home=%_KOTLIN_HOME%" -cp "%_KOTLIN_HOME%\lib\kotlin-runner.jar" ^ "%_JAVACMD%" %JAVA_OPTS% "-Dkotlin.home=%_KOTLIN_HOME%" -cp "%_KOTLIN_HOME%\lib\kotlin-runner.jar" ^
org.jetbrains.kotlin.runner.Main %* org.jetbrains.kotlin.runner.Main %KOTLIN_OPTS%
) else ( ) else (
SET _ADDITIONAL_CLASSPATH= SET _ADDITIONAL_CLASSPATH=
@@ -39,7 +57,7 @@ if not "%_KOTLIN_RUNNER%"=="" (
"%_JAVACMD%" %JAVA_OPTS% -noverify -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^ "%_JAVACMD%" %JAVA_OPTS% -noverify -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^
org.jetbrains.kotlin.preloading.Preloader -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar%_ADDITIONAL_CLASSPATH%" ^ org.jetbrains.kotlin.preloading.Preloader -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar%_ADDITIONAL_CLASSPATH%" ^
%_KOTLIN_COMPILER% %* %_KOTLIN_COMPILER% %KOTLIN_OPTS%
) )
exit /b %ERRORLEVEL% exit /b %ERRORLEVEL%
+3
View File
@@ -0,0 +1,3 @@
fun main() {
println(System.getProperty("result"))
}
@@ -16,41 +16,48 @@
package org.jetbrains.kotlin.cli package org.jetbrains.kotlin.cli
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.util.ExecUtil
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestCaseWithTmpdir import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import java.io.File import org.jetbrains.kotlin.utils.addToStdlib.cast
import java.io.*
import java.util.concurrent.TimeUnit
class LauncherScriptTest : TestCaseWithTmpdir() { class LauncherScriptTest : TestCaseWithTmpdir() {
private fun runProcess( private fun runProcess(
executableName: String, executableName: String,
vararg args: String, vararg args: String,
expectedStdout: String = "", expectedStdout: String = "",
expectedStderr: String = "", expectedStderr: String = "",
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
workDirectory: File? = null workDirectory: File? = null
) { ) {
val executableFileName = if (SystemInfo.isWindows) "$executableName.bat" else executableName val executableFileName = if (SystemInfo.isWindows) "$executableName.bat" else executableName
val launcherFile = File(PathUtil.kotlinPathsForDistDirectory.homePath, "bin/$executableFileName") val launcherFile = File(PathUtil.kotlinPathsForDistDirectory.homePath, "bin/$executableFileName")
assertTrue("Launcher script not found, run dist task: ${launcherFile.absolutePath}", launcherFile.exists()) assertTrue("Launcher script not found, run dist task: ${launcherFile.absolutePath}", launcherFile.exists())
val cmd = GeneralCommandLine(launcherFile.absolutePath, *args) // For some reason, IntelliJ's ExecUtil screws quotes up on windows.
workDirectory?.let(cmd::withWorkDirectory) // So, use ProcessBuilder instead.
val processOutput = ExecUtil.execAndGetOutput(cmd) val pb = ProcessBuilder(
val stdout = StringUtil.convertLineSeparators(processOutput.stdout) launcherFile.absolutePath,
val stderr = StringUtil.convertLineSeparators(processOutput.stderr).replace("Picked up [_A-Z]+:.*\n".toRegex(), "") // In cmd, `=` is delimeter, so we need to surround parameter with quotes.
val exitCode = processOutput.exitCode *quoteIfNeeded(args)
)
pb.directory(workDirectory)
pb.environment().remove("_KOTLIN_RUNNER") // FIXME: HACK
val process = pb.start()
val stdout = StringUtil.convertLineSeparators(process.inputStream.bufferedReader().use { it.readText() })
val stderr = StringUtil.convertLineSeparators(process.errorStream.bufferedReader().use { it.readText() })
.replace("Picked up [_A-Z]+:.*\n".toRegex(), "")
process.waitFor(10, TimeUnit.SECONDS)
val exitCode = process.exitValue()
try { try {
assertEquals(expectedStdout, stdout) assertEquals(expectedStdout, stdout)
assertEquals(expectedStderr, stderr) assertEquals(expectedStderr, stderr)
assertEquals(expectedExitCode, exitCode) assertEquals(expectedExitCode, exitCode)
} } catch (e: Throwable) {
catch (e: Throwable) {
System.err.println("exit code $exitCode") System.err.println("exit code $exitCode")
System.err.println("=== STDOUT ===") System.err.println("=== STDOUT ===")
System.err.println(stdout) System.err.println(stdout)
@@ -60,22 +67,28 @@ class LauncherScriptTest : TestCaseWithTmpdir() {
} }
} }
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 private val testDataDirectory: String
get() = KotlinTestUtils.getTestDataPathBase() + "/launcher" get() = KotlinTestUtils.getTestDataPathBase() + "/launcher"
fun testKotlincSimple() { fun testKotlincSimple() {
runProcess( runProcess(
"kotlinc", "kotlinc",
"$testDataDirectory/helloWorld.kt", "$testDataDirectory/helloWorld.kt",
"-d", tmpdir.path "-d", tmpdir.path
) )
} }
fun testKotlincJvmSimple() { fun testKotlincJvmSimple() {
runProcess( runProcess(
"kotlinc-jvm", "kotlinc-jvm",
"$testDataDirectory/helloWorld.kt", "$testDataDirectory/helloWorld.kt",
"-d", tmpdir.path "-d", tmpdir.path
) )
} }
@@ -108,45 +121,45 @@ class LauncherScriptTest : TestCaseWithTmpdir() {
fun testKotlincJsSimple() { fun testKotlincJsSimple() {
runProcess( runProcess(
"kotlinc-js", "kotlinc-js",
"$testDataDirectory/emptyMain.kt", "$testDataDirectory/emptyMain.kt",
"-output", File(tmpdir, "out.js").path "-output", File(tmpdir, "out.js").path
) )
} }
fun testKotlinNoReflect() { fun testKotlinNoReflect() {
runProcess( runProcess(
"kotlinc", "kotlinc",
"$testDataDirectory/reflectionUsage.kt", "$testDataDirectory/reflectionUsage.kt",
"-d", tmpdir.path "-d", tmpdir.path
) )
runProcess( runProcess(
"kotlin", "kotlin",
"-cp", tmpdir.path, "-cp", tmpdir.path,
"-no-reflect", "-no-reflect",
"ReflectionUsageKt", "ReflectionUsageKt",
expectedStdout = "no reflection" expectedStdout = "no reflection"
) )
} }
fun testDoNotAppendCurrentDirToNonEmptyClasspath() { fun testDoNotAppendCurrentDirToNonEmptyClasspath() {
runProcess( runProcess(
"kotlinc", "kotlinc",
"$testDataDirectory/helloWorld.kt", "$testDataDirectory/helloWorld.kt",
"-d", tmpdir.path "-d", tmpdir.path
) )
runProcess("kotlin", "test.HelloWorldKt", expectedStdout = "Hello!\n", workDirectory = tmpdir) runProcess("kotlin", "test.HelloWorldKt", expectedStdout = "Hello!\n", workDirectory = tmpdir)
val emptyDir = KotlinTestUtils.tmpDirForTest(this) val emptyDir = KotlinTestUtils.tmpDirForTest(this)
runProcess( runProcess(
"kotlin", "kotlin",
"-cp", emptyDir.path, "-cp", emptyDir.path,
"test.HelloWorldKt", "test.HelloWorldKt",
expectedStderr = "error: could not find or load main class test.HelloWorldKt\n", expectedStderr = "error: could not find or load main class test.HelloWorldKt\n",
expectedExitCode = 1, expectedExitCode = 1,
workDirectory = tmpdir workDirectory = tmpdir
) )
} }
@@ -177,4 +190,13 @@ class LauncherScriptTest : TestCaseWithTmpdir() {
runProcess("kotlin", "LegacyAssertEnabledKt", "-J-ea:kotlin._Assertions", workDirectory = tmpdir) runProcess("kotlin", "LegacyAssertEnabledKt", "-J-ea:kotlin._Assertions", workDirectory = tmpdir)
} }
fun testProperty() {
runProcess("kotlinc", "$testDataDirectory/property.kt", "-d", tmpdir.path)
runProcess(
"kotlin", "PropertyKt", "-Dresult=OK",
workDirectory = tmpdir, expectedStdout = "OK\n"
)
}
} }