From c20bbd8ff28c917a43ecfea2b4b8079270ab3677 Mon Sep 17 00:00:00 2001
From: Virgile Prevosto <virgile.prevosto@m4x.org>
Date: Fri, 22 Jan 2021 19:41:20 +0100
Subject: [PATCH] [aorai] add smoke tests asserting that there's always an
 active state

---
 src/plugins/aorai/aorai_option.ml             |   8 ++
 src/plugins/aorai/aorai_option.mli            |   7 ++
 src/plugins/aorai/aorai_utils.ml              |  27 ++++-
 .../aorai/tests/ya/oracle/serial.res.oracle   | 101 +++++++++---------
 src/plugins/aorai/tests/ya/serial.c           |   4 +-
 5 files changed, 91 insertions(+), 56 deletions(-)

diff --git a/src/plugins/aorai/aorai_option.ml b/src/plugins/aorai/aorai_option.ml
index 307652ff225..90946d86242 100644
--- a/src/plugins/aorai/aorai_option.ml
+++ b/src/plugins/aorai/aorai_option.ml
@@ -150,6 +150,14 @@ module Deterministic=
       let default () = false
     end)
 
+module SmokeTests=
+  False
+    (struct
+      let option_name = "-aorai-smoke-tests"
+      let help = "Add assertion in the generated functions to ensure \
+                  that the automaton is always in at least one state"
+    end)
+
 module InstrumentationHistory =
   Int
     (struct
diff --git a/src/plugins/aorai/aorai_option.mli b/src/plugins/aorai/aorai_option.mli
index 633950adb90..b6b220f0fe3 100644
--- a/src/plugins/aorai/aorai_option.mli
+++ b/src/plugins/aorai/aorai_option.mli
@@ -39,6 +39,13 @@ module ConsiderAcceptance: Parameter_sig.Bool
 module AutomataSimplification: Parameter_sig.Bool
 module AddingOperationNameAndStatusInSpecification: Parameter_sig.Bool
 
+(** if [true], adds assertion at the end of the generated function
+    to check that the automaton is not in the rejecting state (in
+    the deterministic case), or that at least one non-rejecting state
+    is active (in the non-deterministic state).
+*)
+module SmokeTests: Parameter_sig.Bool
+
 (** [true] if the user declares that its ya automaton is deterministic. *)
 module Deterministic: State_builder.Ref with type data = bool
 
diff --git a/src/plugins/aorai/aorai_utils.ml b/src/plugins/aorai/aorai_utils.ml
index d2691257484..dd533767fdd 100644
--- a/src/plugins/aorai/aorai_utils.ml
+++ b/src/plugins/aorai/aorai_utils.ml
@@ -874,6 +874,24 @@ let is_out_of_state_exp state loc =
       (Cil.evar (Data_for_aorai.get_state_var state))
       (mk_int_exp 0)
 
+let assert_alive_automaton kf stmt =
+  let pred =
+    if Aorai_option.Deterministic.get() then
+      let reject_state = Data_for_aorai.get_reject_state() in
+      is_out_of_state_pred reject_state
+    else begin
+      let valid_states =
+        List.filter
+          (fun x -> not (Data_for_aorai.is_reject_state x))
+          (fst (Data_for_aorai.getGraph ()))
+      in
+      let valid_preds = List.map is_state_pred valid_states in
+      Logic_const.pors valid_preds
+    end
+  in
+  let pred = { pred with pred_name = "aorai_smoke_test" :: pred.pred_name } in
+  Annotations.add_assert Aorai_option.emitter ~kf stmt pred
+
 (* Utilities for other globals *)
 
 let mk_global_comment txt = add_global (GText (txt))
@@ -2126,10 +2144,15 @@ let auto_func_block generated_kf loc f st status res =
     else
       mk_non_deterministic_body generated_kf loc f st status res
   in
-  let ret = [ Cil.mkStmt ~ghost:true (Cil_types.Return(None,loc)) ] in
+  let ret =
+    Cil.mkStmt ~ghost:true ~valid_sid:true (Cil_types.Return(None,loc))
+  in
+  if Aorai_option.SmokeTests.get () then begin
+    assert_alive_automaton generated_kf ret;
+  end;
   let res_block =
     (Cil.mkBlock
-       ( stmt_begin_list @ stmt_history_update @ main_stmt @ ret))
+       ( stmt_begin_list @ stmt_history_update @ main_stmt @ [ret]))
   in
   res_block.blocals <- local_var;
   Aorai_option.debug ~dkey "Generated body is:@\n%a"
