From b856536a0f01f9837ab1c61f391fdff76294721e Mon Sep 17 00:00:00 2001 From: Valentin Perrelle <valentin.perrelle@cea.fr> Date: Tue, 19 Feb 2019 16:13:57 +0100 Subject: [PATCH] [Dive] Very basic testing --- src/plugins/dive/main.ml | 11 +++-- src/plugins/dive/self.ml | 46 +++++++++++-------- src/plugins/dive/self.mli | 1 + src/plugins/dive/tests/dive/assigned_param.i | 18 ++++++++ src/plugins/dive/tests/dive/const.i | 16 +++++++ .../dive/tests/dive/oracle/assigned_param.dot | 23 ++++++++++ .../dive/oracle/assigned_param.res.oracle | 8 ++++ src/plugins/dive/tests/dive/oracle/const.dot | 28 +++++++++++ .../dive/tests/dive/oracle/const.res.oracle | 16 +++++++ .../dive/tests/dive/oracle/various.dot | 40 ++++++++++++++++ .../dive/tests/dive/oracle/various.res.oracle | 12 +++++ src/plugins/dive/tests/dive/various.i | 28 +++++++++++ src/plugins/dive/tests/test_config | 2 + 13 files changed, 227 insertions(+), 22 deletions(-) create mode 100644 src/plugins/dive/tests/dive/assigned_param.i create mode 100644 src/plugins/dive/tests/dive/const.i create mode 100644 src/plugins/dive/tests/dive/oracle/assigned_param.dot create mode 100644 src/plugins/dive/tests/dive/oracle/assigned_param.res.oracle create mode 100644 src/plugins/dive/tests/dive/oracle/const.dot create mode 100644 src/plugins/dive/tests/dive/oracle/const.res.oracle create mode 100644 src/plugins/dive/tests/dive/oracle/various.dot create mode 100644 src/plugins/dive/tests/dive/oracle/various.res.oracle create mode 100644 src/plugins/dive/tests/dive/various.i create mode 100644 src/plugins/dive/tests/test_config diff --git a/src/plugins/dive/main.ml b/src/plugins/dive/main.ml index e7f7f3ffa0b..51c905e88ab 100644 --- a/src/plugins/dive/main.ml +++ b/src/plugins/dive/main.ml @@ -31,9 +31,14 @@ let main () = let depth_limit = Self.DepthLimit.get () in Self.FromBases.iter (Build.add_var ~depth_limit context); (* Output it *) - let out_channel = open_out "imprecisions.dot" in - Imprecision_graph.ouptput_to_dot out_channel (Build.get_graph context); - close_out out_channel + let output_basename = Self.OutputBasename.get () in + if output_basename <> "" then begin + let filename = output_basename ^ ".dot" in + Self.result "output to %s" filename; + let out_channel = open_out filename in + Imprecision_graph.ouptput_to_dot out_channel (Build.get_graph context); + close_out out_channel + end; end let () = diff --git a/src/plugins/dive/self.ml b/src/plugins/dive/self.ml index 60d794eff33..09a9616fd6b 100644 --- a/src/plugins/dive/self.ml +++ b/src/plugins/dive/self.ml @@ -29,12 +29,19 @@ include Plugin.Register let help = "An interactive imprecision graph generator." end) +module OutputBasename = Empty_string + (struct + let option_name = "-dive-output" + let help = "Outputs the built graph into a file with this basename." + let arg_name = "basename" + end) + module DepthLimit = Int (struct - let default = 5 let option_name = "-dive-depth-limit" let help = "Build dependencies up to a depth of N." let arg_name = "N" + let default = 3 end) module FromAlarms = True @@ -49,26 +56,27 @@ struct let of_string s = let regexp = Str.regexp "^\\([_a-zA-Z0-9]+\\)::\\([_a-zA-Z0-9]+\\)$" in - let name, localisation, error_suffix = - if Str.string_match regexp s 0 then - let function_name = Str.matched_group 1 s - and variable_name = Str.matched_group 2 s in - try - let kf = Globals.Functions.find_by_name function_name in - variable_name, VLocal kf, " in function " ^ function_name + if Str.string_match regexp s 0 then + let function_name = Str.matched_group 1 s + and variable_name = Str.matched_group 2 s in + let kf = try Globals.Functions.find_by_name function_name with Not_found -> raise (Cannot_build ("no function '" ^ function_name ^ "'")) - else - let regexp = Str.regexp "^[_a-zA-Z0-9]+$" in - if Str.string_match regexp s 0 then - s, VGlobal, "" - else - raise (Cannot_build ("wrong syntax: '" ^ s ^ "'")) - in - try - Globals.Vars.find_from_astinfo name localisation - with Not_found -> - raise (Cannot_build ("no variable '" ^ name ^ "'" ^ error_suffix)) + in + try Globals.Vars.find_from_astinfo variable_name (VLocal kf) + with Not_found -> + try Globals.Vars.find_from_astinfo variable_name (VFormal kf) + with Not_found -> + raise (Cannot_build ("no variable '" ^ name ^ "' in function" + ^ function_name)) + else + let regexp = Str.regexp "^[_a-zA-Z0-9]+$" in + if not (Str.string_match regexp s 0) then + raise (Cannot_build ("wrong syntax: '" ^ s ^ "'")); + try + Globals.Vars.find_from_astinfo name VGlobal + with Not_found -> + raise (Cannot_build ("no global variable '" ^ name ^ "'")) let to_string vi = match Kernel_function.find_defining_kf vi with diff --git a/src/plugins/dive/self.mli b/src/plugins/dive/self.mli index f56de61ab58..8d9f9f8b0ec 100644 --- a/src/plugins/dive/self.mli +++ b/src/plugins/dive/self.mli @@ -26,6 +26,7 @@ module type Varinfo_set = Parameter_sig.Set with type elt = Cil_types.varinfo and type t = Cil_datatype.Varinfo.Set.t +module OutputBasename : Parameter_sig.String module DepthLimit : Parameter_sig.Int module FromAlarms : Parameter_sig.Bool module FromBases : Varinfo_set diff --git a/src/plugins/dive/tests/dive/assigned_param.i b/src/plugins/dive/tests/dive/assigned_param.i new file mode 100644 index 00000000000..322aa200478 --- /dev/null +++ b/src/plugins/dive/tests/dive/assigned_param.i @@ -0,0 +1,18 @@ +/* run.config +STDOPT: +"-dive-from main::w" +*/ + +volatile int nondet; + +int f(int x, int z) +{ + if (nondet) + x = z; + return x; +} + +int main(int x, int z) +{ + int w = f(x,z); + return w + 1; +} diff --git a/src/plugins/dive/tests/dive/const.i b/src/plugins/dive/tests/dive/const.i new file mode 100644 index 00000000000..adc5365c8c6 --- /dev/null +++ b/src/plugins/dive/tests/dive/const.i @@ -0,0 +1,16 @@ +/* run.config +STDOPT: +"-dive-from main::res" +*/ + +int f(int x, int y) +{ + const c = x + 1; + int w = y + 1; + return c + w; +} + +int main(int i) +{ + int res = f(i, 2*i); + return res; +} \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/assigned_param.dot b/src/plugins/dive/tests/dive/oracle/assigned_param.dot new file mode 100644 index 00000000000..460be6d9d72 --- /dev/null +++ b/src/plugins/dive/tests/dive/oracle/assigned_param.dot @@ -0,0 +1,23 @@ +digraph G { + cp0 [fillcolor="#AACCFF", color="#88AAFF", style="invis,filled,dotted", ]; + cp1 [label=<w>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp2 [label=<x>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp3 [label=<z>, shape=box, ]; + cp4 [label=<x>, shape=box, ]; + cp5 [label=<z>, shape=box, style="dotted", ]; + + subgraph cluster_file_1 { label=<tests/dive/assigned_param.i>; cp0; + subgraph cluster_function_19 { label=<f>; cp3;cp2; + }; + subgraph cluster_function_24 { label=<main>; cp5;cp4;cp1; + }; + }; + + cp2 -> cp1; + cp3 -> cp2; + cp4 -> cp2; + cp5 -> cp3; + + } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/assigned_param.res.oracle b/src/plugins/dive/tests/dive/oracle/assigned_param.res.oracle new file mode 100644 index 00000000000..01978d95470 --- /dev/null +++ b/src/plugins/dive/tests/dive/oracle/assigned_param.res.oracle @@ -0,0 +1,8 @@ +[kernel] Parsing tests/dive/assigned_param.i (no preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:alarm] tests/dive/assigned_param.i:18: Warning: + signed overflow. assert w + 1 ≤ 2147483647; +[eva] done for function main +[dive] output to tests/dive/result/assigned_param.dot diff --git a/src/plugins/dive/tests/dive/oracle/const.dot b/src/plugins/dive/tests/dive/oracle/const.dot new file mode 100644 index 00000000000..cce0e10e5aa --- /dev/null +++ b/src/plugins/dive/tests/dive/oracle/const.dot @@ -0,0 +1,28 @@ +digraph G { + cp0 [fillcolor="#AACCFF", color="#88AAFF", style="invis,filled,dotted", ]; + cp1 [label=<res>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp2 [fillcolor="#AACCFF", color="#88AAFF", style="invis,filled,dotted", ]; + cp3 [label=<__retres>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp4 [label=<c>, shape=box, ]; + cp5 [label=<w>, shape=box, ]; + cp6 [label=<x>, shape=box, style="dotted", ]; + cp7 [label=<y>, shape=box, style="dotted", ]; + + subgraph cluster_file_1 { label=<tests/dive/const.i>; cp0; + subgraph cluster_function_25 { label=<main>; cp1; + }; + }; + subgraph cluster_file_2 { label=<>; cp2; + subgraph cluster_function_18 { label=<f>; cp7;cp6;cp5;cp4;cp3; + }; + }; + + cp3 -> cp1; + cp4 -> cp3; + cp5 -> cp3; + cp6 -> cp4; + cp7 -> cp5; + + } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/const.res.oracle b/src/plugins/dive/tests/dive/oracle/const.res.oracle new file mode 100644 index 00000000000..7b0b9060658 --- /dev/null +++ b/src/plugins/dive/tests/dive/oracle/const.res.oracle @@ -0,0 +1,16 @@ +[kernel] Parsing tests/dive/const.i (no preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:alarm] tests/dive/const.i:14: Warning: + signed overflow. assert -2147483648 ≤ 2 * i; +[eva:alarm] tests/dive/const.i:14: Warning: + signed overflow. assert 2 * i ≤ 2147483647; +[eva:alarm] tests/dive/const.i:7: Warning: + signed overflow. assert x + 1 ≤ 2147483647; +[eva:alarm] tests/dive/const.i:9: Warning: + signed overflow. assert -2147483648 ≤ c + w; +[eva:alarm] tests/dive/const.i:9: Warning: + signed overflow. assert c + w ≤ 2147483647; +[eva] done for function main +[dive] output to tests/dive/result/const.dot diff --git a/src/plugins/dive/tests/dive/oracle/various.dot b/src/plugins/dive/tests/dive/oracle/various.dot new file mode 100644 index 00000000000..e9d2bb149ea --- /dev/null +++ b/src/plugins/dive/tests/dive/oracle/various.dot @@ -0,0 +1,40 @@ +digraph G { + cp0 [fillcolor="#AACCFF", color="#88AAFF", style="invis,filled,dotted", ]; + cp1 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + style="filled", ]; + cp2 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + style="filled", ]; + cp3 [label=<x>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp4 [label=<g>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp5 [label=<z>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; + cp6 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + style="filled", ]; + cp7 [label=<w>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + style="filled", ]; + cp8 [label=<tmp_0>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + style="filled", ]; + cp9 [label=<pf>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled,dotted", ]; + + subgraph cluster_file_1 { label=<tests/dive/various.i>; cp4;cp0; + subgraph cluster_function_19 { label=<f>; cp2;cp1; + }; + subgraph cluster_function_24 { label=<main>; cp9;cp8;cp7;cp6;cp5;cp3; + }; + }; + + cp1 -> cp2; + cp1 -> cp6; + cp1 -> cp8; + cp2 -> cp1; + cp3 -> cp1; + cp4 -> cp3; + cp6 -> cp5; + cp7 -> cp5; + cp8 -> cp7; + cp9 -> cp8 [color="#00FF00", ]; + + } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/various.res.oracle b/src/plugins/dive/tests/dive/oracle/various.res.oracle new file mode 100644 index 00000000000..fc941299b06 --- /dev/null +++ b/src/plugins/dive/tests/dive/oracle/various.res.oracle @@ -0,0 +1,12 @@ +[kernel] Parsing tests/dive/various.i (no preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva] tests/dive/various.i:10: starting to merge loop iterations +[eva:alarm] tests/dive/various.i:13: Warning: + non-finite float value. + assert \is_finite((float)((double)((double)y * 2.0))); +[eva:alarm] tests/dive/various.i:26: Warning: + non-finite float value. assert \is_finite((float)(y + w)); +[eva] done for function main +[dive] output to tests/dive/result/various.dot diff --git a/src/plugins/dive/tests/dive/various.i b/src/plugins/dive/tests/dive/various.i new file mode 100644 index 00000000000..84c0f7788f7 --- /dev/null +++ b/src/plugins/dive/tests/dive/various.i @@ -0,0 +1,28 @@ +/* run.config +STDOPT: +"-dive-from main::z,f::x2" +*/ + +float g; + +float f(float x2) +{ + float y; + for (int i = 0 ; i < 10 ; i++) + { + y = x2 + 1.0; + x2 = y * 2.0; + } + + return x2; +} + +void main() +{ + float (*pf)(float) = &f; + + float x = 3.0 + g; + float y = f(x); + float w = (*pf)(x); + float z = y + w + 1.0; +} + diff --git a/src/plugins/dive/tests/test_config b/src/plugins/dive/tests/test_config new file mode 100644 index 00000000000..2baab62a7d7 --- /dev/null +++ b/src/plugins/dive/tests/test_config @@ -0,0 +1,2 @@ +LOG: @PTEST_NAME@.dot +OPT: -no-autoload-plugins -load-module from,inout,eva,variadic,scope,dive -check -eva-msg-key=-initial-state -eva-no-show-progress -dive-output @PTEST_RESULT@/@PTEST_NAME@ -- GitLab