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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
use clap::{Parser, ValueEnum};
/// Command line arguments.
///
/// This type represents everything the user can specify via CLI args. The main
/// method is [`from_args`][Arguments::from_args] which reads the global
/// `std::env::args()` and parses them into this type.
///
/// `libtest-mimic` supports a subset of all args/flags supported by the
/// official test harness. There are also some other minor CLI differences, but
/// the main use cases should work exactly like with the built-in harness.
#[derive(Parser, Debug, Clone, Default)]
#[command(
help_template = "USAGE: [OPTIONS] [FILTER]\n\n{all-args}\n\n\n{after-help}",
disable_version_flag = true,
after_help = "By default, all tests are run in parallel. This can be altered with the \n\
--test-threads flag when running tests (set it to 1).",
)]
pub struct Arguments {
// ============== FLAGS ===================================================
/// Run ignored and non-ignored tests.
#[arg(long = "include-ignored", help = "Run ignored tests")]
pub include_ignored: bool,
/// Run only ignored tests.
#[arg(long = "ignored", help = "Run ignored tests")]
pub ignored: bool,
/// Run tests, but not benchmarks.
#[arg(
long = "test",
conflicts_with = "bench",
help = "Run tests and not benchmarks",
)]
pub test: bool,
/// Run benchmarks, but not tests.
#[arg(long = "bench", help = "Run benchmarks instead of tests")]
pub bench: bool,
/// Only list all tests and benchmarks.
#[arg(long = "list", help = "List all tests and benchmarks")]
pub list: bool,
/// No-op, ignored (libtest-mimic always runs in no-capture mode)
#[arg(long = "nocapture", help = "No-op (libtest-mimic always runs in no-capture mode)")]
pub nocapture: bool,
/// No-op, ignored. libtest-mimic does not currently capture stdout.
#[arg(long = "show-output")]
pub show_output: bool,
/// No-op, ignored. Flag only exists for CLI compatibility with libtest.
#[arg(short = 'Z')]
pub unstable_flags: Option<UnstableFlags>,
/// If set, filters are matched exactly rather than by substring.
#[arg(
long = "exact",
help = "Exactly match filters rather than by substring",
)]
pub exact: bool,
/// If set, display only one character per test instead of one line.
/// Especially useful for huge test suites.
///
/// This is an alias for `--format=terse`. If this is set, `format` is
/// `None`.
#[arg(
short = 'q',
long = "quiet",
conflicts_with = "format",
help = "Display one character per test instead of one line. Alias to --format=terse",
)]
pub quiet: bool,
// ============== OPTIONS =================================================
/// Number of threads used for parallel testing.
#[arg(
long = "test-threads",
help = "Number of threads used for running tests in parallel. If set to 1, \n\
all tests are run in the main thread.",
)]
pub test_threads: Option<usize>,
/// Path of the logfile. If specified, everything will be written into the
/// file instead of stdout.
#[arg(
long = "logfile",
value_name = "PATH",
help = "Write logs to the specified file instead of stdout",
)]
pub logfile: Option<String>,
/// A list of filters. Tests whose names contain parts of any of these
/// filters are skipped.
#[arg(
long = "skip",
value_name = "FILTER",
help = "Skip tests whose names contain FILTER (this flag can be used multiple times)",
)]
pub skip: Vec<String>,
/// Specifies whether or not to color the output.
#[arg(
long = "color",
value_enum,
value_name = "auto|always|never",
help = "Configure coloring of output: \n\
- auto = colorize if stdout is a tty and tests are run on serially (default)\n\
- always = always colorize output\n\
- never = never colorize output\n",
)]
pub color: Option<ColorSetting>,
/// Specifies the format of the output.
#[arg(
long = "format",
value_enum,
value_name = "pretty|terse|json",
help = "Configure formatting of output: \n\
- pretty = Print verbose output\n\
- terse = Display one character per test\n\
- json = Print json events\n",
)]
pub format: Option<FormatSetting>,
// ============== POSITIONAL VALUES =======================================
/// Filter string. Only tests which contain this string are run.
#[arg(
value_name = "FILTER",
help = "The FILTER string is tested against the name of all tests, and only those tests \
whose names contain the filter are run.",
)]
pub filter: Option<String>,
}
impl Arguments {
/// Parses the global CLI arguments given to the application.
///
/// If the parsing fails (due to incorrect CLI args), an error is shown and
/// the application exits. If help is requested (`-h` or `--help`), a help
/// message is shown and the application exits, too.
pub fn from_args() -> Self {
Parser::parse()
}
/// Like `from_args()`, but operates on an explicit iterator and not the
/// global arguments. Note that the first element is the executable name!
pub fn from_iter<I>(iter: I) -> Self
where
Self: Sized,
I: IntoIterator,
I::Item: Into<std::ffi::OsString> + Clone,
{
Parser::parse_from(iter)
}
}
/// Possible values for the `--color` option.
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum ColorSetting {
/// Colorize output if stdout is a tty and tests are run on serially
/// (default).
Auto,
/// Always colorize output.
Always,
/// Never colorize output.
Never,
}
impl Default for ColorSetting {
fn default() -> Self {
ColorSetting::Auto
}
}
/// Possible values for the `-Z` option
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum UnstableFlags {
UnstableOptions,
}
/// Possible values for the `--format` option.
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum FormatSetting {
/// One line per test. Output for humans. (default)
Pretty,
/// One character per test. Usefull for test suites with many tests.
Terse,
/// Json output
Json,
}
impl Default for FormatSetting {
fn default() -> Self {
FormatSetting::Pretty
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn verify_cli() {
use clap::CommandFactory;
Arguments::command().debug_assert();
}
}