Skip to content

Commit 14109a4

Browse files
Fix path explorer unit test
Cannot use deprecated bmct anymore.
1 parent c94d0af commit 14109a4

File tree

2 files changed

+136
-90
lines changed

2 files changed

+136
-90
lines changed

unit/path_strategies.cpp

Lines changed: 133 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ Author: Kareem Khazem <[email protected]>, 2018
1616

1717
#include <ansi-c/ansi_c_language.h>
1818

19-
#include <cbmc/bmc.h>
2019
#include <cbmc/cbmc_parse_options.h>
2120

22-
#include <goto-checker/solver_factory.h>
21+
#include <goto-checker/bmc_util.h>
22+
#include <goto-checker/goto_symex_property_decider.h>
23+
#include <goto-checker/symex_bmc.h>
2324

2425
#include <langapi/mode.h>
2526

@@ -42,8 +43,8 @@ Author: Kareem Khazem <[email protected]>, 2018
4243
// `goto` instruction.
4344
//
4445
// Whenever symbolic execution reaches the end of a path, you should expect a
45-
// result. Results are either SUCCESS, meaning that verification of that path
46-
// succeeded, or FAILURE, meaning that there was an assertion failure on that
46+
// result. Results are either DONE, meaning that verification of that path
47+
// succeeded, or FOUND_FAIL, meaning that there was an assertion failure on that
4748
// path.
4849
//
4950
// To figure out what the events should be, run CBMC on the test program with
@@ -80,14 +81,18 @@ SCENARIO("path strategies")
8081
"lifo",
8182
opts_callback,
8283
c,
83-
{symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
84+
{// Entry state is line 0
85+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
86+
symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
8487
symex_eventt::resume(symex_eventt::enumt::NEXT, 5),
8588
symex_eventt::result(symex_eventt::enumt::SUCCESS)});
8689
check_with_strategy(
8790
"fifo",
8891
opts_callback,
8992
c,
90-
{symex_eventt::resume(symex_eventt::enumt::NEXT, 5),
93+
{// Entry state is line 0
94+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
95+
symex_eventt::resume(symex_eventt::enumt::NEXT, 5),
9196
symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
9297
symex_eventt::result(symex_eventt::enumt::SUCCESS)});
9398
}
@@ -120,7 +125,9 @@ SCENARIO("path strategies")
120125
"lifo",
121126
opts_callback,
122127
c,
123-
{// Outer else, inner else
128+
{// Entry state is line 0
129+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
130+
// Outer else, inner else
124131
symex_eventt::resume(symex_eventt::enumt::JUMP, 13),
125132
symex_eventt::resume(symex_eventt::enumt::JUMP, 16),
126133
// Outer else, inner if
@@ -136,7 +143,9 @@ SCENARIO("path strategies")
136143
"fifo",
137144
opts_callback,
138145
c,
139-
{// Expand outer if, but don't continue depth-first
146+
{// Entry state is line 0
147+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
148+
// Expand outer if, but don't continue depth-first
140149
symex_eventt::resume(symex_eventt::enumt::NEXT, 6),
141150
// Jump to outer else, but again don't continue depth-first
142151
symex_eventt::resume(symex_eventt::enumt::JUMP, 13),
@@ -175,6 +184,9 @@ SCENARIO("path strategies")
175184
opts_callback,
176185
c,
177186
{
187+
// Entry state is line 0
188+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
189+
178190
// The path where x != 1 and we have nothing to check:
179191
symex_eventt::resume(symex_eventt::enumt::JUMP, 11),
180192

@@ -204,6 +216,9 @@ SCENARIO("path strategies")
204216
opts_callback,
205217
c,
206218
{
219+
// Entry state is line 0
220+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
221+
207222
// First the path where we enter the if-block at line 4 then on hitting
208223
// the branch at line 6 consider skipping straight to the end, but find
209224
// nothing there to investigate:
@@ -257,7 +272,9 @@ SCENARIO("path strategies")
257272
"lifo",
258273
no_halt_callback,
259274
c,
260-
{symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
275+
{// Entry state is line 0
276+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
277+
symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
261278
symex_eventt::result(symex_eventt::enumt::FAILURE),
262279
symex_eventt::resume(symex_eventt::enumt::NEXT, 5),
263280
symex_eventt::result(symex_eventt::enumt::FAILURE),
@@ -270,7 +287,9 @@ SCENARIO("path strategies")
270287
"lifo",
271288
halt_callback,
272289
c,
273-
{symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
290+
{// Entry state is line 0
291+
symex_eventt::resume(symex_eventt::enumt::NEXT, 0),
292+
symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
274293
symex_eventt::result(symex_eventt::enumt::FAILURE),
275294
// Overall result
276295
symex_eventt::result(symex_eventt::enumt::FAILURE)});
@@ -283,24 +302,24 @@ SCENARIO("path strategies")
283302

284303
void symex_eventt::validate_result(
285304
listt &events,
286-
const safety_checkert::resultt result,
305+
const incremental_goto_checkert::resultt::progresst result,
287306
std::size_t &counter)
288307
{
289308
INFO(
290309
"Expecting result to be '"
291-
<< (result == safety_checkert::resultt::SAFE ? "success" : "failure")
310+
<< (result == incremental_goto_checkert::resultt::progresst::DONE
311+
? "success"
312+
: "failure")
292313
<< "' (item at index [" << counter << "] in expected results list");
293314
++counter;
294315

295-
REQUIRE(result != safety_checkert::resultt::ERROR);
296-
297-
if(result == safety_checkert::resultt::SAFE)
316+
if(result == incremental_goto_checkert::resultt::progresst::DONE)
298317
{
299318
REQUIRE(!events.empty());
300319
REQUIRE(events.front().first == symex_eventt::enumt::SUCCESS);
301320
events.pop_front();
302321
}
303-
else if(result == safety_checkert::resultt::UNSAFE)
322+
else
304323
{
305324
REQUIRE(!events.empty());
306325
REQUIRE(events.front().first == symex_eventt::enumt::FAILURE);
@@ -315,23 +334,25 @@ void symex_eventt::validate_resume(
315334
{
316335
REQUIRE(!events.empty());
317336

318-
int dst = std::stoi(state.saved_target->source_location.get_line().c_str());
337+
int dst = 0;
338+
if(!state.saved_target->source_location.get_line().empty())
339+
dst = std::stoi(state.saved_target->source_location.get_line().c_str());
319340

320-
if(state.has_saved_jump_target)
341+
if(state.has_saved_next_instruction)
321342
{
322343
INFO(
323-
"Expecting resume to be 'jump' to line "
344+
"Expecting resume to be 'next' to line "
324345
<< dst << " (item at index [" << counter
325346
<< "] in expected resumes list)");
326-
REQUIRE(events.front().first == symex_eventt::enumt::JUMP);
347+
REQUIRE(events.front().first == symex_eventt::enumt::NEXT);
327348
}
328-
else if(state.has_saved_next_instruction)
349+
else if(state.has_saved_jump_target)
329350
{
330351
INFO(
331-
"Expecting resume to be 'next' to line "
352+
"Expecting resume to be 'jump' to line "
332353
<< dst << " (item at index [" << counter
333354
<< "] in expected resumes list)");
334-
REQUIRE(events.front().first == symex_eventt::enumt::NEXT);
355+
REQUIRE(events.front().first == symex_eventt::enumt::JUMP);
335356
}
336357
else
337358
REQUIRE(false);
@@ -342,11 +363,8 @@ void symex_eventt::validate_resume(
342363
events.pop_front();
343364
}
344365

345-
// This is a simplified version of bmct::do_language_agnostic_bmc, without all
346-
// the edge cases to deal with java programs, bytecode loaded on demand, etc. We
347-
// need to replicate some of this stuff because the worklist is a local variable
348-
// of do_language_agnostic_bmc, and we need to check the worklist every time
349-
// symex returns.
366+
// This is a simplified copy of single_path_symex_checkert
367+
// because we have to check the worklist every time goto-symex returns.
350368
void _check_with_strategy(
351369
const std::string &strategy,
352370
const std::string &program,
@@ -366,95 +384,122 @@ void _check_with_strategy(
366384
config.main = "main";
367385
config.set(cmdline);
368386

369-
optionst opts;
370-
cbmc_parse_optionst::set_default_options(opts);
371-
opts.set_option("paths", true);
372-
opts.set_option("exploration-strategy", strategy);
373-
374-
opts_callback(opts);
375-
376-
ui_message_handlert mh(cmdline, "path-explore");
377-
mh.set_verbosity(0);
378-
messaget log(mh);
379-
387+
optionst options;
388+
cbmc_parse_optionst::set_default_options(options);
389+
options.set_option("paths", true);
390+
options.set_option("exploration-strategy", strategy);
380391
REQUIRE(is_valid_path_strategy(strategy));
381-
std::unique_ptr<path_storaget> worklist = get_path_strategy(strategy);
382-
guard_managert guard_manager;
392+
opts_callback(options);
383393

384-
goto_modelt gm;
394+
ui_message_handlert ui_message_handler(cmdline, "path-explore");
395+
ui_message_handler.set_verbosity(0);
396+
messaget log(ui_message_handler);
397+
398+
goto_modelt goto_model;
385399
int ret;
386-
ret = cbmc_parse_optionst::get_goto_program(gm, opts, cmdline, log, mh);
400+
ret = cbmc_parse_optionst::get_goto_program(
401+
goto_model, options, cmdline, log, ui_message_handler);
387402
REQUIRE(ret == -1);
388403

389-
namespacet ns(gm.get_symbol_table());
390-
solver_factoryt solver_factory(opts, ns, mh, false);
391-
std::unique_ptr<solver_factoryt::solvert> cbmc_solver =
392-
solver_factory.get_solver();
393-
prop_convt &initial_pc = cbmc_solver->prop_conv();
394-
std::function<bool(void)> callback = []() { return false; };
395-
396-
safety_checkert::resultt overall_result = safety_checkert::resultt::SAFE;
397-
std::size_t expected_results_cnt = 0;
404+
symbol_tablet symex_symbol_table;
405+
namespacet ns(goto_model.get_symbol_table(), symex_symbol_table);
406+
propertiest properties(initialize_properties(goto_model));
407+
std::unique_ptr<path_storaget> worklist = get_path_strategy(strategy);
408+
guard_managert guard_manager;
398409

399-
bmct bmc(
400-
opts,
401-
gm.get_symbol_table(),
402-
mh,
403-
initial_pc,
404-
*worklist,
405-
callback,
406-
guard_manager);
407-
safety_checkert::resultt tmp_result = bmc.run(gm);
408-
409-
if(tmp_result != safety_checkert::resultt::PAUSED)
410410
{
411-
symex_eventt::validate_result(events, tmp_result, expected_results_cnt);
412-
overall_result &= tmp_result;
413-
}
411+
// Put initial state into the work list
412+
symex_target_equationt equation(ui_message_handler);
413+
symex_bmct symex(
414+
ui_message_handler,
415+
goto_model.get_symbol_table(),
416+
equation,
417+
options,
418+
*worklist,
419+
guard_manager);
420+
setup_symex(symex, ns, options, ui_message_handler);
414421

415-
if(
416-
overall_result == safety_checkert::resultt::UNSAFE &&
417-
opts.get_bool_option("stop-on-fail") && opts.is_set("paths"))
418-
{
419-
worklist->clear();
422+
symex.initialize_path_storage_from_entry_point_of(
423+
goto_symext::get_goto_function(goto_model), symex_symbol_table);
420424
}
421425

426+
std::size_t expected_results_cnt = 0;
422427
while(!worklist->empty())
423428
{
424-
cbmc_solver = solver_factory.get_solver();
425-
prop_convt &pc = cbmc_solver->prop_conv();
426429
path_storaget::patht &resume = worklist->peek();
427430

428431
symex_eventt::validate_resume(events, resume.state, expected_results_cnt);
429432

430-
path_explorert pe(
431-
opts,
432-
gm.get_symbol_table(),
433-
mh,
434-
pc,
433+
symex_bmct symex(
434+
ui_message_handler,
435+
goto_model.get_symbol_table(),
435436
resume.equation,
436-
resume.state,
437+
options,
437438
*worklist,
438-
guard_manager,
439-
callback);
440-
tmp_result = pe.run(gm);
439+
guard_manager);
440+
setup_symex(symex, ns, options, ui_message_handler);
441+
442+
symex.resume_symex_from_saved_state(
443+
goto_symext::get_goto_function(goto_model),
444+
resume.state,
445+
&resume.equation,
446+
symex_symbol_table);
447+
postprocess_equation(
448+
symex, resume.equation, options, ns, ui_message_handler);
441449

442-
if(tmp_result != safety_checkert::resultt::PAUSED)
450+
incremental_goto_checkert::resultt result(
451+
incremental_goto_checkert::resultt::progresst::DONE);
452+
453+
if(symex.get_remaining_vccs() > 0)
443454
{
444-
symex_eventt::validate_result(events, tmp_result, expected_results_cnt);
445-
overall_result &= tmp_result;
455+
update_properties_status_from_symex_target_equation(
456+
properties, result.updated_properties, resume.equation);
457+
458+
goto_symex_property_decidert property_decider(
459+
options, ui_message_handler, resume.equation, ns);
460+
461+
const auto solver_runtime = prepare_property_decider(
462+
properties, resume.equation, property_decider, ui_message_handler);
463+
464+
run_property_decider(
465+
result,
466+
properties,
467+
property_decider,
468+
ui_message_handler,
469+
solver_runtime,
470+
false);
471+
472+
symex_eventt::validate_result(
473+
events, result.progress, expected_results_cnt);
446474
}
475+
447476
worklist->pop();
448477

449478
if(
450-
overall_result == safety_checkert::resultt::UNSAFE &&
451-
opts.get_bool_option("stop-on-fail"))
479+
result.progress ==
480+
incremental_goto_checkert::resultt::progresst::FOUND_FAIL &&
481+
options.get_bool_option("stop-on-fail"))
452482
{
453483
worklist->clear();
454484
}
485+
486+
if(worklist->empty())
487+
{
488+
update_status_of_not_checked_properties(
489+
properties, result.updated_properties);
490+
491+
update_status_of_unknown_properties(
492+
properties, result.updated_properties);
493+
}
455494
}
456495

457-
symex_eventt::validate_result(events, overall_result, expected_results_cnt);
496+
const resultt overall_result = determine_result(properties);
497+
symex_eventt::validate_result(
498+
events,
499+
overall_result == resultt::FAIL
500+
? incremental_goto_checkert::resultt::progresst::FOUND_FAIL
501+
: incremental_goto_checkert::resultt::progresst::DONE,
502+
expected_results_cnt);
458503

459504
INFO("The expected results list contains " << events.size() << " items");
460505
REQUIRE(events.empty());

unit/path_strategies.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#define CPROVER_PATH_STRATEGIES_H
77

88
#include <goto-programs/goto_model.h>
9-
#include <goto-programs/safety_checker.h>
9+
10+
#include <goto-checker/incremental_goto_checker.h>
1011

1112
#include <goto-symex/goto_symex_state.h>
1213

@@ -38,7 +39,7 @@ struct symex_eventt
3839

3940
static void validate_result(
4041
listt &events,
41-
const safety_checkert::resultt result,
42+
const incremental_goto_checkert::resultt::progresst result,
4243
std::size_t &);
4344

4445
static void

0 commit comments

Comments
 (0)