@@ -231,15 +231,26 @@ fn format_item_terse(_item: &ParserItem) -> Option<String> {
231
231
/// This could be split into two functions for clarity, but at the moment
232
232
/// it uses the flag `show_checks` which depends on the output format.
233
233
///
234
+ /// This function reports the results of normal checks (e.g. assertions and
235
+ /// arithmetic overflow checks) and cover properties (specified using the
236
+ /// `kani::cover` macro) separately. Cover properties currently do not impact
237
+ /// the overall verification success or failure.
238
+ ///
234
239
/// TODO: We could `write!` to `result_str` instead
235
240
/// <https://github.com/model-checking/kani/issues/1480>
236
241
pub fn format_result ( properties : & Vec < Property > , show_checks : bool ) -> String {
237
242
let mut result_str = String :: new ( ) ;
238
- let mut number_tests_failed = 0 ;
239
- let mut number_tests_unreachable = 0 ;
240
- let mut number_tests_undetermined = 0 ;
243
+ let mut number_checks_failed = 0 ;
244
+ let mut number_checks_unreachable = 0 ;
245
+ let mut number_checks_undetermined = 0 ;
241
246
let mut failed_tests: Vec < & Property > = vec ! [ ] ;
242
247
248
+ // cover checks
249
+ let mut number_covers_satisfied = 0 ;
250
+ let mut number_covers_undetermined = 0 ;
251
+ let mut number_covers_unreachable = 0 ;
252
+ let mut number_covers_unsatisfiable = 0 ;
253
+
243
254
let mut index = 1 ;
244
255
245
256
if show_checks {
@@ -254,14 +265,30 @@ pub fn format_result(properties: &Vec<Property>, show_checks: bool) -> String {
254
265
255
266
match status {
256
267
CheckStatus :: Failure => {
257
- number_tests_failed += 1 ;
268
+ number_checks_failed += 1 ;
258
269
failed_tests. push ( prop) ;
259
270
}
260
271
CheckStatus :: Undetermined => {
261
- number_tests_undetermined += 1 ;
272
+ if prop. is_cover_property ( ) {
273
+ number_covers_undetermined += 1 ;
274
+ } else {
275
+ number_checks_undetermined += 1 ;
276
+ }
262
277
}
263
278
CheckStatus :: Unreachable => {
264
- number_tests_unreachable += 1 ;
279
+ if prop. is_cover_property ( ) {
280
+ number_covers_unreachable += 1 ;
281
+ } else {
282
+ number_checks_unreachable += 1 ;
283
+ }
284
+ }
285
+ CheckStatus :: Satisfied => {
286
+ assert ! ( prop. is_cover_property( ) ) ;
287
+ number_covers_satisfied += 1 ;
288
+ }
289
+ CheckStatus :: Unsatisfiable => {
290
+ assert ! ( prop. is_cover_property( ) ) ;
291
+ number_covers_unsatisfiable += 1 ;
265
292
}
266
293
_ => ( ) ,
267
294
}
@@ -291,16 +318,23 @@ pub fn format_result(properties: &Vec<Property>, show_checks: bool) -> String {
291
318
result_str. push_str ( "\n VERIFICATION RESULT:" ) ;
292
319
}
293
320
294
- let summary = format ! ( "\n ** {number_tests_failed} of {} failed" , properties. len( ) ) ;
321
+ let number_cover_properties = number_covers_satisfied
322
+ + number_covers_unreachable
323
+ + number_covers_unsatisfiable
324
+ + number_covers_undetermined;
325
+
326
+ let number_properties = properties. len ( ) - number_cover_properties;
327
+
328
+ let summary = format ! ( "\n ** {number_checks_failed} of {} failed" , number_properties) ;
295
329
result_str. push_str ( & summary) ;
296
330
297
331
let mut other_status = Vec :: < String > :: new ( ) ;
298
- if number_tests_undetermined > 0 {
299
- let undetermined_str = format ! ( "{number_tests_undetermined } undetermined" ) ;
332
+ if number_checks_undetermined > 0 {
333
+ let undetermined_str = format ! ( "{number_checks_undetermined } undetermined" ) ;
300
334
other_status. push ( undetermined_str) ;
301
335
}
302
- if number_tests_unreachable > 0 {
303
- let unreachable_str = format ! ( "{number_tests_unreachable } unreachable" ) ;
336
+ if number_checks_unreachable > 0 {
337
+ let unreachable_str = format ! ( "{number_checks_unreachable } unreachable" ) ;
304
338
other_status. push ( unreachable_str) ;
305
339
}
306
340
if !other_status. is_empty ( ) {
@@ -310,13 +344,38 @@ pub fn format_result(properties: &Vec<Property>, show_checks: bool) -> String {
310
344
}
311
345
result_str. push ( '\n' ) ;
312
346
347
+ if number_cover_properties > 0 {
348
+ // Print a summary line for cover properties
349
+ let summary = format ! (
350
+ "\n ** {number_covers_satisfied} of {} cover properties satisfied" ,
351
+ number_cover_properties
352
+ ) ;
353
+ result_str. push_str ( & summary) ;
354
+ let mut other_status = Vec :: < String > :: new ( ) ;
355
+ if number_covers_undetermined > 0 {
356
+ let undetermined_str = format ! ( "{number_covers_undetermined} undetermined" ) ;
357
+ other_status. push ( undetermined_str) ;
358
+ }
359
+ if number_covers_unreachable > 0 {
360
+ let unreachable_str = format ! ( "{number_covers_unreachable} unreachable" ) ;
361
+ other_status. push ( unreachable_str) ;
362
+ }
363
+ if !other_status. is_empty ( ) {
364
+ result_str. push_str ( " (" ) ;
365
+ result_str. push_str ( & other_status. join ( "," ) ) ;
366
+ result_str. push ( ')' ) ;
367
+ }
368
+ result_str. push ( '\n' ) ;
369
+ result_str. push ( '\n' ) ;
370
+ }
371
+
313
372
for prop in failed_tests {
314
373
let failure_message = build_failure_message ( prop. description . clone ( ) , & prop. trace . clone ( ) ) ;
315
374
result_str. push_str ( & failure_message) ;
316
375
}
317
376
318
377
let verification_result =
319
- if number_tests_failed == 0 { style ( "SUCCESSFUL" ) . green ( ) } else { style ( "FAILED" ) . red ( ) } ;
378
+ if number_checks_failed == 0 { style ( "SUCCESSFUL" ) . green ( ) } else { style ( "FAILED" ) . red ( ) } ;
320
379
let overall_result = format ! ( "\n VERIFICATION:- {verification_result}\n " ) ;
321
380
result_str. push_str ( & overall_result) ;
322
381
@@ -413,7 +472,7 @@ pub fn postprocess_result(properties: Vec<Property>, extra_ptr_checks: bool) ->
413
472
let ( properties_without_reachs, reach_checks) = filter_reach_checks ( properties_with_undefined) ;
414
473
// Filter out successful sanity checks introduced during compilation
415
474
let properties_without_sanity_checks = filter_sanity_checks ( properties_without_reachs) ;
416
- // Annotate properties with the results from reachability checks
475
+ // Annotate properties with the results of reachability checks
417
476
let properties_annotated =
418
477
annotate_properties_with_reach_results ( properties_without_sanity_checks, reach_checks) ;
419
478
// Remove reachability check IDs from regular property descriptions
@@ -429,7 +488,9 @@ pub fn postprocess_result(properties: Vec<Property>, extra_ptr_checks: bool) ->
429
488
|| has_failed_unwinding_asserts
430
489
|| has_reachable_undefined_functions;
431
490
432
- update_properties_with_reach_status ( properties_filtered, has_fundamental_failures)
491
+ let updated_properties =
492
+ update_properties_with_reach_status ( properties_filtered, has_fundamental_failures) ;
493
+ update_results_of_cover_checks ( updated_properties)
433
494
}
434
495
435
496
/// Determines if there is property with status `FAILURE` and the given description
@@ -495,7 +556,7 @@ fn get_readable_description(property: &Property) -> String {
495
556
original
496
557
}
497
558
498
- /// Performs a last pass to update all properties as follows:
559
+ /// Performs a pass to update all properties as follows:
499
560
/// 1. Descriptions are replaced with more readable ones.
500
561
/// 2. If there were failures that made the verification result unreliable
501
562
/// (e.g., a reachable unsupported construct), changes all `SUCCESS` results
@@ -525,6 +586,23 @@ fn update_properties_with_reach_status(
525
586
properties
526
587
}
527
588
589
+ /// Update the results of cover properties.
590
+ /// We encode cover(cond) as assert(!cond), so if the assertion
591
+ /// fails, then the cover property is satisfied and vice versa.
592
+ /// - SUCCESS -> UNSATISFIABLE
593
+ /// - FAILURE -> SATISFIED
594
+ fn update_results_of_cover_checks ( mut properties : Vec < Property > ) -> Vec < Property > {
595
+ for prop in properties. iter_mut ( ) {
596
+ if prop. is_cover_property ( ) {
597
+ if prop. status == CheckStatus :: Success {
598
+ prop. status = CheckStatus :: Unsatisfiable ;
599
+ } else if prop. status == CheckStatus :: Failure {
600
+ prop. status = CheckStatus :: Satisfied ;
601
+ }
602
+ }
603
+ }
604
+ properties
605
+ }
528
606
/// Some Kani-generated asserts have a unique ID in their description of the form:
529
607
/// ```text
530
608
/// [KANI_CHECK_ID_<crate-fn-name>_<index>]
0 commit comments