36
37:- module(plunit,
38 [ set_test_options/1, 39 begin_tests/1, 40 begin_tests/2, 41 end_tests/1, 42 run_tests/0, 43 run_tests/1, 44 load_test_files/1, 45 running_tests/0, 46 current_test/5, 47 test_report/1 48 ]).
56:- autoload(library(apply), [maplist/3,include/3]). 57:- autoload(library(lists), [member/2,append/2]). 58:- autoload(library(option), [option/3,option/2]). 59:- autoload(library(ordsets), [ord_intersection/3]). 60:- autoload(library(pairs), [group_pairs_by_key/2,pairs_values/2]). 61:- autoload(library(error), [must_be/2]). 62:- autoload(library(thread), [concurrent_forall/2]). 63
64:- meta_predicate valid_options(+, 1). 65
66
67 70
71:- discontiguous
72 user:term_expansion/2. 73
74:- dynamic
75 include_code/1. 76
77including :-
78 include_code(X),
79 !,
80 X == true.
81including.
82
83if_expansion((:- if(G)), []) :-
84 ( including
85 -> ( catch(G, E, (print_message(error, E), fail))
86 -> asserta(include_code(true))
87 ; asserta(include_code(false))
88 )
89 ; asserta(include_code(else_false))
90 ).
91if_expansion((:- else), []) :-
92 ( retract(include_code(X))
93 -> ( X == true
94 -> X2 = false
95 ; X == false
96 -> X2 = true
97 ; X2 = X
98 ),
99 asserta(include_code(X2))
100 ; throw_error(context_error(no_if),_)
101 ).
102if_expansion((:- endif), []) :-
103 retract(include_code(_)),
104 !.
105
106if_expansion(_, []) :-
107 \+ including.
108
109user:term_expansion(In, Out) :-
110 prolog_load_context(module, plunit),
111 if_expansion(In, Out).
112
113swi :- catch(current_prolog_flag(dialect, swi), _, fail), !.
114swi :- catch(current_prolog_flag(dialect, yap), _, fail).
115sicstus :- catch(current_prolog_flag(system_type, _), _, fail).
116
117
118:- if(swi). 119throw_error(Error_term,Impldef) :-
120 throw(error(Error_term,context(Impldef,_))).
121
122:- set_prolog_flag(generate_debug_info, false). 123current_test_flag(Name, Value) :-
124 current_prolog_flag(Name, Value).
125
126set_test_flag(Name, Value) :-
127 create_prolog_flag(Name, Value, []).
128
130goal_expansion(forall(C,A),
131 \+ (C, \+ A)).
132goal_expansion(current_module(Module,File),
133 module_property(Module, file(File))).
134
135:- if(current_prolog_flag(dialect, yap)). 136
137'$set_predicate_attribute'(_, _, _).
138
139:- endif. 140:- endif. 141
142:- if(sicstus). 143throw_error(Error_term,Impldef) :-
144 throw(error(Error_term,i(Impldef))). 145
147:- op(700, xfx, =@=). 148
149'$set_source_module'(_, _).
156:- dynamic test_flag/2. 157
158current_test_flag(optimise, Val) :-
159 current_prolog_flag(compiling, Compiling),
160 ( Compiling == debugcode ; true 161 -> Val = false
162 ; Val = true
163 ).
164current_test_flag(Name, Val) :-
165 test_flag(Name, Val).
170set_test_flag(Name, Val) :-
171 var(Name),
172 !,
173 throw_error(instantiation_error, set_test_flag(Name,Val)).
174set_test_flag( Name, Val ) :-
175 retractall(test_flag(Name,_)),
176 asserta(test_flag(Name, Val)).
177
178:- op(1150, fx, thread_local). 179
180user:term_expansion((:- thread_local(PI)), (:- dynamic(PI))) :-
181 prolog_load_context(module, plunit).
182
183:- endif. 184
185 188
189:- initialization
190 ( current_test_flag(test_options, _)
191 -> true
192 ; set_test_flag(test_options,
193 [ run(make), 194 sto(false)
195 ])
196 ).
232set_test_options(Options) :-
233 valid_options(Options, global_test_option),
234 set_test_flag(test_options, Options).
235
236global_test_option(load(Load)) :-
237 must_be(oneof([never,always,normal]), Load).
238global_test_option(run(When)) :-
239 must_be(oneof([manual,make,make(all)]), When).
240global_test_option(silent(Bool)) :-
241 must_be(boolean, Bool).
242global_test_option(sto(Bool)) :-
243 must_be(boolean, Bool).
244global_test_option(cleanup(Bool)) :-
245 must_be(boolean, Bool).
246global_test_option(concurrent(Bool)) :-
247 must_be(boolean, Bool).
254loading_tests :-
255 current_test_flag(test_options, Options),
256 option(load(Load), Options, normal),
257 ( Load == always
258 -> true
259 ; Load == normal,
260 \+ current_test_flag(optimise, true)
261 ).
262
263 266
267:- dynamic
268 loading_unit/4, 269 current_unit/4, 270 test_file_for/2.
278begin_tests(Unit) :-
279 begin_tests(Unit, []).
280
281begin_tests(Unit, Options) :-
282 valid_options(Options, test_set_option),
283 make_unit_module(Unit, Name),
284 source_location(File, Line),
285 begin_tests(Unit, Name, File:Line, Options).
286
287:- if(swi). 288begin_tests(Unit, Name, File:Line, Options) :-
289 loading_tests,
290 !,
291 '$set_source_module'(Context, Context),
292 ( current_unit(Unit, Name, Context, Options)
293 -> true
294 ; retractall(current_unit(Unit, Name, _, _)),
295 assert(current_unit(Unit, Name, Context, Options))
296 ),
297 '$set_source_module'(Old, Name),
298 '$declare_module'(Name, test, Context, File, Line, false),
299 discontiguous(Name:'unit test'/4),
300 '$set_predicate_attribute'(Name:'unit test'/4, trace, false),
301 discontiguous(Name:'unit body'/2),
302 asserta(loading_unit(Unit, Name, File, Old)).
303begin_tests(Unit, Name, File:_Line, _Options) :-
304 '$set_source_module'(Old, Old),
305 asserta(loading_unit(Unit, Name, File, Old)).
306
307:- else. 308
310
311user:term_expansion((:- begin_tests(Set)),
312 [ (:- begin_tests(Set)),
313 (:- discontiguous(test/2)),
314 (:- discontiguous('unit body'/2)),
315 (:- discontiguous('unit test'/4))
316 ]).
317
318begin_tests(Unit, Name, File:_Line, Options) :-
319 loading_tests,
320 !,
321 ( current_unit(Unit, Name, _, Options)
322 -> true
323 ; retractall(current_unit(Unit, Name, _, _)),
324 assert(current_unit(Unit, Name, -, Options))
325 ),
326 asserta(loading_unit(Unit, Name, File, -)).
327begin_tests(Unit, Name, File:_Line, _Options) :-
328 asserta(loading_unit(Unit, Name, File, -)).
329
330:- endif.
339end_tests(Unit) :-
340 loading_unit(StartUnit, _, _, _),
341 !,
342 ( Unit == StartUnit
343 -> once(retract(loading_unit(StartUnit, _, _, Old))),
344 '$set_source_module'(_, Old)
345 ; throw_error(context_error(plunit_close(Unit, StartUnit)), _)
346 ).
347end_tests(Unit) :-
348 throw_error(context_error(plunit_close(Unit, -)), _).
353:- if(swi). 354
355unit_module(Unit, Module) :-
356 atom_concat('plunit_', Unit, Module).
357
358make_unit_module(Unit, Module) :-
359 unit_module(Unit, Module),
360 ( current_module(Module),
361 \+ current_unit(_, Module, _, _),
362 predicate_property(Module:H, _P),
363 \+ predicate_property(Module:H, imported_from(_M))
364 -> throw_error(permission_error(create, plunit, Unit),
365 'Existing module')
366 ; true
367 ).
368
369:- else. 370
371:- dynamic
372 unit_module_store/2. 373
374unit_module(Unit, Module) :-
375 unit_module_store(Unit, Module),
376 !.
377
378make_unit_module(Unit, Module) :-
379 prolog_load_context(module, Module),
380 assert(unit_module_store(Unit, Module)).
381
382:- endif. 383
384
393expand_test(Name, Options0, Body,
394 [ 'unit test'(Name, Line, Options, Module:'unit body'(Id, Vars)),
395 ('unit body'(Id, Vars) :- !, Body)
396 ]) :-
397 source_location(_File, Line),
398 prolog_load_context(module, Module),
399 atomic_list_concat([Name, '@line ', Line], Id),
400 term_variables(Options0, OptionVars0), sort(OptionVars0, OptionVars),
401 term_variables(Body, BodyVars0), sort(BodyVars0, BodyVars),
402 ord_intersection(OptionVars, BodyVars, VarList),
403 Vars =.. [vars|VarList],
404 ( is_list(Options0) 405 -> Options1 = Options0
406 ; Options1 = [Options0]
407 ),
408 maplist(expand_option, Options1, Options2),
409 valid_options(Options2, test_option),
410 valid_test_mode(Options2, Options).
411
412expand_option(Var, _) :-
413 var(Var),
414 !,
415 throw_error(instantiation_error,_).
416expand_option(A == B, true(A==B)) :- !.
417expand_option(A = B, true(A=B)) :- !.
418expand_option(A =@= B, true(A=@=B)) :- !.
419expand_option(A =:= B, true(A=:=B)) :- !.
420expand_option(error(X), throws(error(X, _))) :- !.
421expand_option(exception(X), throws(X)) :- !. 422expand_option(error(F,C), throws(error(F,C))) :- !. 423expand_option(true, true(true)) :- !.
424expand_option(O, O).
425
426valid_test_mode(Options0, Options) :-
427 include(test_mode, Options0, Tests),
428 ( Tests == []
429 -> Options = [true(true)|Options0]
430 ; Tests = [_]
431 -> Options = Options0
432 ; throw_error(plunit(incompatible_options, Tests), _)
433 ).
434
435test_mode(true(_)).
436test_mode(all(_)).
437test_mode(set(_)).
438test_mode(fail).
439test_mode(throws(_)).
444expand(end_of_file, _) :-
445 loading_unit(Unit, _, _, _),
446 !,
447 end_tests(Unit), 448 fail.
449expand((:-end_tests(_)), _) :-
450 !,
451 fail.
452expand(_Term, []) :-
453 \+ loading_tests.
454expand((test(Name) :- Body), Clauses) :-
455 !,
456 expand_test(Name, [], Body, Clauses).
457expand((test(Name, Options) :- Body), Clauses) :-
458 !,
459 expand_test(Name, Options, Body, Clauses).
460expand(test(Name), _) :-
461 !,
462 throw_error(existence_error(body, test(Name)), _).
463expand(test(Name, _Options), _) :-
464 !,
465 throw_error(existence_error(body, test(Name)), _).
466
467:- if(swi). 468:- multifile
469 system:term_expansion/2. 470:- endif. 471
472system:term_expansion(Term, Expanded) :-
473 ( loading_unit(_, _, File, _)
474 -> source_location(File, _),
475 expand(Term, Expanded)
476 ).
477
478
479 482
483:- if(swi). 484:- else. 485must_be(list, X) :-
486 !,
487 ( is_list(X)
488 -> true
489 ; is_not(list, X)
490 ).
491must_be(Type, X) :-
492 ( call(Type, X)
493 -> true
494 ; is_not(Type, X)
495 ).
496
497is_not(Type, X) :-
498 ( ground(X)
499 -> throw_error(type_error(Type, X), _)
500 ; throw_error(instantiation_error, _)
501 ).
502:- endif.
511valid_options(Options, Pred) :-
512 must_be(list, Options),
513 verify_options(Options, Pred).
514
515verify_options([], _).
516verify_options([H|T], Pred) :-
517 ( call(Pred, H)
518 -> verify_options(T, Pred)
519 ; throw_error(domain_error(Pred, H), _)
520 ).
527test_option(Option) :-
528 test_set_option(Option),
529 !.
530test_option(true(_)).
531test_option(fail).
532test_option(throws(_)).
533test_option(all(_)).
534test_option(set(_)).
535test_option(nondet).
536test_option(fixme(_)).
537test_option(forall(X)) :-
538 must_be(callable, X).
545test_set_option(blocked(X)) :-
546 must_be(ground, X).
547test_set_option(condition(X)) :-
548 must_be(callable, X).
549test_set_option(setup(X)) :-
550 must_be(callable, X).
551test_set_option(cleanup(X)) :-
552 must_be(callable, X).
553test_set_option(sto(V)) :-
554 nonvar(V), member(V, [finite_trees, rational_trees]).
555test_set_option(concurrent(V)) :-
556 must_be(boolean, V).
557
558
559 562
563:- thread_local
564 passed/5, 565 failed/4, 566 failed_assertion/7, 567 blocked/4, 568 sto/4, 569 fixme/5. 570
571:- dynamic
572 running/5.
585run_tests :-
586 cleanup,
587 setup_call_cleanup(
588 setup_trap_assertions(Ref),
589 run_current_units,
590 report_and_cleanup(Ref)).
591
592run_current_units :-
593 forall(current_test_set(Set),
594 run_unit(Set)),
595 check_for_test_errors.
596
597report_and_cleanup(Ref) :-
598 cleanup_trap_assertions(Ref),
599 report,
600 cleanup_after_test.
601
602run_tests(Set) :-
603 cleanup,
604 setup_call_cleanup(
605 setup_trap_assertions(Ref),
606 run_unit_and_check_errors(Set),
607 report_and_cleanup(Ref)).
608
609run_unit_and_check_errors(Set) :-
610 run_unit(Set),
611 check_for_test_errors.
612
613run_unit([]) :- !.
614run_unit([H|T]) :-
615 !,
616 run_unit(H),
617 run_unit(T).
618run_unit(Spec) :-
619 unit_from_spec(Spec, Unit, Tests, Module, UnitOptions),
620 ( option(blocked(Reason), UnitOptions)
621 -> info(plunit(blocked(unit(Unit, Reason))))
622 ; setup(Module, unit(Unit), UnitOptions)
623 -> info(plunit(begin(Spec))),
624 current_test_flag(test_options, GlobalOptions),
625 ( option(concurrent(true), GlobalOptions),
626 option(concurrent(true), UnitOptions, false)
627 -> concurrent_forall((Module:'unit test'(Name, Line, Options, Body),
628 matching_test(Name, Tests)),
629 run_test(Unit, Name, Line, Options, Body))
630 ; forall((Module:'unit test'(Name, Line, Options, Body),
631 matching_test(Name, Tests)),
632 run_test(Unit, Name, Line, Options, Body))),
633 info(plunit(end(Spec))),
634 ( message_level(silent)
635 -> true
636 ; format(user_error, '~N', [])
637 ),
638 cleanup(Module, UnitOptions)
639 ; true
640 ).
641
642unit_from_spec(Unit, Unit, _, Module, Options) :-
643 atom(Unit),
644 !,
645 ( current_unit(Unit, Module, _Supers, Options)
646 -> true
647 ; throw_error(existence_error(unit_test, Unit), _)
648 ).
649unit_from_spec(Unit:Tests, Unit, Tests, Module, Options) :-
650 atom(Unit),
651 !,
652 ( current_unit(Unit, Module, _Supers, Options)
653 -> true
654 ; throw_error(existence_error(unit_test, Unit), _)
655 ).
656
657
658matching_test(X, X) :- !.
659matching_test(Name, Set) :-
660 is_list(Set),
661 memberchk(Name, Set).
662
663cleanup :-
664 thread_self(Me),
665 retractall(passed(_, _, _, _, _)),
666 retractall(failed(_, _, _, _)),
667 retractall(failed_assertion(_, _, _, _, _, _, _)),
668 retractall(blocked(_, _, _, _)),
669 retractall(sto(_, _, _, _)),
670 retractall(fixme(_, _, _, _, _)),
671 retractall(running(_,_,_,_,Me)).
672
673cleanup_after_test :-
674 current_test_flag(test_options, Options),
675 option(cleanup(Cleanup), Options, false),
676 ( Cleanup == true
677 -> cleanup
678 ; true
679 ).
686run_tests_in_files(Files) :-
687 findall(Unit, unit_in_files(Files, Unit), Units),
688 ( Units == []
689 -> true
690 ; run_tests(Units)
691 ).
692
693unit_in_files(Files, Unit) :-
694 is_list(Files),
695 !,
696 member(F, Files),
697 absolute_file_name(F, Source,
698 [ file_type(prolog),
699 access(read),
700 file_errors(fail)
701 ]),
702 unit_file(Unit, Source).
703
704
705
713make_run_tests(Files) :-
714 current_test_flag(test_options, Options),
715 option(run(When), Options, manual),
716 ( When == make
717 -> run_tests_in_files(Files)
718 ; When == make(all)
719 -> run_tests
720 ; true
721 ).
722
723:- if(swi). 724
725unification_capability(sto_error_incomplete).
727unification_capability(rational_trees).
728unification_capability(finite_trees).
729
730set_unification_capability(Cap) :-
731 cap_to_flag(Cap, Flag),
732 set_prolog_flag(occurs_check, Flag).
733
734current_unification_capability(Cap) :-
735 current_prolog_flag(occurs_check, Flag),
736 cap_to_flag(Cap, Flag),
737 !.
738
739cap_to_flag(sto_error_incomplete, error).
740cap_to_flag(rational_trees, false).
741cap_to_flag(finite_trees, true).
742
743:- else. 744:- if(sicstus). 745
746unification_capability(rational_trees).
747set_unification_capability(rational_trees).
748current_unification_capability(rational_trees).
749
750:- else. 751
752unification_capability(_) :-
753 fail.
754
755:- endif. 756:- endif. 757
758 761
762:- if(swi). 763
764:- dynamic prolog:assertion_failed/2. 765
766setup_trap_assertions(Ref) :-
767 asserta((prolog:assertion_failed(Reason, Goal) :-
768 test_assertion_failed(Reason, Goal)),
769 Ref).
770
771cleanup_trap_assertions(Ref) :-
772 erase(Ref).
773
774test_assertion_failed(Reason, Goal) :-
775 thread_self(Me),
776 running(Unit, Test, Line, STO, Me),
777 ( catch(get_prolog_backtrace(10, Stack), _, fail),
778 assertion_location(Stack, AssertLoc)
779 -> true
780 ; AssertLoc = unknown
781 ),
782 current_test_flag(test_options, Options),
783 report_failed_assertion(Unit, Test, Line, AssertLoc,
784 STO, Reason, Goal, Options),
785 assert_cyclic(failed_assertion(Unit, Test, Line, AssertLoc,
786 STO, Reason, Goal)).
787
788assertion_location(Stack, File:Line) :-
789 append(_, [AssertFrame,CallerFrame|_], Stack),
790 prolog_stack_frame_property(AssertFrame,
791 predicate(prolog_debug:assertion/1)),
792 !,
793 prolog_stack_frame_property(CallerFrame, location(File:Line)).
794
795report_failed_assertion(Unit, Test, Line, AssertLoc,
796 STO, Reason, Goal, _Options) :-
797 print_message(
798 error,
799 plunit(failed_assertion(Unit, Test, Line, AssertLoc,
800 STO, Reason, Goal))).
801
802:- else. 803
804setup_trap_assertions(_).
805cleanup_trap_assertions(_).
806
807:- endif. 808
809
810
818run_test(Unit, Name, Line, Options, Body) :-
819 option(forall(Generator), Options),
820 !,
821 unit_module(Unit, Module),
822 term_variables(Generator, Vars),
823 forall(Module:Generator,
824 run_test_once(Unit, @(Name,Vars), Line, Options, Body)).
825run_test(Unit, Name, Line, Options, Body) :-
826 run_test_once(Unit, Name, Line, Options, Body).
827
828run_test_once(Unit, Name, Line, Options, Body) :-
829 current_test_flag(test_options, GlobalOptions),
830 option(sto(false), GlobalOptions, false),
831 !,
832 current_unification_capability(Type),
833 begin_test(Unit, Name, Line, Type),
834 run_test_6(Unit, Name, Line, Options, Body, Result),
835 end_test(Unit, Name, Line, Type),
836 report_result(Result, Options).
837run_test_once(Unit, Name, Line, Options, Body) :-
838 current_unit(Unit, _Module, _Supers, UnitOptions),
839 option(sto(Type), UnitOptions),
840 \+ option(sto(_), Options),
841 !,
842 current_unification_capability(Cap0),
843 call_cleanup(run_test_cap(Unit, Name, Line, [sto(Type)|Options], Body),
844 set_unification_capability(Cap0)).
845run_test_once(Unit, Name, Line, Options, Body) :-
846 current_unification_capability(Cap0),
847 call_cleanup(run_test_cap(Unit, Name, Line, Options, Body),
848 set_unification_capability(Cap0)).
849
850run_test_cap(Unit, Name, Line, Options, Body) :-
851 ( option(sto(Type), Options)
852 -> unification_capability(Type),
853 set_unification_capability(Type),
854 begin_test(Unit, Name, Line, Type),
855 run_test_6(Unit, Name, Line, Options, Body, Result),
856 end_test(Unit, Name, Line, Type),
857 report_result(Result, Options)
858 ; findall(Key-(Type+Result),
859 test_caps(Type, Unit, Name, Line, Options, Body, Result, Key),
860 Pairs),
861 group_pairs_by_key(Pairs, Keyed),
862 ( Keyed == []
863 -> true
864 ; Keyed = [_-Results]
865 -> Results = [_Type+Result|_],
866 report_result(Result, Options) 867 ; pairs_values(Pairs, ResultByType),
868 report_result(sto(Unit, Name, Line, ResultByType), Options)
869 )
870 ).
874test_caps(Type, Unit, Name, Line, Options, Body, Result, Key) :-
875 unification_capability(Type),
876 set_unification_capability(Type),
877 begin_test(Unit, Name, Line, Type),
878 run_test_6(Unit, Name, Line, Options, Body, Result),
879 end_test(Unit, Name, Line, Type),
880 result_to_key(Result, Key),
881 Key \== setup_failed.
882
883result_to_key(blocked(_, _, _, _), blocked).
884result_to_key(failure(_, _, _, How0), failure(How1)) :-
885 ( How0 = succeeded(_T) -> How1 = succeeded ; How0 = How1 ).
886result_to_key(success(_, _, _, Determinism, _), success(Determinism)).
887result_to_key(setup_failed(_,_,_), setup_failed).
888
889report_result(blocked(Unit, Name, Line, Reason), _) :-
890 !,
891 assert(blocked(Unit, Name, Line, Reason)).
892report_result(failure(Unit, Name, Line, How), Options) :-
893 !,
894 failure(Unit, Name, Line, How, Options).
895report_result(success(Unit, Name, Line, Determinism, Time), Options) :-
896 !,
897 success(Unit, Name, Line, Determinism, Time, Options).
898report_result(setup_failed(_Unit, _Name, _Line), _Options).
899report_result(sto(Unit, Name, Line, ResultByType), Options) :-
900 assert(sto(Unit, Name, Line, ResultByType)),
901 print_message(error, plunit(sto(Unit, Name, Line))),
902 report_sto_results(ResultByType, Options).
903
904report_sto_results([], _).
905report_sto_results([Type+Result|T], Options) :-
906 print_message(error, plunit(sto(Type, Result))),
907 report_sto_results(T, Options).
919run_test_6(Unit, Name, Line, Options, _Body,
920 blocked(Unit, Name, Line, Reason)) :-
921 option(blocked(Reason), Options),
922 !.
923run_test_6(Unit, Name, Line, Options, Body, Result) :-
924 option(all(Answer), Options), 925 !,
926 nondet_test(all(Answer), Unit, Name, Line, Options, Body, Result).
927run_test_6(Unit, Name, Line, Options, Body, Result) :-
928 option(set(Answer), Options), 929 !,
930 nondet_test(set(Answer), Unit, Name, Line, Options, Body, Result).
931run_test_6(Unit, Name, Line, Options, Body, Result) :-
932 option(fail, Options), 933 !,
934 unit_module(Unit, Module),
935 ( setup(Module, test(Unit,Name,Line), Options)
936 -> statistics(runtime, [T0,_]),
937 ( catch(Module:Body, E, true)
938 -> ( var(E)
939 -> statistics(runtime, [T1,_]),
940 Time is (T1 - T0)/1000.0,
941 Result = failure(Unit, Name, Line, succeeded(Time)),
942 cleanup(Module, Options)
943 ; Result = failure(Unit, Name, Line, E),
944 cleanup(Module, Options)
945 )
946 ; statistics(runtime, [T1,_]),
947 Time is (T1 - T0)/1000.0,
948 Result = success(Unit, Name, Line, true, Time),
949 cleanup(Module, Options)
950 )
951 ; Result = setup_failed(Unit, Name, Line)
952 ).
953run_test_6(Unit, Name, Line, Options, Body, Result) :-
954 option(true(Cmp), Options),
955 !,
956 unit_module(Unit, Module),
957 ( setup(Module, test(Unit,Name,Line), Options) 958 -> statistics(runtime, [T0,_]),
959 ( catch(call_det(Module:Body, Det), E, true)
960 -> ( var(E)
961 -> statistics(runtime, [T1,_]),
962 Time is (T1 - T0)/1000.0,
963 ( catch(Module:Cmp, E, true)
964 -> ( var(E)
965 -> Result = success(Unit, Name, Line, Det, Time)
966 ; Result = failure(Unit, Name, Line, cmp_error(Cmp, E))
967 )
968 ; Result = failure(Unit, Name, Line, wrong_answer(Cmp))
969 ),
970 cleanup(Module, Options)
971 ; Result = failure(Unit, Name, Line, E),
972 cleanup(Module, Options)
973 )
974 ; Result = failure(Unit, Name, Line, failed),
975 cleanup(Module, Options)
976 )
977 ; Result = setup_failed(Unit, Name, Line)
978 ).
979run_test_6(Unit, Name, Line, Options, Body, Result) :-
980 option(throws(Expect), Options),
981 !,
982 unit_module(Unit, Module),
983 ( setup(Module, test(Unit,Name,Line), Options)
984 -> statistics(runtime, [T0,_]),
985 ( catch(Module:Body, E, true)
986 -> ( var(E)
987 -> Result = failure(Unit, Name, Line, no_exception),
988 cleanup(Module, Options)
989 ; statistics(runtime, [T1,_]),
990 Time is (T1 - T0)/1000.0,
991 ( match_error(Expect, E)
992 -> Result = success(Unit, Name, Line, true, Time)
993 ; Result = failure(Unit, Name, Line, wrong_error(Expect, E))
994 ),
995 cleanup(Module, Options)
996 )
997 ; Result = failure(Unit, Name, Line, failed),
998 cleanup(Module, Options)
999 )
1000 ; Result = setup_failed(Unit, Name, Line)
1001 ).
1008nondet_test(Expected, Unit, Name, Line, Options, Body, Result) :-
1009 unit_module(Unit, Module),
1010 result_vars(Expected, Vars),
1011 statistics(runtime, [T0,_]),
1012 ( setup(Module, test(Unit,Name,Line), Options)
1013 -> ( catch(findall(Vars, Module:Body, Bindings), E, true)
1014 -> ( var(E)
1015 -> statistics(runtime, [T1,_]),
1016 Time is (T1 - T0)/1000.0,
1017 ( nondet_compare(Expected, Bindings, Unit, Name, Line)
1018 -> Result = success(Unit, Name, Line, true, Time)
1019 ; Result = failure(Unit, Name, Line, wrong_answer(Expected, Bindings))
1020 ),
1021 cleanup(Module, Options)
1022 ; Result = failure(Unit, Name, Line, E),
1023 cleanup(Module, Options)
1024 )
1025 )
1026 ; Result = setup_failed(Unit, Name, Line)
1027 ).
1035result_vars(Expected, Vars) :-
1036 arg(1, Expected, CmpOp),
1037 arg(1, CmpOp, Vars).
1047nondet_compare(all(Cmp), Bindings, _Unit, _Name, _Line) :-
1048 cmp(Cmp, _Vars, Op, Values),
1049 cmp_list(Values, Bindings, Op).
1050nondet_compare(set(Cmp), Bindings0, _Unit, _Name, _Line) :-
1051 cmp(Cmp, _Vars, Op, Values0),
1052 sort(Bindings0, Bindings),
1053 sort(Values0, Values),
1054 cmp_list(Values, Bindings, Op).
1055
1056cmp_list([], [], _Op).
1057cmp_list([E0|ET], [V0|VT], Op) :-
1058 call(Op, E0, V0),
1059 cmp_list(ET, VT, Op).
1063cmp(Var == Value, Var, ==, Value).
1064cmp(Var =:= Value, Var, =:=, Value).
1065cmp(Var = Value, Var, =, Value).
1066:- if(swi). 1067cmp(Var =@= Value, Var, =@=, Value).
1068:- else. 1069:- if(sicstus). 1070cmp(Var =@= Value, Var, variant, Value). 1071:- endif. 1072:- endif.
1080:- if((swi|sicstus)). 1081call_det(Goal, Det) :-
1082 call_cleanup(Goal,Det0=true),
1083 ( var(Det0) -> Det = false ; Det = true ).
1084:- else. 1085call_det(Goal, true) :-
1086 call(Goal).
1087:- endif.
1094match_error(Expect, Rec) :-
1095 subsumes_term(Expect, Rec).
1108setup(Module, Context, Options) :-
1109 option(condition(Condition), Options),
1110 option(setup(Setup), Options),
1111 !,
1112 setup(Module, Context, [condition(Condition)]),
1113 setup(Module, Context, [setup(Setup)]).
1114setup(Module, Context, Options) :-
1115 option(setup(Setup), Options),
1116 !,
1117 ( catch(call_ex(Module, Setup), E, true)
1118 -> ( var(E)
1119 -> true
1120 ; print_message(error, plunit(error(setup, Context, E))),
1121 fail
1122 )
1123 ; print_message(error, error(goal_failed(Setup), _)),
1124 fail
1125 ).
1126setup(Module, Context, Options) :-
1127 option(condition(Setup), Options),
1128 !,
1129 ( catch(call_ex(Module, Setup), E, true)
1130 -> ( var(E)
1131 -> true
1132 ; print_message(error, plunit(error(condition, Context, E))),
1133 fail
1134 )
1135 ; fail
1136 ).
1137setup(_,_,_).
1143call_ex(Module, Goal) :-
1144 Module:(expand_goal(Goal, GoalEx),
1145 GoalEx).
1152cleanup(Module, Options) :-
1153 option(cleanup(Cleanup), Options, true),
1154 ( catch(call_ex(Module, Cleanup), E, true)
1155 -> ( var(E)
1156 -> true
1157 ; print_message(warning, E)
1158 )
1159 ; print_message(warning, goal_failed(Cleanup, '(cleanup handler)'))
1160 ).
1161
1162success(Unit, Name, Line, Det, _Time, Options) :-
1163 memberchk(fixme(Reason), Options),
1164 !,
1165 ( ( Det == true
1166 ; memberchk(nondet, Options)
1167 )
1168 -> put_char(user_error, +),
1169 Ok = passed
1170 ; put_char(user_error, !),
1171 Ok = nondet
1172 ),
1173 flush_output(user_error),
1174 assert(fixme(Unit, Name, Line, Reason, Ok)).
1175success(Unit, Name, Line, _, _, Options) :-
1176 failed_assertion(Unit, Name, Line, _,_,_,_),
1177 !,
1178 failure(Unit, Name, Line, assertion, Options).
1179success(Unit, Name, Line, Det, Time, Options) :-
1180 assert(passed(Unit, Name, Line, Det, Time)),
1181 ( ( Det == true
1182 ; memberchk(nondet, Options)
1183 )
1184 -> put_char(user_error, .)
1185 ; unit_file(Unit, File),
1186 print_message(warning, plunit(nondet(File, Line, Name)))
1187 ),
1188 flush_output(user_error).
1189
1190failure(Unit, Name, Line, _, Options) :-
1191 memberchk(fixme(Reason), Options),
1192 !,
1193 put_char(user_error, -),
1194 flush_output(user_error),
1195 assert(fixme(Unit, Name, Line, Reason, failed)).
1196failure(Unit, Name, Line, E, Options) :-
1197 report_failure(Unit, Name, Line, E, Options),
1198 assert_cyclic(failed(Unit, Name, Line, E)).
1208:- if(swi). 1209assert_cyclic(Term) :-
1210 acyclic_term(Term),
1211 !,
1212 assert(Term).
1213assert_cyclic(Term) :-
1214 Term =.. [Functor|Args],
1215 recorda(cyclic, Args, Id),
1216 functor(Term, _, Arity),
1217 length(NewArgs, Arity),
1218 Head =.. [Functor|NewArgs],
1219 assert((Head :- recorded(_, Var, Id), Var = NewArgs)).
1220:- else. 1221:- if(sicstus). 1222:- endif. 1223assert_cyclic(Term) :-
1224 assert(Term).
1225:- endif. 1226
1227
1228
1243begin_test(Unit, Test, Line, STO) :-
1244 thread_self(Me),
1245 assert(running(Unit, Test, Line, STO, Me)),
1246 unit_file(Unit, File),
1247 print_message(silent, plunit(begin(Unit:Test, File:Line, STO))).
1248
1249end_test(Unit, Test, Line, STO) :-
1250 thread_self(Me),
1251 retractall(running(_,_,_,_,Me)),
1252 unit_file(Unit, File),
1253 print_message(silent, plunit(end(Unit:Test, File:Line, STO))).
1259running_tests :-
1260 running_tests(Running),
1261 print_message(informational, plunit(running(Running))).
1262
1263running_tests(Running) :-
1264 findall(running(Unit:Test, File:Line, STO, Thread),
1265 ( running(Unit, Test, Line, STO, Thread),
1266 unit_file(Unit, File)
1267 ), Running).
1274current_test(Unit, Test, Line, Body, Options) :-
1275 current_unit(Unit, Module, _Supers, _UnitOptions),
1276 Module:'unit test'(Test, Line, Options, Body).
1282check_for_test_errors :-
1283 number_of_clauses(failed/4, Failed),
1284 number_of_clauses(failed_assertion/7, FailedAssertion),
1285 number_of_clauses(sto/4, STO),
1286 Failed+FailedAssertion+STO =:= 0.
1293report :-
1294 number_of_clauses(passed/5, Passed),
1295 number_of_clauses(failed/4, Failed),
1296 number_of_clauses(failed_assertion/7, FailedAssertion),
1297 number_of_clauses(blocked/4, Blocked),
1298 number_of_clauses(sto/4, STO),
1299 ( Passed+Failed+FailedAssertion+Blocked+STO =:= 0
1300 -> info(plunit(no_tests))
1301 ; Failed+FailedAssertion+Blocked+STO =:= 0
1302 -> report_fixme,
1303 info(plunit(all_passed(Passed)))
1304 ; report_blocked,
1305 report_fixme,
1306 report_failed_assertions,
1307 report_failed,
1308 report_sto,
1309 info(plunit(passed(Passed)))
1310 ).
1311
1312number_of_clauses(F/A,N) :-
1313 ( current_predicate(F/A)
1314 -> functor(G,F,A),
1315 findall(t, G, Ts),
1316 length(Ts, N)
1317 ; N = 0
1318 ).
1319
1320report_blocked :-
1321 number_of_clauses(blocked/4,N),
1322 N > 0,
1323 !,
1324 info(plunit(blocked(N))),
1325 ( blocked(Unit, Name, Line, Reason),
1326 unit_file(Unit, File),
1327 print_message(informational,
1328 plunit(blocked(File:Line, Name, Reason))),
1329 fail ; true
1330 ).
1331report_blocked.
1332
1333report_failed :-
1334 number_of_clauses(failed/4, N),
1335 info(plunit(failed(N))).
1336
1337report_failed_assertions :-
1338 number_of_clauses(failed_assertion/7, N),
1339 info(plunit(failed_assertions(N))).
1340
1341report_sto :-
1342 number_of_clauses(sto/4, N),
1343 info(plunit(sto(N))).
1344
1345report_fixme :-
1346 report_fixme(_,_,_).
1347
1348report_fixme(TuplesF, TuplesP, TuplesN) :-
1349 fixme(failed, TuplesF, Failed),
1350 fixme(passed, TuplesP, Passed),
1351 fixme(nondet, TuplesN, Nondet),
1352 print_message(informational, plunit(fixme(Failed, Passed, Nondet))).
1353
1354
1355fixme(How, Tuples, Count) :-
1356 findall(fixme(Unit, Name, Line, Reason, How),
1357 fixme(Unit, Name, Line, Reason, How), Tuples),
1358 length(Tuples, Count).
1359
1360
1361report_failure(_, _, _, assertion, _) :-
1362 !,
1363 put_char(user_error, 'A').
1364report_failure(Unit, Name, Line, Error, _Options) :-
1365 print_message(error, plunit(failed(Unit, Name, Line, Error))).
1372test_report(fixme) :-
1373 !,
1374 report_fixme(TuplesF, TuplesP, TuplesN),
1375 append([TuplesF, TuplesP, TuplesN], Tuples),
1376 print_message(informational, plunit(fixme(Tuples))).
1377test_report(What) :-
1378 throw_error(domain_error(report_class, What), _).
1379
1380
1381
1389current_test_set(Unit) :-
1390 current_unit(Unit, _Module, _Context, _Options).
1395unit_file(Unit, File) :-
1396 current_unit(Unit, Module, _Context, _Options),
1397 current_module(Module, File).
1398unit_file(Unit, PlFile) :-
1399 nonvar(PlFile),
1400 test_file_for(TestFile, PlFile),
1401 current_module(Module, TestFile),
1402 current_unit(Unit, Module, _Context, _Options).
1403
1404
1405
1413load_test_files(_Options) :-
1414 ( source_file(File),
1415 file_name_extension(Base, Old, File),
1416 Old \== plt,
1417 file_name_extension(Base, plt, TestFile),
1418 exists_file(TestFile),
1419 ( test_file_for(TestFile, File)
1420 -> true
1421 ; load_files(TestFile,
1422 [ if(changed),
1423 imports([])
1424 ]),
1425 asserta(test_file_for(TestFile, File))
1426 ),
1427 fail ; true
1428 ).
1429
1430
1431
1432
1441info(Term) :-
1442 message_level(Level),
1443 print_message(Level, Term).
1444
1445message_level(Level) :-
1446 current_test_flag(test_options, Options),
1447 option(silent(Silent), Options, false),
1448 ( Silent == false
1449 -> Level = informational
1450 ; Level = silent
1451 ).
1452
1453locationprefix(File:Line) -->
1454 !,
1455 [ '~w:~d:\n\t'-[File,Line]].
1456locationprefix(test(Unit,_Test,Line)) -->
1457 !,
1458 { unit_file(Unit, File) },
1459 locationprefix(File:Line).
1460locationprefix(unit(Unit)) -->
1461 !,
1462 [ 'PL-Unit: unit ~w: '-[Unit] ].
1463locationprefix(FileLine) -->
1464 { throw_error(type_error(locationprefix,FileLine), _) }.
1465
1466:- discontiguous
1467 message//1. 1468
1469message(error(context_error(plunit_close(Name, -)), _)) -->
1470 [ 'PL-Unit: cannot close unit ~w: no open unit'-[Name] ].
1471message(error(context_error(plunit_close(Name, Start)), _)) -->
1472 [ 'PL-Unit: cannot close unit ~w: current unit is ~w'-[Name, Start] ].
1473message(plunit(nondet(File, Line, Name))) -->
1474 locationprefix(File:Line),
1475 [ 'PL-Unit: Test ~w: Test succeeded with choicepoint'- [Name] ].
1476message(error(plunit(incompatible_options, Tests), _)) -->
1477 [ 'PL-Unit: incompatible test-options: ~p'-[Tests] ].
1478
1479 1480:- if(swi). 1481message(plunit(begin(Unit))) -->
1482 [ 'PL-Unit: ~w '-[Unit], flush ].
1483message(plunit(end(_Unit))) -->
1484 [ at_same_line, ' done' ].
1485:- else. 1486message(plunit(begin(Unit))) -->
1487 [ 'PL-Unit: ~w '-[Unit]].
1488message(plunit(end(_Unit))) -->
1489 [ ' done'-[] ].
1490:- endif. 1491message(plunit(blocked(unit(Unit, Reason)))) -->
1492 [ 'PL-Unit: ~w blocked: ~w'-[Unit, Reason] ].
1493message(plunit(running([]))) -->
1494 !,
1495 [ 'PL-Unit: no tests running' ].
1496message(plunit(running([One]))) -->
1497 !,
1498 [ 'PL-Unit: running ' ],
1499 running(One).
1500message(plunit(running(More))) -->
1501 !,
1502 [ 'PL-Unit: running tests:', nl ],
1503 running(More).
1504message(plunit(fixme([]))) --> !.
1505message(plunit(fixme(Tuples))) -->
1506 !,
1507 fixme_message(Tuples).
1508
1509 1510message(plunit(blocked(1))) -->
1511 !,
1512 [ 'one test is blocked:'-[] ].
1513message(plunit(blocked(N))) -->
1514 [ '~D tests are blocked:'-[N] ].
1515message(plunit(blocked(Pos, Name, Reason))) -->
1516 locationprefix(Pos),
1517 test_name(Name),
1518 [ ': ~w'-[Reason] ].
1519
1520 1521message(plunit(no_tests)) -->
1522 !,
1523 [ 'No tests to run' ].
1524message(plunit(all_passed(1))) -->
1525 !,
1526 [ 'test passed' ].
1527message(plunit(all_passed(Count))) -->
1528 !,
1529 [ 'All ~D tests passed'-[Count] ].
1530message(plunit(passed(Count))) -->
1531 !,
1532 [ '~D tests passed'-[Count] ].
1533message(plunit(failed(0))) -->
1534 !,
1535 [].
1536message(plunit(failed(1))) -->
1537 !,
1538 [ '1 test failed'-[] ].
1539message(plunit(failed(N))) -->
1540 [ '~D tests failed'-[N] ].
1541message(plunit(failed_assertions(0))) -->
1542 !,
1543 [].
1544message(plunit(failed_assertions(1))) -->
1545 !,
1546 [ '1 assertion failed'-[] ].
1547message(plunit(failed_assertions(N))) -->
1548 [ '~D assertions failed'-[N] ].
1549message(plunit(sto(0))) -->
1550 !,
1551 [].
1552message(plunit(sto(N))) -->
1553 [ '~D test results depend on unification mode'-[N] ].
1554message(plunit(fixme(0,0,0))) -->
1555 [].
1556message(plunit(fixme(Failed,0,0))) -->
1557 !,
1558 [ 'all ~D tests flagged FIXME failed'-[Failed] ].
1559message(plunit(fixme(Failed,Passed,0))) -->
1560 [ 'FIXME: ~D failed; ~D passed'-[Failed, Passed] ].
1561message(plunit(fixme(Failed,Passed,Nondet))) -->
1562 { TotalPassed is Passed+Nondet },
1563 [ 'FIXME: ~D failed; ~D passed; (~D nondet)'-
1564 [Failed, TotalPassed, Nondet] ].
1565message(plunit(failed(Unit, Name, Line, Failure))) -->
1566 { unit_file(Unit, File) },
1567 locationprefix(File:Line),
1568 test_name(Name),
1569 [': '-[] ],
1570 failure(Failure).
1571:- if(swi). 1572message(plunit(failed_assertion(Unit, Name, Line, AssertLoc,
1573 _STO, Reason, Goal))) -->
1574 { unit_file(Unit, File) },
1575 locationprefix(File:Line),
1576 test_name(Name),
1577 [ ': assertion'-[] ],
1578 assertion_location(AssertLoc, File),
1579 assertion_reason(Reason), ['\n\t'],
1580 assertion_goal(Unit, Goal).
1581
1582assertion_location(File:Line, File) -->
1583 [ ' at line ~w'-[Line] ].
1584assertion_location(File:Line, _) -->
1585 [ ' at ~w:~w'-[File, Line] ].
1586assertion_location(unknown, _) -->
1587 [].
1588
1589assertion_reason(fail) -->
1590 !,
1591 [ ' failed'-[] ].
1592assertion_reason(Error) -->
1593 { message_to_string(Error, String) },
1594 [ ' raised "~w"'-[String] ].
1595
1596assertion_goal(Unit, Goal) -->
1597 { unit_module(Unit, Module),
1598 unqualify(Goal, Module, Plain)
1599 },
1600 [ 'Assertion: ~p'-[Plain] ].
1601
1602unqualify(Var, _, Var) :-
1603 var(Var),
1604 !.
1605unqualify(M:Goal, Unit, Goal) :-
1606 nonvar(M),
1607 unit_module(Unit, M),
1608 !.
1609unqualify(M:Goal, _, Goal) :-
1610 callable(Goal),
1611 predicate_property(M:Goal, imported_from(system)),
1612 !.
1613unqualify(Goal, _, Goal).
1614
1615:- endif. 1616 1617message(plunit(error(Where, Context, Exception))) -->
1618 locationprefix(Context),
1619 { message_to_string(Exception, String) },
1620 [ 'error in ~w: ~w'-[Where, String] ].
1621
1622 1623message(plunit(sto(Unit, Name, Line))) -->
1624 { unit_file(Unit, File) },
1625 locationprefix(File:Line),
1626 test_name(Name),
1627 [' is subject to occurs check (STO): '-[] ].
1628message(plunit(sto(Type, Result))) -->
1629 sto_type(Type),
1630 sto_result(Result).
1631
1632 1633:- if(swi). 1634message(interrupt(begin)) -->
1635 { thread_self(Me),
1636 running(Unit, Test, Line, STO, Me),
1637 !,
1638 unit_file(Unit, File)
1639 },
1640 [ 'Interrupted test '-[] ],
1641 running(running(Unit:Test, File:Line, STO, Me)),
1642 [nl],
1643 '$messages':prolog_message(interrupt(begin)).
1644message(interrupt(begin)) -->
1645 '$messages':prolog_message(interrupt(begin)).
1646:- endif. 1647
1648test_name(@(Name,Bindings)) -->
1649 !,
1650 [ 'test ~w (forall bindings = ~p)'-[Name, Bindings] ].
1651test_name(Name) -->
1652 !,
1653 [ 'test ~w'-[Name] ].
1654
1655sto_type(sto_error_incomplete) -->
1656 [ 'Finite trees (error checking): ' ].
1657sto_type(rational_trees) -->
1658 [ 'Rational trees: ' ].
1659sto_type(finite_trees) -->
1660 [ 'Finite trees: ' ].
1661
1662sto_result(success(_Unit, _Name, _Line, Det, Time)) -->
1663 det(Det),
1664 [ ' success in ~2f seconds'-[Time] ].
1665sto_result(failure(_Unit, _Name, _Line, How)) -->
1666 failure(How).
1667
1668det(true) -->
1669 [ 'deterministic' ].
1670det(false) -->
1671 [ 'non-deterministic' ].
1672
1673running(running(Unit:Test, File:Line, STO, Thread)) -->
1674 thread(Thread),
1675 [ '~q:~q at ~w:~d'-[Unit, Test, File, Line] ],
1676 current_sto(STO).
1677running([H|T]) -->
1678 ['\t'], running(H),
1679 ( {T == []}
1680 -> []
1681 ; [nl], running(T)
1682 ).
1683
1684thread(main) --> !.
1685thread(Other) -->
1686 [' [~w] '-[Other] ].
1687
1688current_sto(sto_error_incomplete) -->
1689 [ ' (STO: error checking)' ].
1690current_sto(rational_trees) -->
1691 [].
1692current_sto(finite_trees) -->
1693 [ ' (STO: occurs check enabled)' ].
1694
1695:- if(swi). 1696write_term(T, OPS) -->
1697 ['~@'-[write_term(T,OPS)]].
1698:- else. 1699write_term(T, _OPS) -->
1700 ['~q'-[T]].
1701:- endif. 1702
1703expected_got_ops_(Ex, E, OPS, Goals) -->
1704 [' Expected: '-[]], write_term(Ex, OPS), [nl],
1705 [' Got: '-[]], write_term(E, OPS), [nl],
1706 ( { Goals = [] } -> []
1707 ; [' with: '-[]], write_term(Goals, OPS), [nl]
1708 ).
1709
1710
1711failure(Var) -->
1712 { var(Var) },
1713 !,
1714 [ 'Unknown failure?' ].
1715failure(succeeded(Time)) -->
1716 !,
1717 [ 'must fail but succeeded in ~2f seconds~n'-[Time] ].
1718failure(wrong_error(Expected, Error)) -->
1719 !,
1720 { copy_term(Expected-Error, Ex-E, Goals),
1721 numbervars(Ex-E-Goals, 0, _),
1722 write_options(OPS)
1723 },
1724 [ 'wrong error'-[], nl ],
1725 expected_got_ops_(Ex, E, OPS, Goals).
1726failure(wrong_answer(Cmp)) -->
1727 { Cmp =.. [Op,Answer,Expected],
1728 !,
1729 copy_term(Expected-Answer, Ex-A, Goals),
1730 numbervars(Ex-A-Goals, 0, _),
1731 write_options(OPS)
1732 },
1733 [ 'wrong answer (compared using ~w)'-[Op], nl ],
1734 expected_got_ops_(Ex, A, OPS, Goals).
1735failure(wrong_answer(CmpExpected, Bindings)) -->
1736 { ( CmpExpected = all(Cmp)
1737 -> Cmp =.. [_Op1,_,Expected],
1738 Got = Bindings,
1739 Type = all
1740 ; CmpExpected = set(Cmp),
1741 Cmp =.. [_Op2,_,Expected0],
1742 sort(Expected0, Expected),
1743 sort(Bindings, Got),
1744 Type = set
1745 )
1746 },
1747 [ 'wrong "~w" answer:'-[Type] ],
1748 [ nl, ' Expected: ~q'-[Expected] ],
1749 [ nl, ' Found: ~q'-[Got] ].
1750:- if(swi). 1751failure(cmp_error(_Cmp, Error)) -->
1752 { message_to_string(Error, Message) },
1753 [ 'Comparison error: ~w'-[Message] ].
1754failure(Error) -->
1755 { Error = error(_,_),
1756 !,
1757 message_to_string(Error, Message)
1758 },
1759 [ 'received error: ~w'-[Message] ].
1760:- endif. 1761failure(Why) -->
1762 [ '~p~n'-[Why] ].
1763
1764fixme_message([]) --> [].
1765fixme_message([fixme(Unit, _Name, Line, Reason, How)|T]) -->
1766 { unit_file(Unit, File) },
1767 fixme_message(File:Line, Reason, How),
1768 ( {T == []}
1769 -> []
1770 ; [nl],
1771 fixme_message(T)
1772 ).
1773
1774fixme_message(Location, Reason, failed) -->
1775 [ 'FIXME: ~w: ~w'-[Location, Reason] ].
1776fixme_message(Location, Reason, passed) -->
1777 [ 'FIXME: ~w: passed ~w'-[Location, Reason] ].
1778fixme_message(Location, Reason, nondet) -->
1779 [ 'FIXME: ~w: passed (nondet) ~w'-[Location, Reason] ].
1780
1781
1782write_options([ numbervars(true),
1783 quoted(true),
1784 portray(true),
1785 max_depth(100),
1786 attributes(portray)
1787 ]).
1788
1789:- if(swi). 1790
1791:- multifile
1792 prolog:message/3,
1793 user:message_hook/3. 1794
1795prolog:message(Term) -->
1796 message(Term).
1797
1799
1800user:message_hook(make(done(Files)), _, _) :-
1801 make_run_tests(Files),
1802 fail. 1803
1804:- endif. 1805
1806:- if(sicstus). 1807
1808user:generate_message_hook(Message) -->
1809 message(Message),
1810 [nl].
1819user:message_hook(informational, plunit(begin(Unit)), _Lines) :-
1820 format(user_error, '% PL-Unit: ~w ', [Unit]),
1821 flush_output(user_error).
1822user:message_hook(informational, plunit(end(_Unit)), _Lines) :-
1823 format(user, ' done~n', []).
1824
1825:- endif.
Unit Testing
Unit testing environment for SWI-Prolog and SICStus Prolog. For usage, please visit http://www.swi-prolog.org/pldoc/package/plunit. */