The purpose of this module is to find which part of the program has been used by a certain goal. Usage is defined in terms of clauses for which the head unification succeeded. For each clause we count how often it succeeded and how often it failed. In addition we track all call sites, creating goal-by-goal annotated clauses.
The result is represented as a list of clause-references. As the references to clauses of dynamic predicates cannot be guaranteed, these are omitted from the result.
Using coverage/2
with the option annotate(true)
, implied by ext(Ext)
or
dir(Dir)
, the analysis creates a line-by-line copy of the
source files that is annotated with how many times this line was
executed and with what logical results. These annotations rely on
relating executable code to source locations which is shared by the
source level debugger. Source level rewrites due to term or goal
expansion may harm the results.
The typical usage is to load the program and run the query below to
get a report by file with percentages and a directory cov
holding annotated files that provide line-by-line annotations. See
show_coverage/1
for details.
?-
coverage(Goal, [dir(cov)])
.
The coverage collect data structure is shared by threads created from the thread that is collecting coverage data. Currently, this thread should be joined before we can operate on the coverage data.
The coverage tools allow both combining data from running multiple queries as combining data from multiple Prolog processes.
For multiple queries in the same process, coverage data may be collected using coverage/1 which, unlike coverage/2, does not change the non-deterministic semantics of the Goal and adds to the already collected data. If no current collection is in progress, the currently collected data can be displayed using show_coverage/1.
Coverage data may be saved to a file using cov_save_data/2.
Saved data can be reloaded using cov_load_data/2.
Data from multiple Prolog runs can be combined in the same file using cov_save_data/2
with the
append(true)
option. When possible, file locking is used to
ensure that concurrect processes can safely use the same data file. The
result can be shown by loading the code that was relevant to all runs,
use
cov_load_data/2
and show the result using show_coverage/1.
Note that saving an loading the coverage data saves and restores references to the clauses as the Nth clause of a predicate defined in a specific file. This implies that the program must be loaded in exactly the same way, including optimization level, term/goal expansion and order of multifile predicates.
call(Goal)
, collecting coverage information while Goal
is running. If Goal succeeds with a choice point, coverage
collection is suspended and resumed if we backtrack into Goal.
Calls to
coverage/1 may
be nested.true
(default), call show_coverage/1
passing Options to show the collected coverage data and reset
the data. When
false
, collect the data but do not reset it. If there is
already existing data the new data is added.dir(Dir)
, detailed line-by-line annotated files are created
in the directory Dir. Other options control the level of detail.
ext
or dir
option are specified.
### Clause was never executed. ++N Clause was entered N times and always succeeded --N Clause was entered N times and never succeeded +N-M Clause has succeeded N times and failed M times +N*M Clause was entered N times and succeeded M times
All call sites are annotated using the same conventions,
except that ---
is used to annotate subgoals that were
never called.
true
(default), add line numbers to the annotated file.true
.
For example, run a goal and create annotated files in a directory
cov
using:
?- show_coverage([dir(cov)]).
less
may be used with the -r
flag. Alternatively, programs such as ansi2html
(Linux) may
be used to convert the files to HTML. It would probably be better to
integrate the output generation with library(pldoc/doc_htmlsrc)
.
The File is opened using lock(exclusive)
,
which implies that, provided the OS and file system implements file
locking, multiple processes may save coverage data to the same file.
The saved data is highly specific to the setup in which it has been created. It can typically only be reloaded using cov_load_data/2 in the same Prolog executable using the same options and with all relevant source file unmodified at the same location.
Reproducibility can be improved by using‘.qlf` files or saved states.
true
, do not emit messages on not loaded source files.
Data is assumed to be reliable if the Nth-clause of a predicate is
loaded from the same file at the same line number and has the same size.
Unreliable data is ignored, silently if silent(true)
is
used.