@@ -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,65 +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- /* verify `dist/bin/scalac` */
44+ /* verify `dist/bin/scalac` non-interference with command line args following script name */
4645 @ Test def verifyScalacArgs =
47- printf(" scalacPath[%s]\n " , scalacPath)
4846 val commandline = (Seq (scalacPath, " -script" , showArgsScript) ++ testScriptArgs).mkString(" " )
49- if bashPath.toFile.exists then
50- var cmd = Array (bashExe, " -c" , commandline)
51- val output = Process (cmd).lazyLines_!
47+ val (validTest, exitCode, stdout, stderr) = bashCommand(commandline)
48+ if validTest then
5249 var fail = false
5350 printf(" \n " )
54- for (line, expect) <- output zip expectedOutput do
51+ for (line, expect) <- stdout zip expectedOutput do
5552 printf(" expected: %-17s\n actual : %s\n " , expect, line)
5653 if line != expect then
5754 fail = true
5855
5956 if fail then
60- assert(output == expectedOutput)
57+ assert(stdout == expectedOutput)
6158
62- /* verify `dist/bin/scala` */
59+ /* verify `dist/bin/scala` non-interference with command line args following script name */
6360 @ Test def verifyScalaArgs =
6461 val commandline = (Seq (scalaPath, showArgsScript) ++ testScriptArgs).mkString(" " )
65- if bashPath.toFile.exists then
66- var cmd = Array (bashExe, " -c" , commandline)
67- val output = for {
68- line <- Process (cmd).lazyLines_!
69- } yield line
62+ val (validTest, exitCode, stdout, stderr) = bashCommand(commandline)
63+ if validTest then
7064 var fail = false
7165 printf(" \n " )
7266 var mismatches = List .empty[(String , String )]
73- for (line, expect) <- output zip expectedOutput do
67+ for (line, expect) <- stdout zip expectedOutput do
7468 printf(" expected: %-17s\n actual : %s\n " , expect, line)
7569 if line != expect then
7670 fail = true
7771
7872 if fail then
79- assert(output == expectedOutput)
73+ assert(stdout == expectedOutput)
8074
8175 /*
82- * 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".
8378 */
8479 @ Test def verifyScriptPathProperty =
8580 val scriptFile = testFiles.find(_.getName == " scriptPath.sc" ).get
8681 val expected = s " / ${scriptFile.getName}"
8782 printf(" ===> verify valid system property script.path is reported by script [%s]\n " , scriptFile.getName)
88- val (exitCode, stdout, stderr) = bashCommand( scriptFile.absPath )
89- if exitCode == 0 && ! stderr.exists(_.contains( " Permission denied " )) then
90- // var cmd = Array(bashExe, "-c", scriptFile.absPath)
91- // val stdout = Process(cmd).lazyLines_!
92- 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 " , _) }
9388 val valid = stdout.exists { _.endsWith(expected) }
9489 if valid then printf(" # valid script.path reported by [%s]\n " , scriptFile.getName)
9590 assert(valid, s " script ${scriptFile.absPath} did not report valid script.path value " )
@@ -99,58 +94,111 @@ class BashScriptsTests:
9994 */
10095 @ Test def verifyScalaOpts =
10196 val scriptFile = testFiles.find(_.getName == " classpathReport.sc" ).get
102- printf(" ===> verify valid system property script.path is reported by script [%s]\n " , scriptFile.getName)
103- val argsfile = createArgsFile() // avoid problems caused by drive letter
97+ printf(" ===> verify SCALA_OPTS='@argsfile' is properly handled by `dist/bin/scala`\n " )
10498 val envPairs = List ((" SCALA_OPTS" , s " @ $argsfile" ))
105- val (exitCode, stdout, stderr) = bashCommand(scriptFile.absPath, envPairs:_* )
106- if exitCode != 0 || stderr.exists(_.contains(" Permission denied" )) then
107- stderr.foreach { System .err.printf(" stderr [%s]\n " , _) }
108- printf(" unable to execute script, return value is %d\n " , exitCode)
109- else
110- // val stdout: Seq[String] = Process(cmd, cwd, envPairs:_*).lazyLines_!.toList
111- 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}"
112102 val List (line1 : String , line2 : String ) = stdout.take(2 )
113103 val valid = line2.dropWhile( _ != ' ' ).trim.startsWith(expected)
114- 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)
115105 assert(valid, s " script ${scriptFile.absPath} did not report valid java.class.path first entry " )
116106
117- 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
118110
111+ lazy val argsfile = createArgsFile() // avoid problems caused by drive letter
119112 def createArgsFile (): String =
120113 val utfCharset = java.nio.charset.StandardCharsets .UTF_8 .name
121- val text = s " -classpath ${cwd.absPath}"
122114 val path = Files .createTempFile(" scriptingTest" , " .args" )
115+ val text = s " -classpath ${workingDirectory.absPath}"
123116 Files .write(path, text.getBytes(utfCharset))
124117 path.toFile.getAbsolutePath.replace('\\ ' , '/' )
125118
126- extension (str : String ) def dropExtension : String =
127- 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+ }
135+
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+ }
141+
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+ }
147+
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
128153
129- extension( f : File ) def absPath : String =
130- f.getAbsolutePath.replace( ' \\ ' , '/' )
154+ // use optional working directory TEST_CWD, if defined
155+ lazy val workingDirectory : String = envOrElse( " TEST_CWD " , userDir )
131156
132- lazy val osname = Option (sys.props(" os.name" )).getOrElse(" " ).toLowerCase
157+ // use optional TEST_BASH if defined, otherwise, bash must be in PATH
158+ lazy val bashExe : String = envOrElse(" TEST_BASH" , whichBash)
133159
134- def getBashPath : String =
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 =
135177 var whichBash = " "
136- // printf("osname[%s]\n", osname)
137178 if osname.startsWith(" windows" ) then
138179 whichBash = which(" bash.exe" )
139180 else
140181 whichBash = which(" bash" )
141182
142183 whichBash
143184
144- def bashCommand (cmdstr : String , envPairs : (String , String )* ): (Int , Seq [String ], Seq [String ]) = {
145- import scala .sys .process ._
146- val cmd = Seq (bashExe, " -c" , cmdstr)
147- val proc = Process (cmd, None , envPairs * )
185+ def bashCommand (cmdstr : String , additionalEnvPairs: List [(String , String )] = Nil ): (Boolean , Int , Seq [String ], Seq [String ]) = {
148186 var (stdout, stderr) = (List .empty[String ], List .empty[String ])
149- val exitVal = proc ! ProcessLogger (
150- (out : String ) => stdout ::= out,
151- (err : String ) => stderr ::= err
152- )
153- (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 )
154202 }
155203
156204 def execCmd (command : String , options : String * ): Seq [String ] =
0 commit comments