/*

Unit tests look like either:

    unit_test(true).            % good for short tests

or

    unit_test_unique_name_of_this_test :-       % fine for longer one
             true.

Recognizing the second form automatically as we do is perhaps a bit
too clever, since you could just do:

      unit_test_unique_name_of_this_test :- 
             true.
      unit_test(unit_test_unique_name_of_this_test).

... and have the same effect.  With the current code, that would make
the test be run twice.
  
*/

:- dynamic(unit_test/1).
:- multifile(unit_test/1).

run_unit_tests :-
	flag(unit_test_pass, _, 0),
	flag(unit_test_fail, _, 0),
	(
	  unit_test(X),
	  (   debug(unit_test, 'unit_test calling ~q', [X]),
	      X
	  ->  flag(unit_test_pass, N, N+1)
	  ;   flag(unit_test_fail, N, N+1),
	      clause(unit_test(X), _Body, Reference),
	      clause_property(Reference, file(File)),
	      clause_property(Reference, line_count(Line)),
	      print_message(error, unit_test_failed(X, file(File), line(Line)))
	  ),
	  fail
	)
	;
	(
	  % this is perhaps too clever.  We could just require people to
	  % say    unit_test(their_predicate).
	  % instead of finding their_predicate based on its name.....
	  % [ oh, but introspective programs are so fun! ]
	  current_predicate(Name, Head),
	  atom_concat('unit_test_', _TestName, Name),
	  %format('Test: ~a~n', [TestName]),
	  (   debug(unit_test, 'unit_test calling ~q', [Head]),
	      Head
	  ->  flag(unit_test_pass, N, N+1)
	  ;   flag(unit_test_fail, N, N+1),
	      predicate_property(Head, file(File)),
	      predicate_property(Head, line_count(Line)),
	      print_message(error, unit_test_failed(Head, file(File), line(Line)))
	  ),
	  fail
	)
	;
	flag(unit_test_pass, Passed, Passed),
	flag(unit_test_fail, Failed, Failed),
	print_message(informational, format('unit tests: ~a passed, ~a failed', [Passed, Failed])),
	Failed = 0.

	      
nofail(Callable) :-
	(   Callable
	->  true
	;   throw(nofail_failed(Callable))
	).