diff --git a/src/plugins/aorai/tests/ya/oracle/serial.res.oracle b/src/plugins/aorai/tests/ya/oracle/serial.res.oracle
index 2692e58379b..dbf366abac3 100644
--- a/src/plugins/aorai/tests/ya/oracle/serial.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/serial.res.oracle
@@ -21,33 +21,20 @@
 [eva] tests/ya/serial.c:58: starting to merge loop iterations
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 100 states
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 300 states
-[aorai] tests/ya/serial.c:92: aorai_reject <- aorai_reject <- Complete
-[aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [8192..16383]
-[aorai] tests/ya/serial.c:92: aorai_reject <- Error <- Complete
-[aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [8192..16383]
+[eva:alarm] tests/ya/serial.c:33: Warning: 
+  assertion 'Aorai,aorai_smoke_test' got status invalid (stopping propagation).
 [aorai] tests/ya/serial.c:92: Wait1 <- Wait1 <- Complete
 [aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [8192..16383]
-[aorai] tests/ya/serial.c:92: aorai_reject <- aorai_reject <- Complete
-[aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [0..8191]
-[aorai] tests/ya/serial.c:92: aorai_reject <- Error <- Complete
-[aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [0..8191]
 [aorai] tests/ya/serial.c:92: Wait1 <- Wait1 <- Complete
 [aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [0..8191]
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 500 states
-[eva:alarm] tests/ya/serial.c:65: Warning: 
-  accessing uninitialized left-value. assert \initialized(&status);
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 700 states
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 900 states
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 1200 states
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 1400 states
-[aorai] tests/ya/serial.c:92: aorai_reject <- aorai_reject <- aorai_reject
-[aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [8192..16383]
-[aorai] tests/ya/serial.c:92: aorai_reject <- aorai_reject <- aorai_reject
-[aorai] tests/ya/serial.c:92: n in {5},x in [0..16383],y in [0..8191]
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 1500 states
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 1600 states
 [eva] tests/ya/serial.c:63: Trace partitioning superposing up to 1700 states
-[eva] tests/ya/serial.c:63: Trace partitioning superposing up to 1800 states
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function input_data_post_func:
@@ -84,15 +71,15 @@
   aorai_y2 ∈ [0..2147483647]
   aorai_CurOperation ∈ {2}
   aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 24}
-  aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13; 24}
+  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6}
+  aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13}
 [eva:final-states] Values at end of function input_data_pre_func:
   aorai_CurOperation ∈ {2}
   aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {1; 2; 3; 4; 5; 6; 24}
-  aorai_StatesHistory_1 ∈ {8; 9; 10; 11; 12; 13; 24}
-  aorai_StatesHistory_2 ∈ {14; 15; 16; 17; 18; 24}
+  aorai_CurStates ∈ {1; 2; 3; 4; 5; 6}
+  aorai_StatesHistory_1 ∈ {8; 9; 10; 11; 12; 13}
+  aorai_StatesHistory_2 ∈ {14; 15; 16; 17; 18}
 [eva:final-states] Values at end of function input_data:
   Frama_C_entropy_source ∈ [--..--]
   aorai_x1 ∈
@@ -128,46 +115,46 @@
   aorai_y2 ∈ [0..2147483647]
   aorai_CurOperation ∈ {2}
   aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 24}
-  aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13; 24}
+  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6}
+  aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13}
 [eva:final-states] Values at end of function input_status_post_func:
   aorai_CurOperation ∈ {1}
   aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18; 24}
