Skip to content

Commit bb9c8ff

Browse files
authored
Merge pull request #15657 from dwijnand/cleanup-BashExitCodeTests
2 parents d247c37 + a5966f9 commit bb9c8ff

File tree

7 files changed

+53
-182
lines changed

7 files changed

+53
-182
lines changed

compiler/test-resources/scripting/exit-code-tests/compileError.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/test-resources/scripting/exit-code-tests/positiveTest.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/test-resources/scripting/exit-code-tests/runtimeError.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/test-resources/scripting/exit-code-tests/scriptCompileError.sc

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/test-resources/scripting/exit-code-tests/scriptPositive.sc

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/test-resources/scripting/exit-code-tests/scriptRuntimeError.sc

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/test/dotty/tools/scripting/BashExitCodeTests.scala

Lines changed: 53 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -4,187 +4,64 @@ package scripting
44

55
import scala.language.unsafeNulls
66

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 }
109
import org.junit.Assert.assertEquals
1110
import org.junit.experimental.categories.Category
1211

1312
import ScriptTestEnv.*
1413

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-
12514
@Category(Array(classOf[BootstrappedOnlyTests]))
12615
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()
13419

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"\nstd$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

Comments
 (0)