Files
WACC_37/src/test/wacc/examples.scala

123 lines
3.9 KiB
Scala

package wacc
import org.scalatest.BeforeAndAfterAll
import org.scalatest.Inspectors.forEvery
import org.scalatest.matchers.should.Matchers._
import org.scalatest.freespec.AsyncFreeSpec
import cats.effect.testing.scalatest.AsyncIOSpec
import java.io.File
import java.nio.file.Path
import sys.process._
import scala.io.Source
import cats.effect.IO
import wacc.{compile as compileWacc}
class ParallelExamplesSpec extends AsyncFreeSpec with AsyncIOSpec 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))
}
forEvery(files) { (filename, expectedResult) =>
val baseFilename = filename.stripSuffix(".wacc")
s"$filename" - {
"should be compiled with correct result" in {
compileWacc(Path.of(filename), outputDir = None, log = false).map { result =>
expectedResult should contain(result)
}
}
if (expectedResult == List(0)) {
"should run with correct result" in {
if (fileIsDisallowedBackend(filename))
IO.pure(
succeed
) // TODO: remove when advanced tests removed. not sure how to "pending" this otherwise
else {
for {
contents <- IO(Source.fromFile(File(filename)).getLines.toList)
inputLine = extractInput(contents)
expectedOutput = extractOutput(contents)
expectedExit = extractExit(contents)
asmFilename = baseFilename + ".s"
execFilename = baseFilename
gccResult <- IO(s"gcc -o $execFilename -z noexecstack $asmFilename".!)
_ = assert(gccResult == 0)
stdout <- IO.pure(new StringBuilder)
process <- IO {
s"timeout 5s $execFilename" run ProcessIO(
in = w => {
w.write(inputLine.getBytes)
w.close()
},
out = Source.fromInputStream(_).addString(stdout),
err = _ => ()
)
}
exitCode <- IO.pure(process.exitValue)
} yield {
exitCode shouldBe expectedExit
normalizeOutput(stdout.toString) shouldBe expectedOutput
}
}
}
}
}
}
def allWaccFiles(dir: String): IndexedSeq[os.Path] =
val d = java.io.File(dir)
os.walk(os.Path(d.getAbsolutePath)).filter(_.ext == "wacc")
// TODO: eventually remove this I think
def fileIsDisallowedBackend(filename: String): Boolean =
Seq(
"^.*wacc-examples/valid/advanced.*$"
).exists(filename.matches)
private def extractInput(contents: List[String]): String =
contents
.find(_.matches("^# ?[Ii]nput:.*$"))
.map(_.split(":").last.strip + "\n")
.getOrElse("")
private def extractOutput(contents: List[String]): String = {
val outputLineIdx = contents.indexWhere(_.matches("^# ?[Oo]utput:.*$"))
if (outputLineIdx == -1) ""
else
contents
.drop(outputLineIdx + 1)
.takeWhile(_.startsWith("#"))
.map(_.stripPrefix("#").stripLeading)
.mkString("\n")
}
private def extractExit(contents: List[String]): Int = {
val exitLineIdx = contents.indexWhere(_.matches("^# ?[Ee]xit:.*$"))
if (exitLineIdx == -1) 0
else contents(exitLineIdx + 1).stripPrefix("#").strip.toInt
}
private def normalizeOutput(output: String): String =
output
.replaceAll("0x[0-9a-f]+", "#addrs#")
.replaceAll("fatal error:.*", "#runtime_error#\u0000")
.takeWhile(_ != '\u0000')
}