From 164744c91b65fe43f58356b9d02524aaad430823 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 22 Jul 2021 17:47:10 -0600 Subject: [PATCH 1/3] test added to BashScriptsTests to verify script.path property --- .../tools/scripting/BashScriptsTests.scala | 23 +++++++++++++++---- .../tools/scripting/ClasspathTests.scala | 3 +-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala index 499111f02f26..9fca7b2788cd 100644 --- a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala +++ b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala @@ -11,7 +11,10 @@ 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") } @@ -45,9 +48,7 @@ class BashScriptsTests: 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 @@ -77,6 +78,20 @@ class BashScriptsTests: if fail then assert(output == expectedOutput) + /* + * 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) + var cmd = Array(bashExe, "-c", scriptFile.absPath) + val output = Process(cmd).lazyLines_! + output.foreach { printf("[%s]\n",_) } + val valid = output.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") + extension (str: String) def dropExtension = str.reverse.dropWhile(_ != '.').drop(1).reverse 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) From 9dc41ffdebae82f0cb5194570ecd72c7a5b8e883 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 22 Jul 2021 19:09:49 -0600 Subject: [PATCH 2/3] test to verify SCALA_OPTS=@argsfile correctly adds to java.class.path --- .../tools/scripting/BashScriptsTests.scala | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala index 9fca7b2788cd..11ff84acac5e 100644 --- a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala +++ b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala @@ -17,7 +17,7 @@ import vulpix.TestConfiguration */ 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]", @@ -92,10 +92,35 @@ class BashScriptsTests: 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") - extension (str: String) def dropExtension = + /* + * 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")) + var cmd = Array(bashExe, "-c", scriptFile.absPath) + val output: Seq[String] = Process(cmd,cwd,envPairs:_*).lazyLines_!.toList + val expected = s"${cwd.toString}" + val List(line1: String, line2: String) = output.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 From 7705bafcd5182baa2d687bf4118a0c9bb39b8fe0 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 22 Jul 2021 20:15:05 -0600 Subject: [PATCH 3/3] prevent execute permissions from failing BashScriptsTests --- compiler/test-resources/scripting/hashBang.sc | 0 .../scripting/mainClassOnStack.sc | 0 .../test-resources/scripting/scriptPath.sc | 0 .../tools/scripting/BashScriptsTests.scala | 60 ++++++++++++------- 4 files changed, 39 insertions(+), 21 deletions(-) mode change 100644 => 100755 compiler/test-resources/scripting/hashBang.sc mode change 100644 => 100755 compiler/test-resources/scripting/mainClassOnStack.sc mode change 100644 => 100755 compiler/test-resources/scripting/scriptPath.sc 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 11ff84acac5e..4c0c17ec6cd1 100644 --- a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala +++ b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala @@ -31,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 @@ -44,7 +44,7 @@ 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) @@ -69,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 @@ -85,12 +85,14 @@ class BashScriptsTests: 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) - var cmd = Array(bashExe, "-c", scriptFile.absPath) - val output = Process(cmd).lazyLines_! - output.foreach { printf("[%s]\n",_) } - val valid = output.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") + 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`. @@ -99,23 +101,27 @@ class BashScriptsTests: 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")) - var cmd = Array(bashExe, "-c", scriptFile.absPath) - val output: Seq[String] = Process(cmd,cwd,envPairs:_*).lazyLines_!.toList - val expected = s"${cwd.toString}" - val List(line1: String, line2: String) = output.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") + 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") + val path = Files.createTempFile("scriptingTest", ".args") Files.write(path, text.getBytes(utfCharset)) - path.toFile.getAbsolutePath.replace('\\','/') + path.toFile.getAbsolutePath.replace('\\', '/') extension (str: String) def dropExtension: String = str.reverse.dropWhile(_ != '.').drop(1).reverse @@ -127,7 +133,7 @@ class BashScriptsTests: 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 @@ -135,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 {