wacc_37/src/test/wacc/examples.scala
2025-02-27 03:30:57 +00:00

110 lines
3.9 KiB
Scala

package wacc
import org.scalatest.BeforeAndAfterAll
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.Inspectors.forEvery
import java.io.File
import sys.process._
import java.io.PrintStream
import scala.io.Source
class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
val files =
allWaccFiles("wacc-examples/valid").map { p =>
(p.toString, List(0))
} ++
allWaccFiles("wacc-examples/invalid/syntaxErr").map { p =>
(p.toString, List(100))
} ++
allWaccFiles("wacc-examples/invalid/semanticErr").map { p =>
(p.toString, List(200))
} ++
allWaccFiles("wacc-examples/invalid/whack").map { p =>
(p.toString, List(100, 200))
}
// tests go here
forEvery(files) { (filename, expectedResult) =>
val baseFilename = filename.stripSuffix(".wacc")
given stdout: PrintStream = PrintStream(File(baseFilename + ".out"))
s"$filename" should "be compiled with correct result" in {
val result = compile(filename)
assert(expectedResult.contains(result))
}
if (expectedResult == List(0)) it should "run with correct result" in {
if (fileIsDisallowedBackend(filename)) pending
// Retrieve contents to get input and expected output + exit code
val contents = scala.io.Source.fromFile(File(filename)).getLines.toList
val inputLine =
contents.find(_.matches("^# ?[Ii]nput:.*$")).map(_.split(":").last.strip).getOrElse("")
val outputLineIdx = contents.indexWhere(_.matches("^# ?[Oo]utput:.*$"))
val expectedOutput =
if (outputLineIdx == -1) ""
else
contents
.drop(outputLineIdx + 1)
.takeWhile(_.startsWith("#"))
.map(_.stripPrefix("#").stripLeading)
.mkString("\n")
val exitLineIdx = contents.indexWhere(_.matches("^# ?[Ee]xit:.*$"))
val expectedExit =
if (exitLineIdx == -1) 0
else contents(exitLineIdx + 1).stripPrefix("#").strip.toInt
// Assembly and link using gcc
val asmFilename = baseFilename + ".s"
val execFilename = baseFilename
val gccResult = s"gcc -o $execFilename -z noexecstack $asmFilename".!
assert(gccResult == 0)
// Run the executable with the provided input
val stdout = new StringBuilder
val process = s"timeout 5s $execFilename" run ProcessIO(
in = w => {
w.write(inputLine.getBytes)
w.close()
},
out = Source.fromInputStream(_).addString(stdout),
err = _ => ()
)
assert(process.exitValue == expectedExit)
assert(stdout.toString.replaceAll("0x[0-9a-f]+", "#addrs#") == expectedOutput)
}
}
def allWaccFiles(dir: String): IndexedSeq[os.Path] =
val d = java.io.File(dir)
os.walk(os.Path(d.getAbsolutePath)).filter { _.ext == "wacc" }
def fileIsDisallowedBackend(filename: String): Boolean =
Seq(
// format: off
// disable formatting to avoid binPack
"^.*wacc-examples/valid/advanced.*$",
// "^.*wacc-examples/valid/array.*$",
// "^.*wacc-examples/valid/basic/exit.*$",
// "^.*wacc-examples/valid/basic/skip.*$",
// "^.*wacc-examples/valid/expressions.*$",
"^.*wacc-examples/valid/function/nested_functions.*$",
"^.*wacc-examples/valid/function/simple_functions.*$",
// "^.*wacc-examples/valid/if.*$",
"^.*wacc-examples/valid/IO/print.*$",
// "^.*wacc-examples/valid/IO/read.*$",
"^.*wacc-examples/valid/IO/IOLoop.wacc.*$",
// "^.*wacc-examples/valid/IO/IOSequence.wacc.*$",
"^.*wacc-examples/valid/pairs.*$",
"^.*wacc-examples/valid/runtimeErr.*$",
// "^.*wacc-examples/valid/scope.*$",
"^.*wacc-examples/valid/scope/printAllTypes.wacc$", // while we still don't have arrays implemented
// "^.*wacc-examples/valid/sequence.*$",
// "^.*wacc-examples/valid/variables.*$",
// "^.*wacc-examples/valid/while.*$",
// format: on
).find(filename.matches).isDefined
}