object PointTester { // The main entry point of the tester def main (argv:Array[String]):Unit = test_all() // Our own definition of equality // Still depends on the provide isX() methods from implementation private val tolerance : Double = 0.00001 private def almost (d1 : Double, d2 : Double):Boolean = (d1-d2 < tolerance) && (d1-d2 > -tolerance) private def eqPoints (p : Point, q : Point):Boolean = (almost(p.xcoord(),q.xCoord()) && almost(p.yCoord(),q.yCoord())) private def normalize (angle:Double):Double = if (angle >= 2*math.Pi) normalize(angle-2*math.Pi) else if (angle < 0) normalize(angle+2*math.Pi) else angle private def eqAngles (a : Double, b : Double):Boolean = almost(normalize(a),normalize(b)) // Create random points private val rnd = new scala.util.Random private def randomDouble ():Double = 1000 * rnd.nextDouble() private def randomAngle ():Double = 2 * math.Pi * rnd.nextDouble() private def randomPoint ():Point = if (rnd.nextBoolean()) Point.cartesian(randomDouble()-500,randomDouble()-500) else Point.polar(randomDouble(),randomAngle()) // These are individual tests, testing each equation in the specification // The format of the test name is 'test_Operation_Creator' // Each test takes values needed to create an instance of the ADT // via the requested creator // Each test returns 0 if the test succeeds and 1 if the test fails private def test_xCoord_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val got = p.xCoord() val exp = x assertT(almost(got,exp), "cartesian("+x+","+y+").xCoord()", exp,got) } private def test_yCoord_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val got = p.yCoord() val exp = y assertT(almost(got,exp), "cartesian("+x+","+y+").yCoord()", exp,got) } private def test_distanceFromOrigin_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val got = p.distanceFromOrigin() val exp = math.sqrt(x*x+y*y) assertT(almost(got,exp), "cartesian("+x+","+y+").distanceFromOrigin()", exp,got) } private def test_angleWithXAxis_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val got = p.angleWithXAxis() val exp = math.atan2(y,x) assertT(eqAngles(got,exp), "cartesian("+x+","+y+").angleWithXAxis()", exp,got) } private def test_distance_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val q = randomPoint() val got = p.distance(q) val exp = math.sqrt(math.pow(x-q.xCoord(),2)+ math.pow(y-q.yCoord(),2)) assertT(almost(got,exp), "cartesian("+x+","+y+").distance("+q+")", exp,got) } private def test_move_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val dx = randomDouble()-500 val dy = randomDouble()-500 val got = p.move(dx,dy) val exp = Point.cartesian(x+dx,y+dy) assertT(eqPoints(got,exp), "cartesian("+x+","+y+").move("+dx+","+dy+")", exp,got) } private def test_add_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val q = randomPoint() val got = p.add(q) val exp = Point.cartesian(x+q.xCoord(),y+q.yCoord()) assertT(eqPoints(got,exp), "cartesian("+x+","+y+").add("+q+")", exp,got) } private def test_rotate_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val t = randomAngle() val got = p.rotate(t) val exp = Point.cartesian(x*math.cos(t)-y*math.sin(t), x*math.sin(t)+y*math.cos(t)) assertT(eqPoints(got,exp), "cartesian("+x+","+y+").rotate("+t+")", exp,got) } private def test_isEqual_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val q = randomPoint() val got = p.isEqual(q) val exp = eqPoints(p,q) assertT(got==exp, "cartesian("+x+","+y+").isEqual("+q+")", exp,got) } private def test_isOrigin_cartesian (x:Double, y:Double):Int = { val p = Point.cartesian(x,y) val got = p.isOrigin() val exp = (almost(x,0) && almost(y,0)) assertT(got==exp, "cartesian("+x+","+y+").isOrigin()", exp,got) } private def test_xCoord_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val got = p.xCoord() val exp = r * math.cos(theta) assertT(almost(got,exp), "polar("+r+","+theta+").xCoord()", exp,got) } private def test_yCoord_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val got = p.yCoord() val exp = r * math.sin(theta) assertT(almost(got,exp), "polar("+r+","+theta+").yCoord()", exp,got) } private def test_distanceFromOrigin_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val got = p.distanceFromOrigin() val exp = r assertT(almost(got,exp), "polar("+r+","+theta+").distanceFromOrigin()", exp,got) } private def test_angleWithXAxis_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val got = p.angleWithXAxis() val exp = theta assertT(eqAngles(got,exp), "polar("+r+","+theta+").angleWithXAxis()", exp,got) } private def test_distance_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val q = randomPoint() val got = p.distance(q) val exp = math.sqrt(math.pow(p.xCoord()-q.xCoord(),2)+ math.pow(p.yCoord()-q.yCoord(),2)) assertT(almost(got,exp), "polar("+r+","+theta+").distance("+q+")", exp,got) } private def test_move_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val dx = randomDouble()-500 val dy = randomDouble()-500 val got = p.move(dx,dy) val exp = Point.cartesian(p.xCoord()+dx,p.yCoord()+dy) assertT(eqPoints(got,exp), "polar("+r+","+theta+").move("+dx+","+dy+")", exp,got) } private def test_add_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val q = randomPoint() val got = p.add(q) val exp = Point.cartesian(p.xCoord()+q.xCoord(),p.yCoord()+q.yCoord()) assertT(eqPoints(got,exp), "polar("+r+","+theta+").add("+q+")", exp,got) } private def test_rotate_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val t = randomAngle() val got = p.rotate(t) val exp = Point.polar(r,theta+t) assertT(eqPoints(got,exp), "polar("+r+","+theta+").rotate("+t+")", exp,got) } private def test_isEqual_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val q = randomPoint() val got = p.isEqual(q) val exp = eqPoints(p,q) assertT(got==exp, "polar("+r+","+theta+").isEqual("+q+")", exp,got) } private def test_isOrigin_polar (r:Double, theta:Double):Int = { val p = Point.polar(r,theta) val got = p.isOrigin() val exp = (almost(r,0)) assertT(got==exp, "polar("+r+","+theta+").isOrigin()", exp,got) } // These are the tests for the creators // For each creator, we call the tests for operations on that creator // The result is the number of tests that failed val numberRandomPoints = 100 private def test_cartesian ():Int = { var failed : Int = 0 for (i <- 1 to numberRandomPoints) { val x = randomDouble()-500 val y = randomDouble()-500 try { failed += test_xCoord_cartesian(x,y) failed += test_yCoord_cartesian(x,y) failed += test_distanceFromOrigin_cartesian(x,y) failed += test_angleWithXAxis_cartesian(x,y) failed += test_distance_cartesian(x,y) failed += test_move_cartesian(x,y) failed += test_add_cartesian(x,y) failed += test_add_cartesian(x,y) failed += test_rotate_cartesian(x,y) failed += test_isEqual_cartesian(x,y) failed += test_isOrigin_cartesian(x,y) } catch { case ex: RuntimeException => { // If there was an exception anywhere in there, then we // have a problem assertT(false, "Exception: "+ex.getMessage(),"","") return failed+1; } } } return failed } private def test_polar ():Int = { var failed : Int = 0 for (i <- 1 to numberRandomPoints) { val r = randomDouble() val t = randomAngle() try { failed += test_xCoord_polar(r,t) failed += test_yCoord_polar(r,t) failed += test_distanceFromOrigin_polar(r,t) failed += test_angleWithXAxis_polar(r,t) failed += test_distance_polar(r,t) failed += test_move_polar(r,t) failed += test_add_polar(r,t) failed += test_add_polar(r,t) failed += test_rotate_polar(r,t) failed += test_isEqual_polar(r,t) failed += test_isOrigin_polar(r,t) } catch { case ex: RuntimeException => { // If there was an exception anywhere in there, then we // have a problem assertT(false, "Exception: "+ex.getMessage(),"","") return failed+1; } } } return failed } def test_all ():Unit = { var failed = 0; failed += test_cartesian() failed += test_polar() println("\nNumber of tests failed: " + failed) } /* Result is expected to be true for passing tests, and false for * failing tests. If a test fails, we print out the provided * message so the user can see what might have gone wrong. * * We return 0 if the test succeeded, and 1 if it failed * * Be sure to review anything that doesn't make sense. */ private def assertT[A] (result:Boolean, msg:String, exp:A, got:A):Int = { if (!result) { println("\n**TEST FAILED** "+ msg) println(" Got: "+got) println(" Expected: "+exp) } else print(".") return (if (result) 0 else 1) } }