@@ -448,6 +448,7 @@ def group(props):
448448parser .add_argument ("--hard" , action = "store_true" , help = "In explore mode, try harder to prove properties (1hr timeout, more engines)." )
449449parser .add_argument ("--no-run" , action = "store_true" , help = "In explore mode don't run proofs again to check steps." )
450450parser .add_argument ("--no-kill" , action = "store_true" , help = "Don't kill proof processes due to running out of memory." )
451+ parser .add_argument ("--check-complete" , action = "store_true" , help = "In prove mode, fail if there are unskipped properties without proofs." )
451452args = parser .parse_args ()
452453
453454SKIPPED_PROPS = [
@@ -535,7 +536,7 @@ async def info_mode(by_step, by_step_skipped):
535536 print (red (f"Step { step } :: UNACCOUNTED :: :: :: { ' ' .join (unaccounted )} " ))
536537 print (f"{ total_steps } proof steps in total" )
537538
538- async def prove_mode (by_step ):
539+ async def prove_mode (all_props , by_step ):
539540 all_strategies = []
540541 for step , props in enumerate (by_step ):
541542 if step < args .start :
@@ -555,6 +556,17 @@ async def prove_mode(by_step):
555556 else :
556557 all_strategies .extend (strategy )
557558
559+ if args .check_complete :
560+ covered = set ()
561+ for step in all_strategies :
562+ covered .update (step [1 ])
563+ uncovered = set (prop [1 ] for prop in all_props ).difference (covered )
564+ if len (uncovered ) > 0 :
565+ print (red (f"Missing proof steps for { len (uncovered )} properties: { ' ' .join (uncovered )} " ))
566+ exit (1 )
567+ else :
568+ print (green (f"All { len (all_props )} properties are covered." ))
569+
558570 if not args .by_step :
559571 print (white (f"Running strategy for everything" ))
560572 run_start = time .time ()
@@ -563,12 +575,16 @@ async def prove_mode(by_step):
563575 print (white (f"Ran strategy in { run_dt :.3f} s" ))
564576
565577 unsats = 0
578+ has_errors = False
566579 for res , step in results :
567580 if res [0 ] == 20 :
568581 unsats += 1
569582 else :
583+ has_errors = True
570584 print (red (f"Failed to prove step { step [0 ]} proof step with code { res [0 ]} (see above, or logfile.txt, for more details): { ' ' .join (step [1 ])} " ))
571- print (white (f"{ unsats } /{ len (all_strategies )} proofs steps were UNSAT" ))
585+ print (white (f"{ unsats } /{ len (all_strategies )} proof steps were UNSAT" ))
586+ if has_errors :
587+ exit (1 ) # Failed
572588
573589async def construct_strategy (step , props ):
574590 strategy = load_strategy (step ) or []
@@ -658,7 +674,6 @@ async def logopt(by_step):
658674 continue
659675 [props , step , sha , config ] = ins
660676 if len (outs ) != 6 or type (outs [0 ]) != int or type (outs [1 ]) != float or type (outs [2 ]) != float or type (outs [3 ]) != str or type (outs [4 ]) != str or type (outs [4 ]) != str :
661- print ("ERR 2" )
662677 continue
663678 [code , mem , dt , kind , stdout , stderr ] = outs
664679 props .sort ()
@@ -740,7 +755,7 @@ def group_by_step(names, max=None):
740755 case "info" :
741756 await info_mode (by_step , skipped_by_step )
742757 case "prove" :
743- await prove_mode (by_step )
758+ await prove_mode (props , by_step )
744759 case "explore" :
745760 await explore_mode (by_step )
746761 case "logopt" :
0 commit comments