Source file clerk_runtest.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
144
145
146
147
148
149
open Catala_utils
let run_catala_test test_flags catala_exe catala_opts file program args oc =
let cmd_in_rd, cmd_in_wr = Unix.pipe () in
Unix.set_close_on_exec cmd_in_wr;
let command_oc = Unix.out_channel_of_descr cmd_in_wr in
let catala_exe =
if String.contains catala_exe Filename.dir_sep.[0] then
Unix.realpath catala_exe
else catala_exe
in
let cmd =
match args with
| cmd0 :: flags ->
let cmd0, flags =
match String.lowercase_ascii cmd0, flags, test_flags with
| "test-scope", scope_name :: flags, test_flags ->
"interpret", (("--scope=" ^ scope_name) :: flags) @ test_flags
| "test-scope", [], _ ->
output_string oc
"[INVALID TEST] Invalid test command syntax, the 'test-scope' \
pseudo-command takes a scope name as first argument\n";
"interpret", test_flags
| cmd0, flags, [] -> cmd0, flags
| _, _, _ :: _ ->
raise Exit
in
Array.of_list
((catala_exe :: cmd0 :: catala_opts) @ flags @ ["--name=" ^ file; "-"])
| [] -> Array.of_list ((catala_exe :: catala_opts) @ [file])
in
let env =
Unix.environment ()
|> Array.to_seq
|> Seq.filter (fun s ->
not
(String.starts_with ~prefix:"OCAMLRUNPARAM=" s
|| String.starts_with ~prefix:"CATALA_" s))
|> Seq.cons "CATALA_OUT=-"
|> Seq.cons "CATALA_PLUGINS="
|> Array.of_seq
in
flush oc;
let ocfd = Unix.descr_of_out_channel oc in
let pid = Unix.create_process_env catala_exe cmd env cmd_in_rd ocfd ocfd in
Unix.close cmd_in_rd;
Seq.iter (output_string command_oc) program;
close_out command_oc;
let return_code =
match Unix.waitpid [] pid with
| _, Unix.WEXITED n -> n
| _, (Unix.WSIGNALED n | Unix.WSTOPPED n) -> 128 - n
in
if return_code <> 0 then Printf.fprintf oc "#return code %d#\n" return_code
(** Directly runs the test (not using ninja, this will be called by ninja rules
through the "clerk runtest" command) *)
let run_inline_tests catala_exe catala_opts test_flags filename =
let module L = Surface.Lexer_common in
let lang =
match Clerk_scan.get_lang filename with
| Some l -> l
| None ->
Message.error "Can't infer catala dialect from file extension of %a"
File.format filename
in
let lines = Surface.Parser_driver.lines filename lang in
let oc = stdout in
let lines_until_now = Queue.create () in
let push str =
output_string oc str;
Queue.add str lines_until_now
in
let rec run_test lines =
match Seq.uncons lines with
| None ->
output_string oc
"[INVALID TEST] Missing test command, use '$ catala <args>'\n"
| Some ((str, L.LINE_BLOCK_END), lines) ->
output_string oc
"[INVALID TEST] Missing test command, use '$ catala <args>'\n";
push str;
process lines
| Some ((str, _), lines) -> (
push str;
match Clerk_scan.test_command_args str with
| None ->
output_string oc
"[INVALID TEST] Invalid test command syntax, must match '$ catala \
<args>'\n";
skip_block lines
| Some args -> (
let args = String.split_on_char ' ' args in
let program =
let rec drop_last seq () =
match seq () with
| Seq.Nil -> assert false
| Seq.Cons (x, next) -> (
match next () with
| Seq.Nil -> Seq.Nil
| Seq.Cons _ as s -> Seq.Cons (x, drop_last (fun () -> s)))
in
Queue.to_seq lines_until_now |> drop_last |> drop_last
in
match
run_catala_test test_flags catala_exe catala_opts filename program
args oc
with
| () -> skip_block lines
| exception Exit -> process lines))
and skip_block lines =
match Seq.uncons lines with
| None -> ()
| Some ((str, L.LINE_BLOCK_END), lines) ->
push str;
process lines
| Some ((str, _), lines) ->
Queue.add str lines_until_now;
skip_block lines
and process lines =
match Seq.uncons lines with
| Some ((str, L.LINE_INLINE_TEST), lines) ->
push str;
run_test lines
| Some ((str, _), lines) ->
push str;
process lines
| None -> ()
in
process lines