• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use clap::{Parser, ValueEnum};
2 
3 /// Command line arguments.
4 ///
5 /// This type represents everything the user can specify via CLI args. The main
6 /// method is [`from_args`][Arguments::from_args] which reads the global
7 /// `std::env::args()` and parses them into this type.
8 ///
9 /// `libtest-mimic` supports a subset of all args/flags supported by the
10 /// official test harness. There are also some other minor CLI differences, but
11 /// the main use cases should work exactly like with the built-in harness.
12 #[derive(Parser, Debug, Clone, Default)]
13 #[command(
14     help_template = "USAGE: [OPTIONS] [FILTER]\n\n{all-args}\n\n\n{after-help}",
15     disable_version_flag = true,
16     after_help = "By default, all tests are run in parallel. This can be altered with the \n\
17         --test-threads flag when running tests (set it to 1).",
18 )]
19 pub struct Arguments {
20     // ============== FLAGS ===================================================
21     /// Run ignored and non-ignored tests.
22     #[arg(long = "include-ignored", help = "Run ignored tests")]
23     pub include_ignored: bool,
24 
25     /// Run only ignored tests.
26     #[arg(long = "ignored", help = "Run ignored tests")]
27     pub ignored: bool,
28 
29     /// Run tests, but not benchmarks.
30     #[arg(
31         long = "test",
32         conflicts_with = "bench",
33         help = "Run tests and not benchmarks",
34     )]
35     pub test: bool,
36 
37     /// Run benchmarks, but not tests.
38     #[arg(long = "bench", help = "Run benchmarks instead of tests")]
39     pub bench: bool,
40 
41     /// Only list all tests and benchmarks.
42     #[arg(long = "list", help = "List all tests and benchmarks")]
43     pub list: bool,
44 
45     /// No-op, ignored (libtest-mimic always runs in no-capture mode)
46     #[arg(long = "nocapture", help = "No-op (libtest-mimic always runs in no-capture mode)")]
47     pub nocapture: bool,
48 
49     /// If set, filters are matched exactly rather than by substring.
50     #[arg(
51         long = "exact",
52         help = "Exactly match filters rather than by substring",
53     )]
54     pub exact: bool,
55 
56     /// If set, display only one character per test instead of one line.
57     /// Especially useful for huge test suites.
58     ///
59     /// This is an alias for `--format=terse`. If this is set, `format` is
60     /// `None`.
61     #[arg(
62         short = 'q',
63         long = "quiet",
64         conflicts_with = "format",
65         help = "Display one character per test instead of one line. Alias to --format=terse",
66     )]
67     pub quiet: bool,
68 
69     // ============== OPTIONS =================================================
70     /// Number of threads used for parallel testing.
71     #[arg(
72         long = "test-threads",
73         help = "Number of threads used for running tests in parallel. If set to 1, \n\
74             all tests are run in the main thread.",
75     )]
76     pub test_threads: Option<usize>,
77 
78     /// Path of the logfile. If specified, everything will be written into the
79     /// file instead of stdout.
80     #[arg(
81         long = "logfile",
82         value_name = "PATH",
83         help = "Write logs to the specified file instead of stdout",
84     )]
85     pub logfile: Option<String>,
86 
87     /// A list of filters. Tests whose names contain parts of any of these
88     /// filters are skipped.
89     #[arg(
90         long = "skip",
91         value_name = "FILTER",
92         help = "Skip tests whose names contain FILTER (this flag can be used multiple times)",
93     )]
94     pub skip: Vec<String>,
95 
96     /// Specifies whether or not to color the output.
97     #[arg(
98         long = "color",
99         value_enum,
100         value_name = "auto|always|never",
101         help = "Configure coloring of output: \n\
102             - auto = colorize if stdout is a tty and tests are run on serially (default)\n\
103             - always = always colorize output\n\
104             - never = never colorize output\n",
105     )]
106     pub color: Option<ColorSetting>,
107 
108     /// Specifies the format of the output.
109     #[arg(
110         long = "format",
111         value_enum,
112         value_name = "pretty|terse|json",
113         help = "Configure formatting of output: \n\
114             - pretty = Print verbose output\n\
115             - terse = Display one character per test\n",
116     )]
117     pub format: Option<FormatSetting>,
118 
119     // ============== POSITIONAL VALUES =======================================
120     /// Filter string. Only tests which contain this string are run.
121     #[arg(
122         value_name = "FILTER",
123         help = "The FILTER string is tested against the name of all tests, and only those tests \
124                 whose names contain the filter are run.",
125     )]
126     pub filter: Option<String>,
127 }
128 
129 impl Arguments {
130     /// Parses the global CLI arguments given to the application.
131     ///
132     /// If the parsing fails (due to incorrect CLI args), an error is shown and
133     /// the application exits. If help is requested (`-h` or `--help`), a help
134     /// message is shown and the application exits, too.
from_args() -> Self135     pub fn from_args() -> Self {
136         Parser::parse()
137     }
138 
139     /// Like `from_args()`, but operates on an explicit iterator and not the
140     /// global arguments. Note that the first element is the executable name!
from_iter<I>(iter: I) -> Self where Self: Sized, I: IntoIterator, I::Item: Into<std::ffi::OsString> + Clone,141     pub fn from_iter<I>(iter: I) -> Self
142     where
143         Self: Sized,
144         I: IntoIterator,
145         I::Item: Into<std::ffi::OsString> + Clone,
146     {
147         Parser::parse_from(iter)
148     }
149 }
150 
151 /// Possible values for the `--color` option.
152 #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
153 pub enum ColorSetting {
154     /// Colorize output if stdout is a tty and tests are run on serially
155     /// (default).
156     Auto,
157 
158     /// Always colorize output.
159     Always,
160 
161     /// Never colorize output.
162     Never,
163 }
164 
165 impl Default for ColorSetting {
default() -> Self166     fn default() -> Self {
167         ColorSetting::Auto
168     }
169 }
170 
171 /// Possible values for the `--format` option.
172 #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
173 pub enum FormatSetting {
174     /// One line per test. Output for humans. (default)
175     Pretty,
176 
177     /// One character per test. Usefull for test suites with many tests.
178     Terse,
179 }
180 
181 impl Default for FormatSetting {
default() -> Self182     fn default() -> Self {
183         FormatSetting::Pretty
184     }
185 }
186 
187 #[cfg(test)]
188 mod tests {
189     use super::*;
190 
191     #[test]
verify_cli()192     fn verify_cli() {
193         use clap::CommandFactory;
194         Arguments::command().debug_assert();
195     }
196 }
197