-  aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23; 24}
+  aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18}
+  aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23}
 [eva:final-states] Values at end of function input_status_pre_func:
   aorai_CurOperation ∈ {1}
   aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {14; 15; 16; 17; 18; 24}
-  aorai_StatesHistory_1 ∈ {0; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_2 ∈ {1; 2; 3; 4; 5; 6; 7; 14; 15; 16; 17; 18; 19; 24}
+  aorai_CurStates ∈ {14; 15; 16; 17; 18}
+  aorai_StatesHistory_1 ∈ {0; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_2 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 19}
 [eva:final-states] Values at end of function input_status:
   Frama_C_entropy_source ∈ [--..--]
   aorai_CurOperation ∈ {1}
   aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18; 24}
-  aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23; 24}
+  aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18}
+  aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23}
 [eva:final-states] Values at end of function output_post_func:
   aorai_CurOperation ∈ {0}
   aorai_CurOpStatus ∈ {1}
   aorai_CurStates ∈ {19; 24}
-  aorai_StatesHistory_1 ∈ {7; 19; 24}
-  aorai_StatesHistory_2 ∈ {0; 24}
+  aorai_StatesHistory_1 ∈ {7; 19}
+  aorai_StatesHistory_2 ∈ {0}
 [eva:final-states] Values at end of function output_pre_func:
   aorai_CurOperation ∈ {0}
   aorai_CurOpStatus ∈ {0}
   aorai_CurStates ∈ {7; 19; 24}
-  aorai_StatesHistory_1 ∈ {0; 24}
-  aorai_StatesHistory_2 ∈ {5; 24}
+  aorai_StatesHistory_1 ∈ {0}
+  aorai_StatesHistory_2 ∈ {5}
 [eva:final-states] Values at end of function output:
   aorai_CurOperation ∈ {0}
   aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {19; 24}
-  aorai_StatesHistory_1 ∈ {7; 19; 24}
-  aorai_StatesHistory_2 ∈ {0; 24}
+  aorai_CurStates ∈ {19}
+  aorai_StatesHistory_1 ∈ {19}
+  aorai_StatesHistory_2 ∈ {0}
 [eva:final-states] Values at end of function read:
   Frama_C_entropy_source ∈ [--..--]
   s ∈
@@ -223,9 +210,9 @@
   aorai_y2 ∈ [0..2147483647]
   aorai_CurOperation ∈ {1; 2}
   aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 24}
-  aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23; 24}
+  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18}
+  aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
 [eva:final-states] Values at end of function main:
   Frama_C_entropy_source ∈ [--..--]
   buffer[0] ∈
@@ -283,25 +270,24 @@
   aorai_y2 ∈ [0..2147483647]
   aorai_CurOperation ∈ {0; 1; 2}
   aorai_CurOpStatus ∈ {0; 1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23; 24}
-  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 7; 14; 15; 16; 17; 18; 19; 24}
-  aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23; 24}
+  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
+  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 19}
+  aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
 [eva:summary] ====== ANALYSIS SUMMARY ======
   ----------------------------------------------------------------------------
   11 functions analyzed (out of 11): 100% coverage.
-  In these functions, 222 statements reached (out of 261): 85% coverage.
+  In these functions, 206 statements reached (out of 261): 78% coverage.
   ----------------------------------------------------------------------------
   Some errors and warnings have been raised during the analysis:
     by the Eva analyzer:      0 errors    0 warnings
     by the Frama-C kernel:    0 errors    1 warning
   ----------------------------------------------------------------------------
-  1 alarm generated by the analysis:
-       1 access to uninitialized left-values
+  0 alarms generated by the analysis.
   ----------------------------------------------------------------------------
   Evaluation of the logical properties reached by the analysis:
-    Assertions        0 valid     0 unknown     0 invalid      0 total
+    Assertions        4 valid     2 unknown     0 invalid      6 total
     Preconditions     2 valid     0 unknown     0 invalid      2 total
