diff options
author | Jack Sangdahl <[email protected]> | 2024-12-12 21:02:58 -0700 |
---|---|---|
committer | Jack Sangdahl <[email protected]> | 2024-12-12 21:02:58 -0700 |
commit | 08f9cae13d0dce99d40a6d93432a84cb075bebfc (patch) | |
tree | 5714d73c616b511d8fa5ea8a0ef1d8405f13ce90 /lab3/src/test/scala | |
parent | 0d13c649bdabafde59233609be7bd88e273c7ae6 (diff) | |
download | csci3155-08f9cae13d0dce99d40a6d93432a84cb075bebfc.tar.gz csci3155-08f9cae13d0dce99d40a6d93432a84cb075bebfc.zip |
Unit 3
Signed-off-by: Jack Sangdahl <[email protected]>
Diffstat (limited to 'lab3/src/test/scala')
-rw-r--r-- | lab3/src/test/scala/jsy/lab3/Lab3Spec.scala | 150 | ||||
-rw-r--r-- | lab3/src/test/scala/jsy/tester/JavascriptyTester.scala | 23 |
2 files changed, 173 insertions, 0 deletions
diff --git a/lab3/src/test/scala/jsy/lab3/Lab3Spec.scala b/lab3/src/test/scala/jsy/lab3/Lab3Spec.scala new file mode 100644 index 0000000..1b40c01 --- /dev/null +++ b/lab3/src/test/scala/jsy/lab3/Lab3Spec.scala @@ -0,0 +1,150 @@ +package jsy.lab3 + +import org.scalatest.flatspec.AnyFlatSpec +import Parser.parse +import ast._ +import Lab3._ + +class Lab3StudentSpec extends AnyFlatSpec { + + "StudentSpec" should "evaluate a higher order function" in { + val jsyStr: String = + "(function f(g) { return g(g)}) (function g(x) { return x }) (5);" + val answer: Either[DynamicTypeError, Expr] = Right(N(5)) + assert(answer === iterateStep(parse(jsyStr))) + } + + it should "evaluate a recursive function" in { + val jsyStr: String = + "(function f(x) { return x <= 1 ? 1 : x * f(x - 1)}) (3);" + val answer: Either[DynamicTypeError, Expr] = Right(N(6)) + assert(answer === iterateStep(parse(jsyStr))) + } + + it should "evaluate your test case" in { + val jsyStr: String = "1 + 1" + val answer: Either[DynamicTypeError, Expr] = Right(N(2)) + assert(answer === iterateStep(parse(jsyStr))) + } + +} + +class Lab3Spec extends AnyFlatSpec { + + "substitute" should "perform syntatic substitution respecting shadowing" in { + val xplus1 = parse("x + 1") + val twoplus1 = parse("2 + 1") + assert(substitute(N(2), "x", xplus1) === twoplus1) + val constx3 = parse("const x = 3; x") + val shadowx = Binary(Plus, constx3, Var("x")) + assert(substitute(N(2), "x", shadowx) === Binary(Plus, constx3, N(2))) + } + + "iterateBasic" should "work for sumTo(100)" in { + def sumTo(n: Int) = { + iterateBasic(0) { case (acc, i) => + require(n >= 0) + if (i > n) None + else Some(acc + i) + } + } + + assertResult(5050) { sumTo(100) } + } + + { + def sumTo(n: Int): Either[String, Int] = { + iterate(0) { case (acc, i) => + if (n < 0) Some(Left("requirement failed")) + else if (i > n) None + else Some(Right(acc + i)) + } + } + + "iterate" should "work for sumTo(100)" in { + assertResult(Right(5050)) { sumTo(100) } + } + + "iterate" should "work for sumTo(-1)" in { + assertResult(Left("requirement failed")) { sumTo(-1) } + } + + val one = parse("1") + + it should "stop if the callback body returns None" in { + assertResult(Right(one)) { + iterate(one) { (_, _) => None } + } + } + + it should "increment the loop counter on each iteration and use e if the callback body returns Some(e)" in { + assertResult(Right(parse("--1"))) { + iterate(one) { (e: Expr, n: Int) => + if (n == 2) None else Some(Right(Unary(Neg, e))) + } + } + } + } + + "step/call" should "evaluate a function using small-step semantics" in { + val f = "f" + val x = "x" + val e1 = Fun(None, x, Binary(Plus, Var(x), N(1))) + val e2 = N(2) + val e3 = iterateStep(Call(e1, e2)) + assert(e3 === Right(N(3))) + } + + it should "handle recursive functions using small-step semantics" in { + val f = "f" + val x = "x" + val fbody = If( + Binary(Eq, Var(x), N(0)), + Var(x), + Binary(Plus, Var(x), Call(Var(f), Binary(Minus, Var(x), N(1)))) + ) + val e1 = Fun(Some(f), x, fbody) + val e2 = N(3) + val e3 = iterateStep(Call(e1, e2)) + assert(e3 === Right(N(6))) + } + + /* Some tests based on rules */ + + { + val xval = N(2) + val varx = Var("x") + + val e1 = parse("2 - 1 - 1") + val e1p = parse("1 - 1") + val e2 = parse("3 - 1 - 1") + val e2p = parse("2 - 1") + val v1 = N(0) + val v2 = N(1) + + val vidfunction = parse("function (x) { return x }") + + "DoNeg" should "perform DoNeg" in { + val np = -0 + assertResult(Right(N(np))) { + step(Unary(Neg, v1)) + } + } + + "SearchUnary" should "perform SearchUnary" in { + assertResult(Right(Unary(Neg, e1p))) { + step(Unary(Neg, e1)) + } + } + + val e_callerror = Call(N(1), N(2)) + + "TypeErrorCall" should "perform TypeErrorCall" in { + assertResult(Left(DynamicTypeError(e_callerror))) { + step(e_callerror) + } + } + } +} + +class Lab3JsyTests extends jsy.tester.JavascriptyTester(None, "lab3", Lab3) diff --git a/lab3/src/test/scala/jsy/tester/JavascriptyTester.scala b/lab3/src/test/scala/jsy/tester/JavascriptyTester.scala new file mode 100644 index 0000000..48e789c --- /dev/null +++ b/lab3/src/test/scala/jsy/tester/JavascriptyTester.scala @@ -0,0 +1,23 @@ +package jsy.tester +import java.io.File +import jsy.util.JsyApplication +import org.scalatest._ +import flatspec._ + +/* + * A ScalaTest interface for running system tests. + */ +class JavascriptyTester(rootPrefix: Option[String], testDirectory: String, jsy: JsyApplication) extends AnyFlatSpec { + val testResources = s"src${File.separator}test${File.separator}resources" + val testPrefix = rootPrefix match { + case None => testResources + case Some(p) => s"${p}${File.separator}${testResources}" + } + val testPath = s"${testPrefix}${File.separator}${testDirectory}" + jsy.test(new File(testPath)) { case (in,ans,assertion) => + s"eval on ${in}" should s"match ${ans}" in { + val (b: Boolean, msg: String) = assertion + assert(b, msg) + } + } +} |