123 lines
3.9 KiB
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')
|
|
}
|