-
Notifications
You must be signed in to change notification settings - Fork 81
/
Copy pathstrip_randomness.ml
143 lines (136 loc) · 4.05 KB
/
strip_randomness.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
let ( ^^ ) a b = Re.seq [ a; b ]
let standardise_filesep =
let re = Re.compile (Re.str Filename.dir_sep) in
Re.replace_string ~all:true re ~by:"/"
let build_context_replace =
let open Re in
let lterm, rterm =
(* Contexts in which directories are printed (tests, manpage output
etc.). *)
( group (alt [ char '`'; str "(absent=" ]),
group (alt [ char '\''; char ')' ]) )
in
let dir_sep = alt [ str Filename.dir_sep; char '/' ] in
let t =
seq
[
lterm;
rep any;
str "_build";
dir_sep;
str "_tests";
opt dir_sep;
group (rep (diff any (set "\\/")))
(* <test-dir>: May be a UUID or a suite name (symlink), depending on
whether or not we're running on Windows *);
group (opt (seq [ dir_sep; rep any ]));
rterm;
]
in
let re = compile t in
fun s ->
replace ~all:true re s ~f:(fun g ->
let test_dir_opt = if Group.get g 2 = "" then "" else "<test-dir>" in
let test_name = standardise_filesep (Group.get g 3) in
Group.get g 1
^ "<build-context>/_build/_tests/"
^ test_dir_opt
^ test_name
^ Group.get g 4)
let uuid_replace =
let open Re in
let t =
seq [ str "ID `"; repn (alt [ rg 'A' 'Z'; digit ]) 8 (Some 8); char '\'' ]
in
let re = compile t in
fun s -> replace_string ~all:true re ~by:"ID `<uuid>'" s
let time_replace =
let open Re in
let float = rep1 digit ^^ char '.' ^^ rep1 digit in
let t =
alt
[
group
(alt
[
(* Maybe ANSI escape, depending on [--color] *)
opt cntrl ^^ str "Test Successful" ^^ opt cntrl ^^ str " in ";
rep1 digit ^^ str " failure! in ";
rep1 digit ^^ str " failures! in ";
str "\"time\": ";
])
^^ float
^^ group (opt (char 's'));
]
in
let re = compile t in
fun s ->
replace re s ~f:(fun g -> Group.get g 1 ^ "<test-duration>" ^ Group.get g 2)
let stacktrace_replace =
let open Re in
let stack_trace_line verb =
str verb
^^ opt (rep1 print ^^ str " in ") (* exception name *)
^^ str "file \""
^^ rep1 print
^^ str "\""
^^ opt (str " (inlined)")
^^ str ", line "
^^ rep1 digit
^^ str ", characters "
^^ rep1 digit
^^ str "-"
^^ rep1 digit
|> compile
in
let raised_at = stack_trace_line "Raised at "
and called_from = stack_trace_line "Called from " in
let called_from_unknown = str "Called from unknown location" |> compile in
fun s ->
match execp called_from s with
| true ->
(* The number of "Called from ..." lines is compiler-dependent, so we
remove them all. *)
`None
| false -> (
match execp called_from_unknown s with
| true ->
`Unknown
(replace_string ~all:true called_from_unknown s ~by:"<stacktrace>")
| false ->
`Some (replace_string ~all:true raised_at s ~by:"<stacktrace>"))
let executable_name_normalization =
let open Re in
let t = alt [ str ".exe"; str ".bc.js" ] in
let re = compile t in
replace_string ~all:true re ~by:".<ext>"
(* Remove all non-deterministic output in a given Alcotest log and write
the result to std.out *)
let () =
let in_channel = open_in Sys.argv.(1) in
let ( >>| ) x f = match x with None -> None | Some x -> Some (f x) in
let ( >>= ) x f = match x with None -> `None | Some x -> f x in
try
let rec loop unknown_last =
let sanitized_line =
Some (input_line in_channel)
>>| uuid_replace
>>| build_context_replace
>>| time_replace
>>| executable_name_normalization
>>= stacktrace_replace
in
let unknown_last =
match sanitized_line with
| `Some s ->
Printf.printf "%s\n" s;
false
| `None -> false
| `Unknown s ->
if not unknown_last then Printf.printf "%s\n" s;
true
in
loop unknown_last
in
loop false
with End_of_file -> close_in in_channel