@@ -12,23 +12,42 @@ pub mod cprover_api {
1212 // the definitions on the C++ side (i.e. it will treat C++ as the
1313 // source of truth rather than Rust).
1414
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.
1522 #[ derive( Debug ) ]
1623 #[ repr( i32 ) ]
1724 enum verifier_resultt {
25+ /// The verification engine run hasn't been run yet.
1826 UNKNOWN ,
27+ /// No properties were violated.
1928 PASS ,
29+ /// Some properties were violated.
2030 FAIL ,
31+ /// An error occured during the running of the solver.
2132 ERROR ,
2233 }
2334
35+ /// This type is similar to [verifier_resultt] above, but reflects the
36+ /// status of a single property checked.
2437 #[ derive( Debug ) ]
2538 #[ repr( i32 ) ]
2639 enum prop_statust {
40+ /// The property was not checked.
2741 NOT_CHECKED ,
42+ /// The checker was unable to determine the status of the property.
2843 UNKNOWN ,
44+ /// The property was proven to be unreachable.
2945 NOT_REACHABLE ,
46+ /// The property was not violated.
3047 PASS ,
48+ /// The property was violated.
3149 FAIL ,
50+ /// An error occured in the solver during checking the property's status.
3251 ERROR ,
3352 }
3453
@@ -44,6 +63,14 @@ pub mod cprover_api {
4463
4564 type verifier_resultt ;
4665 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.
4774 type verification_resultt ;
4875
4976 /// Provide a unique pointer to the API handle. This will be required to interact
@@ -69,16 +96,31 @@ pub mod cprover_api {
6996 /// the CProver CLI option `--drop-unused-functions`
7097 fn drop_unused_functions ( self : & api_sessiont ) -> Result < ( ) > ;
7198
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.
72102 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.
73106 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`.
74111 fn get_property_description < ' a > (
75112 result : & ' a UniquePtr < verification_resultt > ,
76113 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`.
78120 fn get_property_status (
79121 result : & UniquePtr < verification_resultt > ,
80122 property_id : & CxxString ,
81- ) -> prop_statust ;
123+ ) -> Result < prop_statust > ;
82124
83125 // WARNING: Please don't use this function - use its public interface in [ffi_util::translate_rust_vector_to_cpp].
84126 // 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 {
364406 let results = client. verify_model ( ) ;
365407 if let Ok ( el) = results {
366408 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+ }
371420 } else {
372421 Err ( "Unable to produce results from the verification engine" . to_string ( ) )
373422 }
374423 }
375424
376425 #[ 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 > {
378428 let binding = cprover_api:: new_api_session ( ) ;
379429 let client = match binding. as_ref ( ) {
380430 Some ( api_ref) => api_ref,
@@ -391,12 +441,47 @@ mod tests {
391441 return Err ( error_msg) ;
392442 }
393443
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+
394479 let results = client. verify_model ( ) ;
395480 if let Ok ( el) = results {
396481 let_cxx_string ! ( existing_property_id = "main.assertion.1" ) ;
397482 let prop_status = cprover_api:: get_property_status ( & el, & existing_property_id) ;
398483 match prop_status {
399- prop_statust:: FAIL => Ok ( ( ) ) ,
484+ Ok ( prop_statust:: FAIL ) => Ok ( ( ) ) ,
400485 _ => {
401486 let error_msg = format ! (
402487 "Property status for property {:?} was {:?} - expected FAIL" ,
@@ -409,4 +494,40 @@ mod tests {
409494 Err ( "Unable to produce results from the verification engine" . to_string ( ) )
410495 }
411496 }
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+ }
412533}
0 commit comments