Skip to content

Commit 932599e

Browse files
Merge pull request #5636 from hannes-steffenhagen-diffblue/feature/cover-failed-assertions
Cover failed assertions
2 parents c7e3c5d + bad0d16 commit 932599e

File tree

13 files changed

+101
-20
lines changed

13 files changed

+101
-20
lines changed

jbmc/src/jdiff/jdiff_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ void jdiff_parse_optionst::help()
367367
"\n"
368368
"Program instrumentation options:\n"
369369
HELP_GOTO_CHECK
370-
" --cover CC create test-suite with coverage criterion CC\n" // NOLINT(*)
370+
HELP_COVER
371371
"Java Bytecode frontend options:\n"
372372
JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP
373373
"Other options:\n"

jbmc/src/jdiff/jdiff_parse_options.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Author: Peter Schrammel
2323
#include <goto-programs/show_goto_functions.h>
2424
#include <goto-programs/show_properties.h>
2525

26+
#include <goto-instrument/cover.h>
27+
2628
class goto_modelt;
2729

2830
// clang-format off
@@ -31,7 +33,7 @@ class goto_modelt;
3133
OPT_SHOW_GOTO_FUNCTIONS \
3234
OPT_SHOW_PROPERTIES \
3335
OPT_GOTO_CHECK \
34-
"(cover):" \
36+
OPT_COVER \
3537
"(verbosity):(version)" \
3638
"(no-lazy-methods)" /* should go away */ \
3739
"(no-refine-strings)" /* should go away */ \
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE paths-lifo-expected-failure
2+
test.c
3+
--cover location --pointer-check --malloc-may-fail --malloc-fail-null
4+
\[main\.coverage\.4\] file test\.c line \d+ function main block 4 \(lines test\.c:main:17,18\): SATISFIED
5+
\[main\.coverage\.3\] file test\.c line \d+ function main block 3 \(lines test\.c:main:15\): FAILED
6+
\[main\.coverage\.2\] file test\.c line \d+ function main block 2 \(lines test\.c:main:5,6,12,14\): SATISFIED
7+
\[main\.coverage\.1\] file test\.c line \d+ function main block 1 \(lines test\.c:main:5\): SATISFIED
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
11+
^warning: ignoring
12+
--
13+
This is checking that without the --cover-failed-assertions flag we still get the same result as we did before adding
14+
it in this example.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdlib.h>
2+
3+
int main()
4+
{
5+
int *ptr = malloc(sizeof(*ptr));
6+
int a;
7+
8+
// pointer check would detect the dereference of a null pointer here
9+
// default --cover lines behaviour is to treat non-cover assertions as
10+
// assumptions instead, so in the ptr == NULL case we don't get past this line
11+
// leading to failed coverage for the body of the if statement down below
12+
a = *ptr;
13+
14+
if(ptr == NULL)
15+
a = 1;
16+
17+
return 0;
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE paths-lifo-expected-failure
2+
test.c
3+
--cover location --cover-failed-assertions --pointer-check --malloc-may-fail --malloc-fail-null
4+
\[main.coverage\.4\] file test\.c line \d+ function main block 4 \(lines test\.c:main:17,18\): SATISFIED
5+
\[main.coverage\.3\] file test\.c line \d+ function main block 3 \(lines test\.c:main:15\): SATISFIED
6+
\[main.coverage\.2\] file test\.c line \d+ function main block 2 \(lines test\.c:main:5,6,12,14\): SATISFIED
7+
\[main.coverage\.1\] file test\.c line \d+ function main block 1 \(lines test\.c:main:5\): SATISFIED
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
11+
^warning: ignoring
12+
--
13+
This is checking that the if statement body can actually be covered with the new flag

regression/validate-trace-xml-schema/check.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
['unknown-argument-suggestion', 'test.desc'],
3535
# this one produces XML intermingled with main XML output when used with --xml-ui
3636
['graphml_witness2', 'test.desc'],
37+
# these are producing coverage goals which aren't included in the schema
38+
['cover-failed-assertions', 'test.desc'],
39+
['cover-failed-assertions', 'test-no-failed-assertions.desc'],
3740
# produces intermingled XML on the command line
3841
['coverage_report1', 'test.desc'],
3942
['coverage_report1', 'paths.desc'],

src/cbmc/README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,15 @@ by other mechanism may categorise their properties differently.
7777

7878
### Coverage mode
7979

80-
There is one further BMC mode that differs more fundamentally: when `--cover` is
81-
passed, assertions in the program text are converted into assumptions (these
80+
There is one further BMC mode that differs more fundamentally: when `--cover`
81+
is passed, assertions in the program text are converted into assumptions (these
8282
must hold for control flow to proceed past them, but are not goals for the
83-
equation solver), while new `assert(false)` statements are added throughout the
84-
source program representing coverage goals. The equation solving process then
85-
proceeds the same as in all-properties mode. Coverage solving is implemented by
86-
`bmc_covert`, but is structurally practically identical to
83+
equation solver; In cases where this behaviour is undesirable you can pass the
84+
`--cover-failed-assertions` which makes coverage checking continue even for
85+
paths where assertions fail), while new `assert(false)` statements are added
86+
throughout the source program representing coverage goals. The equation solving
87+
process then proceeds the same as in all-properties mode. Coverage solving is
88+
implemented by `bmc_covert`, but is structurally practically identical to
8789
`bmc_all_propertiest`-- only the reporting differs (goals are called "covered"
8890
rather than "failed").
8991

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ void cbmc_parse_optionst::help()
11191119
" --no-assertions ignore user assertions\n"
11201120
" --no-assumptions ignore user assumptions\n"
11211121
" --error-label label check that label is unreachable\n"
1122-
" --cover CC create test-suite with coverage criterion CC\n" // NOLINT(*)
1122+
HELP_COVER
11231123
" --mm MM memory consistency model for concurrent programs\n" // NOLINT(*)
11241124
// NOLINTNEXTLINE(whitespace/line_length)
11251125
" --malloc-fail-assert set malloc failure mode to assert-then-assume\n"

src/cbmc/cbmc_parse_options.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Author: Daniel Kroening, [email protected]
3434
#include <json/json_interface.h>
3535
#include <xmllang/xml_interface.h>
3636

37+
#include <goto-instrument/cover.h>
38+
3739
class goto_functionst;
3840
class optionst;
3941

@@ -74,7 +76,8 @@ class optionst;
7476
"(error-label):(verbosity):(no-library)" \
7577
"(nondet-static)" \
7678
"(version)" \
77-
"(cover):(symex-coverage-report):" \
79+
OPT_COVER \
80+
"(symex-coverage-report):" \
7881
"(mm):" \
7982
OPT_TIMESTAMP \
8083
"(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)(gcc)" \

src/goto-diff/goto_diff_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ void goto_diff_parse_optionst::help()
411411
"\n"
412412
"Program instrumentation options:\n"
413413
HELP_GOTO_CHECK
414-
" --cover CC create test-suite with coverage criterion CC\n" // NOLINT(*)
414+
HELP_COVER
415415
"Other options:\n"
416416
" --version show version and exit\n"
417417
" --json-ui use JSON-formatted output\n"

src/goto-diff/goto_diff_parse_options.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Author: Peter Schrammel
2222
#include <goto-programs/show_goto_functions.h>
2323
#include <goto-programs/show_properties.h>
2424

25+
#include <goto-instrument/cover.h>
26+
2527
class goto_modelt;
2628
class optionst;
2729

@@ -31,7 +33,7 @@ class optionst;
3133
OPT_SHOW_GOTO_FUNCTIONS \
3234
OPT_SHOW_PROPERTIES \
3335
OPT_GOTO_CHECK \
34-
"(cover):" \
36+
OPT_COVER \
3537
"(verbosity):(version)" \
3638
OPT_FLUSH \
3739
OPT_TIMESTAMP \

src/goto-instrument/cover.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ void parse_cover_options(const cmdlinet &cmdline, optionst &options)
164164
options.set_option(
165165
"cover-traces-must-terminate",
166166
cmdline.isset("cover-traces-must-terminate"));
167+
options.set_option(
168+
"cover-failed-assertions", cmdline.isset("cover-failed-assertions"));
167169
}
168170

