Making test fail (not warning) when choice point is left

Can a (unit) test be configured to fail when a choice point is left – rather than issue a warning only.

Didn’t find it in the documentation …

thanks,

Dan

That doesn’t exist. You can run the tests --on-warning=status to make Prolog stop with a non-zero exit status after a warning is issued during the execution. And, of course you can explicitly test, e.g.

 call_cleanup(Goal, Det=true),
 Det == true.

Thank you.

Why does it work - it seems like Det is bound to true upon success …

The docu is pretty convoluted but non-determinism doesn’t seem to be described.

call_cleanup/2 calls the cleanup handler after Goal completes. Complete means fail, succeed without a choice point, raise an exception or pruning choice points (cut, exceptions) closes its choicepoints. So (note the !):

25 ?- call_cleanup((writeln(1);writeln(2)), writeln(done)).
1
true ;
2
done
true.

26 ?- call_cleanup((writeln(1);writeln(2)), writeln(done)), !.
1
done
true.

I am still a bit confused.

I don’t want to prune choice points – but detect when they are there – which signals an error.

The Goal is designed to leave no choice points – but, sometimes it does for example, when an earlier cleanup failed – or when there is a coding error duplicating something which should be a singleton.

I now recalled the @det directive – perhaps it can be used to raise an error

Jan’s code above will evaluate to false if there are choicepoints left after completing Goal, because the “cleanup” Det=true won’t be executed, so Det == true will be false, making the test fail. You could of course do something like Det == true ; throw(error(...)) instead, to have it be an exception instead of “just” a test failure.

Thank you – reading your comment and looking up the documentation again …

" If Setup succeeds, Cleanup will be called exactly once after Goal is finished: either on failure, deterministic success, commit, or an exception. "

I guess, I missed this in the documentation – but, i guess, determinstic success and failure would lead to det=true – making both cases indistinguishable.

I guess I would want failure be fail and non-determinism to fail as well.

Just try

?- call_cleanup(fail, Det=true).
false.

Or, more illustrative

?- call_cleanup(fail, writeln(done)).
done
false.

I.e., call_cleanup/2 behaves as call/1 with respect to its first argument. It just causes the 2nd argument to be called at the moment the first argument vanishes. It is normally intended to undo side effects such as closing opened streams, cleaning temporary dynamic predicates, etc. Most applications should use its more recent setup_call_cleanup/3 to avoid a problem in this:

     open(File, read, In),
     call_cleanup(process(In), close(In)).

This code may leak the file handle if a signal arrives between the open/3 and call_cleanup/2 or the call_cleanup/2 call cannot be started due to a stack overflow.