From cccfc6ba87785a01b6909745e8b9a280a3975aef Mon Sep 17 00:00:00 2001
From: Patrick Baudin <patrick.baudin@cea.fr>
Date: Tue, 6 Apr 2021 14:24:34 +0200
Subject: [PATCH] [Ptests] performs FILTER commands at the comparison stage

---
 ptests/ptests.ml | 225 ++++++++++++++++++++++++-----------------------
 1 file changed, 113 insertions(+), 112 deletions(-)

diff --git a/ptests/ptests.ml b/ptests/ptests.ml
index 36f96f0ee65..74001218c82 100644
--- a/ptests/ptests.ml
+++ b/ptests/ptests.ml
@@ -1250,104 +1250,29 @@ end = struct
     if command.timeout = "" then raw_command
     else "ulimit -t " ^ command.timeout ^ " && " ^ raw_command
 
-  (* Searches for executable [s] in the directories contained in the PATH
-     environment variable. Returns [None] if not found, or
-     [Some <fullpath>] otherwise. *)
-  let find_in_path s =
-    let trim_right s =
-      let n = ref (String.length s - 1) in
-      let last_char_to_keep =
-        try
-          while !n > 0 do
-            if String.get s !n <> ' ' then raise Exit;
-            n := !n - 1
-          done;
-          0
-        with Exit -> !n
-      in
-      String.sub s 0 (last_char_to_keep+1)
+  let command_string command =
+    let log_prefix = log_prefix command in
+    let reslog,errlog = match command.filter with
+      | None -> log_prefix ^ ".res.log", log_prefix ^ ".err.log"
+      | Some _ ->log_prefix ^ ".res.unfiltered-log", log_prefix ^ ".err.unfiltered-log"
     in
-    let s = trim_right s in
-    let path_separator = if Sys.os_type = "Win32" then ";" else ":" in
-    let re_path_sep = Str.regexp path_separator in
-    let path_dirs = Str.split re_path_sep (Sys.getenv "PATH") in
-    let found = ref "" in
-    try
-      List.iter (fun dir ->
-          let fullname = dir ^ Filename.dir_sep ^ s in
-          if Sys.file_exists fullname then begin
-            found := fullname;
-            raise Exit
-          end
-        ) path_dirs;
-      None
-    with Exit ->
-      Some !found
-
-  let command_string =
-    let regexp_ptest_oracle = Str.regexp "@PTEST_ORACLE@" in
-    fun command ->
-      let log_prefix = log_prefix command in
-      let errlog = log_prefix ^ ".err.log" in
-      let stderr = match command.filter with
-          None -> errlog
-        | Some _ ->
-          let stderr =
-            Filename.temp_file (Filename.basename log_prefix) ".err.log"
-          in
-          at_exit (fun () ->  unlink stderr);
-          stderr
-      in
-      let filter = match command.filter with
-        | None -> None
-        | Some filter ->
-          let foracle = (Filename.basename log_prefix) ^ ".res.oracle" in
-          let filter = Str.global_replace regexp_ptest_oracle foracle filter in
-          let exec_name, params = command_partition filter in
-          let exec_name =
-            if Sys.file_exists exec_name || not (Filename.is_relative exec_name)
-            then exec_name
-            else
-              match find_in_path exec_name with
-              | Some full_exec_name -> full_exec_name
-              | None ->
-                Filename.concat
-                  (Filename.dirname (Filename.dirname log_prefix))
-                  (Filename.basename exec_name)
-          in
-          Some (exec_name ^ params)
-      in
-      let command_str = basic_command_string command in
-      let command_str =
-        command_str ^ " 2>" ^ (Filename.sanitize stderr)
-      in
-      let command_str = match filter with
-        | None -> command_str
-        | Some filter -> command_str ^ " | " ^ filter
-      in
-      let res = Filename.sanitize (log_prefix ^ ".res.log") in
-      let command_str = command_str ^ " >" ^ res in
-      let command_str =
-        match command.timeout with
-        | "" -> command_str
-        | s ->
-          Printf.sprintf
-            "%s; if test $? -gt 127; then \
-             echo 'TIMEOUT (%s); ABORTING EXECUTION' > %s; \
-             fi"
-            command_str s (Filename.sanitize stderr)
-      in
-      let command_str = match filter with
-        | None -> command_str
-        | Some filter ->
-          Printf.sprintf "%s && %s < %s >%s && rm -f %s" (* exit code ? *)
-            command_str
-            filter
-            (Filename.sanitize stderr)
-            (Filename.sanitize errlog)
-            (Filename.sanitize stderr)
-      in
-      command_str
+    let reslog = Filename.sanitize reslog in
+    let errlog = Filename.sanitize errlog in
+    let command_str = basic_command_string command in
+    let command_str =
+      command_str ^ " >" ^ reslog ^ " 2>" ^ errlog
+    in
+    let command_str =
+      match command.timeout with
+      | "" -> command_str
+      | s ->
+        Printf.sprintf
+          "%s; if test $? -gt 127; then \
+           echo 'TIMEOUT (%s); ABORTING EXECUTION' > %s; \
+           fi"
+          command_str s errlog
+    in
+    command_str
 
   let update_toplevel_command command =
     let log_prefix = log_prefix command in
@@ -1640,6 +1565,73 @@ let check_file_is_empty_or_nonexisting diff ~log_file =
     1
   end
 
