@@ -65,6 +65,8 @@ SCENARIO("path strategies")
6565 std::string c;
6666 GIVEN (" a simple conditional program" )
6767 {
68+ std::function<void (optionst &)> opts_callback = [](optionst &opts) {};
69+
6870 c =
6971 " /* 1 */ int main() \n "
7072 " /* 2 */ { \n "
@@ -75,28 +77,28 @@ SCENARIO("path strategies")
7577 " /* 7 */ x = 0; \n "
7678 " /* 8 */ } \n " ;
7779
78- const unsigned unwind_limit = 0U ;
79-
8080 check_with_strategy (
8181 " lifo" ,
82+ opts_callback,
8283 c,
8384 {symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
8485 symex_eventt::result (symex_eventt::enumt::SUCCESS),
8586 symex_eventt::resume (symex_eventt::enumt::NEXT, 5 ),
86- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
87- unwind_limit);
87+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
8888 check_with_strategy (
8989 " fifo" ,
90+ opts_callback,
9091 c,
9192 {symex_eventt::resume (symex_eventt::enumt::NEXT, 5 ),
9293 symex_eventt::result (symex_eventt::enumt::SUCCESS),
9394 symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
94- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
95- unwind_limit);
95+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
9696 }
9797
9898 GIVEN (" a program with nested conditionals" )
9999 {
100+ std::function<void (optionst &)> opts_callback = [](optionst &opts) {};
101+
100102 c =
101103 " /* 1 */ int main() \n "
102104 " /* 2 */ { \n "
@@ -117,10 +119,9 @@ SCENARIO("path strategies")
117119 " /* 17 */ } \n "
118120 " /* 18 */ } \n " ;
119121
120- const unsigned unwind_limit = 0U ;
121-
122122 check_with_strategy (
123123 " lifo" ,
124+ opts_callback,
124125 c,
125126 {// Outer else, inner else
126127 symex_eventt::resume (symex_eventt::enumt::JUMP, 13 ),
@@ -135,11 +136,11 @@ SCENARIO("path strategies")
135136 symex_eventt::result (symex_eventt::enumt::SUCCESS),
136137 // Outer if, inner if
137138 symex_eventt::resume (symex_eventt::enumt::NEXT, 7 ),
138- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
139- unwind_limit);
139+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
140140
141141 check_with_strategy (
142142 " fifo" ,
143+ opts_callback,
143144 c,
144145 {// Expand outer if, but don't continue depth-first
145146 symex_eventt::resume (symex_eventt::enumt::NEXT, 6 ),
@@ -155,12 +156,15 @@ SCENARIO("path strategies")
155156 symex_eventt::resume (symex_eventt::enumt::NEXT, 14 ),
156157 symex_eventt::result (symex_eventt::enumt::SUCCESS),
157158 symex_eventt::resume (symex_eventt::enumt::JUMP, 16 ),
158- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
159- unwind_limit);
159+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
160160 }
161161
162162 GIVEN (" a loop program to test functional correctness" )
163163 {
164+ std::function<void (optionst &)> opts_callback = [](optionst &opts) {
165+ opts.set_option (" unwind" , 2U );
166+ };
167+
164168 c =
165169 " /* 1 */ int main() \n "
166170 " /* 2 */ { \n "
@@ -173,10 +177,9 @@ SCENARIO("path strategies")
173177 " /* 9 */ assert(x); \n "
174178 " /* 10 */ } \n " ;
175179
176- const unsigned unwind_limit = 2U ;
177-
178180 check_with_strategy (
179181 " lifo" ,
182+ opts_callback,
180183 c,
181184 {
182185 // The path where we skip the loop body. Successful because the path is
@@ -194,11 +197,11 @@ SCENARIO("path strategies")
194197 // infeasible.
195198 symex_eventt::resume (symex_eventt::enumt::NEXT, 7 ),
196199 symex_eventt::result (symex_eventt::enumt::SUCCESS),
197- },
198- unwind_limit);
200+ });
199201
200202 check_with_strategy (
201203 " fifo" ,
204+ opts_callback,
202205 c,
203206 {
204207 // The path where we skip the loop body. Successful because the path is
@@ -219,8 +222,46 @@ SCENARIO("path strategies")
219222 // executing the loop once, decrementing x to 0; assert(x) should fail.
220223 symex_eventt::resume (symex_eventt::enumt::JUMP, 9 ),
221224 symex_eventt::result (symex_eventt::enumt::FAILURE),
222- },
223- unwind_limit);
225+ });
226+ }
227+
228+ GIVEN (" program to check for stop-on-fail with path exploration" )
229+ {
230+ std::function<void (optionst &)> halt_callback = [](optionst &opts) {
231+ opts.set_option (" stop-on-fail" , true );
232+ };
233+ std::function<void (optionst &)> no_halt_callback = [](optionst &opts) {};
234+
235+ c =
236+ " /* 1 */ int main() \n "
237+ " /* 2 */ { \n "
238+ " /* 3 */ int x, y; \n "
239+ " /* 4 */ if(x) \n "
240+ " /* 5 */ assert(0); \n "
241+ " /* 6 */ else \n "
242+ " /* 7 */ assert(0); \n "
243+ " /* 8 */ } \n " ;
244+
245+ GIVEN (" no stopping on failure" )
246+ {
247+ check_with_strategy (
248+ " lifo" ,
249+ no_halt_callback,
250+ c,
251+ {symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
252+ symex_eventt::result (symex_eventt::enumt::FAILURE),
253+ symex_eventt::resume (symex_eventt::enumt::NEXT, 5 ),
254+ symex_eventt::result (symex_eventt::enumt::FAILURE)});
255+ }
256+ GIVEN (" stopping on failure" )
257+ {
258+ check_with_strategy (
259+ " lifo" ,
260+ halt_callback,
261+ c,
262+ {symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
263+ symex_eventt::result (symex_eventt::enumt::FAILURE)});
264+ }
224265 }
225266}
226267
@@ -286,7 +327,7 @@ void symex_eventt::validate_resume(
286327void _check_with_strategy (
287328 const std::string &strategy,
288329 const std::string &program,
289- const unsigned unwind_limit ,
330+ std::function< void (optionst &)> opts_callback ,
290331 symex_eventt::listt &events)
291332{
292333 temporary_filet tmp (" path-explore_" , " .c" );
@@ -307,11 +348,7 @@ void _check_with_strategy(
307348 opts.set_option (" paths" , true );
308349 opts.set_option (" exploration-strategy" , strategy);
309350
310- if (unwind_limit)
311- {
312- opts.set_option (" unwind" , unwind_limit);
313- cmdline.set (" unwind" , std::to_string (unwind_limit));
314- }
351+ opts_callback (opts);
315352
316353 ui_message_handlert mh (cmdline, " path-explore" );
317354 mh.set_verbosity (0 );
@@ -337,6 +374,13 @@ void _check_with_strategy(
337374 safety_checkert::resultt result = bmc.run (gm);
338375 symex_eventt::validate_result (events, result);
339376
377+ if (
378+ result == safety_checkert::resultt::UNSAFE &&
379+ opts.get_bool_option (" stop-on-fail" ) && opts.is_set (" paths" ))
380+ {
381+ worklist->clear ();
382+ }
383+
340384 while (!worklist->empty ())
341385 {
342386 cbmc_solverst solvers (opts, gm.get_symbol_table (), mh);
@@ -360,6 +404,13 @@ void _check_with_strategy(
360404
361405 symex_eventt::validate_result (events, result);
362406 worklist->pop ();
407+
408+ if (
409+ result == safety_checkert::resultt::UNSAFE &&
410+ opts.get_bool_option (" stop-on-fail" ))
411+ {
412+ worklist->clear ();
413+ }
363414 }
364415 REQUIRE (events.empty ());
365416}
0 commit comments