bde955c276
These small examples are designed to run quickly with the Gerrit prolog-shell, but not depending on a local Gerrit repository server. Change-Id: I8f58a6740c6f2c79ae1314f2ae593409ee60440d
79 lines
2.2 KiB
Prolog
79 lines
2.2 KiB
Prolog
%% Unit test helpers
|
|
|
|
% Write one line message.
|
|
msg(A) :- write(A), nl.
|
|
msg(A,B) :- write(A), msg(B).
|
|
msg(A,B,C) :- write(A), msg(B,C).
|
|
msg(A,B,C,D) :- write(A), msg(B,C,D).
|
|
msg(A,B,C,D,E) :- write(A), msg(B,C,D,E).
|
|
msg(A,B,C,D,E,F) :- write(A), msg(B,C,D,E,F).
|
|
|
|
% Redefine a caluse.
|
|
redefine(Atom,Arity,Clause) :- abolish(Atom/Arity), assertz(Clause).
|
|
|
|
% Increment/decrement of pass/fail counters.
|
|
set_counters(N,X,Y) :- redefine(test_count,3,test_count(N,X,Y)).
|
|
get_counters(N,X,Y) :- clause(test_count(N,X,Y), _) -> true ; (X=0, Y=0).
|
|
inc_pass_count :- get_counters(N,P,F), P1 is P + 1, set_counters(N,P1,F).
|
|
inc_fail_count :- get_counters(N,P,F), F1 is F + 1, set_counters(N,P,F1).
|
|
|
|
% Report pass or fail of G.
|
|
pass_1(G) :- msg('PASS: ', G), inc_pass_count.
|
|
fail_1(G) :- msg('FAIL: ', G), inc_fail_count.
|
|
|
|
% Report pass or fail of not(G).
|
|
pass_0(G) :- msg('PASS: not(', G, ')'), inc_pass_count.
|
|
fail_0(G) :- msg('FAIL: not(', G, ')'), inc_fail_count.
|
|
|
|
% Report a test as failed if it passed 2 or more times
|
|
pass_twice(G) :-
|
|
msg('FAIL: (pass twice): ', G),
|
|
inc_fail_count.
|
|
pass_many(G) :-
|
|
G = [A,B|_],
|
|
length(G, N),
|
|
msg('FAIL: (pass ', N, ' times): ', [A,B,'...']),
|
|
inc_fail_count.
|
|
|
|
% Test if G fails.
|
|
test0(G) :- once(G) -> fail_0(G) ; pass_0(G).
|
|
|
|
% Test if G passes exactly once.
|
|
test1(G) :-
|
|
findall(G, G, S), length(S, N),
|
|
(N == 0
|
|
-> fail_1(G)
|
|
; (N == 1
|
|
-> pass_1(S)
|
|
; (N == 2 -> pass_twice(S) ; pass_many(S))
|
|
)
|
|
).
|
|
|
|
% Report the begin of test N.
|
|
begin_tests(N) :-
|
|
nl,
|
|
msg('BEGIN test ',N),
|
|
set_counters(N,0,0).
|
|
|
|
% Repot the end of test N and total pass/fail counts,
|
|
% and check if the numbers are as exected OutP/OutF.
|
|
end_tests(OutP,OutF) :-
|
|
get_counters(N,P,F),
|
|
(OutP = P
|
|
-> msg('Expected #PASS: ', OutP)
|
|
; (msg('ERROR: expected #PASS is ',OutP), !, fail)
|
|
),
|
|
(OutF = F
|
|
-> msg('Expected #FAIL: ', OutF)
|
|
; (msg('ERROR: expected #FAIL is ',OutF), !, fail)
|
|
),
|
|
msg('END test ', N),
|
|
nl.
|
|
|
|
% Repot the end of test N and total pass/fail counts.
|
|
end_tests(N) :- end_tests(N,_,_).
|
|
|
|
% Call end_tests/2 and halt if the fail count is unexpected.
|
|
end_tests_or_halt(ExpectedFails) :-
|
|
end_tests(_,ExpectedFails); (flush_output, halt(1)).
|