@@ -12,23 +12,42 @@ pub mod cprover_api {
12
12
// the definitions on the C++ side (i.e. it will treat C++ as the
13
13
// source of truth rather than Rust).
14
14
15
+ /// This type reflects the success of the whole verification run.
16
+ /// E.g. If all of the assertions have been passing, then the result is
17
+ /// going to be `PASS` - if there's just one failing, the verification
18
+ /// result will be `FAIL`. You can get `UNKNOWN` only in the case where
19
+ /// you request verification results before running the verification
20
+ /// engine (not possible through the Rust interface) and `ERROR` if there
21
+ /// is something that causes the SAT solver to fail.
15
22
#[ derive( Debug ) ]
16
23
#[ repr( i32 ) ]
17
24
enum verifier_resultt {
25
+ /// The verification engine run hasn't been run yet.
18
26
UNKNOWN ,
27
+ /// No properties were violated.
19
28
PASS ,
29
+ /// Some properties were violated.
20
30
FAIL ,
31
+ /// An error occured during the running of the solver.
21
32
ERROR ,
22
33
}
23
34
35
+ /// This type is similar to [verifier_resultt] above, but reflects the
36
+ /// status of a single property checked.
24
37
#[ derive( Debug ) ]
25
38
#[ repr( i32 ) ]
26
39
enum prop_statust {
40
+ /// The property was not checked.
27
41
NOT_CHECKED ,
42
+ /// The checker was unable to determine the status of the property.
28
43
UNKNOWN ,
44
+ /// The property was proven to be unreachable.
29
45
NOT_REACHABLE ,
46
+ /// The property was not violated.
30
47
PASS ,
48
+ /// The property was violated.
31
49
FAIL ,
50
+ /// An error occured in the solver during checking the property's status.
32
51
ERROR ,
33
52
}
34
53
@@ -44,6 +63,14 @@ pub mod cprover_api {
44
63
45
64
type verifier_resultt ;
46
65
type prop_statust ;
66
+
67
+ /// This type acts as an opaque handle to the verification results object.
68
+ /// This will be given back to us through a UniquePtr, which we pass into
69
+ /// the functions that will give us back the results in a more granular level:
70
+ /// * [get_verification_result] will give the full verification engine run result,
71
+ /// * [get_property_ids] will give the list of property identifiers of the model,
72
+ /// * [get_property_description] will give a string description for a property identifier
73
+ /// * [get_property_status] will give the status of a property for a given identifier.
47
74
type verification_resultt ;
48
75
49
76
/// Provide a unique pointer to the API handle. This will be required to interact
@@ -69,16 +96,31 @@ pub mod cprover_api {
69
96
/// the CProver CLI option `--drop-unused-functions`
70
97
fn drop_unused_functions ( self : & api_sessiont ) -> Result < ( ) > ;
71
98
99
+ /// Gets a pointer to the opaque type describing the aggregate verification results and
100
+ /// returns an enum value of type [verifier_resultt] representing the whole of the verification
101
+ /// engine run.
72
102
fn get_verification_result ( result : & UniquePtr < verification_resultt > ) -> verifier_resultt ;
103
+ /// Gets a pointer to the opaque type describing the aggregate verification results
104
+ /// and returns a C++ Vector of C++ Strings containing the identifiers of the
105
+ /// properties present in the model.
73
106
fn get_property_ids ( result : & UniquePtr < verification_resultt > ) -> & CxxVector < CxxString > ;
107
+ /// Given a pointer to the opaque type representing the aggregate verification results
108
+ /// and a property identifier using a C++ string (you can use `cxx:let_cxx_string` to
109
+ /// declare), returns a C++ string that contains the property description.
110
+ /// If a bad identifier is given, this returns an `Result::Err`.
74
111
fn get_property_description < ' a > (
75
112
result : & ' a UniquePtr < verification_resultt > ,
76
113
property_id : & CxxString ,
77
- ) -> & ' a CxxString ;
114
+ ) -> Result < & ' a CxxString > ;
115
+ /// Given a pointer to the opaque type representing the aggregate verification results
116
+ /// and a property identifier using a C++ string (you can use `cxx:let_cxx_string` to
117
+ /// declare), returns a value of type [prop_statust] that contains the individual
118
+ /// property's status.
119
+ /// If a bad identifier is given, this returns an `Result::Err`.
78
120
fn get_property_status (
79
121
result : & UniquePtr < verification_resultt > ,
80
122
property_id : & CxxString ,
81
- ) -> prop_statust ;
123
+ ) -> Result < prop_statust > ;
82
124
83
125
// WARNING: Please don't use this function - use its public interface in [ffi_util::translate_rust_vector_to_cpp].
84
126
// The reason this is here is that it's implemented on the C++ shim, and to link this function against
@@ -364,17 +406,25 @@ mod tests {
364
406
let results = client. verify_model ( ) ;
365
407
if let Ok ( el) = results {
366
408
let_cxx_string ! ( existing_property_id = "main.assertion.1" ) ;
367
- let description =
368
- cprover_api:: get_property_description ( & el, & existing_property_id) . to_string ( ) ;
369
- assert_eq ! ( description, "expected failure: arr[3] == 3" ) ;
370
- Ok ( ( ) )
409
+ let description = cprover_api:: get_property_description ( & el, & existing_property_id) ;
410
+ if let Ok ( description_text) = description {
411
+ assert_eq ! ( description_text, "expected failure: arr[3] == 3" ) ;
412
+ Ok ( ( ) )
413
+ } else {
414
+ let error_msg = format ! (
415
+ "Unable to get description for property {:?}" ,
416
+ & existing_property_id
417
+ ) ;
418
+ Err ( error_msg)
419
+ }
371
420
} else {
372
421
Err ( "Unable to produce results from the verification engine" . to_string ( ) )
373
422
}
374
423
}
375
424
376
425
#[ test]
377
- fn it_can_get_the_property_status_for_existing_property ( ) -> Result < ( ) , String > {
426
+ fn it_raises_an_exception_when_getting_the_property_description_for_nonexisting_property (
427
+ ) -> Result < ( ) , String > {
378
428
let binding = cprover_api:: new_api_session ( ) ;
379
429
let client = match binding. as_ref ( ) {
380
430
Some ( api_ref) => api_ref,
@@ -391,12 +441,47 @@ mod tests {
391
441
return Err ( error_msg) ;
392
442
}
393
443
444
+ let results = client. verify_model ( ) ;
445
+ if let Ok ( el) = results {
446
+ let_cxx_string ! ( non_existing_property = "main.the.jabberwocky" ) ;
447
+ if let Err ( _) = cprover_api:: get_property_description ( & el, & non_existing_property) {
448
+ Ok ( ( ) )
449
+ } else {
450
+ let error_msg = format ! (
451
+ "Got a description for non-existent property {:?}" ,
452
+ & non_existing_property
453
+ ) ;
454
+ Err ( error_msg)
455
+ }
456
+ } else {
457
+ Err ( "Unable to produce results from the verification engine" . to_string ( ) )
458
+ }
459
+ }
460
+
461
+ #[ test]
462
+ fn it_can_get_the_property_status_for_existing_property ( ) -> Result < ( ) , String > {
463
+ let binding = cprover_api:: new_api_session ( ) ;
464
+ let client = match binding. as_ref ( ) {
465
+ Some ( api_ref) => api_ref,
466
+ None => panic ! ( "Failed to acquire API session handle" ) ,
467
+ } ;
468
+
469
+ let vec: Vec < String > = vec ! [ "other/example.c" . to_owned( ) ] ;
470
+
471
+ let vect = ffi_util:: translate_rust_vector_to_cpp ( vec) ;
472
+ assert_eq ! ( vect. len( ) , 1 ) ;
473
+
474
+ if let Err ( _) = client. load_model_from_files ( vect) {
475
+ let error_msg = format ! ( "Failed to load GOTO model from files: {:?}" , vect) ;
476
+ return Err ( error_msg) ;
477
+ }
478
+
394
479
let results = client. verify_model ( ) ;
395
480
if let Ok ( el) = results {
396
481
let_cxx_string ! ( existing_property_id = "main.assertion.1" ) ;
397
482
let prop_status = cprover_api:: get_property_status ( & el, & existing_property_id) ;
398
483
match prop_status {
399
- prop_statust:: FAIL => Ok ( ( ) ) ,
484
+ Ok ( prop_statust:: FAIL ) => Ok ( ( ) ) ,
400
485
_ => {
401
486
let error_msg = format ! (
402
487
"Property status for property {:?} was {:?} - expected FAIL" ,
@@ -409,4 +494,40 @@ mod tests {
409
494
Err ( "Unable to produce results from the verification engine" . to_string ( ) )
410
495
}
411
496
}
497
+
498
+ #[ test]
499
+ fn it_raises_an_exception_when_getting_status_of_non_existing_property ( ) -> Result < ( ) , String > {
500
+ let binding = cprover_api:: new_api_session ( ) ;
501
+ let client = match binding. as_ref ( ) {
502
+ Some ( api_ref) => api_ref,
503
+ None => panic ! ( "Failed to acquire API session handle" ) ,
504
+ } ;
505
+
506
+ let vec: Vec < String > = vec ! [ "other/example.c" . to_owned( ) ] ;
507
+
508
+ let vect = ffi_util:: translate_rust_vector_to_cpp ( vec) ;
509
+ assert_eq ! ( vect. len( ) , 1 ) ;
510
+
511
+ if let Err ( _) = client. load_model_from_files ( vect) {
512
+ let error_msg = format ! ( "Failed to load GOTO model from files: {:?}" , vect) ;
513
+ return Err ( error_msg) ;
514
+ }
515
+
516
+ let results = client. verify_model ( ) ;
517
+ if let Ok ( el) = results {
518
+ let_cxx_string ! ( non_existing_property = "main.the.jabberwocky" ) ;
519
+ let prop_status = cprover_api:: get_property_status ( & el, & non_existing_property) ;
520
+ if let Err ( status) = prop_status {
521
+ Ok ( ( ) )
522
+ } else {
523
+ let error_msg = format ! (
524
+ "Produced verification status for non-existing property: {:?}" ,
525
+ non_existing_property
526
+ ) ;
527
+ Err ( error_msg)
528
+ }
529
+ } else {
530
+ Err ( "Unable to produce results from the verification engine" . to_string ( ) )
531
+ }
532
+ }
412
533
}
0 commit comments