+(* Searches for executable [s] in the directories contained in the PATH
+     environment variable. Returns [None] if not found, or
+     [Some <fullpath>] otherwise. *)
+let find_in_path s =
+  let trim_right s =
+    let n = ref (String.length s - 1) in
+    let last_char_to_keep =
+      try
+        while !n > 0 do
+          if String.get s !n <> ' ' then raise Exit;
+          n := !n - 1
+        done;
+        0
+      with Exit -> !n
+    in
+    String.sub s 0 (last_char_to_keep+1)
+  in
+  let s = trim_right s in
+  let path_separator = if Sys.os_type = "Win32" then ";" else ":" in
+  let re_path_sep = Str.regexp path_separator in
+  let path_dirs = Str.split re_path_sep (Sys.getenv "PATH") in
+  let found = ref "" in
+  try
+    List.iter (fun dir ->
+        let fullname = dir ^ Filename.dir_sep ^ s in
+        if Sys.file_exists fullname then begin
+          found := fullname;
+          raise Exit
+        end
+      ) path_dirs;
+    None
+  with Exit ->
+    Some !found
+
+let do_filter =
+  let regexp_ptest_oracle = Str.regexp "@PTEST_ORACLE@" in
+  fun cmd kind ->
+    match cmd.filter with
+    | None -> ()
+    | Some filter ->
+      let log_prefix = Cmd.log_prefix cmd in
+      let log_ext = log_ext kind in
+      let log_file = Filename.sanitize (log_prefix ^ log_ext ^ ".log") in
+      let foracle = (Filename.basename log_prefix) ^ log_ext ^ ".oracle" in
+      let filter = Str.global_replace regexp_ptest_oracle foracle filter in
+      let exec_name, params = command_partition filter in
+      let exec_name =
+        if Sys.file_exists exec_name || not (Filename.is_relative exec_name)
+        then exec_name
+        else
+          match find_in_path exec_name with
+          | Some full_exec_name -> full_exec_name
+          | None ->
+            Filename.concat
+              (Filename.dirname (Filename.dirname log_prefix))
+              (Filename.basename exec_name)
+      in
+      let unfiltered_file = Filename.sanitize (log_prefix ^ log_ext ^ ".unfiltered-log") in
+      let filter_cmd = Format.sprintf "%s | %s%s > %s 2> /dev/null"
+          (* the filter command can be a diff from a [@PTEST_ORACLE@] *)
+          (if Sys.file_exists unfiltered_file then "cat " ^ unfiltered_file else "echo \"\"")
+          exec_name params log_file
+      in
+      if !verbosity >= 1
+      then lock_printf "%tFilter command:@\n%s@." print_default_env filter_cmd;
+      ignore (launch filter_cmd)
+
 let compare_one_file cmp log_prefix oracle_prefix log_kind =
   if !behavior = Show
   then begin
@@ -1652,6 +1644,7 @@ let compare_one_file cmp log_prefix oracle_prefix log_kind =
     let ext = log_ext log_kind in
     let log_file = Filename.sanitize (log_prefix ^ ext ^ ".log") in
     let oracle_file = Filename.sanitize (oracle_prefix ^ ext ^ ".oracle") in
+    do_filter cmp log_kind;
     if log_kind = Err && not (Sys.file_exists oracle_file) then
       check_file_is_empty_or_nonexisting (Command_error (cmp,log_kind)) ~log_file
     else begin
@@ -1765,6 +1758,7 @@ let do_diff = function
     let log_prefix = Cmd.log_prefix diff in
     let log_ext = log_ext kind in
     let log_file = Filename.sanitize (log_prefix ^ log_ext ^ ".log") in
+    do_filter diff kind ;
     let command_string = Cmd.command_string diff in
     lock_printf "%tCommand:@\n%s@." print_default_env command_string;
     if !behavior = Show
@@ -1933,19 +1927,26 @@ let dispatcher () =
         fun {toplevel; opts=options; logs=log_files; macros; exit_code; timeout} ->
           let n = !i in
           incr i;
-          { file; options; toplevel; nb_files; directory; n; log_files;
-            filter = config.dc_filter; macros;
-            exit_code = begin
-              match exit_code with
-              | None -> 0
-              | Some exit_code ->
-                try int_of_string exit_code with
-                | _ -> lock_eprintf "@[%s: integer required for directive EXIT: %s (defaults to 0)@]@." file exit_code ; 0
-            end;
-            execnow=false;
-            timeout;
-          }
-      in
+          let cmd =
+            { file; options; toplevel; nb_files; directory; n; log_files;
+              filter = config.dc_filter; macros;
+              exit_code = begin
+                match exit_code with
+                | None -> 0
+                | Some exit_code ->
+                  try int_of_string exit_code with
+                  | _ -> lock_eprintf "@[%s: integer required for directive EXIT: %s (defaults to 0)@]@." file exit_code ; 0
+              end;
+              execnow=false;
+              timeout;
+            }
+          in
+          let macros = Cmd.get_macros cmd in
+          match cmd.filter with
+          | None -> cmd
+          | Some filter ->
+            { cmd with filter = Some (Macros.expand macros filter) }
+       in
       let nb_files_execnow = List.length config.dc_execnow in
       let make_execnow_cmd =
         let e = ref 0 in
@@ -1977,9 +1978,9 @@ let dispatcher () =
             ex_timeout = execnow.ex_timeout;
           }
       in
-      let treat_option q option =
+      let treat_option q cmd =
         Queue.push
-          (Toplevel (make_toplevel_cmd option))
+          (Toplevel (make_toplevel_cmd cmd))
           q;
       in
       if not config.dc_dont_run
-- 
GitLab