Skip to content
Snippets Groups Projects
Aorai_test.ml 4.33 KiB
Newer Older
(* Small script to test that the code generated by aorai can be parsed again
 * by frama-c.
Virgile Prevosto's avatar
Virgile Prevosto committed
*)
module P = Plugin.Register
Virgile Prevosto's avatar
Virgile Prevosto committed
    (struct
      let name = "aorai testing module"
      let shortname = "aorai-test"
      let help = "utility script for aorai regtests"
    end)
    (struct
      let option_name = "-aorai-test-number"
      let help = "test number when multiple tests are run over the same file"
      let arg_name = "n"
Virgile Prevosto's avatar
Virgile Prevosto committed
    end)
Virgile Prevosto's avatar
Virgile Prevosto committed
  struct
    let option_name = "-aorai-test-wp-share"
    let help = "use custom wp share dir (when in internal plugin mode)"
    let arg_name = "dir"
    let existence = Filepath.Must_exist
    let file_kind = "wp share directory"
  end)
module WpCache =
  P.Filepath(
  struct
    let option_name = "-aorai-test-wp-cache"
    let help = "use custom session dir for storing cache"
    let arg_name = "dir"
    let existence = Filepath.Must_exist
    let file_kind = "wp session directory"
  end)

Virgile Prevosto's avatar
Virgile Prevosto committed
  struct
    let option_name = "-aorai-test-prove-aux-spec"
    let help = "use WP + alt-ergo to prove that generated spec and body \
                of auxiliary automata functions match"
  end)

let ok = ref false

let is_suffix suf str =
  let lsuf = String.length suf in
  let lstr = String.length str in
  if lstr <= lsuf then false
  else
    let estr = String.sub str (lstr - lsuf) lsuf in
    estr = suf

let extend () =
  let myrun =
    let run = !Db.Toplevel.run in
    fun f ->
      let my_project = Project.create "Reparsing" in
      let wp_compute_kf kf =
        let vcs = Wp.VC.generate_kf kf in
        Wp.VC.command vcs;
        Bag.iter
          (fun vc ->
             if not (Wp.VC.is_proved vc) then
               P.warning "Could not prove %a in automaton function %a"
                 Property.pretty (Wp.VC.get_property vc)
                 Kernel_function.pretty kf)
          vcs
      in
      let check_auto_func kf =
        let name = Kernel_function.get_name kf in
        if Kernel_function.is_definition kf &&
           (is_suffix "_pre_func" name || is_suffix "_post_func" name)
        then
          wp_compute_kf kf
      let tmpdir = Filename.get_temp_dir_name () in
      let tmpdir =
        match Filename.chop_suffix_opt ~suffix:"/" tmpdir with
        | None -> tmpdir
        | Some dir -> dir
      in
        tmpdir ^ "/aorai_" ^
        Filename.(
          chop_extension (basename (List.hd (Kernel.Files.get()):>string))) ^
        "_" ^ (string_of_int (TestNumber.get ())) ^ ".i"
      in
      let () =
        Extlib.safe_at_exit
          (fun () ->
             if Debug.get () >= 1 || not !ok then
               result "Keeping temp file %s" tmpfile
             else Extlib.safe_remove tmpfile)
      in
      let chan = open_out tmpfile in
      let fmt = Format.formatter_of_out_channel chan in
      let aorai_prj = Project.from_unique_name "aorai" in
      Project.on aorai_prj Kernel.PrintLibc.on ();
      File.pretty_ast ~prj:aorai_prj ~fmt ();
      close_out chan;
      let selection =
        List.fold_left
          (fun selection state ->
             State_selection.union
               (State_selection.with_codependencies state) selection)
          State_selection.empty
          [ InternalWpShare.self; ProveAuxSpec.self; WpCache.self ]
      in
      Project.copy ~selection my_project;
      Project.set_current my_project;
      Kernel.SymbolicPath.add
        (Filepath.Normalized.of_string (Filename.get_temp_dir_name ()),
         Some "TMPDIR");
      Files.append_after [ Filepath.Normalized.of_string tmpfile ];
Virgile Prevosto's avatar
Virgile Prevosto committed
      Kernel.LogicalOperators.on ();
      Constfold.off ();
      Ast.compute();
      if ProveAuxSpec.get () then begin
        if InternalWpShare.is_set() then
          Wp.Wp_parameters.Share.set (InternalWpShare.get());
        Wp.Wp_parameters.Let.off();
        Wp.Wp_parameters.Split.on();
        Wp.Wp_parameters.SplitMax.set 32;
        Wp.Wp_parameters.Verbose.set 0;
        if WpCache.is_set () then
          Wp.Wp_parameters.Session.set (WpCache.get());
        Wp.Wp_parameters.Cache.set "update";
        Globals.Functions.iter check_auto_func;
      end else begin
        File.pretty_ast ();
      end;
      ok:=true (* no error, we can erase the file *)
  in
  Db.Toplevel.run := myrun

let () = extend ()