2023-07-18 17:00:53 +03:00
|
|
|
(* This file is part of the Catala build system, a specification language for
|
2023-08-25 15:12:02 +03:00
|
|
|
tax and social benefits computation rules. Copyright (C) 2022-2023 Inria,
|
2023-07-18 17:00:53 +03:00
|
|
|
contributors: Louis Gesbert <louis.gesbert@inria.fr>
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
License for the specific language governing permissions and limitations under
|
|
|
|
the License. *)
|
|
|
|
|
|
|
|
open Catala_utils
|
|
|
|
|
2024-02-26 12:18:08 +03:00
|
|
|
let run_catala_test test_flags catala_exe catala_opts file program args oc =
|
2024-05-24 16:01:12 +03:00
|
|
|
let cmd_in_rd, cmd_in_wr = Unix.pipe ~cloexec:true () in
|
|
|
|
let cmd_out_rd, cmd_out_wr = Unix.pipe ~cloexec:true () in
|
2023-09-26 12:42:46 +03:00
|
|
|
let command_oc = Unix.out_channel_of_descr cmd_in_wr in
|
2024-05-24 16:01:12 +03:00
|
|
|
let command_ic = Unix.in_channel_of_descr cmd_out_rd in
|
2023-09-26 12:42:46 +03:00
|
|
|
let catala_exe =
|
|
|
|
(* If the exe name contains directories, make it absolute. Otherwise don't
|
|
|
|
modify it so that it can be looked up in PATH. *)
|
|
|
|
if String.contains catala_exe Filename.dir_sep.[0] then
|
|
|
|
Unix.realpath catala_exe
|
|
|
|
else catala_exe
|
2023-07-18 17:00:53 +03:00
|
|
|
in
|
2023-09-26 12:42:46 +03:00
|
|
|
let cmd =
|
|
|
|
match args with
|
|
|
|
| cmd0 :: flags ->
|
2024-02-26 12:18:08 +03:00
|
|
|
let cmd0, flags =
|
2024-02-26 16:47:45 +03:00
|
|
|
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 (* Skip other tests when test-flags is specified *)
|
2024-02-26 12:18:08 +03:00
|
|
|
in
|
2023-09-26 12:42:46 +03:00
|
|
|
Array.of_list
|
|
|
|
((catala_exe :: cmd0 :: catala_opts) @ flags @ ["--name=" ^ file; "-"])
|
|
|
|
| [] -> Array.of_list ((catala_exe :: catala_opts) @ [file])
|
2023-07-18 17:00:53 +03:00
|
|
|
in
|
2023-09-26 12:42:46 +03:00
|
|
|
let env =
|
|
|
|
Unix.environment ()
|
|
|
|
|> Array.to_seq
|
2024-04-19 17:34:53 +03:00
|
|
|
|> Seq.filter (fun s ->
|
|
|
|
not
|
|
|
|
(String.starts_with ~prefix:"OCAMLRUNPARAM=" s
|
|
|
|
|| String.starts_with ~prefix:"CATALA_" s))
|
2023-09-26 12:42:46 +03:00
|
|
|
|> Seq.cons "CATALA_OUT=-"
|
|
|
|
(* |> Seq.cons "CATALA_COLOR=never" *)
|
|
|
|
|> Seq.cons "CATALA_PLUGINS="
|
|
|
|
|> Array.of_seq
|
|
|
|
in
|
2024-05-24 16:01:12 +03:00
|
|
|
let pid =
|
|
|
|
Unix.create_process_env catala_exe cmd env cmd_in_rd cmd_out_wr cmd_out_wr
|
|
|
|
in
|
2023-09-26 12:42:46 +03:00
|
|
|
Unix.close cmd_in_rd;
|
2024-05-24 16:01:12 +03:00
|
|
|
Unix.close cmd_out_wr;
|
2024-02-15 15:54:11 +03:00
|
|
|
Seq.iter (output_string command_oc) program;
|
2023-09-26 12:42:46 +03:00
|
|
|
close_out command_oc;
|
2024-05-24 16:01:12 +03:00
|
|
|
let out_lines =
|
|
|
|
Seq.of_dispenser (fun () -> In_channel.input_line command_ic)
|
|
|
|
in
|
|
|
|
Seq.iter (fun line ->
|
|
|
|
output_string oc line;
|
|
|
|
output_char oc '\n')
|
|
|
|
out_lines;
|
2023-09-26 12:42:46 +03:00
|
|
|
let return_code =
|
|
|
|
match Unix.waitpid [] pid with
|
|
|
|
| _, Unix.WEXITED n -> n
|
|
|
|
| _, (Unix.WSIGNALED n | Unix.WSTOPPED n) -> 128 - n
|
2023-07-18 17:00:53 +03:00
|
|
|
in
|
2023-09-26 12:42:46 +03:00
|
|
|
if return_code <> 0 then Printf.fprintf oc "#return code %d#\n" return_code
|
2023-07-18 17:00:53 +03:00
|
|
|
|
|
|
|
(** Directly runs the test (not using ninja, this will be called by ninja rules
|
|
|
|
through the "clerk runtest" command) *)
|
2024-02-26 12:18:08 +03:00
|
|
|
let run_inline_tests catala_exe catala_opts test_flags filename =
|
2023-09-26 12:42:46 +03:00
|
|
|
let module L = Surface.Lexer_common in
|
|
|
|
let lang =
|
|
|
|
match Clerk_scan.get_lang filename with
|
|
|
|
| Some l -> l
|
|
|
|
| None ->
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.error "Can't infer catala dialect from file extension of %a"
|
2023-09-26 12:42:46 +03:00
|
|
|
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
|
2024-02-26 16:47:45 +03:00
|
|
|
| Some args -> (
|
2023-09-26 12:42:46 +03:00
|
|
|
let args = String.split_on_char ' ' args in
|
2024-02-15 15:54:11 +03:00
|
|
|
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
|
2024-02-26 16:47:45 +03:00
|
|
|
match
|
|
|
|
run_catala_test test_flags catala_exe catala_opts filename program
|
|
|
|
args oc
|
|
|
|
with
|
|
|
|
| () -> skip_block lines
|
|
|
|
| exception Exit -> process lines))
|
2023-09-26 12:42:46 +03:00
|
|
|
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
|