#!/usr/bin/swipl

% Test script for lab 5 functions:
%   to run the script (once you've finished your lab5.pl)
%   type the following from the linux command line:
%      ./tester.pl

:- initialization main.   % will use main to start script execution

% initialization of some stock rectangles

initR(big, rectangle(0, 10, 10, 0)).        % covers whole 10x10 area
initR(upperLeft, rectangle(0, 4, 9, 6)).    % inside big, bordering top half of left edge
initR(lowerRight, rectangle(6, 10, 4, 1)).  % inside big, bordering bottom half of right edge
initR(lowerLeft, rectangle(1, 4, 4, 0)).    % inside big, bordering left side of top edge
initR(upperRight, rectangle(6, 9, 10, 6)).  % inside big, bordering right side of bottom edge
initR(largeMiddle, rectangle(3, 7, 7, 3)).  % center of big, overlapping all above
initR(smallMiddle, rectangle(4, 6, 6, 4)).  % center of big, touching four corners of smalls

% runTest(T,D,Exp)
% ----------------
% apply test goal T to data D, where the expected result is Exp
%    compare actual result to expected and display a PASS/FAIL summary
runTest(T,D,true) :-
   format("   Running ~w on ~w, expecting success~n   ", [T,D]),
   (apply(T,D) -> Msg = "PASS: Test succeeded" ; Msg = "  FAIL: test failed"),
   format("   ~w~n", [Msg]).

runTest(T,D,false) :-
   format("   Running ~w on ~w, expecting a false result~n   ", [T,D]),
   (apply(T,D) -> Msg = "FAIL: incorrect true result" ; Msg = "  PASS: correct false result"),
   format("   ~w~n", [Msg]).


% tests for rectangle(L,R,T,B)
% ----------------------------
% test that rectangle approves two valid rectangles
testRs(valid) :-
    runTest(rectangle, [1,3,5,2], true),
    runTest(rectangle, [3.3,3.4,2.2,2.1], true).

% test that rectangle rejects cases where L >= R or B >= T
testRs(badCoords) :-
    runTest(rectangle, [3,1,5,2], false),
    runTest(rectangle, [1,3,2,5], false),
    runTest(rectangle, [3,3,2,5], false),
    runTest(rectangle, [3,1,4,4], false).

% test that rectangle rejects non-numeric values
testRs(notNums) :-
    runTest(rectangle, [foo,3,5,1], false),
    runTest(rectangle, [1,foo,5,1], false),
    runTest(rectangle, [1,3,foo,1], false),
    runTest(rectangle, [1,3,5,foo], false).


% tests for separate(R1,R2)
% -------------------------
% tests with clear separation
testSs(gap) :-
    initR(upperLeft, R1), initR(lowerRight,R2), runTest(separate,[R1,R2], true),
    initR(lowerRight, R3), initR(upperLeft,R4), runTest(separate,[R3,R4], true),
    initR(lowerRight, R5), initR(lowerLeft,R6), runTest(separate,[R5,R6], true),
    initR(upperRight, R7), initR(lowerRight,R8), runTest(separate,[R7,R8], true).

% tests with clear overlap
testSs(over) :-
    initR(big, R1), initR(smallMiddle,R2), runTest(separate,[R1,R2], false),
    initR(lowerRight, R3), initR(largeMiddle,R4), runTest(separate,[R3,R4], false),
    initR(largeMiddle, R5), initR(upperLeft,R6), runTest(separate,[R5,R6], false),
    initR(smallMiddle, R7), initR(largeMiddle,R8), runTest(separate,[R7,R8], false).

% tests where rectangles touch (border or corner)
testSs(touch) :-
    initR(lowerLeft, R1), initR(smallMiddle,R2), runTest(separate,[R1,R2], false),
    initR(upperRight, R3), initR(smallMiddle,R4), runTest(separate,[R3,R4], false),
    initR(smallMiddle, R5), initR(upperLeft,R6), runTest(separate,[R5,R6], false),
    initR(smallMiddle, R7), initR(lowerRight,R8), runTest(separate,[R7,R8], false).


% tests for overlap(R1,R2)
% ------------------------

% tests with clear separation
testOs(gap) :-
    initR(upperLeft, R1), initR(lowerRight,R2), runTest(overlap,[R1,R2], false),
    initR(lowerRight, R3), initR(upperLeft,R4), runTest(overlap,[R3,R4], false),
    initR(lowerRight, R5), initR(lowerLeft,R6), runTest(overlap,[R5,R6], false),
    initR(upperRight, R7), initR(lowerRight,R8), runTest(overlap,[R7,R8], false).

% tests with clear overlap
testOs(over) :-
    initR(big, R1), initR(smallMiddle,R2), runTest(overlap,[R1,R2], true),
    initR(lowerRight, R3), initR(largeMiddle,R4), runTest(overlap,[R3,R4], true),
    initR(largeMiddle, R5), initR(upperLeft,R6), runTest(overlap,[R5,R6], true),
    initR(smallMiddle, R7), initR(largeMiddle,R8), runTest(overlap,[R7,R8], true).

% tests where rectangles touch (border or corner)
testOs(touch) :-
    initR(lowerLeft, R1), initR(smallMiddle,R2), runTest(overlap,[R1,R2], true),
    initR(upperRight, R3), initR(smallMiddle,R4), runTest(overlap,[R3,R4], true),
    initR(smallMiddle, R5), initR(upperLeft,R6), runTest(overlap,[R5,R6], true),
    initR(smallMiddle, R7), initR(lowerRight,R8), runTest(overlap,[R7,R8], true).


% main routine: begin actual testing
% -----------------------------------

main(_) :-
   format("~n---Loading lab5.pl---~n"),
   consult('lab5.pl'),
   format("Finished loading~n"),
   format("~nTesting rectangle(L,R,T,B) with valid entries~n"),
   testRs(valid),
   format("~nTesting rectangle(L,R,T,B) where left/right or top/bottom incorrect~n   "),
   testRs(badCoords),
   format("~nTesting rectangle(L,R,T,B) with non-numeric values~n"),
   testRs(notNums),
   format("~nTesting separate on non-overlapping rectangles~n"),
   testSs(gap),
   format("~nTesting separate on overlapping rectangles~n"),
   testSs(over),
   format("~nTesting separate on rectangles that just touch~n"),
   testSs(touch),
   format("~nTesting overlap on non-overlapping rectangles~n"),
   testOs(gap),
   format("~nTesting overlap on overlapping rectangles~n"),
   testOs(over),
   format("~nTesting overlap on rectangles that just touch~n"),
   testOs(touch),
   format("~n---ALL TESTS COMPLETE---~n~n").

main(1).