169171
/// Build data structures controlling coverage from command-line options.
@@ -223,6 +225,9 @@ cover_configt get_cover_config(
223225
cover_config.traces_must_terminate =
224226
options.get_bool_option("cover-traces-must-terminate");
225227

228+
cover_config.cover_failed_assertions =
229+
options.get_bool_option("cover-failed-assertions");
230+
226231
return cover_config;
227232
}
228233

@@ -285,16 +290,22 @@ static void instrument_cover_goals(
285290
// Simplify the common case where we have ASSERT(x); ASSUME(x):
286291
if(i_it->is_assert())
287292
{
288-
auto successor = std::next(i_it);
289-
if(
290-
successor != function.body.instructions.end() &&
291-
successor->is_assume() &&
292-
successor->get_condition() == i_it->get_condition())
293+
if(!cover_config.cover_failed_assertions)
293294
{
294-
successor->turn_into_skip();
295+
auto successor = std::next(i_it);
296+
if(
297+
successor != function.body.instructions.end() &&
298+
successor->is_assume() &&
299+
successor->get_condition() == i_it->get_condition())
300+
{
301+
successor->turn_into_skip();
302+
}
303+
i_it->type = goto_program_instruction_typet::ASSUME;
304+
}
305+
else
306+
{
307+
i_it->turn_into_skip();
295308
}
296-
297-
i_it->type = goto_program_instruction_typet::ASSUME;
298309
}
299310
}
300311
}

src/goto-instrument/cover.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ class message_handlert;
2222
class cmdlinet;
2323
class optionst;
2424

25+
#define OPT_COVER \
26+
"(cover):" \
27+
"(cover-failed-assertions)"
28+
29+
#define HELP_COVER \
30+
" --cover CC create test-suite with coverage criterion " \
31+
"CC\n" \
32+
" --cover-failed-assertions do not stop coverage checking at failed " \
33+
"assertions\n" \
34+
" (this is the default for --cover " \
35+
"assertions)\n"
36+
2537
enum class coverage_criteriont
2638
{
2739
LOCATION,
@@ -37,6 +49,7 @@ enum class coverage_criteriont
3749
struct cover_configt
3850
{
3951
bool keep_assertions;
52+
bool cover_failed_assertions;
4053
bool traces_must_terminate;
4154
irep_idt mode;
4255
function_filterst function_filters;

0 commit comments

Comments
 (0)