@@ -10,6 +10,7 @@ import org.junit.Test
1010
1111import vulpix .TestConfiguration
1212
13+ import dotty .tools .dotc .config .Properties ._
1314
1415/** Verifies correct handling of command line arguments by `dist/bin/scala` and `dist/bin/scalac`.
1516 * +. arguments following a script path must be treated as script arguments
@@ -19,6 +20,13 @@ class BashScriptsTests:
1920 // classpath tests managed by scripting.ClasspathTests.scala
2021 def testFiles = scripts(" /scripting" )
2122
23+ printf(" osname[%s]\n " , osname)
24+ printf(" using JAVA_HOME=%s\n " , javaHome)
25+ printf(" using SCALA_HOME=%s\n " , scalaHome)
26+ printf(" first 5 PATH entries:\n %s\n " , pathEntries.take(5 ).mkString(" \n " ))
27+ printf(" scala path: [%s]\n " , scalaPath)
28+ printf(" scalac path: [%s]\n " , scalacPath)
29+
2230 lazy val expectedOutput = List (
2331 " arg 0:[a]" ,
2432 " arg 1:[b]" ,
@@ -31,70 +39,52 @@ class BashScriptsTests:
3139 lazy val testScriptArgs = Seq (
3240 " a" , " b" , " c" , " -repl" , " -run" , " -script" , " -debug"
3341 )
34- lazy val (bashExe, bashPath) =
35- val bexe = getBashPath
36- val bpath = Paths .get(bexe)
37- // printf("bashExe: [%s]\n", bexe)
38- (bexe, bpath)
39-
4042 val showArgsScript = testFiles.find(_.getName == " showArgs.sc" ).get.absPath
4143
42- val scalacPath = " dist/target/pack/bin/scalac" // which("scalac")
43- val scalaPath = " dist/target/pack/bin/scala" // which("scala")
44-
45- def isFile (path : String ): Boolean =
46- Files .isRegularFile(Paths .get(path))
47-
48- /* verify `dist/bin/scalac` */
44+ /* verify `dist/bin/scalac` non-interference with command line args following script name */
4945 @ Test def verifyScalacArgs =
50- assert(isFile(scalacPath))
51- printf(" scalacPath[%s]\n " ,scalacPath)
5246 val commandline = (Seq (scalacPath, " -script" , showArgsScript) ++ testScriptArgs).mkString(" " )
53- if bashPath.toFile.exists then
54- var cmd = Array (bashExe, " -c" , commandline)
55- val output = Process (cmd).lazyLines_!
47+ val (validTest, exitCode, stdout, stderr) = bashCommand(commandline)
48+ if validTest then
5649 var fail = false
5750 printf(" \n " )
58- for (line, expect) <- output zip expectedOutput do
51+ for (line, expect) <- stdout zip expectedOutput do
5952 printf(" expected: %-17s\n actual : %s\n " , expect, line)
6053 if line != expect then
6154 fail = true
6255
6356 if fail then
64- assert(output == expectedOutput)
57+ assert(stdout == expectedOutput)
6558
66- /* verify `dist/bin/scala` */
59+ /* verify `dist/bin/scala` non-interference with command line args following script name */
6760 @ Test def verifyScalaArgs =
68- assert(isFile(scalaPath))
6961 val commandline = (Seq (scalaPath, showArgsScript) ++ testScriptArgs).mkString(" " )
70- if bashPath.toFile.exists then
71- var cmd = Array (bashExe, " -c" , commandline)
72- val output = for {
73- line <- Process (cmd).lazyLines_!
74- } yield line
62+ val (validTest, exitCode, stdout, stderr) = bashCommand(commandline)
63+ if validTest then
7564 var fail = false
7665 printf(" \n " )
7766 var mismatches = List .empty[(String , String )]
78- for (line, expect) <- output zip expectedOutput do
67+ for (line, expect) <- stdout zip expectedOutput do
7968 printf(" expected: %-17s\n actual : %s\n " , expect, line)
8069 if line != expect then
8170 fail = true
8271
8372 if fail then
84- assert(output == expectedOutput)
73+ assert(stdout == expectedOutput)
8574
8675 /*
87- * verify that scriptPath.sc sees a valid script.path property.
76+ * verify that scriptPath.sc sees a valid script.path property,
77+ * and that it's value is the path to "scriptPath.sc".
8878 */
8979 @ Test def verifyScriptPathProperty =
9080 val scriptFile = testFiles.find(_.getName == " scriptPath.sc" ).get
9181 val expected = s " / ${scriptFile.getName}"
9282 printf(" ===> verify valid system property script.path is reported by script [%s]\n " , scriptFile.getName)
93- val (exitCode, stdout, stderr) = bashCommand( scriptFile.absPath )
94- if exitCode == 0 && ! stderr.exists(_.contains( " Permission denied " )) then
95- // var cmd = Array(bashExe, "-c", scriptFile.absPath)
96- // val stdout = Process(cmd).lazyLines_!
97- stdout .foreach { printf(" ######### [%s]\n " , _) }
83+ printf( " calling scriptFile: %s \n " , scriptFile)
84+ val (validTest, exitCode, stdout, stderr) = bashCommand(scriptFile.absPath)
85+ if validTest then
86+ stdout.foreach { printf( " stdout: [%s] \n " , _) }
87+ stderr .foreach { printf(" stderr: [%s]\n " , _) }
9888 val valid = stdout.exists { _.endsWith(expected) }
9989 if valid then printf(" # valid script.path reported by [%s]\n " , scriptFile.getName)
10090 assert(valid, s " script ${scriptFile.absPath} did not report valid script.path value " )
@@ -104,58 +94,111 @@ class BashScriptsTests:
10494 */
10595 @ Test def verifyScalaOpts =
10696 val scriptFile = testFiles.find(_.getName == " classpathReport.sc" ).get
107- printf(" ===> verify valid system property script.path is reported by script [%s]\n " , scriptFile.getName)
108- val argsfile = createArgsFile() // avoid problems caused by drive letter
97+ printf(" ===> verify SCALA_OPTS='@argsfile' is properly handled by `dist/bin/scala`\n " )
10998 val envPairs = List ((" SCALA_OPTS" , s " @ $argsfile" ))
110- val (exitCode, stdout, stderr) = bashCommand(scriptFile.absPath, envPairs:_* )
111- if exitCode != 0 || stderr.exists(_.contains(" Permission denied" )) then
112- stderr.foreach { System .err.printf(" stderr [%s]\n " , _) }
113- printf(" unable to execute script, return value is %d\n " , exitCode)
114- else
115- // val stdout: Seq[String] = Process(cmd, cwd, envPairs:_*).lazyLines_!.toList
116- val expected = s " ${cwd.toString}"
99+ val (validTest, exitCode, stdout, stderr) = bashCommand(scriptFile.absPath, envPairs)
100+ if validTest then
101+ val expected = s " ${workingDirectory.toString}"
117102 val List (line1 : String , line2 : String ) = stdout.take(2 )
118103 val valid = line2.dropWhile( _ != ' ' ).trim.startsWith(expected)
119- if valid then printf(s " \n ===> success: classpath begins with %s, as reported by [%s] \n " , cwd , scriptFile.getName)
104+ if valid then printf(s " \n ===> success: classpath begins with %s, as reported by [%s] \n " , workingDirectory , scriptFile.getName)
120105 assert(valid, s " script ${scriptFile.absPath} did not report valid java.class.path first entry " )
121106
122- lazy val cwd = Paths .get(dotty.tools.dotc.config.Properties .userDir).toFile
107+ def existingPath : String = envOrElse(" PATH" ," " ).norm
108+ def adjustedPath = s " $javaHome/bin $psep$scalaHome/bin $psep$existingPath"
109+ def pathEntries = adjustedPath.split(psep).toList
123110
111+ lazy val argsfile = createArgsFile() // avoid problems caused by drive letter
124112 def createArgsFile (): String =
125113 val utfCharset = java.nio.charset.StandardCharsets .UTF_8 .name
126- val text = s " -classpath ${cwd.absPath}"
127114 val path = Files .createTempFile(" scriptingTest" , " .args" )
115+ val text = s " -classpath ${workingDirectory.absPath}"
128116 Files .write(path, text.getBytes(utfCharset))
129117 path.toFile.getAbsolutePath.replace('\\ ' , '/' )
130118
131- extension (str : String ) def dropExtension : String =
132- str.reverse.dropWhile(_ != '.' ).drop(1 ).reverse
119+ def fixHome (s : String ): String =
120+ s.startsWith(" ~" ) match {
121+ case false => s
122+ case true => s.replaceFirst(" ~" ,userHome)
123+ }
124+
125+ extension(s : String ) {
126+ def toPath : Path = Paths .get(fixHome(s)) // .toAbsolutePath
127+ def toFile : File = s.toPath.toFile
128+ def absPath : String = s.toFile.absPath
129+ def norm : String = s.replace('\\ ' , '/' ) // bash expects forward slash
130+ def isFile : Boolean = s.toFile.isFile
131+ def exists : Boolean = s.toPath.toFile.exists
132+ def name : String = s.toFile.getName
133+ def dropExtension : String = s.reverse.dropWhile(_ != '.' ).drop(1 ).reverse
134+ }
133135
134- extension(f : File ) def absPath : String =
135- f.getAbsolutePath.replace('\\ ' , '/' )
136+ extension(p : Path ) {
137+ def listFiles : Seq [File ] = p.toFile.listFiles.toList
138+ def norm : String = p.normalize.toString.replace('\\ ' , '/' )
139+ def name : String = p.toFile.getName
140+ }
136141
137- lazy val osname = Option (sys.props(" os.name" )).getOrElse(" " ).toLowerCase
142+ extension(f : File ) {
143+ def name = f.getName
144+ def norm : String = f.toPath.normalize.norm
145+ def absPath : String = f.getAbsolutePath.norm
146+ }
138147
139- def getBashPath : String =
148+ lazy val psep : String = propOrElse(" path.separator" ," " )
149+ lazy val osname = propOrElse(" os.name" , " " ).toLowerCase
150+
151+ lazy val scalacPath = s " $workingDirectory/dist/target/pack/bin/scalac " .norm
152+ lazy val scalaPath = s " $workingDirectory/dist/target/pack/bin/scala " .norm
153+
154+ // use optional working directory TEST_CWD, if defined
155+ lazy val workingDirectory : String = envOrElse(" TEST_CWD" , userDir)
156+
157+ // use optional TEST_BASH if defined, otherwise, bash must be in PATH
158+ lazy val bashExe : String = envOrElse(" TEST_BASH" , whichBash)
159+
160+ // test env SCALA_HOME is:
161+ // dist/target/pack, if present
162+ // else, SCALA_HOME if defined
163+ // else, not defined
164+ lazy val scalaHome =
165+ if scalacPath.isFile then scalacPath.replaceAll(" /bin/scalac" ," " )
166+ else envOrElse(" SCALA_HOME" , " " ).norm
167+
168+ lazy val javaHome = envOrElse(" JAVA_HOME" , " " ).norm
169+
170+ lazy val testEnvPairs = List (
171+ (" JAVA_HOME" , javaHome),
172+ (" SCALA_HOME" , scalaHome),
173+ (" PATH" , adjustedPath),
174+ ).filter { case (name,valu) => valu.nonEmpty }
175+
176+ lazy val whichBash : String =
140177 var whichBash = " "
141- // printf("osname[%s]\n", osname)
142178 if osname.startsWith(" windows" ) then
143179 whichBash = which(" bash.exe" )
144180 else
145181 whichBash = which(" bash" )
146182
147183 whichBash
148184
149- def bashCommand (cmdstr : String , envPairs : (String , String )* ): (Int , Seq [String ], Seq [String ]) = {
150- import scala .sys .process ._
151- val cmd = Seq (bashExe, " -c" , cmdstr)
152- val proc = Process (cmd, None , envPairs * )
185+ def bashCommand (cmdstr : String , additionalEnvPairs: List [(String , String )] = Nil ): (Boolean , Int , Seq [String ], Seq [String ]) = {
153186 var (stdout, stderr) = (List .empty[String ], List .empty[String ])
154- val exitVal = proc ! ProcessLogger (
155- (out : String ) => stdout ::= out,
156- (err : String ) => stderr ::= err
157- )
158- (exitVal, stdout.reverse, stderr.reverse)
187+ if bashExe.toFile.exists then
188+ val cmd = Seq (bashExe, " -c" , cmdstr)
189+ val envPairs = testEnvPairs ++ additionalEnvPairs
190+ val proc = Process (cmd, None , envPairs * )
191+ val exitVal = proc ! ProcessLogger (
192+ (out : String ) => stdout ::= out,
193+ (err : String ) => stderr ::= err
194+ )
195+ val validTest = exitVal == 0 && ! stderr.exists(_.contains(" Permission denied" ))
196+ if ! validTest then
197+ printf(" \n unable to execute script, return value is %d\n " , exitVal)
198+ stderr.foreach { System .err.printf(" stderr [%s]\n " , _) }
199+ (validTest, exitVal, stdout.reverse, stderr.reverse)
200+ else
201+ (false , - 1 , Nil , Nil )
159202 }
160203
161204 def execCmd (command : String , options : String * ): Seq [String ] =
0 commit comments