@@ -4,187 +4,64 @@ package scripting
4
4
5
5
import scala .language .unsafeNulls
6
6
7
- import java .io .File
8
- import java .nio .file .Files
9
- import org .junit .Test
7
+ import java .nio .file .Files , java .nio .charset .StandardCharsets .UTF_8
8
+ import org .junit .{ After , Test }
10
9
import org .junit .Assert .assertEquals
11
10
import org .junit .experimental .categories .Category
12
11
13
12
import ScriptTestEnv .*
14
13
15
-
16
- object BashExitCodeTests :
17
- private def testFiles = scripts(" /scripting/exit-code-tests" )
18
-
19
- /*
20
- * Compiles the class checking exit code
21
- *
22
- * @param testName name of the test
23
- * @param expectedExitCode expected exit code from the output
24
- */
25
- private def compileAndVerifyExitCode (
26
- testName : String ,
27
- expectedExitCode : Int ,
28
- )(using temporaryDir : File ): Unit =
29
- assertTestExists(testName) { testFile =>
30
- val testFilePath = testFile.absPath
31
- val commandline = (Seq (scalacPath, " -d" , temporaryDir.absPath, testFilePath)).mkString(" " )
32
- val (validTest, exitCode, _, _) = bashCommand(commandline)
33
- if verifyValid(validTest) then
34
- assertEquals(expectedExitCode, exitCode)
35
- }
36
-
37
- /*
38
- * Runs compiled code checking the exit code
39
- *
40
- * @param className name of compiled class
41
- * @param runExitCode expected exit code from the runner
42
- */
43
- private def runClassAndVerifyExitCode (
44
- className : String ,
45
- expectedExitCode : Int
46
- )(using temporaryDir : File ): Unit =
47
- val testClassFile = temporaryDir.files.find(_.getName == s " $className.class " )
48
- assert(testClassFile.isDefined)
49
- val commandline = (Seq (scalaPath, " -classpath" , temporaryDir.absPath, className)).mkString(" " )
50
- val (validTest, exitCode, _, _) = bashCommand(commandline)
51
- if verifyValid(validTest) then
52
- assertEquals(expectedExitCode, exitCode)
53
-
54
- /*
55
- * Compiles and then runs code verifying runner status code
56
- *
57
- * @param testName name of the test
58
- * @param className name of compiled class
59
- * @param expectedRunExitCode expected exit code from the runner
60
- */
61
- private def compileRunAndVerifyExitCode (
62
- testName : String ,
63
- className : String ,
64
- expectedRunExitCode : Int ,
65
- )(using File ): Unit =
66
- compileAndVerifyExitCode(testName, 0 )
67
- runClassAndVerifyExitCode(className, expectedRunExitCode)
68
-
69
- /*
70
- * Runs the command and checks the exit code
71
- *
72
- * @param args arguments for command line
73
- * @param expectedExitCode expected exit code from the output
74
- */
75
- private def testCommandExitCode (args : Seq [String ], expectedExitCode : Int ): Unit =
76
- val commandline = args.mkString(" " )
77
- val (validTest, exitCode, _, _) = bashCommand(commandline)
78
- if verifyValid(validTest) then
79
- assertEquals(expectedExitCode, exitCode)
80
-
81
- /*
82
- * Checks if scripting test resources contains test with given `testName`
83
- * And then runs function `test`
84
- *
85
- * @param testName name of the test containing the extension
86
- * @param test check to be run on found test file
87
- */
88
- private def assertTestExists (testName : String )(test : File => Unit ) =
89
- val file = testFiles.find(_.getName == testName)
90
- assert(file.isDefined)
91
- test(file.get)
92
-
93
- /*
94
- * Runs test for created temporary file
95
- * and ensures it deletion after function execution
96
- *
97
- * @param test check to be run on found test file
98
- */
99
- private def withTempFile (test : File => Unit ) =
100
- val tempFile = Files .createTempFile(" temp-file" , " .class" ).toFile
101
- try {
102
- test(tempFile)
103
- } finally {
104
- Util .deleteFile(tempFile)
105
- }
106
-
107
- /*
108
- * Runs test with implicit temporary directory
109
- * and ensures it deletion after the function execution
110
- *
111
- * @param test test to be run with given temporary directory
112
- */
113
- private def withTempDirectory (test : File ?=> Unit ) =
114
- given file : File = Files .createTempDirectory(" exit-code-tests" ).toFile
115
- try { test } finally { Util .deleteFile(file) }
116
-
117
- /*
118
- * Returns path to the generated tasty file for given directory and classname
119
- */
120
- private def getGeneratedTastyPath (className : String )(using temporaryDir : File ): String =
121
- val file = temporaryDir.files.find(_.getName == s " $className.tasty " )
122
- assert(file.isDefined)
123
- file.get.absPath
124
-
125
14
@ Category (Array (classOf [BootstrappedOnlyTests ]))
126
15
class BashExitCodeTests :
127
- import BashExitCodeTests .*
128
-
129
- @ Test def verifyExitCodeOnCompileError : Unit =
130
- withTempDirectory(compileAndVerifyExitCode(" compileError.scala" , 1 ))
131
-
132
- @ Test def verifyExitCodeOnRuntimeError : Unit =
133
- withTempDirectory(compileRunAndVerifyExitCode(" runtimeError.scala" , " runtimeError" , 1 ))
16
+ private var myTmpDir : String | Null = null
17
+ private lazy val tmpDir = { myTmpDir = Files .createTempDirectory(" exit-code-tests" ).toFile.absPath; myTmpDir }
18
+ @ After def cleanup (): Unit = if myTmpDir != null then io.Directory (myTmpDir).deleteRecursively()
134
19
135
- @ Test def verifyExitCode : Unit =
136
- withTempDirectory(compileRunAndVerifyExitCode(" positiveTest.scala" , " positiveTest" , 0 ))
137
-
138
- @ Test def verifyExitCodeOnScriptError : Unit =
139
- assertTestExists(" scriptRuntimeError.sc" ){ file =>
140
- testCommandExitCode(Seq (scalacPath, " -script" , file.absPath), 1 )
141
- }
142
-
143
- @ Test def verifyExitCodeOnScriptErrorCompiler : Unit =
144
- assertTestExists(" scriptRuntimeError.sc" ) { file =>
145
- testCommandExitCode(Seq (scalacPath, " -script" , file.absPath), 1 )
146
- }
147
-
148
- @ Test def verifyExitCodeOnScript : Unit =
149
- assertTestExists(" scriptPositive.sc" ) { file =>
150
- testCommandExitCode(Seq (scalaPath, file.absPath), 0 )
151
- }
152
-
153
- @ Test def verifyExitCodeOnScriptCompiler : Unit =
154
- assertTestExists(" scriptPositive.sc" ) { file =>
155
- testCommandExitCode(Seq (scalacPath, " -script" , file.absPath), 0 )
156
- }
157
-
158
- @ Test def verifyExitCodeOnDecompilation : Unit =
159
- withTempDirectory {
160
- compileAndVerifyExitCode(" positiveTest.scala" , 0 )
161
- testCommandExitCode(Seq (scalacPath, " -decompile" , getGeneratedTastyPath(" positiveTest" )), 0 )
162
- }
163
-
164
- @ Test def verifyExitCodeOnPrintTasty : Unit =
165
- withTempDirectory {
166
- compileAndVerifyExitCode(" positiveTest.scala" , 0 )
167
- testCommandExitCode(Seq (scalacPath, " -print-tasty" , getGeneratedTastyPath(" positiveTest" )), 0 )
168
- }
169
-
170
- @ Test def verifyExitCodeOnDecompilationFailure : Unit =
171
- withTempFile(file => testCommandExitCode(Seq (scalacPath, " -decompile" , file.absPath), 1 ))
172
- testCommandExitCode(Seq (scalacPath, " -decompile" , " non-existing-file.tasty" ), 1 )
173
-
174
- @ Test def verifyExitCodeOnPrintTastyFailure : Unit =
175
- withTempFile(file => testCommandExitCode(Seq (scalacPath, " -print-tasty" , file.absPath), 1 ))
176
- testCommandExitCode(Seq (scalacPath, " -print-tasty" , " non-existing-file.tasty" ), 1 )
177
-
178
- @ Test def verifyExitCodeOnExpressionCompileError : Unit =
179
- testCommandExitCode(Seq (scalaPath, " -e" , " 'prinln(10*10)'" ), 1 )
180
-
181
- @ Test def verifyExitCodeOnExpressionRuntimeError : Unit =
182
- testCommandExitCode(Seq (scalaPath, " -e" , " '1/0'" ), 1 )
183
-
184
- @ Test def verifyExitCodeOnExpression : Unit =
185
- testCommandExitCode(Seq (scalaPath, " -e" , " 'println(10*10)'" ), 0 )
186
-
187
- @ Test def verifyExitCodeOnInfo : Unit =
188
- List (" --help" , " --version" , " -Xplugin-list" , " -Vphases" ).foreach { flag =>
189
- testCommandExitCode(Seq (scalaPath, flag), 0 )
190
- }
20
+ /** Verify the exit code of running `cmd args*`. */
21
+ def verifyExit (cmd : String , args : String * )(expectedExitCode : Int ): Unit =
22
+ val (validTest, exitCode, stdout, stderr) = bashCommand((cmd +: args).mkString(" " ))
23
+ if verifyValid(validTest) then
24
+ assertEquals({
25
+ def pp (n : String , ss : Seq [String ]) = if ss.isEmpty then " " else s " \n std $n: ${ss.map(" \n " + _).mkString}"
26
+ s " expected $expectedExitCode but got $exitCode${pp(" out" , stdout)}${pp(" err" , stderr)}"
27
+ }, expectedExitCode, exitCode)
28
+
29
+ // Helpers for running scala, scalac, and scalac without the the output directory ("raw")
30
+ def scala (args : String * ) = verifyExit(scalaPath, args* )
31
+ def scalacRaw (args : String * ) = verifyExit(scalacPath, args* )
32
+ def scalac (args : String * ) = scalacRaw((" -d" +: tmpDir +: args)* )
33
+
34
+ /** The path to the test file for this class. */
35
+ def f (body : String , suffix : String = " .scala" ): String =
36
+ Files .write(Files .createTempFile(tmpDir.toPath, getClass.getSimpleName, suffix), body.getBytes(UTF_8 )).absPath
37
+
38
+ @ Test def neg = scalac(f(" @main def Test = prin" ))(1 )
39
+ @ Test def run = scalac(f(" @main def Test = ???" ))(0 ) & scala(" -classpath" , tmpDir, " Test" )(1 )
40
+ @ Test def pos = scalac(f(" @main def Test = ()" ))(0 ) & scala(" -classpath" , tmpDir, " Test" )(0 )
41
+
42
+ @ Test def runNeg = scala(f(" @main def Test = prin" , " .sc" ))(1 )
43
+ @ Test def runRun = scala(f(" @main def Test = ???" , " .sc" ))(1 )
44
+ @ Test def runPos = scala(f(" @main def Test = ()" , " .sc" ))(0 )
45
+
46
+ @ Test def scNeg = scalac(" -script" , f(" @main def Test = prin" , " .sc" ))(1 )
47
+ @ Test def scRun = scalac(" -script" , f(" @main def Test = ???" , " .sc" ))(1 )
48
+ @ Test def scPos = scalac(" -script" , f(" @main def Test = ()" , " .sc" ))(0 )
49
+
50
+ @ Test def evalNeg = scala(" -e" , " 'prinln(10*10)'" )(1 )
51
+ @ Test def evalRun = scala(" -e" , " '1/0'" )(1 )
52
+ @ Test def evalPos = scala(" -e" , " 'println(10*10)'" )(0 )
53
+
54
+ @ Test def decompileNeg = scalac(" -decompile" , " non-existing-file.tasty" )(1 )
55
+ @ Test def decompilePos = scalac(f(" class Test" ))(0 ) & scalacRaw(" -decompile" , s " $tmpDir/Test.tasty " )(0 )
56
+
57
+ @ Test def printTastyNeg = scalac(" -print-tasty" , " non-existing-file.tasty" )(1 )
58
+ @ Test def printTastyPos = scalac(f(" class Test" ))(0 ) & scalacRaw(" -print-tasty" , s " $tmpDir/Test.tasty " )(0 )
59
+
60
+ @ Test def help = scala(" --help" )(0 )
61
+ @ Test def version = scala(" --version" )(0 )
62
+ @ Test def xPluginList = scala(" -Xplugin-list" )(0 )
63
+ @ Test def vPhases = scala(" -Vphases" )(0 )
64
+
65
+ /** A utility for running two commands in a row, like you do in bash. */
66
+ extension (inline u1 : Unit ) inline def & (inline u2 : Unit ): Unit = { u1; u2 }
67
+ end BashExitCodeTests
0 commit comments