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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
include Cli_intf
open! Import
open Cmdliner
module Make (P : Platform.MAKER) (M : Monad.S) :
V1_types.S with type return = unit M.t = struct
(** *)
(** The priority order for determining options should be as follows:
+ 1. if a CLI flag/option is _explicitly_ set, use that;
+ 2. if the corresponding environment variable is _explicitly_ set, use
that;
+ 3. if the flag/option is set by [run ?argv]
+ 4. if the flag/option is passed to [run] directly, use that;
+ 5. otherwise, use the default behaviour set by {!Alcotest.Core}. *)
module C = Core.V1.Make (P) (M)
include C
module P = P (M)
open Cmdliner_syntax
let ci_env =
let doc =
Printf.sprintf "Whether Alcotest is running in a CI system, if set to %s."
(Arg.doc_quote "true")
in
Cmdliner.Cmd.Env.info "CI" ~doc
let github_actions_env =
let doc =
Printf.sprintf
"Whether Alcotest is running in GitHub Actions, if set to %s. Display \
tests errors and outputs GitHub Actions annotations."
(Arg.doc_quote "true")
in
Cmdliner.Cmd.Env.info "GITHUB_ACTIONS" ~doc
let alcotest_source_code_position =
let doc =
"Whether Alcotest should guess the source code position of test \
failures, if any. Defaults to true, set to a falsy value to disable."
in
Cmdliner.Cmd.Env.info "ALCOTEST_SOURCE_CODE_POSITION" ~doc
let alcotest_columns =
let doc =
"Number of columns after which Alcotest truncates or splits written \
lines. Default is to auto-detect using the terminal's dimensions, or \
fallback to 80 columns."
in
Cmdliner.Cmd.Env.info "ALCOTEST_COLUMNS" ~doc
let envs =
[
ci_env;
github_actions_env;
alcotest_source_code_position;
alcotest_columns;
]
let set_color stdout stderr =
let env = Cmd.Env.info "ALCOTEST_COLOR" in
let+ color_flag =
let enum = [ ("auto", `Auto); ("always", `Ansi_tty); ("never", `None) ] in
let color = Arg.enum enum in
let enum_alts = Arg.doc_alts_enum enum in
let doc =
Fmt.str
"Colorize the output. $(docv) must be %s. Defaults to %s when \
running inside Dune, otherwise defaults to %s."
enum_alts (Arg.doc_quote "always") (Arg.doc_quote "auto")
in
Arg.(
value & opt (some color) None & info [ "color" ] ~env ~doc ~docv:"WHEN")
in
let style_renderer =
match color_flag with
| Some `Auto -> None
| Some (`Ansi_tty | `None) as a -> a
| None -> (
try
let (_ : string) = Sys.getenv "INSIDE_DUNE" in
Some `Ansi_tty
with Not_found -> None)
in
P.setup_std_outputs ?style_renderer stdout stderr
let default_cmd config args library_name tests =
let and_exit = Config.User.and_exit config
and record_backtrace = Config.User.record_backtrace config
and ci = Config.User.ci config
and stdout = Config.User.stdout config
and stderr = Config.User.stderr config in
let exec_name = Filename.basename Sys.argv.(0) in
let doc = "Run all the tests." in
let term =
let+ () = set_color stdout stderr
and+ cli_config =
Config.User.term ~stdout ~stderr ~and_exit ~record_backtrace ~ci
and+ args = args in
let config = Config.User.(cli_config || config) in
run_with_args' config library_name args tests
in
(term, Cmd.info exec_name ~doc ~envs)
let test_cmd config args library_name tests =
let ci = Config.User.ci config
and stdout = Config.User.stdout config
and stderr = Config.User.stderr config in
let doc = "Run a subset of the tests." in
let term =
let+ () = set_color stdout stderr
and+ cli_config =
Config.User.term ~stdout ~stderr ~and_exit:true ~record_backtrace:true
~ci
and+ args = args in
let config = Config.User.(cli_config || config) in
run_with_args' config library_name args tests
in
(term, Cmd.info "test" ~doc ~envs)
let list_cmd ~stdout ~stderr tests =
let doc = "List all available tests." in
( (let+ () = set_color stdout stderr in
list_tests tests),
Cmd.info "list" ~doc )
let run_with_args' (type a) ~argv config name (args : a Term.t)
(tl : a test list) =
let ( >>= ) = M.bind in
let stdout = Config.User.stdout config
and stderr = Config.User.stderr config in
let choices =
List.map
(fun (term, info) -> Cmd.v info term)
[ list_cmd ~stdout ~stderr tl; test_cmd config args name tl ]
in
let and_exit = Config.User.and_exit config in
let exit_or_return exit_code =
if and_exit then exit exit_code else M.return ()
in
let result =
let default, info = default_cmd config args name tl in
Cmd.eval_value ?argv
~catch:and_exit
(Cmd.group ~default info choices)
in
match result with
| Ok (`Ok unit_m) -> unit_m >>= fun () -> exit_or_return Cmd.Exit.ok
| Ok (`Help | `Version) -> exit_or_return Cmd.Exit.ok
| Error (`Parse | `Term) -> exit_or_return Cmd.Exit.cli_error
| Error `Exn -> exit Cmd.Exit.internal_error
let run_with_args ?stdout ?stderr ?and_exit ?verbose ?compact ?tail_errors
?quick_only ?show_errors ?json ?filter ?log_dir ?bail ?record_backtrace
?ci ?argv =
Config.User.kcreate (run_with_args' ~argv) ?stdout ?stderr ?and_exit
?verbose ?compact ?tail_errors ?quick_only ?show_errors ?json ?filter
?log_dir ?bail ?record_backtrace ?ci
let run =
Config.User.kcreate (fun config ?argv name tl ->
run_with_args' config ~argv name (Term.const ()) tl)
end
module V1 = struct
include V1_types
module Make = Make
end