libtest_with/
args.rs

1use 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)]
19pub 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    /// No-op, ignored. libtest-mimic does not currently capture stdout.
50    #[arg(long = "show-output")]
51    pub show_output: bool,
52
53    /// No-op, ignored. Flag only exists for CLI compatibility with libtest.
54    #[arg(short = 'Z')]
55    pub unstable_flags: Option<UnstableFlags>,
56
57    /// If set, filters are matched exactly rather than by substring.
58    #[arg(
59        long = "exact",
60        help = "Exactly match filters rather than by substring",
61    )]
62    pub exact: bool,
63
64    /// If set, display only one character per test instead of one line.
65    /// Especially useful for huge test suites.
66    ///
67    /// This is an alias for `--format=terse`. If this is set, `format` is
68    /// `None`.
69    #[arg(
70        short = 'q',
71        long = "quiet",
72        conflicts_with = "format",
73        help = "Display one character per test instead of one line. Alias to --format=terse",
74    )]
75    pub quiet: bool,
76
77    // ============== OPTIONS =================================================
78    /// Number of threads used for parallel testing.
79    #[arg(
80        long = "test-threads",
81        help = "Number of threads used for running tests in parallel. If set to 1, \n\
82            all tests are run in the main thread.",
83    )]
84    pub test_threads: Option<usize>,
85
86    /// Path of the logfile. If specified, everything will be written into the
87    /// file instead of stdout.
88    #[arg(
89        long = "logfile",
90        value_name = "PATH",
91        help = "Write logs to the specified file instead of stdout",
92    )]
93    pub logfile: Option<String>,
94
95    /// A list of filters. Tests whose names contain parts of any of these
96    /// filters are skipped.
97    #[arg(
98        long = "skip",
99        value_name = "FILTER",
100        help = "Skip tests whose names contain FILTER (this flag can be used multiple times)",
101    )]
102    pub skip: Vec<String>,
103
104    /// Specifies whether or not to color the output.
105    #[arg(
106        long = "color",
107        value_enum,
108        value_name = "auto|always|never",
109        help = "Configure coloring of output: \n\
110            - auto = colorize if stdout is a tty and tests are run on serially (default)\n\
111            - always = always colorize output\n\
112            - never = never colorize output\n",
113    )]
114    pub color: Option<ColorSetting>,
115
116    /// Specifies the format of the output.
117    #[arg(
118        long = "format",
119        value_enum,
120        value_name = "pretty|terse|json",
121        help = "Configure formatting of output: \n\
122            - pretty = Print verbose output\n\
123            - terse = Display one character per test\n\
124            - json = Print json events\n",
125    )]
126    pub format: Option<FormatSetting>,
127
128    // ============== POSITIONAL VALUES =======================================
129    /// Filter string. Only tests which contain this string are run.
130    #[arg(
131        value_name = "FILTER",
132        help = "The FILTER string is tested against the name of all tests, and only those tests \
133                whose names contain the filter are run.",
134    )]
135    pub filter: Option<String>,
136}
137
138impl Arguments {
139    /// Parses the global CLI arguments given to the application.
140    ///
141    /// If the parsing fails (due to incorrect CLI args), an error is shown and
142    /// the application exits. If help is requested (`-h` or `--help`), a help
143    /// message is shown and the application exits, too.
144    pub fn from_args() -> Self {
145        Parser::parse()
146    }
147
148    /// Like `from_args()`, but operates on an explicit iterator and not the
149    /// global arguments. Note that the first element is the executable name!
150    pub fn from_iter<I>(iter: I) -> Self
151    where
152        Self: Sized,
153        I: IntoIterator,
154        I::Item: Into<std::ffi::OsString> + Clone,
155    {
156        Parser::parse_from(iter)
157    }
158}
159
160/// Possible values for the `--color` option.
161#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
162pub enum ColorSetting {
163    /// Colorize output if stdout is a tty and tests are run on serially
164    /// (default).
165    Auto,
166
167    /// Always colorize output.
168    Always,
169
170    /// Never colorize output.
171    Never,
172}
173
174impl Default for ColorSetting {
175    fn default() -> Self {
176        ColorSetting::Auto
177    }
178}
179
180/// Possible values for the `-Z` option
181#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
182pub enum UnstableFlags {
183    UnstableOptions,
184}
185
186/// Possible values for the `--format` option.
187#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
188pub enum FormatSetting {
189    /// One line per test. Output for humans. (default)
190    Pretty,
191
192    /// One character per test. Usefull for test suites with many tests.
193    Terse,
194
195    /// Json output
196    Json,
197}
198
199impl Default for FormatSetting {
200    fn default() -> Self {
201        FormatSetting::Pretty
202    }
203}
204
205#[cfg(test)]
206mod tests {
207    use super::*;
208
209    #[test]
210    fn verify_cli() {
211        use clap::CommandFactory;
212        Arguments::command().debug_assert();
213    }
214}