Files
mercury/extras/morphine/source/coverage.op
Erwan Jahier e1b25b19ee Fix the monitors that were computing coverage rates in Morphine.
Estimated hours taken: 10

Branches: main, release

Fix the monitors that were computing coverage rates in Morphine.  The
problem was the following. In order to check that two successes and
one failure occur for a multi predicate, I was looking at two exits
and one fail; but this is wrong since, of course, the two exits can
be produced by different calls, and since all multi predicates ends
up with a fail event. To get it right, I need to associate the call
number to exit and fail events. To do that, I maintain at exit ports
the list of call numbers; when an exit event occurs, I consider it as
covered iff the current call number is in the list. On the contrary,
I consider a failure as covered at a fail port iff the current call
number is not in the list. This also holds for semidet and nondet
procedures.


extras/morphine/non-regression-tests/queens.exp:
	Update the new expected outputs.

extras/morphine/non-regression-tests/queens.in:
	Update the year of the copyrigth message.

extras/morphine/source/call_site_cov.in:
extras/morphine/source/pred_cov.in:
	Change the code so that it does what it is supposed to do.

	Also use a map instead of a list to store what has to be
	covered for each procedure.

extras/morphine/source/generate_pred_cov.m:
extras/morphine/source/generate_call_site_cov.m:
extras/morphine/source/coverage_util.m:
	Generate an initialize/1 predicate that uses map instead of lists.

extras/morphine/source/coverage.op:
	Coverage monitors now output assoc lists.
2002-03-06 07:36:49 +00:00

174 lines
5.7 KiB
Plaintext

