From 95f81d4b500814d36f8c3de00977461e38b67581 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Sun, 20 Sep 2009 22:29:02 +0000 Subject: [PATCH] restored collects/tests/profj, since kathy needs to get the profj tests out, and since it also includes the test-engine tests svn: r16095 --- collects/tests/info.ss | 1 + collects/tests/profj/TestEngineTest.ss | 57 ++ collects/tests/profj/advanced-tests.ss | 506 +++++++++++++++++ collects/tests/profj/all-tests.ss | 7 + collects/tests/profj/beginner-tests.ss | 575 +++++++++++++++++++ collects/tests/profj/beginnerTest.java | 142 +++++ collects/tests/profj/full-tests.ss | 377 +++++++++++++ collects/tests/profj/intermediate-tests.ss | 623 +++++++++++++++++++++ collects/tests/profj/intermediateTest.java | 125 +++++ collects/tests/profj/profj-testing.ss | 261 +++++++++ 10 files changed, 2674 insertions(+) create mode 100644 collects/tests/profj/TestEngineTest.ss create mode 100644 collects/tests/profj/advanced-tests.ss create mode 100644 collects/tests/profj/all-tests.ss create mode 100644 collects/tests/profj/beginner-tests.ss create mode 100644 collects/tests/profj/beginnerTest.java create mode 100644 collects/tests/profj/full-tests.ss create mode 100644 collects/tests/profj/intermediate-tests.ss create mode 100644 collects/tests/profj/intermediateTest.java create mode 100644 collects/tests/profj/profj-testing.ss diff --git a/collects/tests/info.ss b/collects/tests/info.ss index 6045b132e5..5fd8b6aad9 100644 --- a/collects/tests/info.ss +++ b/collects/tests/info.ss @@ -17,6 +17,7 @@ "plai" "planet" "plot" + "profj" "r6rs" "srfi" "srpersist" diff --git a/collects/tests/profj/TestEngineTest.ss b/collects/tests/profj/TestEngineTest.ss new file mode 100644 index 0000000000..c9db8df40e --- /dev/null +++ b/collects/tests/profj/TestEngineTest.ss @@ -0,0 +1,57 @@ +;; The first three lines of this file were inserted by DrScheme. They record metadata +;; about the language level of this file in a form that our tools can easily process. +#reader(lib "htdp-beginner-reader.ss" "lang")((modname TestEngineTest) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ()))) +;;Expect 37 checks, 17 failures + +(define (count f) + (cond + [(zero? f) 1] + [else (add1 (count (sub1 f)))])) + +(check-expect (count 3) 3) ; fails +(check-expect (count 3) 4) + +(check-within 1.345 1.3 .05) +(check-within 1.345 1.3 .005) ; fails + +(check-expect (cons 1 (cons 2 (cons 3 empty))) (cons 2 (cons 2 (cons 2 empty)))) ;fails +(check-expect (cons 1 (cons 2 (cons 3 empty))) empty) ;fails +(check-expect (cons 1 (cons 2 (cons 3 empty))) (cons 1 (cons 2 (cons 3 empty)))) +(check-within (cons 1 (cons 2 (cons 3 empty))) (cons 1.1 (cons 2.1 (cons 3.1 empty))) .2) +(check-within (cons 1 (cons 2 (cons 3 empty))) (cons 1.1 (cons 2.1 (cons 3.1 empty))) .01) ;fails + +(check-expect 'red 'blue) ;fails +(check-expect 'red 'red) +(check-within 'red 'red .002) +(check-expect 'red "red") ;fails + +(check-expect "red" "red") +(check-expect "red " "red") ;fails +(check-expect "Hello" "red") ;fails +(check-within "hello" "Hello" .03) ;fails + +(define-struct ball (point rad color)) + +(check-expect (make-ball 4 5 'blue) (make-ball 4 5 'blue)) +(check-expect (make-ball (make-posn 1 2) 3.5 'blue) (make-ball (make-posn 1 2) 3.5 'blue)) +(check-expect (make-ball 3 (make-posn 1 2) "blue") (make-ball (make-posn 1 2) 3.3 "blue")) ;fails +(check-within (make-ball (make-posn 1 3) 3.4 "blue") (make-ball (make-posn 1 3) 3.3 "blue") .1) +(check-within (make-ball (make-posn 1 3) 3.4 "blue") (make-ball (make-posn 1 3) 3.3 "blue") .01) ;fails + +(check-error (error 'test "hi") "test: hi") +(check-error (/ 1 0) "/: division by zero") +(check-error 3 "some message") ;fails +(check-error (first empty) "another message") ;fails + +(check-member-of (make-ball 1 1 'blue) (make-ball 1 2 'blue) (make-ball 1 1 'blue) (make-ball 1 2 'red) 'red) +(check-member-of 1 1 1 1 1) +(check-member-of (make-ball 2 2 'blue) (make-ball 1 2 'blue) (make-ball 1 1 'blue) (make-ball 1 2 'red) 'red) ;fails + +(check-range 5 0 10) +(check-range 0 0 10) +(check-range 10 0 10) +(check-range 11 0 10) ;fails +(check-range 5.01 0 10.5) +(check-range 0.0 0 10.5) +(check-range 10.5 0 10.5) +(check-range 10.5001 0 10.5) ;fails diff --git a/collects/tests/profj/advanced-tests.ss b/collects/tests/profj/advanced-tests.ss new file mode 100644 index 0000000000..f690eb17f9 --- /dev/null +++ b/collects/tests/profj/advanced-tests.ss @@ -0,0 +1,506 @@ +(module advanced-tests mzscheme + (require "profj-testing.ss") + (require profj/libs/java/lang/String) + + (prepare-for-tests "Advanced") + + ;;Execution tests without errors + + (execute-test + "interface mustbepublic { + int a(); + int b(); + } + class musthavepublic implements mustbepublic { + public int a() { return 3; } + public int b() { return 5; } + }" 'advanced #f "public implementation of an interface" + ) + + (execute-test + "class OneC { } + class TwoC extends OneC { } + class ThreeC extends TwoC { } + class Overload { + int num(OneC o) { return 1; } + int num(TwoC o) { return 2; } + int t() { return num(new ThreeC()); } + } + " 'advanced #f "Overloading resolution") + + (execute-test + "class Checkclass { } + class ExampleCheck { + boolean t1 = check new Checkclass[10] expect new Checkclass[10]; + boolean t2 = check (new int[3])[1] expect 0; + }" + 'advanced #f "check expressions") + + (execute-test + "class Blah { + Blah () {} + int addUp (int top) { + int answer = 0; + int counter = 1; + while (counter <= top) { + answer += counter; + ++counter; + } + return answer; + } + }" + 'advanced #f "while loop with statements after") + + (execute-test + "interface Abs { int a( int x); } + abstract class Babs implements Abs { } + " + 'advanced #f "abs. class with interface not all impl., with args") + + (execute-test + "public class Xprivate { + private int x() { return 3; } + }" + 'advanced #f "Class with private method") + + (execute-test + "public class Something { + private int x; + public boolean equals( Object o ) { + return (o instanceof Something) && x == ((Something) o).x; + } + }" + 'advanced + #f + "Correct overriding of equals") + + (execute-test + "public interface F { + int f(); + } + public class P implements F { + private int g; + public int f() { return g; } + }" 'advanced #f "Correct implementing of public interface") + + (execute-test + "public class Statics { + public static int[] a; + public static boolean b; + private static boolean c; + + public static void main( String[] args) { + return; + } + public static int getA( int pos) { + return a[pos]; + } + }" 'advanced #f "Class containing several static members") + + (execute-test + "public class Inits { + private int f; + private boolean condition; + + public Inits() { } + + { if (condition) + f = 4; + else + f = 3; + } + }" + 'advanced #f "Class containing inits") + + (execute-test + "class Xfinal { + final int x() { return 4; } + }" + 'advanced #f "Class with final method") + + (execute-test + "class Xoverload { + int x() { return 3; } + int x( int y ) { return y; } + }" 'advanced #f "Class with overloaded methods") + + (execute-test + "class Ret { + boolean rets() { + if (true) + return true; + return false; + } + }" + 'advanced #f "If with no else, reachable return") + + ;;Execution tests with errors + + (execute-test + "interface a { int a(); } + class b implements a{ int a() { return 3; } }" + 'advanced #t "Interface implement without public" + ) + + (execute-test + "class X { + final int x = 4; + }" 'advanced #t "Class with final field") + + (execute-test + "class X { + final int x() { return 3; } + } + class Y extends X { + int x() { return 3 ; } + }" 'advanced #t "Attempt to override a final method") + + (execute-test + "class X { + public int x () { return 3 ; } + } + class Y extends X { + int x() { return super.x() + 3; } + }" 'advanced #t "Attempt to weaken access privlege") + + (execute-test + "class X { + { x = 3; + int x; } + }" 'advanced #t "Attempt to set before named, init") + + (execute-test + "class Xth { Xth() { this(1); } + Xth(int i) { this(); }}" + 'advanced #t "Cyclic calls to this") + + (execute-test + "class X { + int x() { return 3; } + int x( int x ) { return 35; } + int y() { return x(3,5); } + }" 'advanced #t "Miss overload call") + + (execute-test + "class X { + int x() { return 3; } + int x( int y, int z ) { return y; } + int y() { return x(y()); } + }" 'advanced #t "Miss overload call the other way") + + (execute-test + "class X { + int x() { return 3; } + boolean x(int y) { return true; } + int f() { return x(3); } + }" 'advanced #t "Miss overloading") + + (execute-test + "public class StatInits { + private static int x; + static { x = 45; } + }" 'advanced #t "Class containing static inits") + + (execute-test + "public class F { + public f() { return 3; } + }" + 'advanced #t "Forgotten return type after public") + + (execute-test + "pulic class F { }" + 'advanced #t "Parse error, misspelled public") + + (execute-test + "class TestClass{ + ALoObj iterFilter(){ + for (;false;){} + } + }/end SameAuthor" + 'advanced + #t "Parse error check") + + (execute-test + "class Today{ + + int dayNumber; + boolean meetings; + String QoD; + + Today(int dayNumber, boolean meetings, String QoD) + { + this.dayNumber = dayNumber; + this.meetings = meetings; + this.QoD = QoD; + } + + int getDayNumber() + { + return dayNumber; + } + + boolean getMeetings() + { + return meetings; + } + + void setMeetings() + { + this.meetings = true; + } + + String getQoD() + { + return QoD; + } + +} + + +class WeeklyPlanner{ + + Today[] weeklyPlanner; + int totalDays = 7; + + WeeklyPlanner() + { + + weeklyPlanner = new Today[totalDays]; + + for(int i = 0; i < totalDays; i++) + { + weeklyPlanner[i] = new Today(i, False, \"\"); + } + } + + void addMeeting(int dayNumber) + { + weeklyPlanner[dayNumber].setMeetings(); ////////<<<<<<< that.rooms; } + // actual: h1.isBigger(h2), expected: false + // actual: h2.isBigger(h3), expected: true + + //determine if this house's city as the same as a given city + boolean thisCity(String city) { return this.city.equals(city); } + + // h1.thisCity(\"Brookline)\"--true + // h2.thisCity(\"Brookline\")--false + } + + /* + Address a1 = new Address(23, \"Maple Street\", \"Brookline\"); + Address a2 = new Address(5, \"Joye Road\", \"Newton\"); + Address a3 = new Address(83, \"Winslow Street\", \"Waltham\"); + + House h1 = new House(\"Ranch\", 7, a1, 375000); + House h2 = new House(\"Colonial\", 9, a2, 450000); + House h3 = new House(\"Cape\", 6, a3, 235000); + + ALoH mtlist = new MTLoH(); + ALoH list1 = new ConsHouse(h1, mtlist); + ALoH list2 = new ConsHouse(h3, list1); + */" + 'beginner #t "Error message bug") + + (interact-test + "interface A { }" + language + (list "new A()") + (list 'error) + "Trying to create an instance of an interface") + + (interact-test + "class X { X() { } double f() { return 2; } }" + language + (list "double x = 1;" "x" "new X().f()") + (list '(void) 1.0 2.0) + "Converting ints into doubles appropriately") + + (interact-test + language + (list "check true expect true" + "check true expect 1" + "check true expect true within 1" + "check new Object() expect \"hi\"" + "check \"hi\" expect new Object()" + "check 1.4 expect 1" + "check 1.4 expect 1 within .5" + "check 1.4 expect 1 within true") + (list #t 'error #t #f 'error 'error #t 'error) + "Calling check in many ways") + + (report-test-results)) diff --git a/collects/tests/profj/beginnerTest.java b/collects/tests/profj/beginnerTest.java new file mode 100644 index 0000000000..1c7f4eb399 --- /dev/null +++ b/collects/tests/profj/beginnerTest.java @@ -0,0 +1,142 @@ +// Expected results: +// 14 checks +// 2 failed checks, one in each test class +// 6 tests, all passing +// All methods of both classes are covered + +interface Automobile { + int milesTraveled(); + Automobile travel( int miles ); + String makeAndModel(); + double price(int year); +} + +class Car implements Automobile { + + String make; + String model; + int miles; + double basePrice; + + Car(String make, String model, int miles, double basePrice) { + this.make = make; + this.model = model; + this.miles = miles; + this.basePrice = basePrice; + } + + int milesTraveled() { + return this.miles; + } + String makeAndModel() { + return this.make.concat(this.model); + } + + Automobile travel(int miles) { + return new Car(this.make, this.model, this.miles+miles, this.basePrice); + } + + double price(int year) { + if ((2006 - year) == 0) { + return this.basePrice; + } else { + if ((2006 - year) > 0) { + return this.basePrice - (this.basePrice / (2006 - year)); + } else { + return this.basePrice + (this.basePrice / (year - 2006)); + } + } + } + +} + +class CarExamples { + + CarExamples() { } + + Car myCar = new Car("Toyota","Tercel",100000, 16000.00); + Car momCar = new Car("Honda","Excel",10000, 32000.00); + + boolean test1 = check this.myCar expect this.momCar; + boolean test2 = check this.myCar.milesTraveled() expect 100000; + + boolean testTravel() { + return (check this.myCar.travel(10) expect new Car("Toyota","Tercel",100010, 16000.00)) || + (check this.momCar.travel(90000) expect this.myCar); + } + + boolean testMakeModel() { + return check this.myCar.makeAndModel() expect "ToyotaTercel"; + } + + boolean testPrice() { + return (check this.myCar.price(2006) expect 16000.00 within .01) && + (check this.myCar.price(1991) expect 14933.33 within .01) && + (check this.myCar.price(2007) expect 32000.00 within .01); + } + +} + +class Truck implements Automobile { + String make; + int miles; + int numDoors; + boolean extendedBed; + double basePrice; + + Truck( String make, int miles, int numDoors, boolean bed, double basePrice) { + this.make = make; + this.miles = miles; + this.numDoors = numDoors; + this.extendedBed = bed; + this.basePrice = basePrice; + } + + int milesTraveled() { return this.miles; } + String makeAndModel() { + if (this.extendedBed) { + return this.make.concat("Extended"); + } else { + return this.make.concat(String.valueOf(this.numDoors)); + } + } + Automobile travel(int miles) { + return new Truck(this.make, this.miles + miles, this.numDoors, this.extendedBed, this.basePrice); + } + double price( int year ) { + // Uncomment to test runtime error behavior + //return this.basePrice - (2 * (this.basePrice / (2006 -year))); + if (year == 2006) { + return this.basePrice; + } else { + return this.basePrice - (2 * (this.basePrice / (2006 - year))); + } + } + +} + +class TruckExamples { + Truck oneTruck = new Truck("Toyota",10000, 2,false,20000.00); + Truck twoTruck = new Truck("Ford",100000,2,true,35000.00); + + boolean test1 = check this.oneTruck.milesTraveled() expect 10000; + boolean test2 = check this.oneTruck expect this.twoTruck; + + TruckExamples() { } + + boolean testPrice() { + return (check this.oneTruck.price(2006) expect 20000.00 within .01) && + (check this.oneTruck.price(1996) expect 16000.00 within .01); + } + + boolean testTravel() { + return check this.oneTruck.travel(1000) expect new Truck("Toyota",11000,2,false,20000.00); + } + + boolean testMakeAndModel() { + return (check this.oneTruck.makeAndModel() expect "Toyota2") && + (check this.twoTruck.makeAndModel() expect "FordExtended"); + } + +} + diff --git a/collects/tests/profj/full-tests.ss b/collects/tests/profj/full-tests.ss new file mode 100644 index 0000000000..8931b51f38 --- /dev/null +++ b/collects/tests/profj/full-tests.ss @@ -0,0 +1,377 @@ +(module full-tests mzscheme + (require "profj-testing.ss" + (lib "parameters.ss" "profj")) + + (prepare-for-tests "Full") + + (execute-test + "class AnExceptionThrower { + int m() throws Throwable { + if (true) + throw new Throwable(); + throw new Exception(); + } + }" 'full #f "Throwable is a subclass of Throwable for purpose of throws clause") + + (execute-test + "class AnotherExceptionThrower { + int m() throws Exception { + throw new Exception(); + }}" 'full #f "Throwable is imported when using throw") + + (interact-test + "class YAET { + int m() throws Exception { + throw new Exception(); + } + }" + 'full '("check new YAET().m() catch Exception" "check new YAET().m() catch Throwable") + '(#t #t) "Check properly catching exceptions") + + (execute-test + "import java.util.*; + class Random { }" + 'full #f "Hiding an import * name with a local class" + ) + + (interact-test + "import java.util.*; + class Random { + int getInt() { return 3; } + }" + 'full '("new Random().getInt()") '(3) + "Using the local Random and not the imported one") + + (interact-test + "class allPublic { + public int x() { return 3; } + } + class onePrivate { + private int x() { return new allPublic().x(); } + public int y() { return x(); } + } + " + 'full + '("new onePrivate().y()") '(3) "Private method calling public method of same name") + + (execute-test + "class withPrivate { + withPublic f; + + private int with() { return this.f.with(); } + } + + class withPublic { + withPrivate r = new withPrivate(); + + public int with() { return 3; } + }" 'full #f "Potential conflict of names for private method") + + (execute-test + "class hasCharArray { + char[] b = new char[]{'a'}; + }" 'full #f "Test of array alloc init") + + (execute-test + "class Aextendee { + int f (Aextendee x) { return 4; } + } + class Bextendor extends Aextendee { + int f( Bextendor x) { return 5; } + }" + 'full #f + "Overloading introduced on extends") + + (execute-test + "class Xforward { + int x = y; + int y; + }" 'full #t "Forward reference error") + + (interact-test + "class Xnoundef { + int x = this.y; + int y = 2; + }" + 'full + '("new Xnoundef().x" "new Xnoundef().y") + '(0 2) + "Testing no undefined fields") + + (parameterize ((dynamic? #t)) + (interact-test + "class Xeq { }" + 'full + '("Xeq x = new Xeq();" "Xeq y = (dynamic) x;" "x.equals(y)" "y.equals(x)" "y==x" "x==y") + '((void) (void) #t #t #t #t) + "Equality test of a wrapped and unwrapped object")) + + (parameterize ((dynamic? #t)) + (interact-test + "class Xacc { int y; Xacc(int y) { this.y = y; } }" + 'full + '("Xacc x = new Xacc(3);" "Xacc y = (dynamic) x;" "x.y = 4" "y.y" "y.y=5" "x.y") + '((void) (void) 4 4 5 5) + "Accessing fields of a dynamic value")) + + (execute-test + "package a; class a { int x; + Object get() { class b { int y() { return a.this.x; } } return new b(); }}" + 'full #f "Statement inner class accessing package field") + + (parameterize ((dynamic? #t)) + (interact-test "class Acast { }" + 'full + '("dynamic x = new Acast();" "Acast a = x;" "(Acast) a") + '((void) (void) a~f) + "Casting a guarded/asserted value back to the original type")) + + (parameterize ((dynamic? #t)) + (interact-test + "interface I { int m( int x); } + class C implements I { + public int m(int x) { return x; } + boolean n(boolean y) { return !y; } + dynamic q(I x) { return x; } + }" 'full + '("(new C().q(new C())).n(true)" "(new C().q(new C())).m(5)") + '(error 5) + "Returning a dynamic value, properly quarded. Should not be send")) + + (parameterize ((dynamic? #t)) + (interact-test + "class Xcastd{ int x( int i) { return i; }}" + 'full + '("((dynamic) new Xcastd()).x(1)" "((dynamic) new Xcastd()).x()") + '(1 error) + "Test of casting known values to dynamic")) + + (execute-test + "interface Aa {} + interface Ba {} + class Ca implements Aa, Ba { + static void go() { + Ca c = new Ca(); + Aa a = c; + Ba b = c; + + if (a == b) { + b=b; + } + if (a == c) { + a=a; + } + if (c == b) { + b=b; + } + } + }" 'full #f "test of ==, using castable") + + (execute-test + "class Ab { } + class Bb extends Ab { } + class Cb extends Ab { } + class Xb { + Ab a = new Bb(); + Cb b = new Cb(); + boolean e() { + return a == b; + } + }" 'full #f "Test of ==") + + (execute-test + "class Ac { } + class Bc extends Ac { } + class Cc extends Ac { } + class Xc { + Bc a = new Bc(); + Cc b = new Cc(); + boolean e() { + return a == b; + } + }" 'full #t "Incompatible type test ==") + + (execute-test + "class Ad { + boolean b() { + return \"hi\" == new Object(); + } + }" 'full #f "Comparing String and Object") + + (execute-test + "final class Ae { + } + interface Be { } + class Xe { + Object o( Ae a ) { + return (Be) a; + } + }" 'full #t "Cast from final class to unimpl interface") + + (interact-test + 'full + (list "float x = 3/2;" "x" "double y = 3.2/2;" "y") + (list '(void) 1 '(void) 1.6) "Test of choosing integer vs floating point division") + + (parameterize ((dynamic? #t)) + (execute-test + "class Xf { int m(dynamic x) { return x(1); } }" + 'full #f "Using a dynamic parameter as a method")) + + (parameterize ((dynamic? #t)) + (execute-test + "class Xg { dynamic x; }" + 'full #f "Dynamic variable (unused) in class") + (execute-test + "class Xh { dynamic x; int foo() { return x; } }" + 'full #f "Dynamic variable used, but not executed in class") + (execute-test + "class Xi { dynamic f() { return 3; } }" + 'full #f "Method returning dynamic with actual an int") + (execute-test + "class Xj { int f(dynamic x) { return 3; }}" + 'full #f "Method with dynamic parm, not used") + (execute-test + "class Xk {float f(dynamic x, dynamic y) { return x + y; }}" + 'full #f "Method adding two dynamics, returning a float") + (interact-test + "class Xl { float f( dynamic x, dynamic y) { return x + y; }}" + 'full (list "new Xl().f(1,1);") + (list 2) + "Method adding two dynamics (returning a float), called")) + + + + (execute-test + "class Crv { + void x() { return 1; } + }" + 'full #t "Trying to return value from void method") + + (interact-test + 'full + (list "return 1 + true;") + (list 'error) + "Make sure returns are type-checked in interactions") + + (execute-test + "class Abames { + void n() { } + void s() { } + void src() { } + void p() { } + void c() { } }" + 'full #f "Names that used to get clobbered") + + (interact-test + "class Ainner { + class B { + B() { } + Ainner m = Ainner.this; + } + //B b = new B(); + }" + 'full + (list "Ainner a = new Ainner();" "Ainner.B b = a.new B();" "a.new B().m") + (list '(void) '(void) 'a~f) + "Inner class creation") + + (execute-test "/* empty */" + 'full + #f + "Empty file of comments") + + (execute-test + "interface Bt { int largestNum(); } + + class Leaf implements Bt { public int largestNum() { return 1 ;} } + + class Heap implements Bt { + Bt left; + Bt right; + public int largestNum(){ + if(this.left instanceof Heap && + this.right instanceof Heap) + return this.right.largestNum(); + else if(this.left instanceof Heap) + return this.right.largestNum(); + else + return this.right.largestNum(); + } + }" 'full #f "Instanceof test") + + + (execute-test "interface Faa { + int foo(int x); + } + interface Gaa extends Faa { + int foo(int x); + } + + class Aia implements Gaa { + Aia() { } + public int foo(int x) { return 3; } + }" 'full #f "Extending an interface while overriding a method") + + (execute-test + "class Foo { + private static int getX() { return 5; } + public static int x = getX(); + }" + 'full #f "Static access and order") + + (interact-test + "public class hasStatic1 { + private int myId; + + public hasStatic1( int id ) { + super(); + this.myId = id; + } + + public static int returnId( hasStatic1 s ) { + return s.myId; + } + }" + 'full (list "hasStatic1.returnId(new hasStatic1(4))") (list 4) "Static use of private field") + + (interact-test 'full + (list "int x = 4;" "x") + (list `(void) 4) + "Use of interactions fields") + + (interact-test 'full + (list "String x = 4;") + (list 'error) + "Incorrect field assignment") + + (interact-test 'full + (list "1.0 == 1.0") + (list #t) + "Floating point ==") + + (execute-test + "class A { + int x; + A() { + this.x = 4; + super(); + } + }" + 'full #t "Misplaced super call") + + (interact-test + "class Az { + static int x= 0; + static { + for(int i = 0; i< 10; i++) + x += i; + } + }" + 'full (list "Az.x") (list 45) "for loop in static section") + + (execute-test + "class Azz { Azz() { super.toString(); } }" + 'full #f "Calling a super method") + + (report-test-results)) diff --git a/collects/tests/profj/intermediate-tests.ss b/collects/tests/profj/intermediate-tests.ss new file mode 100644 index 0000000000..445d67bdc2 --- /dev/null +++ b/collects/tests/profj/intermediate-tests.ss @@ -0,0 +1,623 @@ +(module intermediate-tests mzscheme + (require "profj-testing.ss") + + (prepare-for-tests "Intermediate") + + ;;Execute tests without errors + + (execute-test + "interface A { int a(); } + abstract class B implements A { } + " + 'intermediate + #f "abstract class not fully implementing an interface") + + (execute-test + "interface A1 { int a(); } + abstract class B1 implements A1 { } + class C1 extends B1 { + int a() { return 3; } + }" + 'intermediate + #f "class implementing abstract class's unimplmenented interface") + + (execute-test + "interface ToImplement { int a(); } + abstract class ToExtend implements ToImplement { int a() { return 2; } } + class ToBe extends ToExtend implements ToImplement { + }" + 'intermediate + #f "Repetition of fully satisfied interface in class hierarchy") + + + (execute-test + "abstract class Foo { + abstract int f(); + }" + 'intermediate + #f "Simple abstract class with abstract method") + + (execute-test + "abstract class Foo1 { + abstract int f(); + } + class FooP extends Foo1 { + int f() { return 3; } + }" + 'intermediate + #f "Simple abstract class with extending sub class") + + (execute-test + "abstract class Foo2 { + abstract int f(); + int fp() { return 3; } + } + class FooP2 extends Foo2 { + int f() { return this.fp(); } + }" + 'intermediate + #f "Abstract class with abstract and non abstract methods; implemented") + + (execute-test + "abstract class Fo { + int dist; + }" + 'intermediate #f "Abstract class with field") + + (execute-test + "abstract class F { + abstract int fp(); + } + abstract class G extends F { + abstract int gp(); + }" + 'intermediate #f "Abstract class extending abstract class") + + (execute-test + "class first { } + class second extends first { }" + 'intermediate #f "Class extension") + + (execute-test + "class first1 { int x() { return 3; } } + class second1 extends first1 { int x() { return 6; }}" + 'intermediate #f "Overriding") + + (execute-test + "class first { int x() { return 3; }} + class second extends first { int x() { return super.x() + 3; }}" + 'intermediate #f "Use of super in the method body") + + (execute-test + "interface f { int fp(); } + interface g extends f { int fp(); int gp(); } + abstract class F implements g { + int fp() { return 2; } + abstract boolean i( int c ); + } + class G extends F { + int gp() { return 2; } + boolean i ( int c ) { return c == this.gp(); } + }" + 'intermediate #f "Abstract class with interface") + + (execute-test + "class HasMethod { + HasMethod() { } + int myMethod() { + return 4; + } + } + class HasInheritedMethod extends HasMethod{ + HasInheritedMethod() { } + + int otherMethod() { + return this.myMethod(); + } + }" + 'intermediate + #f "Method Inheritance Test") + + (execute-test + "class ForError { + int x; + } + + class extendForError extends ForError { + } + + class UseError { + int f(ForError a) { + return a.x; + } + } + + class NoError extends UseError { + int fPrime() { + return this.f( new extendForError() ); + } + }" 'intermediate #f "Former inheritance error") + + (execute-test + "class voidMethod { + void doNothing() { return; } + }" 'intermediate #f "Test of return of no arguments") + + (execute-test + "class Date { + int day; + int month; + int year; + + Date(int day, int month, int year) { + this.day = day; + this.month = month; + this.year = year; + } + } + class ClockTime { + int hour; + int minute; + + ClockTime(int hour, int minute){ + this.hour = hour; + this.minute = minute; + } + } + abstract class AMuseTicket { + Date d; + int price; + } + class MuseAdm extends AMuseTicket { + MuseAdm(Date d, int price) { + this.d = d; + this.price = price; + } + } + class OmniMax extends AMuseTicket { + ClockTime t; + String title; + OmniMax(Date d, int price, ClockTime t, String title) { + this.d = d; + this.price = price; + this.t = t; + this.title = title; + } + } + class LaserShow extends AMuseTicket { + ClockTime t; + String row; + int seat; + + LaserShow(Date d, int price, ClockTime t, String row, int seat) { + this.d = d; + this.price = price; + this.t = t; + this.row = row; + this.seat = seat; + } + }" + 'intermediate #f "Book Test Date") + + (execute-test + "abstract class AZooAnimal{ + String name; + int weight; + } + class Lion extends AZooAnimal{ + int meat; + + Lion(String name, int weight, int meat){ + this.name = name; + this.weight = weight; + this.meat = meat; + } + } + class Snake extends AZooAnimal{ + int length; + + Snake(String name, int weight, int length){ + this.name = name; + this.weight = weight; + this.length = length; + } + } + class Monkey extends AZooAnimal{ + String food;; + + Monkey(String name, int weight, String food){ + this.name = name; + this.weight = weight; + this.food = food; + } + }" + 'intermediate #f "Book Test: ZooAnimal") + + (execute-test + "class Foo { + Foo() { + super(); + x = 5; + } + + int x; + int adder( int v ) { + return v + x; + } + }" + 'intermediate #f "Calling super") + + (execute-test + "interface foo { + int size(); + } + class M implements foo { + int size() { return 1;} + }" + 'intermediate #f "Interface implemented") + + (execute-test + "abstract class Path { abstract boolean isOk(); } + abstract class Success extends Path { + boolean isOk() { return true; } + } + class Left extends Success { + Success rest; + Left(Success rest) { this.rest = rest; } + }" + 'intermediate #f "Abstract method implemented, class subclassed") + + (execute-test + "class XIof { + boolean equals( Object o ) { + return o instanceof XIof; + } + }" + 'intermediate #f "Correct instanceof usage") + + (execute-test + "class A { } + class B extends A { } + class C { + A a = new B(); + Object o () { + return ((B) a); + } + Object ob( B b) { + return ((A) b); + } + }" 'intermediate #f "Simple correct casting") + + (execute-test + "interface A { } + class C { + Object e( C c ) { + return (A) c; + } + }" 'intermediate #f "Cast of non-final class to empty interface") + + (execute-test + "interface A { } + interface B { int foo(); } + class C { + Object e( A a ) { + return (B) a; + } + }" 'intermediate #f "Cast of empty interface to non-empty interface") + + (execute-test + "interface A { int foo(); } + interface B { boolean foo(int i); } + class C { + Object e( A a) { + return (B) a; + } + }" 'intermediate #f "Cast of two non-same non-conflicting interfaces") + + (execute-test + "interface A { } + class C implements A { + Object e ( C c) { + return ((A) c); + } + Object e2( A a) { + return ((C) a); + } + }" 'intermediate #f "Casts of class to implementing iface, and reverse") + + ;;Execute tests with errors + + (execute-test + " +interface I {} + +interface J extends I {} + +abstract class implements J {}" 'intermediate #t "Parser error, class identifier") + + (execute-test + "class CheckError { + void foo() { } + } + class Examples { + boolean t1 = check new CheckError().foo() expect false; + } + " 'intermediate #t "Check with void method call in test") + + (execute-test + "class CheckError { + void foo() { } + } + class Examples { + boolean t1 = check 3 expect new CheckError().foo(); + }" 'intermediate #t "Check with void method call in expect") + + (execute-test + "class A { + a b c; + }" + 'intermediate + #t "Parse error with three identifiers in a row") + + (execute-test + "interface A { int a(); } + abstract class B implements A { } + class C extends B { int a() { return super.a() + 3; } }" + 'intermediate + #t "Extending class calls super.a() of an abstract method") + + + (execute-test + "interface A { int a(); } + abstract class B implements A { } + class C extends B { }" + 'intermediate + #t + "Extending class fails to implement abstract parent's unimplemented interfaces") + + (execute-test + "class Foo { + Foo() {} + boolean compare(int x, int y, int z) { + return (x == y) (y == z); + } +}" + 'intermediate #t "Parse error, two expressions (one parened) without an operator") + + (execute-test + "abstract class F{ abstract int f(); } + class G extends F { }" + 'intermediate #t "Extending abstract class without method") + + (execute-test + "abstract class F { abstract int f(); } + class g extends F { boolean f() { return true; } }" + 'intermediate #t "Extending abstract class with incorrect method") + + (execute-test + "abstract class F { } + class G extends F { + int f() { return super.f(); } + }" + 'intermediate #t "Super call for non-existing method") + + (execute-test + "class A { int a; } + class B extends A { int a; } + " 'intermediate #t "Test of shadowing dissallowed") + + (execute-test + "interface A { } + class B extends A { }" + 'intermediate #t "extending an interface") + + (execute-test + "interface A { } + class B implements A { } + interface AAA { int f(); } + abstract class BBBB extends B implements AAA { } + class NotImplementIFace extends BBBB { }" + 'intermediate #t "Interface not implemented, by inheritance") + + (execute-test + "abstract class ALoC + { + boolean this.isMT; + abstract boolean compareTo(ALoC that); + abstract Coach getFst(); + abstract ALoC getRst(); + }" + 'intermediate #t "Illegal use of this as a name") + + (execute-test + "class ConsList extends List{ + Swimmer first; + List rest; + ConsList(Swimmer first, List rest){ + this.first = first; + this.rest = rest; + } + //the longer method takes a number and returns a list of all of the Swimmers + //in the original list that are longer than the given number. + List longer(int n){ + + if (n <= this.first.length) { + rest.longer(n); + } else { + rest.longer(n) + return this.first; + } + } + }" + 'intermediate #t "Incorrect statement- parse error") + + (execute-test + "interface Filter { Object filt(Object o); } + class Longer implements Filter{ + double l; + Longer(double l) { + this.l=l; + } + boolean filt(Object o){ + return (((Swimmer)o).length > l); + } + }" 'intermediate #t "Incompatible return type from inherited interface") + + (execute-test + "class X2 { + int c (Object o) { + return (int) o; + } + }" 'intermediate #t "Cast of object to primitive") + + (execute-test + "class X3 { + int c () { + return (int) false; + } + }" 'intermediate #t "cast of boolean to integer") + + (execute-test + "interface A { int x();} + interface B { boolean x(); } + class X4 { + Object o(A a) { + return (B) a; + } + }" 'intermediate #t "cast of incompatible interfaces") + + + ;;Interact tests + + (interact-test + "class cycleA { + cycleB b; + cycleA( cycleB b) { + this.b = b; + b.addMyA(this); + } + } + class cycleB { + cycleA a; + cycleB() { } + + void addMyA( cycleA a) { + this.a = a; + } + }" + 'intermediate + (list "cycleA a = new cycleA( new cycleB());" "a") + (list '(void) 'a~f) + "Cyclic class constructors") + + + (interact-test + "class A { + int a() { return 2; } + } + class B extends A { + int a() { return 3 + super.a(); } + }" + 'intermediate + (list "new B().a()") + (list 5) + "Calling a super method") + + (interact-test + 'intermediate + '("(double) 1" "(double) 1.0" "double x;" "x" "x = 1;" "(int) x") + '(1.0 1.0 (void) 0.0 1.0 1) + "Double-int conversions") + + (interact-test + "import draw.*; + import colors.*; +class BlockWorld extends World { + int WIDTH = 100; + int HEIGHT = 100; + AColor BACKGROUND = new Red(); + DrpBlock block; + BlockWorld(DrpBlock block) { + this. block = block; + } + World onTick() { + return new BlockWorld(this. block.drop()); + } + + World onKeyEvent(String ke) { + return this; + } + boolean erase() { + return this. drawBackground(); + } + boolean draw() { + return this. block.draw(this); + } + boolean drawBackground() { + return true;//this. theCanvas.drawRect(new Posn(0,0),this. WIDTH,this. HEIGHT,this. BACKGROUND); + } +} + +class Examples extends BlockWorld { + Examples() { + super(new DrpBlock(10,0)); + } +} +class DrpBlock { + int down; + int right; + int HEIGHT = 10; + int WIDTH = 10; + int deltaY = 5; + int deltaX = 3; + + DrpBlock(int down, int right) { + this. down = down; + this. right = right; + } + DrpBlock drop() { + return new DrpBlock(this. down + this. deltaY,this. right); + } + boolean draw(World w) { + return w.theCanvas.drawRect(new Posn(this.right,this.down),this.HEIGHT,this.WIDTH,new Red()); + } + boolean erase(BlockWorld w) { + return w.theCanvas.drawRect(new Posn(this.right,this.down),this.HEIGHT,this.WIDTH,w.BACKGROUND); + } + boolean hasLanded(BlockWorld w) { + if (this. down + this. HEIGHT >= w.HEIGHT) { + return true; + } else { + return false; + } + } + DrpBlock steer(String ke) { + if (ke.equals(\"left\")) { + return new DrpBlock(this. down,this. right - this. deltaX); + } else { + if (ke.equals(\"right\")) { + return new DrpBlock(this. down,this. right + this. deltaX); + } else { + return this; + } + } + } + boolean toStop(BlockWorld w, int down) { + if (this. down + this. HEIGHT >= down) { + return true; + } else { + return false; + } + } +}" + 'intermediate + '("Examples a = new Examples();") '((void)) + "Cycle: used to cause multiple declarations of a class") + + (interact-test + 'intermediate + '("int a = 3;" "a = 45;" "a") + '((void) 45 45) + "Test of assignment") + + (report-test-results)) diff --git a/collects/tests/profj/intermediateTest.java b/collects/tests/profj/intermediateTest.java new file mode 100644 index 0000000000..066338a0ae --- /dev/null +++ b/collects/tests/profj/intermediateTest.java @@ -0,0 +1,125 @@ +// 14 checks; 2 failures +// 6 tests; no failures +// Order of calling testMethods crucial for test success + +interface Automobile { + int milesTraveled(); + void travel( int miles ); +} + +abstract class Auto implements Automobile { + int miles; + int milesTraveled() { return miles; } + + void travel(int miles) { + this.miles = this.miles + miles; + } +} + +class Car extends Auto { + + double basePrice; + + Car(int miles, double basePrice) { + this.miles = miles; + this.basePrice = basePrice; + } + + double price(int year) { + if ((2006 - year) == 0) { + return this.basePrice; + } else { + if ((2006 - year) > 0) { + return this.basePrice - (this.basePrice / (2006 - year)); + } else { + return this.basePrice + (this.basePrice / (year - 2006)); + } + } + } + +} + +class CarExamples { + + Car myCar = new Car(100000, 16000.00); + Car momCar = new Car(10000, 32000.00); + + boolean test1 = check this.myCar expect this.momCar; + boolean test2 = check this.myCar.milesTraveled() expect 100000; + + boolean testTravel() { + myCar.travel(10); + return (check this.myCar expect new Car(100010, 16000.00)); + } + + boolean testTravel2() { + myCar.travel(10); + return (check this.myCar expect new Car(100020, 16000.00)); + } + + boolean testPrice() { + return (check this.myCar.price(2006) expect 16000.00 within .01) && + (check this.myCar.price(1991) expect 14933.33 within .01) && + (check this.myCar.price(2007) expect 32000.00 within .01); + } + +} + +class Truck extends Auto { + String make; + int numDoors; + boolean extendedBed; + double basePrice; + + Truck( String make, int miles, int numDoors, boolean bed, double basePrice) { + this.make = make; + this.miles = miles; + this.numDoors = numDoors; + this.extendedBed = bed; + this.basePrice = basePrice; + } + + String makeAndModel() { + if (this.extendedBed) { + return this.make.concat("Extended"); + } else { + return this.make.concat(String.valueOf(this.numDoors)); + } + } + double price( int year ) { + // Uncomment to test runtime error behavior + //return this.basePrice - (2 * (this.basePrice / (2006 -year))); + if (year == 2006) { + return this.basePrice; + } else { + return this.basePrice - (2 * (this.basePrice / (2006 - year))); + } + } + +} + +class TruckExamples { + Truck oneTruck = new Truck("Toyota",10000, 2,false,20000.00); + Truck twoTruck = new Truck("Ford",100000,2,true,35000.00); + + boolean test1 = check this.oneTruck.milesTraveled() expect 10000; + boolean test2 = check this.oneTruck expect this.twoTruck; + + TruckExamples() { } + + boolean testPrice() { + return (check this.oneTruck.price(2006) expect 20000.00 within .01) && + (check this.oneTruck.price(1996) expect 16000.00 within .01); + } + + boolean testTravel() { + oneTruck.travel(1000); + return check this.oneTruck expect new Truck("Toyota",11000,2,false,20000.00); + } + + boolean testMakeAndModel() { + return (check this.oneTruck.makeAndModel() expect "Toyota2") && + (check this.twoTruck.makeAndModel() expect "FordExtended"); + } + +} \ No newline at end of file diff --git a/collects/tests/profj/profj-testing.ss b/collects/tests/profj/profj-testing.ss new file mode 100644 index 0000000000..0591618a21 --- /dev/null +++ b/collects/tests/profj/profj-testing.ss @@ -0,0 +1,261 @@ +(module profj-testing scheme + + (require profj/compile + (lib "parameters.ss" "profj") + (lib "display-java.ss" "profj") + mzlib/class) + + (define report-expected-error-messages (make-parameter #t)) + + (define interaction-errors (make-parameter 0)) + (define execution-errors (make-parameter 0)) + (define file-errors (make-parameter 0)) + (define interaction-msgs (make-parameter null)) + (define execution-msgs (make-parameter null)) + (define file-msgs (make-parameter null)) + (define missed-expected-errors (make-parameter 0)) + (define expected-failed-tests (make-parameter null)) + (define expected-error-messages (make-parameter null)) + + (provide java-values-equal?) + (define (java-values-equal? v1 v2) + (java-equal? v1 v2 null null)) + + ;java-equal?: 'a 'a (list 'a) (list 'a)-> bool + (define (java-equal? v1 v2 visited-v1 visited-v2) + (or (eq? v1 v2) + (already-seen? v1 v2 visited-v1 visited-v2) + (and (number? v1) (number? v2) (= v1 v2)) + (cond + ((and (object? v1) (object? v2)) + (cond + ((equal? "String" (send v1 my-name)) + (and (equal? "String" (send v2 my-name)) + (equal? (send v1 get-mzscheme-string) (send v2 get-mzscheme-string)))) + ((equal? "array" (send v1 my-name)) + (and (equal? "array" (send v2 my-name)) + (= (send v1 length) (send v2 length)) + (let ((v1-vals (array->list v1)) + (v2-vals (array->list v2))) + (andmap (lambda (x) x) + (map java-equal? v1-vals v2-vals + (map (lambda (v) (cons v1 visited-v1)) v1-vals) + (map (lambda (v) (cons v2 visited-v2)) v2-vals)))))) + (else + (and (equal? (send v1 my-name) (send v2 my-name)) + (let ((v1-fields (send v1 field-values)) + (v2-fields (send v2 field-values))) + (and (= (length v1-fields) (length v2-fields)) + (andmap (lambda (x) x) + (map java-equal? v1-fields v2-fields + (map (lambda (v) (cons v1 visited-v1)) v1-fields) + (map (lambda (v) (cons v2 visited-v2)) v2-fields))))))))) + ((and (not (object? v1)) (not (object? v2))) (equal? v1 v2)) + (else #f)))) + + ;array->list: java-array -> (list 'a) + (define (array->list v) + (letrec ((len (send v length)) + (build-up + (lambda (c) + (if (= c len) + null + (cons (send v access c) + (build-up (add1 c))))))) + (build-up 0))) + + ;already-seen?: 'a 'a (list 'a) (list 'a)-> bool + (define (already-seen? v1 v2 visited-v1 visited-v2) + (cond + ((and (null? visited-v1) (null? visited-v2)) #f) + ((memq v1 visited-v1) + (let ((position-v1 (get-position v1 visited-v1 0))) + (eq? v2 (list-ref visited-v2 position-v1)))) + (else #f))) + + ;get-position: 'a (list 'a) int -> int + (define (get-position v1 visited pos) + (if (eq? v1 (car visited)) + pos + (get-position v1 (cdr visited) (add1 pos)))) + + ;interact-internal: symbol (list string) (list evalable-value) string type-record -> void + (define (interact-internal level interacts vals msg type-recs namespace) + (for-each (lambda (ent val) + (let ((st (open-input-string ent))) + (with-handlers + ([exn? + (lambda (exn) + (cond + ((and (eq? val 'error) (report-expected-error-messages)) + (expected-error-messages (cons (cons msg (exn-message exn)) (expected-error-messages)))) + ((not (eq? val 'error)) + (interaction-errors (add1 (interaction-errors))) + (interaction-msgs (cons + (format "Test ~a: Exception raised for ~a : ~a" + msg ent (exn-message exn)) (interaction-msgs))))))]) + (parameterize ([current-namespace namespace][coverage? #f]) + (let ((new-val (eval `(begin (require mzlib/class + (prefix-in javaRuntime: (lib "runtime.ss" "profj" "libs" "java")) + (prefix-in c: scheme/contract)) + ,(compile-interactions st st type-recs level))))) + (when (eq? val 'error) + (missed-expected-errors (add1 (missed-expected-errors))) + (expected-failed-tests (cons msg (expected-failed-tests)))) + (unless (and (not (eq? val 'error)) (java-equal? (eval val) new-val null null)) + (interaction-errors (add1 (interaction-errors))) + (interaction-msgs (cons (format "Test ~a: ~a evaluated to ~a instead of ~a" + msg ent new-val val) (interaction-msgs))))))))) + interacts vals)) + + ;interact-test: symbol (list string) (list evalable-value) string | + ; : string stymbol (list string) (list evalable-value) string -> void + (define interact-test + (case-lambda + [(level in val msg) + (interact-internal level in val msg (create-type-record) (make-base-namespace))] + ((defn level in val msg) + (let* ((type-recs (create-type-record)) + (def-st (open-input-string defn)) + (cur-namespace (make-base-namespace))) + (with-handlers + ([exn? + (lambda (exn) + (interaction-errors (add1 (interaction-errors))) + (interaction-msgs (cons (format "Test ~a: Exception raised in definition : ~a" + msg (exn-message exn)) + (interaction-msgs))))]) + (execution? #t) + (eval-modules (compile-java 'port 'port level #f def-st def-st type-recs) cur-namespace) + (interact-internal level in val msg type-recs cur-namespace)))))) + + ;interact-test-java-expected: string symbol (list string) (list string) string -> void + (define (interact-test-java-expected defn level in val msg) + (let* ((type-recs (create-type-record)) + (def-st (open-input-string defn)) + (cur-namespace (make-base-namespace))) + (with-handlers + ([exn? + (lambda (exn) + (interaction-errors (add1 (interaction-errors))) + (interaction-msgs (cons (format "Test ~a: Exception raised in definition : ~a" + msg (exn-message exn)) + (interaction-msgs))))]) + (execution? #t) + (eval-modules (compile-java 'port 'port level #f def-st def-st type-recs) cur-namespace) + (let ((vals (map (lambda (ex-val) + (let ((st (open-input-string ex-val))) + (parameterize ((current-namespace cur-namespace)) + (eval `(begin (require mzlib/class + (prefix-in javaRuntime: (lib "runtime.ss" "profj" "libs" "java"))) + ,(compile-interactions st st type-recs level)))))) + val))) + (interact-internal level in vals msg type-recs cur-namespace))))) + + (define (execute-test defn level error? msg) + (let ((st (open-input-string defn))) + (with-handlers + ([exn? + (lambda (exn) + (cond + ((and error? (report-expected-error-messages)) + (expected-error-messages (cons (cons msg (exn-message exn)) (expected-error-messages)))) + ((not error?) + (execution-errors (add1 (execution-errors))) + (execution-msgs (cons + (format "Test ~a : Exception-raised: ~a" msg (exn-message exn)) (execution-msgs))))))]) + (eval-modules (compile-java 'port 'port level #f st st) (make-base-namespace)) + (when error? + (missed-expected-errors (add1 (missed-expected-errors))) + (expected-failed-tests (cons msg (expected-failed-tests)))) + ))) + + ;run-test: symbol string (U string (list string)) (U string (list string)) -> (U (list (list symbol bool string)) (list ...)) + (define (run-test level defn interact val) + (let* ((type-recs (create-type-record)) + (def-st (open-input-string defn)) + (check-vals + (lambda (interact val) + (with-handlers + ([exn? + (lambda (exn) + (list 'interact #f (exn-message exn)))]) + (let* ((get-val (lambda (v-st v-pe) + (eval `(begin (require mzlib/class) + (require (prefix-in javaRuntime: (lib "runtime.ss" "profj" "libs" "java"))) + ,(compile-interactions v-st v-st type-recs level))))) + (i-st (open-input-string interact)) + (v-st (open-input-string val)) + (i-pe (lambda () (open-input-string interact))) + (v-pe (lambda () (open-input-string val))) + (given-val (get-val i-st i-pe)) + (exp-val (get-val v-st v-pe))) + (list 'interact (java-equal? given-val exp-val null null) (format-java-value given-val #t 'field null #f 0))))))) + (with-handlers + ([exn? + (lambda (exn) + (list 'defn #f (exn-message exn)))]) + (execution? #t) + (eval-modules (compile-java 'port 'port level #f def-st def-st type-recs)) + (cond + ((and (pair? interact) (pair? val)) + (map check-vals interact val)) + ((and (string? interact) (string? val)) + (check-vals interact val)))))) + + (define (file-test file level error? msg) + (with-handlers + ([exn? + (lambda (exn) + (unless error? + (file-errors (add1 (file-errors))) + (file-msgs (cons + (format "Test ~a :Exception-raised: ~a" msg (exn-message exn)) (file-msgs)))))]) + (eval-modules (compile-java 'file 'port level file #f #f)))) + + (define (eval-modules modules namespace) + (parameterize ([current-namespace namespace]) + (for-each eval + (apply append + (map compilation-unit-code modules))))) + + ;prepare-for-tests: String -> void + (define (prepare-for-tests lang-level) + (printf "Running tests for ~a~n" lang-level) + (interaction-errors 0) + (interaction-msgs null) + (execution-errors 0) + (execution-msgs null) + (file-errors 0) + (file-msgs null) + (missed-expected-errors 0) + (expected-failed-tests null) + (expected-error-messages null)) + + + ;report-test-results: -> void + (define (report-test-results) + (when (> (interaction-errors) 0) + (printf "~a Interaction errors occurred~n" (interaction-errors)) + (for-each (lambda (m) (printf "~a~n" m)) (interaction-msgs)) + (newline)) + (when (> (execution-errors) 0) + (printf "~a Execution errors occurred~n" (execution-errors)) + (for-each (lambda (m) (printf "~a~n" m)) (execution-msgs)) + (newline)) + (when (> (file-errors) 0) + (printf "~a file errors occurred~n" (file-errors)) + (for-each (lambda (m) (printf "~a~n" m)) (file-msgs)) + (newline)) + (when (> (missed-expected-errors) 0) + (printf "Failed to receive errors for these ~a tests:~n" (missed-expected-errors)) + (for-each (lambda (m) (printf "~a~n" m)) (expected-failed-tests)) + (newline)) + (when (report-expected-error-messages) + (printf "Received these expected error messages:~n") + (for-each (lambda (m) (printf "Error for test ~a : ~a~n" (car m) (cdr m))) (expected-error-messages))) + (printf "Tests completed~n")) + + (provide interact-test execute-test interact-test-java-expected file-test run-test + report-test-results prepare-for-tests report-expected-error-messages) + )