Remove stale Autounit module

Reviewed By: sblackshear

Differential Revision: D3648331

fbshipit-source-id: 3c06b38
master
Josh Berdine 9 years ago committed by Facebook Github Bot 5
parent bed9b31c62
commit 3064caacdb

@ -1,658 +0,0 @@
(*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! Utils
(** Generate unit tests automatically from specs *)
module L = Logging
module F = Format
let (++) = IntLit.add
let (--) = IntLit.sub
module IdMap = Map.Make (Ident) (** maps from identifiers *)
(** Constraint solving module *)
module Constraint : sig
(** Collect constraints on [vars] from [pi], and return a satisfying instantiation *)
val solve_from_pure : Sil.atom list -> Ident.t list -> IntLit.t IdMap.t
end = struct
(** flag for debug mode of the module *)
let debug = false
(** denote a range of values [bottom] <= val <= [top], except [excluded] *)
type range =
{ mutable bottom: IntLit.t option; (** lower bound *)
mutable excluded: IntLit.t list; (** individual values not in range *)
mutable top: IntLit.t option; (** upper bound *) }
type eval = range IdMap.t (** evaluation for variables *)
(** create a new range *)
let new_range () =
{ bottom = None; excluded = []; top = None }
(** pretty print a range *)
let pp_range id fmt rng =
let pp_opt fmt = function
| None -> F.fprintf fmt "_"
| Some n -> IntLit.pp fmt n in
F.fprintf fmt "%a <= %a <= %a [%a]"
pp_opt rng.bottom (Ident.pp pe_text) id pp_opt rng.top (pp_comma_seq IntLit.pp) rng.excluded
(** pretty print an evaluation *)
let pp_eval fmt ev =
let do_id id rng =
F.fprintf fmt "%a@." (pp_range id) rng in
IdMap.iter do_id ev
(** create a new evaluation *)
let new_eval vars : eval =
let ev = ref IdMap.empty in
let add_var id =
ev := IdMap.add id (new_range ()) !ev in
IList.iter add_var vars;
!ev
let gt_bottom i r =
match r.bottom with
| None -> true
| Some j -> IntLit.gt i j
let geq_bottom i r =
match r.bottom with
| None -> true
| Some j -> IntLit.geq i j
let lt_top i r =
match r.top with
| None -> true
| Some j -> IntLit.lt i j
let leq_top i r =
match r.top with
| None -> true
| Some j -> IntLit.leq i j
(** normalize [r]: the excluded elements must be strictly between bottom and top *)
let normalize r =
r.excluded <- IList.filter (fun i -> geq_bottom i r && leq_top i r) r.excluded;
let rec normalize_bottom () = match r.bottom with
| None -> ()
| Some i ->
if IList.mem IntLit.eq i r.excluded then begin
r.excluded <- IList.filter (IntLit.neq i) r.excluded;
r.bottom <- Some (i ++ IntLit.one);
normalize_bottom ()
end in
let rec normalize_top () = match r.top with
| None -> ()
| Some i ->
if IList.mem IntLit.eq i r.excluded then begin
r.excluded <- IList.filter (IntLit.neq i) r.excluded;
r.top <- Some (i -- IntLit.one);
normalize_top ()
end in
normalize_bottom ();
normalize_top ()
(** global variable set to true every time a range is changed *)
let changed = ref false
let mark_changed id r =
changed := true;
if debug then F.fprintf F.std_formatter "changed: %a@." (pp_range id) r
(** exclude one element from the range *)
let add_excluded r id i =
if geq_bottom i r && leq_top i r && not (IList.mem IntLit.eq i r.excluded)
then begin
r.excluded <- i :: r.excluded;
normalize r;
mark_changed id r;
end
(** make the bottom of the range >= [i] *)
let add_bottom r id i =
if gt_bottom i r then
begin
r.bottom <- Some i;
normalize r;
mark_changed id r
end
(** make the top of the range <= [i] *)
let add_top r id i =
if lt_top i r then
begin
r.top <- Some i;
normalize r;
mark_changed id r
end
(** choose an element in the range *)
let choose id rng =
if debug then F.fprintf F.std_formatter "choosing %a@." (pp_range id) rng;
let found = ref None in
let num_iter = IList.length rng.excluded in
let try_candidate candidate =
if geq_bottom candidate rng
&& leq_top candidate rng
&& not (IList.mem IntLit.eq candidate rng.excluded)
then (
found := Some candidate;
rng.bottom <- Some candidate;
rng.top <- Some candidate;
rng.excluded <- []
) in
let search_up () =
let base = match rng.bottom with None -> IntLit.zero | Some n -> n in
for i = 0 to num_iter do
if !found = None then
let candidate = IntLit.add base (IntLit.of_int i) in
try_candidate candidate
done in
let search_down () =
let base = match rng.top with None -> IntLit.zero | Some n -> n in
for i = 0 to num_iter do
if !found = None then
let candidate = IntLit.sub base (IntLit.of_int i) in
try_candidate candidate
done in
search_up ();
if !found = None then search_down ();
if !found = None then
(L.err "Constraint Error: empty range %a@." (pp_range id) rng;
rng.top <- Some IntLit.zero;
rng.bottom <- Some IntLit.zero;
rng.excluded <- [])
(** return the solution if the id is solved (has unique solution) *)
let solved ev id =
let rng = IdMap.find id ev in
match rng.bottom, rng.top with
| Some n1, Some n2 when IntLit.eq n1 n2 -> Some n1
| _ -> None
let rec pi_iter do_le do_lt do_neq pi =
let do_atom a = match a with
| Sil.Aeq (Sil.BinOp (Binop.Le, e1, e2), Sil.Const (Const.Cint i)) when IntLit.isone i ->
do_le e1 e2
| Sil.Aeq (Sil.BinOp (Binop.Lt, e1, e2), Sil.Const (Const.Cint i)) when IntLit.isone i ->
do_lt e1 e2
| Sil.Aeq _ -> ()
| Sil.Aneq (e1, e2) ->
do_neq e1 e2 in
changed := false;
IList.iter do_atom pi;
if !changed then pi_iter do_le do_lt do_neq pi
(** Collect constraints on [vars] from [pi], and return a satisfying instantiation *)
let solve_from_pure pi vars =
if debug then F.fprintf F.std_formatter "solve_from_pure pi: %a@." (Prop.pp_pi pe_text) pi;
let vars_fav = Sil.fav_from_list vars in
let atom_is_relevant a =
let fav = Sil.atom_fav a in
Sil.fav_for_all fav (fun id -> Sil.fav_mem vars_fav id) in
let pi_relevant = IList.filter atom_is_relevant pi in
let ev = new_eval vars in
let update_top rng id n_op = match rng.top, n_op with
| Some _, Some n -> add_top rng id n
| _ -> () in
let update_bottom rng id n_op = match rng.bottom, n_op with
| Some _, Some n -> add_bottom rng id n
| _ -> () in
let (+++) n1_op n2_op = match n1_op, n2_op with
| Some n1, Some n2 -> Some (IntLit.add n1 n2)
| _ -> None in
let (---) n1_op n2_op = match n1_op, n2_op with
| Some n1, Some n2 -> Some (IntLit.sub n1 n2)
| _ -> None in
let do_le e1 e2 = match e1, e2 with
| Sil.Var id, Sil.Const (Const.Cint n) ->
let rng = IdMap.find id ev in
add_top rng id n
| Sil.BinOp (Binop.MinusA, Sil.Var id1, Sil.Var id2), Sil.Const (Const.Cint n) ->
let rng1 = IdMap.find id1 ev in
let rng2 = IdMap.find id2 ev in
update_top rng1 id1 (rng2.top +++ (Some n));
update_bottom rng2 id2 (rng1.bottom --- (Some n))
| Sil.BinOp (Binop.PlusA, Sil.Var id1, Sil.Var id2), Sil.Const (Const.Cint n) ->
let rng1 = IdMap.find id1 ev in
let rng2 = IdMap.find id2 ev in
update_top rng1 id1 (Some n --- rng2.bottom);
update_top rng2 id2 (Some n --- rng1.bottom)
| _ -> if debug then assert false in
let do_lt e1 e2 = match e1, e2 with
| Sil.Const (Const.Cint n), Sil.Var id ->
let rng = IdMap.find id ev in
add_bottom rng id (n ++ IntLit.one)
| Sil.Const (Const.Cint n), Sil.BinOp (Binop.PlusA, Sil.Var id1, Sil.Var id2) ->
let rng1 = IdMap.find id1 ev in
let rng2 = IdMap.find id2 ev in
update_bottom rng1 id1 (Some (n ++ IntLit.one) --- rng2.top);
update_bottom rng2 id2 (Some (n ++ IntLit.one) --- rng1.top)
| _ -> if debug then assert false in
let rec do_neq e1 e2 = match e1, e2 with
| Sil.Var id, Sil.Const (Const.Cint n)
| Sil.Const(Const.Cint n), Sil.Var id ->
let rng = IdMap.find id ev in
add_excluded rng id n
| Sil.Var id1, Sil.Var id2 ->
(match solved ev id1, solved ev id2 with
| None, None -> ()
| Some _, Some _ -> ()
| Some n1, None ->
do_neq (Sil.exp_int n1) e2
| None, Some n2 ->
do_neq e1 (Sil.exp_int n2))
| Sil.Var id1, Sil.BinOp(Binop.PlusA, Sil.Var id2, Sil.Const (Const.Cint n)) ->
(match solved ev id1, solved ev id2 with
| None, None -> ()
| Some _, Some _ -> ()
| Some n1, None ->
do_neq (Sil.exp_int (n1 -- n)) (Sil.Var id2)
| None, Some n2 ->
do_neq (Sil.Var id1) (Sil.exp_int (n2 ++ n)))
| _ -> if debug then assert false in
let do_ident id =
if debug then F.fprintf F.std_formatter "constraints before doing %a:@.%a@." (Ident.pp pe_text) id pp_eval ev;
let rng = IdMap.find id ev in
pi_iter do_le do_lt do_neq pi_relevant;
choose id rng in
IList.iter do_ident vars;
if debug then F.fprintf F.std_formatter "solution to pure constraints:@.%a@." pp_eval ev;
let solution = IdMap.map (function { bottom = Some n } -> n | _ -> assert false) ev in
solution
end
type varinfo =
{ typ: Typ.t; (* type of the variable *)
alloc: bool (* whether the variable needs allocation (on lhs of |->, lists) *)
}
type idmap = varinfo IdMap.t (* map from identifier to varinfo *)
let extend_idmap id vinfo idmap =
let vinfo' =
try
let old_vinfo = IdMap.find id !idmap in
{ old_vinfo with alloc = old_vinfo.alloc || vinfo.alloc }
with Not_found -> vinfo in
idmap := IdMap.add id vinfo' !idmap
let pe = pe_text
(** Given a sigma, create an idmap *)
let create_idmap sigma : idmap =
let idmap = ref IdMap.empty in
let rec do_exp e typ = match e, typ with
| Sil.Const _, _ -> ()
| Sil.Var id, _ ->
extend_idmap id { typ = typ; alloc = false } idmap
| Sil.BinOp (Binop.PlusA, e1, e2), _ ->
do_exp e1 typ;
do_exp e2 typ
| Sil.BinOp (Binop.PlusPI, e1, e2), _ ->
do_exp e1 typ;
do_exp e2 (Typ.Tint Typ.IULong)
| Sil.Lfield (e1, _, _), _ ->
do_exp e1 typ
| Sil.Sizeof _, _ -> ()
| _ ->
L.err "Unmatched exp: %a : %a@." (Sil.pp_exp pe) e (Typ.pp_full pe) typ;
assert false in
let rec do_se se typ = match se, typ with
| Sil.Eexp (e, _), _ ->
do_exp e typ
| Sil.Estruct (fsel, _), Typ.Tstruct { Typ.instance_fields } ->
do_struct fsel instance_fields
| Sil.Earray (len, esel, _), Typ.Tarray (typ, _) ->
do_se (Sil.Eexp (len, Sil.inst_none)) (Typ.Tint Typ.IULong);
do_array esel typ
| _ ->
L.err "Unmatched sexp: %a : %a@." (Sil.pp_sexp pe) se (Typ.pp_full pe) typ;
assert false
and do_struct fsel ftal = match fsel, ftal with
| [], _ -> ()
| (f1, se) :: fsel', (f2, typ, _) :: ftl' when Ident.fieldname_equal f1 f2 ->
do_se se typ;
do_struct fsel' ftl'
| _ :: _, _ :: ftal' ->
do_struct fsel ftal'
| _:: _, [] -> assert false
and do_array esel typ = match esel with
| (e, se):: esel' ->
do_se (Sil.Eexp (e, Sil.inst_none)) (Typ.Tint Typ.IULong);
do_se se typ;
do_array esel' typ
| [] -> () in
let do_lhs_e e t = match e with
| Sil.Var id ->
extend_idmap id { typ = t; alloc = true } idmap
| _ -> () in
let do_hpred = function
| Sil.Hpointsto (e, se, Sil.Sizeof (typ, _, _)) ->
do_lhs_e e (Typ.Tptr (typ, Typ.Pk_pointer));
do_se se typ
| Sil.Hlseg (_, _, e, f, el) ->
do_lhs_e e (Typ.Tptr (Typ.Tvoid, Typ.Pk_pointer));
do_se (Sil.Eexp (f, Sil.inst_none)) (Typ.Tptr (Typ.Tvoid, Typ.Pk_pointer));
IList.iter (fun e -> do_se (Sil.Eexp (e, Sil.inst_none)) Typ.Tvoid) el
| hpred ->
L.err "do_hpred not implemented %a@." (Sil.pp_hpred pe) hpred in
IList.iter do_hpred sigma;
!idmap
module Code : sig
type t
val add_from_pp : t -> (Format.formatter -> unit -> unit) -> unit
val add_line : t -> string -> unit
val append : t -> t -> unit
val empty : unit -> t
val pp : F.formatter -> t -> unit
val set_indent : string -> unit
(* val to_list : t -> string list *)
end = struct
type t = string list ref
let indent = ref ""
let to_list code =
IList.rev !code
let pp fmt code =
let doit line = F.fprintf fmt "%s@\n" line in
IList.iter doit (to_list code);
F.fprintf fmt "@."
let empty () = ref []
let add_line code l =
code := (!indent ^ l) :: !code
let add_from_pp code pp =
add_line code (pp_to_string pp ())
let append code1 code2 =
code1 := !code2 @ !code1
let set_indent s =
indent := s
end
type code = Code.t
(** pretty print generated code *)
let pp_code = Code.pp
(** pretty print an ident in C *)
let pp_id_c fmt id =
let name = Ident.get_name id in
let stamp = Ident.get_stamp id in
let varname = Ident.name_to_string name in
F.fprintf fmt "%s%d" varname stamp
(** pretty print an expression in C *)
let rec pp_exp_c pe fmt = function
| Sil.Lfield (e, f, _) ->
F.fprintf fmt "&(%a->%a)" (pp_exp_c pe) e Ident.pp_fieldname f
| Sil.Var id ->
pp_id_c fmt id
| e ->
Sil.pp_exp pe fmt e
(** pretty print a type in C *)
let pp_typ_c pe typ =
let pp_nil _ () = () in
Typ.pp_decl pe pp_nil typ
(** Convert a pvar to a string by just extracting the name *)
let to_string pvar =
Mangled.to_string (Pvar.get_name pvar)
(** pretty print an expression list in C *)
let pp_exp_list_c pe f expl =
(pp_seq (pp_exp_c pe)) f expl
(** Name of the recusive function for a specific list para *)
let mk_lseg_name id proc_name spec_num =
"mk_lseg_" ^ string_of_int id ^ Procname.to_string proc_name ^ "_spec" ^ string_of_int spec_num
let mk_size_name id =
"_size_" ^ string_of_int id
let pp_texp_for_malloc fmt =
let rec handle_arr_len typ = match typ with
| Typ.Tvar _ | Typ.Tint _ | Typ.Tfloat _ | Typ.Tvoid | Typ.Tfun _ ->
typ
| Typ.Tptr (t, pk) ->
Typ.Tptr (handle_arr_len t, pk)
| Typ.Tstruct struct_typ ->
let instance_fields =
IList.map (fun (f, t, a) -> (f, handle_arr_len t, a)) struct_typ.Typ.instance_fields in
Typ.Tstruct { struct_typ with Typ.instance_fields }
| Typ.Tarray (t, e) ->
Typ.Tarray (handle_arr_len t, e) in
function
| Sil.Sizeof (typ, _, _) ->
let typ' = handle_arr_len typ in
F.fprintf fmt "sizeof(%a)" (pp_typ_c pe) typ'
| e -> pp_exp_c pe fmt e
(* generate code for sigma *)
let gen_sigma code proc_name spec_num env sigma =
let post_code = Code.empty () in
let rec do_strexp code' base need_deref = function
| Sil.Eexp (e, _) ->
let lhs = if need_deref then "(*"^base^")" else base in
let pp f () = F.fprintf f "%s = %a;" lhs (pp_exp_c pe) e in
Code.add_from_pp code' pp
| Sil.Estruct (fsel, _) ->
let accessor = if need_deref then "->" else "." in
IList.iter (fun (f, se) -> do_strexp code' (base ^ accessor ^ Ident.fieldname_to_string f) false se) fsel
| Sil.Earray (_, esel, _) ->
IList.iter (fun (e, se) ->
let pp f () = F.fprintf f "%a" (pp_exp_c pe) e in
let index = pp_to_string pp () in
do_strexp code' (base ^ "[" ^ index ^ "]") false se) esel in
let gen_hpred = function
| Sil.Hpointsto (Sil.Lvar pvar, se, _) ->
let base = to_string pvar in
do_strexp post_code base false se
| Sil.Hpointsto (Sil.Var id, se, te) ->
let pp1 f () =
F.fprintf f "%a = malloc(%a);" pp_id_c id pp_texp_for_malloc te in
let pp2 f () =
F.fprintf f "if(%a == NULL) exit(12);" pp_id_c id in
Code.add_from_pp code pp1;
Code.add_from_pp code pp2;
let pp3 f () = F.fprintf f "%a" pp_id_c id in
let base = pp_to_string pp3 () in
do_strexp post_code base true se
| Sil.Hlseg (_, hpar, Sil.Var id, f, el) ->
let hpara_id = Sil.Predicates.get_hpara_id env hpar in
let size_var = mk_size_name hpara_id in
let mk_name = mk_lseg_name hpara_id proc_name spec_num in
let pp_el fmt el =
if el != [] then pp_exp_list_c pe fmt el in
let pp1 fmt () =
F.fprintf fmt "int %s = 42;" size_var in
let pp2 fmt () =
F.fprintf fmt "%a = %s(%s, %a%a);" pp_id_c id mk_name size_var (pp_exp_c pe) f pp_el el in
Code.add_from_pp code pp1;
Code.add_from_pp code pp2
| hpred ->
L.err "gen_hpred not implemented: %a@." (Sil.pp_hpred pe) hpred in
IList.iter gen_hpred sigma;
Code.append code post_code
(* generate code corresponding to equalities in the pure part *)
let gen_init_equalities code pure =
let do_atom = function
| Sil.Aeq (Sil.Var id, e) ->
let pp f () = F.fprintf f "%a = %a;" pp_id_c id (pp_exp_c pe) e in
Code.add_from_pp code pp
| _ -> () in
IList.iter do_atom pure
(** generate variable declarations *)
let gen_var_decl code idmap parameters =
let do_parameter (name, typ) =
let pp_name f () = Mangled.pp f name in
let pp f () = F.fprintf f "%a;" (Typ.pp_decl pe pp_name) typ in
Code.add_from_pp code pp in
let do_vinfo id { typ } =
let pp_var f () = pp_id_c f id in
let pp f () = F.fprintf f "%a;" (Typ.pp_decl pe pp_var) typ in
Code.add_from_pp code pp in
IList.iter do_parameter parameters;
IdMap.iter do_vinfo idmap
(** initialize variables not requiring allocation *)
let gen_init_vars code solutions idmap =
let get_const id c =
try Const.Cint (IdMap.find id solutions)
with Not_found -> c in
let do_vinfo id { typ = typ; alloc = alloc } =
if not alloc then
let const = match typ with
| Typ.Tint _ | Typ.Tvoid ->
get_const id (Const.Cint IntLit.zero)
| Typ.Tfloat _ ->
Const.Cfloat 0.0
| Typ.Tptr _ ->
get_const id (Const.Cint IntLit.zero)
| Typ.Tfun _ ->
Const.Cint IntLit.zero
| typ ->
L.err "do_vinfo type undefined: %a@." (Typ.pp_full pe) typ;
assert false in
let pp fmt () =
F.fprintf fmt "%a = (%a) %a;"
pp_id_c id (Typ.pp_full pe) typ (Sil.pp_exp pe) (Sil.Const const) in
Code.add_from_pp code pp in
IdMap.iter do_vinfo idmap
(** apply a filter to the identifiers of an idmap *)
let filter_idmap filter idmap =
let idmap' = ref IdMap.empty in
IdMap.iter (fun id x -> if filter id then idmap' := IdMap.add id x !idmap') idmap;
!idmap'
let pp_svars fmt svars =
if svars != [] then F.fprintf fmt "%a" (pp_comma_seq pp_id_c) svars
let gen_hpara code proc_name spec_num env id hpara =
let mk_name = mk_lseg_name id proc_name spec_num in
let size_name = mk_size_name id in
let pp1 f () =
F.fprintf f "void* %s(int %s, void* %a%a) {"
mk_name size_name pp_id_c hpara.Sil.next pp_svars hpara.Sil.svars in
let pp2 f () =
F.fprintf f "%a= %s(%s -1 , %a%a);"
pp_id_c hpara.Sil.next mk_name size_name pp_id_c hpara.Sil.next pp_svars hpara.Sil.svars in
let line1 = pp_to_string pp1 () in
let idmap = create_idmap hpara.Sil.body in
let idmap_ex =
let filter i =
IList.exists (Ident.equal i) hpara.Sil.evars in
filter_idmap filter idmap in
let idmap_no_next =
let filter i =
not (Ident.equal i hpara.Sil.next) in
filter_idmap filter idmap in
let line11 = "if ("^size_name^" == 0) {" in
let line12 = "return " ^ (pp_to_string pp_id_c hpara.Sil.next) ^ ";" in
let line13 ="} else {" in
let line14 = pp_to_string pp2 () in
let line2 = "return " ^ (pp_to_string pp_id_c hpara.Sil.root) ^ ";" in
let line3 = "}" in
Code.add_line code line1;
Code.set_indent " ";
gen_var_decl code idmap_no_next [];
Code.add_line code line11;
Code.set_indent " ";
Code.add_line code line12;
Code.set_indent " ";
Code.add_line code line13;
Code.set_indent " ";
Code.add_line code line14;
gen_init_vars code IdMap.empty idmap_ex;
gen_sigma code proc_name spec_num env hpara.Sil.body;
Code.add_line code line2;
Code.set_indent " ";
Code.add_line code line3;
Code.set_indent "";
Code.add_line code line3;
Code.add_line code ""
let gen_hpara_dll _ _ _ _ _ _ = assert false
(** Generate epilog for the test case *)
let gen_epilog code proc_name (parameters : (Mangled.t * Typ.t) list) =
let pp_parameter fmt (name, _) = Mangled.pp fmt name in
let pp f () = F.fprintf f "%a(%a);" Procname.pp proc_name (pp_comma_seq pp_parameter) parameters in
let line1 = pp_to_string pp () in
let line2 = "}" in
Code.add_line code line1;
Code.set_indent "";
Code.add_line code line2
let test_function_name proc_name spec_num =
"unit_test_" ^ Procname.to_string proc_name ^ "_spec" ^ string_of_int spec_num
(** Generate prolog for test case *)
let gen_prolog code fname proc_name spec_num =
let pp f () =
let fun_name = test_function_name proc_name spec_num in
F.fprintf f "/**@\n *@\n * Procedure: %a()@\n * File: %s@\n" Procname.pp proc_name fname;
F.fprintf f " * Unit Test: %s()@\n * Created: %a@\n *@\n */@\n@\n" fun_name pp_current_time ();
F.fprintf f "void %s() {" fun_name in
Code.add_from_pp code pp;
Code.set_indent " "
let solve_constraints pure idmap =
let vars = ref [] in
let do_vinfo id { alloc } =
if not alloc then vars := !vars @ [id] in
IdMap.iter do_vinfo idmap;
Constraint.solve_from_pure pure !vars
(** generate a unit test form a spec *)
let genunit fname proc_name spec_num parameters spec =
let pre = Specs.Jprop.to_prop spec.Specs.pre in
let pure = Prop.get_pure pre in
let sigma = Prop.get_sigma pre in
let env = Prop.prop_pred_env pre in
let idmap = create_idmap sigma in
let code = Code.empty () in
Sil.Predicates.iter env
(gen_hpara code proc_name spec_num env)
(gen_hpara_dll code proc_name spec_num env);
gen_prolog code fname proc_name spec_num;
gen_var_decl code idmap parameters;
gen_init_vars code (solve_constraints pure idmap) idmap;
gen_init_equalities code pure;
gen_sigma code proc_name spec_num env sigma;
gen_epilog code proc_name parameters;
code
(** generate code for a main calling all the unit test functions passed as argument *)
let genmain proc_numspecs_list =
let code = Code.empty () in
let do_one_proc (proc_name, num_specs) =
for i = 1 to num_specs do
let test_fun_name = test_function_name proc_name i in
let line = test_fun_name ^ "();" in
Code.add_line code line done in
Code.add_line code "int main() {";
Code.set_indent " ";
IList.iter do_one_proc proc_numspecs_list;
Code.add_line code "printf(\"unit test terminated\\n\");";
Code.add_line code "return 0;";
Code.set_indent "";
Code.add_line code "}";
code

@ -1,26 +0,0 @@
(*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! Utils
(** Generate unit tests automatically from specs *)
(** type of generated code *)
type code
(** pretty print generated code *)
val pp_code : Format.formatter -> code -> unit
(** generate a unit test form a spec *)
val genunit : string -> Procname.t -> int -> (Mangled.t * Typ.t) list
-> Prop.normal Specs.spec -> code
(** generate code for a main calling all the unit test functions passed as argument *)
val genmain : (Procname.t * int) list -> code

@ -1059,11 +1059,6 @@ and type_size =
CLOpt.mk_bool ~deprecated:["type_size"] ~long:"type-size"
"Consider the size of types during analysis"
(** command line flag: if true, produce unit test for each spec *)
and unit_test =
CLOpt.mk_bool ~deprecated:["unit_test"] ~long:"unit-test"
"Print unit test code"
and unsafe_malloc =
CLOpt.mk_bool ~long:"unsafe-malloc"
~exes:CLOpt.[Analyze;Toplevel]
@ -1398,7 +1393,6 @@ and trace_error = !trace_error
and trace_join = !trace_join
and trace_rearrange = !trace_rearrange
and type_size = !type_size
and unit_test = !unit_test
and unsafe_malloc = !unsafe_malloc
and whole_seconds = !whole_seconds
and worklist_mode = !worklist_mode

@ -241,7 +241,6 @@ val trace_error : bool
val trace_join : bool
val trace_rearrange : bool
val type_size : bool
val unit_test : bool
val unsafe_malloc : bool
val whole_seconds : bool
val worklist_mode : int

@ -540,32 +540,6 @@ module CallsCsv = struct
Specs.CallStats.iter do_call stats.Specs.call_stats
end
module UnitTest = struct
(** Store the unit test functions generated, so that they can be called by main at the end *)
let procs_done = ref []
(** Print unit test for every spec in the summary *)
let print_unit_test proc_name summary =
let cnt = ref 0 in
let fmt = F.std_formatter in
let do_spec spec =
incr cnt;
let c_file = Filename.basename
(DB.source_file_to_string summary.Specs.attributes.ProcAttributes.loc.Location.file) in
let code =
Autounit.genunit c_file proc_name !cnt (Specs.get_formals summary) spec in
F.fprintf fmt "%a@." Autounit.pp_code code in
let specs = Specs.get_specs_from_payload summary in
IList.iter do_spec specs;
procs_done := (proc_name, IList.length specs) :: !procs_done
(** Print main function which calls all the unit test functions generated *)
let print_unit_test_main () =
let fmt = F.std_formatter in
let code = Autounit.genmain !procs_done in
F.fprintf fmt "%a@." Autounit.pp_code code
end
(** Module to compute the top procedures.
A procedure is top if it has specs and any procedure calling it has no specs *)
module TopProcedures : sig
@ -788,7 +762,6 @@ let process_summary filters linereader stats (top_proc_set: Procname.Set.t) (fna
do_outf Config.bugs_xml (fun outf -> BugsXml.pp_bugs error_filter linereader outf.fmt summary);
do_outf Config.report (fun _ -> Stats.process_summary error_filter summary linereader stats);
if Config.precondition_stats then PreconditionStats.do_summary proc_name summary;
if Config.unit_test then UnitTest.print_unit_test proc_name summary;
Config.pp_simple := pp_simple_saved;
do_outf Config.latex (fun outf -> write_summary_latex outf.fmt summary);
if Config.svg then begin
@ -972,7 +945,6 @@ let () =
let linereader = Printer.LineReader.create () in
let stats = Stats.create () in
iterate_summaries (process_summary filters linereader stats top_proc_set);
if Config.unit_test then UnitTest.print_unit_test_main ();
do_outf Config.procs_csv close_outf;
do_outf Config.procs_xml (fun outf -> ProcsXml.pp_procs_close outf.fmt (); close_outf outf);
do_outf Config.bugs_csv close_outf;

Loading…
Cancel
Save