%------------------------------------------------------------------------------%
% Copyright (C) 2001, 2002 IFSIC.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file License in the Morphine distribution.
%
% Author : Erwan Jahier <jahier@irisa.fr>
%
% This file implements the coverage scenario, which provides various commands
% to perform test coverage.
opium_scenario(
name : coverage,
files : [coverage],
scenarios : [],
message :
"Provides commands to perform predicate and call site coverage.\
"
).
%-----------------------------------------------------------------------%
opium_command(
name : pred_cov,
arg_list : [Call, Uncovered],
arg_type_list : [string, var],
abbrev : pc,
interface : menu,
command_type : opium,
implementation : pred_cov_Op,
parameters : [],
message :
"Takes a call to Mercury program (compiled in a debug mode) \
(\"Call\") and unifies its 2nd argument with the uncovered predicate \
criteria of the called module as well as the modules it imports which \
are in the current directory. A predicate criterion is a \
3-tuple containing a module name, a procedure name, and a list of `exit' and \
`fail' atoms; for example, the predicate criterion \
`pc(mod, foo, [exit, fail])' means that the procedure foo in module mod \
has to succeed and fail exactly once to be considered as covered. \
\n\
\n\
pred_cov/2 works as follows; it calls `morphine/bin/generate_pred_cov \
<Module>.m' which generates 2 files: \"<Module>__pred_cov\" that contains \
a monitor to perform the coverage, and \"<Module>__pred\" that contains \
the list of call sites of <Module>. Then it runs the \"<Module>__pred_cov\" \
monitor, which outputs the list of uncovered call sites. The file \
\"<Module>__pred\" is used to display the coverage ratio.\
").
pred_cov_Op(ProgramCall, Uncovered) :-
split_string(ProgramCall, " ", " ", [Module|_Args]),
append_strings(Module, ".m", FileName),
getenv("MERCURY_MORPHINE_DIR", MorphineDir),
( exists("pred_cov.in") ->
true
;
concat_string(["ln -s ", MorphineDir,
"/source/pred_cov.in "], Cmd1),
sh(Cmd1)
),
append_strings(Module, "__pred_cov", MonitorName),
append_strings(Module, "__pred", CritListFile),
( exists(MonitorName) ->
true
;
concat_string([MorphineDir, "/bin/generate_pred_cov ", FileName],
Cmd2),
print(Cmd2), nl,
sh(Cmd2)
),
crit_cov(pred, ProgramCall, MonitorName, CritListFile, Uncovered).
%-----------------------------------------------------------------------%
opium_command(
name : call_site_cov,
arg_list : [Module, Uncovered],
arg_type_list : [string, var],
abbrev : csc,
interface : menu,
command_type : opium,
implementation : call_site_cov_Op,
parameters : [],
message :
"Takes a Mercury module name \"Module\", and unifies its 2nd argument \
with the uncovered call sites criteria of \"Module\" and the modules it \
imports which are in the current directory. A call site criterion is a \
4-tuple containing a module name, a procedure name, a line number, and a \
list of `exit' and `fail' atoms; for example, the call site criterion \
`csc(mod, foo, 14, [exit, fail])' denotes the call to procedure foo in \
module mod at line 14, which has to succeed and fail exactly once to be \
considered as covered. \
\n\
\n\
call_site_cov/2 works as follows; it calls `morphine/bin/generate_call_site_cov \
<Module>.m' which generates 2 files: \"Module__call_site_cov\" that contains \
a monitor to perform the coverage, and \"Module__call_site\" that contains \
the list of call sites of Module. Then it runs the \"Module__call_site_cov\" \
monitor, which outputs the list of uncovered call sites. The file \
\"Module__call_site\" is used to display the coverage ratio.\
").
call_site_cov_Op(ProgramCall, Uncovered) :-
split_string(ProgramCall, " ", " ", [Module|_Args]),
append_strings(Module, ".m", FileName),
getenv("MERCURY_MORPHINE_DIR", MorphineDir),
( exists("call_site_cov.in") ->
true
;
concat_string(["ln -s ", MorphineDir,
"/source/call_site_cov.in "], Cmd1),
sh(Cmd1)
),
append_strings(Module, "__call_site_cov", MonitorName),
append_strings(Module, "__call_site", CritListFile),
( exists(MonitorName) ->
true
;
concat_string([MorphineDir, "/bin/generate_call_site_cov ",
FileName, " ", MorphineDir, "/../../library/"], Cmd2),
print(Cmd2), nl,
sh(Cmd2)
),
crit_cov(call_site, ProgramCall, MonitorName, CritListFile, Uncovered).
%-----------------------------------------------------------------------%
crit_cov(CovType, ProgramCall, MonitorName, CritListFile, Uncovered) :-
run(ProgramCall),
collect(MonitorName, Uncovered0),
assoc_list_to_crit(Uncovered0, Uncovered),
count_crit(CovType, Uncovered, UncoveredCard),
print("Uncovered: "), print(UncoveredCard), nl,
get_crit_list_from_file(CritListFile, ToCover),
count_crit(CovType, ToCover, ToCoverCard),
print("To cover: "), print(ToCoverCard), nl,
CoverageRate is ((ToCoverCard-UncoveredCard)/ToCoverCard*100),
printf("The coverage rate is %2g \% \n", CoverageRate).
get_crit_list_from_file(CritListFileName, CritList) :-
open(CritListFileName, read, Stream),
read(Stream, CritList),
close(Stream).
count_crit(call_site, [], 0).
count_crit(call_site, [csc(_,_,_,List) | Tail], N) :-
length(List, L),
count_crit(call_site, Tail, N0),
N is N0 + L.
count_crit(pred, [], 0).
count_crit(pred, [pc(_,_,List) | Tail], N) :-
length(List, L),
count_crit(pred, Tail, N0),
N is N0 + L.
assoc_list_to_crit(AssocList, CritList) :-
maplist(assoc_to_crit, AssocList, CritList).
assoc_to_crit(Assoc, Crit) :-
(
Assoc = p(Mod, Name) - pc(_, List),
Crit = pc(Mod, Name, List), !
;
Assoc = p(Mod, Name, LN) - csc(_, List),
Crit = csc(Mod, Name, LN, List)
).