diff --git a/compiler/test-resources/scripting/hashBang.sc b/compiler/test-resources/scripting/hashBang.sc old mode 100644 new mode 100755 diff --git a/compiler/test-resources/scripting/mainClassOnStack.sc b/compiler/test-resources/scripting/mainClassOnStack.sc old mode 100644 new mode 100755 diff --git a/compiler/test-resources/scripting/scriptPath.sc b/compiler/test-resources/scripting/scriptPath.sc old mode 100644 new mode 100755 diff --git a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala index 499111f02f26..4c0c17ec6cd1 100644 --- a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala +++ b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala @@ -11,10 +11,13 @@ import org.junit.Test import vulpix.TestConfiguration -/** Runs all tests contained in `compiler/test-resources/scripting/` */ +/** Verifies correct handling of command line arguments by `dist/bin/scala` and `dist/bin/scalac`. + * +. arguments following a script path must be treated as script arguments + * +. preserve script command line arguments. + */ class BashScriptsTests: // classpath tests managed by scripting.ClasspathTests.scala - def testFiles = scripts("/scripting").filter { ! _.getName.startsWith("classpath") } + def testFiles = scripts("/scripting") lazy val expectedOutput = List( "arg 0:[a]", @@ -28,10 +31,10 @@ class BashScriptsTests: lazy val testScriptArgs = Seq( "a", "b", "c", "-repl", "-run", "-script", "-debug" ) - lazy val (bashExe,bashPath) = + lazy val (bashExe, bashPath) = val bexe = getBashPath val bpath = Paths.get(bexe) - printf("bashExe: [%s]\n", bexe) + // printf("bashExe: [%s]\n", bexe) (bexe, bpath) val showArgsScript = testFiles.find(_.getName == "showArgs.sc").get.absPath @@ -41,13 +44,11 @@ class BashScriptsTests: /* verify `dist/bin/scalac` */ @Test def verifyScalacArgs = - printf("scalacPath[%s]\n",scalacPath) + printf("scalacPath[%s]\n", scalacPath) val commandline = (Seq(scalacPath, "-script", showArgsScript) ++ testScriptArgs).mkString(" ") if bashPath.toFile.exists then var cmd = Array(bashExe, "-c", commandline) - val output = for { - line <- Process(cmd).lazyLines_! - } yield line + val output = Process(cmd).lazyLines_! var fail = false printf("\n") for (line, expect) <- output zip expectedOutput do @@ -68,7 +69,7 @@ class BashScriptsTests: } yield line var fail = false printf("\n") - var mismatches = List.empty[(String,String)] + var mismatches = List.empty[(String, String)] for (line, expect) <- output zip expectedOutput do printf("expected: %-17s\nactual : %s\n", expect, line) if line != expect then @@ -77,17 +78,62 @@ class BashScriptsTests: if fail then assert(output == expectedOutput) - extension (str: String) def dropExtension = + /* + * verify that scriptPath.sc sees a valid script.path property. + */ + @Test def verifyScriptPathProperty = + val scriptFile = testFiles.find(_.getName == "scriptPath.sc").get + val expected = s"/${scriptFile.getName}" + printf("===> verify valid system property script.path is reported by script [%s]\n", scriptFile.getName) + val (exitCode, stdout, stderr) = bashCommand(scriptFile.absPath) + if exitCode == 0 && ! stderr.exists(_.contains("Permission denied")) then + // var cmd = Array(bashExe, "-c", scriptFile.absPath) + // val stdout = Process(cmd).lazyLines_! + stdout.foreach { printf("######### [%s]\n", _) } + val valid = stdout.exists { _.endsWith(expected) } + if valid then printf("# valid script.path reported by [%s]\n", scriptFile.getName) + assert(valid, s"script ${scriptFile.absPath} did not report valid script.path value") + + /* + * verify SCALA_OPTS can specify an @argsfile when launching a scala script in `dist/bin/scala`. + */ + @Test def verifyScalaOpts = + val scriptFile = testFiles.find(_.getName == "classpathReport.sc").get + printf("===> verify valid system property script.path is reported by script [%s]\n", scriptFile.getName) + val argsfile = createArgsFile() // avoid problems caused by drive letter + val envPairs = List(("SCALA_OPTS", s"@$argsfile")) + val (exitCode, stdout, stderr) = bashCommand(scriptFile.absPath, envPairs:_*) + if exitCode != 0 || stderr.exists(_.contains("Permission denied")) then + stderr.foreach { System.err.printf("stderr [%s]\n", _) } + printf("unable to execute script, return value is %d\n", exitCode) + else + // val stdout: Seq[String] = Process(cmd, cwd, envPairs:_*).lazyLines_!.toList + val expected = s"${cwd.toString}" + val List(line1: String, line2: String) = stdout.take(2) + val valid = line2.dropWhile( _ != ' ').trim.startsWith(expected) + if valid then printf(s"\n===> success: classpath begins with %s, as reported by [%s]\n", cwd, scriptFile.getName) + assert(valid, s"script ${scriptFile.absPath} did not report valid java.class.path first entry") + + lazy val cwd = Paths.get(dotty.tools.dotc.config.Properties.userDir).toFile + + def createArgsFile(): String = + val utfCharset = java.nio.charset.StandardCharsets.UTF_8.name + val text = s"-classpath ${cwd.absPath}" + val path = Files.createTempFile("scriptingTest", ".args") + Files.write(path, text.getBytes(utfCharset)) + path.toFile.getAbsolutePath.replace('\\', '/') + + extension (str: String) def dropExtension: String = str.reverse.dropWhile(_ != '.').drop(1).reverse - extension(f: File) def absPath = + extension(f: File) def absPath: String = f.getAbsolutePath.replace('\\', '/') lazy val osname = Option(sys.props("os.name")).getOrElse("").toLowerCase def getBashPath: String = var whichBash = "" - printf("osname[%s]\n", osname) + //printf("osname[%s]\n", osname) if osname.startsWith("windows") then whichBash = which("bash.exe") else @@ -95,6 +141,18 @@ class BashScriptsTests: whichBash + def bashCommand(cmdstr: String, envPairs: (String, String)*): (Int, Seq[String], Seq[String]) = { + import scala.sys.process._ + val cmd = Seq(bashExe, "-c", cmdstr) + val proc = Process(cmd, None, envPairs *) + var (stdout, stderr) = (List.empty[String], List.empty[String]) + val exitVal = proc ! ProcessLogger ( + (out: String) => stdout ::= out, + (err: String) => stderr ::= err + ) + (exitVal, stdout.reverse, stderr.reverse) + } + def execCmd(command: String, options: String *): Seq[String] = val cmd = (command :: options.toList).toSeq for { diff --git a/compiler/test/dotty/tools/scripting/ClasspathTests.scala b/compiler/test/dotty/tools/scripting/ClasspathTests.scala index 7788884923f7..7ef0f9ee3fb3 100755 --- a/compiler/test/dotty/tools/scripting/ClasspathTests.scala +++ b/compiler/test/dotty/tools/scripting/ClasspathTests.scala @@ -56,8 +56,7 @@ class ClasspathTests: printf("bash is [%s]\n", bashExe) if packBinScalaExists then - val echoTest = "" // "SCALAC_ECHO_TEST=1" - val bashCmdline = s"SCALA_OPTS= $echoTest ${scalaCopy.norm} -classpath '$wildcardEntry' $relpath" + val bashCmdline = s"SCALA_OPTS= ${scalaCopy.norm} -classpath '$wildcardEntry' $relpath" // ask [dist/bin/scalac] to echo generated command line so we can verify some things val cmd = Array(bashExe, "-c", bashCmdline)