-  100% of the logical properties reached have been proven.
+  75% of the logical properties reached have been proven.
   ----------------------------------------------------------------------------
 [kernel] Parsing TMPDIR/aorai_serial_0.i (no preprocessing)
 /* Generated by Frama-C */
@@ -575,6 +561,8 @@ int n = 0;
                         else 
                           if (13 == aorai_CurStates) aorai_CurStates = StatusReq5;
                           else aorai_CurStates = aorai_reject;
+    /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
+    ;
     return;
   }
 
@@ -628,6 +616,8 @@ int n = 0;
                                 if (18 == aorai_CurStates && (res & 1) == 0) 
                                   aorai_CurStates = Wait5;
                                 else aorai_CurStates = aorai_reject;
+    /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
+    ;
     return;
   }
 
@@ -677,6 +667,8 @@ int input_status(void)
                       else 
                         if (19 == aorai_CurStates) aorai_CurStates = Error;
                         else aorai_CurStates = aorai_reject;
+    /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
+    ;
     return;
   }
 
@@ -738,6 +730,8 @@ int input_status(void)
                                     aorai_y1 = res;
                                   }
                                   else aorai_CurStates = aorai_reject;
+    /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
+    ;
     return;
   }
 
@@ -799,6 +793,8 @@ int input_data(void)
                                                               128 * aorai_y2)) 
                               aorai_CurStates = Wait1;
                             else aorai_CurStates = aorai_reject;
+    /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
+    ;
     return;
   }
 
@@ -814,6 +810,8 @@ int input_data(void)
     aorai_StatesHistory_1 = aorai_CurStates;
     if (19 == aorai_CurStates) aorai_CurStates = Wait1;
     else aorai_CurStates = aorai_reject;
+    /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
+    ;
     return;
   }
 
@@ -851,7 +849,6 @@ void main(void)
     int data = read(& status);
     if (data != -1) {
       int tmp_0;
-      /*@ assert Eva: initialization: \initialized(&status); */ ;
       if (status != 0) {
         n = 0;
         continue;
diff --git a/src/plugins/aorai/tests/ya/serial.c b/src/plugins/aorai/tests/ya/serial.c
index 98795b7b3d5..9efe13a270b 100644
--- a/src/plugins/aorai/tests/ya/serial.c
+++ b/src/plugins/aorai/tests/ya/serial.c
@@ -1,8 +1,8 @@
 /* run.config
-  OPT: -aorai-automata @PTEST_DIR@/@PTEST_NAME@.ya -load-module tests/Aorai_test.cmxs -aorai-test-number @PTEST_NUMBER@ -aorai-no-acceptance -aorai-instrumentation-history 2 -aorai-no-generate-annotations -aorai-no-generate-deterministic-lemmas -then-last -eva -eva-partition-value n -eva-ilevel 256
+  OPT: -aorai-automata @PTEST_DIR@/@PTEST_NAME@.ya -load-module tests/Aorai_test.cmxs -aorai-smoke-tests -aorai-test-number @PTEST_NUMBER@ -aorai-no-acceptance -aorai-instrumentation-history 2 -aorai-no-generate-annotations -aorai-no-generate-deterministic-lemmas -then-last -eva -eva-partition-value n -eva-ilevel 256
 */
 /* run.config_prove
-OPT: -cpp-extra-args="-DFOR_WP" -aorai-automata @PTEST_DIR@/@PTEST_NAME@_wp.ya -load-module tests/Aorai_test.cmxs -aorai-test-number @PTEST_NUMBER@ -aorai-no-acceptance @PROVE_OPTIONS@
+OPT: -cpp-extra-args="-DFOR_WP" -aorai-automata @PTEST_DIR@/@PTEST_NAME@_wp.ya -load-module tests/Aorai_test.cmxs  -aorai-smoke-tests -aorai-test-number @PTEST_NUMBER@ -aorai-no-acceptance @PROVE_OPTIONS@
 */
 
 #include "__fc_builtin.h"
-- 
GitLab