-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathrunner.ml
125 lines (110 loc) · 4.04 KB
/
runner.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module Json = Yojson.Basic
open Shexp_process
open Base
let (let*) x f = bind x ~f
type result =
| OutputMatches
| OutputDoesntMatch
| OutputMissing
| TypeCheckerFailed
| ReducerFailed
| NotTestFile
[@@deriving show, eq]
let rec mapM ~f xs =
match xs with
| [] -> return []
| x::xs ->
let* r = f x in
let* res = mapM ~f xs in
return (r::res)
let identity x = x
let with_output ?(silent=true) file k =
with_temp_file ~prefix:"garbage" ~suffix:"err" (fun err ->
with_temp_file ~prefix:"test" ~suffix:"ml" (fun f ->
let* _ = print (file ^ "\n") in
let* exit_ = chdir "reducer" ((if silent then stderr_to err else identity) (stdout_to f (run_exit_code "cargo" ["run"; file]))) in
if not (Int.equal exit_ 0) then
return (file, ReducerFailed)
else
let* (exit_, output) = (pipe_both ((if silent then stderr_to err else identity) (run_exit_code "dune" ["utop"; "oxide"; "--"; f])) read_all) in
if not (Int.equal exit_ 0) then
return (file, TypeCheckerFailed)
else
k output))
let run_file file =
with_output file (fun output ->
let* exists = file_exists (file ^ ".output") in
if not exists then
return (file, OutputMissing)
else
let expected = Stdio.In_channel.read_all (file ^ ".output") in
return (file, if String.equal expected output then
OutputMatches
else OutputDoesntMatch)
)
let write_results results dir =
let h t =
`List (List.map ~f:(fun x -> `String (fst x))
(List.filter ~f:(fun x -> equal_result (snd x) t)
results)) in
stdout_to (dir ^ "/results.json")
(print
(Json.pretty_to_string
(`Assoc [("matches", h OutputMatches);
("doesntmatch", h OutputDoesntMatch);
("missing", h OutputMissing);
("typeerror", h TypeCheckerFailed);
("reducererror", h ReducerFailed)])))
let rec run_dir dir =
let _ = Stdio.print_endline dir in
let* files = readdir dir in
let* results = mapM ~f:(fun name ->
if String.is_prefix name ~prefix:"." then return (name, NotTestFile)
else let* s = stat (dir ^ "/" ^ name) in
if phys_equal s.st_kind Unix.S_DIR
then run_dir (dir ^ "/" ^ name)
else if String.is_suffix ~suffix:".rs" name
then run_file (dir ^ "/" ^ name)
else return (name, NotTestFile))
files in
let* _ = write_results results dir in
(* let* _ = eprint ([%derive.show: (string * result) list] results) in *)
return (dir, NotTestFile)
let check file =
with_output ~silent:false file (fun output ->
let* _ = print output in
return (file, OutputMissing))
let trust file =
with_output file (fun output ->
let* _ = stdout_to (file ^ ".output") (print output) in
return (file, OutputMissing))
let retrust path =
pipe (run "jq" ["-r"; ".doesntmatch | .[]"; path ^ "/results.json"]) (iter_lines (fun file -> let* _ = trust file in return ()))
let _ =
let usage () =
(Stdio.print_endline "usage: ";
Stdio.print_endline " PROGNAME run path/to/root/of/tests";
Stdio.print_endline " PROGNAME check path/to/single/test.rs";
Stdio.print_endline " PROGNAME trust path/to/single/test.rs";
Stdio.print_endline " PROGNAME retrust path/to/root/of/tests") in
if Array.length (Sys.get_argv()) < 3 then
(* NOTE(2019-06-28): Argument parsing, done terribly. *)
usage ()
else
let _ = eval (
let* wd = cwd_logical in
let pth =
if String.is_prefix ~prefix:"/" (Sys.get_argv()).(2)
then (Sys.get_argv()).(2) else wd ^ "/" ^ (Sys.get_argv()).(2)
in
match (Sys.get_argv()).(1) with
|"run" ->
let* _ = run_dir pth in return ()
|"check" ->
let* _ = check pth in return ()
|"trust" ->
let* _ = trust pth in return ()
|"retrust" ->
let* _ = retrust pth in return ()
|_ -> usage (); return ()
) in ()