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 num_args = 1, 93 help = "Skip tests whose names contain FILTER (this flag can be used multiple times)", 94 )] 95 pub skip: Vec<String>, 96 97 /// Specifies whether or not to color the output. 98 #[arg( 99 long = "color", 100 value_enum, 101 value_name = "auto|always|never", 102 help = "Configure coloring of output: \n\ 103 - auto = colorize if stdout is a tty and tests are run on serially (default)\n\ 104 - always = always colorize output\n\ 105 - never = never colorize output\n", 106 )] 107 pub color: Option<ColorSetting>, 108 109 /// Specifies the format of the output. 110 #[arg( 111 long = "format", 112 value_enum, 113 value_name = "pretty|terse|json", 114 help = "Configure formatting of output: \n\ 115 - pretty = Print verbose output\n\ 116 - terse = Display one character per test\n", 117 )] 118 pub format: Option<FormatSetting>, 119 120 // ============== POSITIONAL VALUES ======================================= 121 /// Filter string. Only tests which contain this string are run. 122 #[arg( 123 value_name = "FILTER", 124 help = "The FILTER string is tested against the name of all tests, and only those tests \ 125 whose names contain the filter are run.", 126 )] 127 pub filter: Option<String>, 128 } 129 130 impl Arguments { 131 /// Parses the global CLI arguments given to the application. 132 /// 133 /// If the parsing fails (due to incorrect CLI args), an error is shown and 134 /// the application exits. If help is requested (`-h` or `--help`), a help 135 /// message is shown and the application exits, too. from_args() -> Self136 pub fn from_args() -> Self { 137 Parser::parse() 138 } 139 140 /// Like `from_args()`, but operates on an explicit iterator and not the 141 /// 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,142 pub fn from_iter<I>(iter: I) -> Self 143 where 144 Self: Sized, 145 I: IntoIterator, 146 I::Item: Into<std::ffi::OsString> + Clone, 147 { 148 Parser::parse_from(iter) 149 } 150 } 151 152 /// Possible values for the `--color` option. 153 #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)] 154 pub enum ColorSetting { 155 /// Colorize output if stdout is a tty and tests are run on serially 156 /// (default). 157 Auto, 158 159 /// Always colorize output. 160 Always, 161 162 /// Never colorize output. 163 Never, 164 } 165 166 impl Default for ColorSetting { default() -> Self167 fn default() -> Self { 168 ColorSetting::Auto 169 } 170 } 171 172 /// Possible values for the `--format` option. 173 #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)] 174 pub enum FormatSetting { 175 /// One line per test. Output for humans. (default) 176 Pretty, 177 178 /// One character per test. Usefull for test suites with many tests. 179 Terse, 180 } 181 182 impl Default for FormatSetting { default() -> Self183 fn default() -> Self { 184 FormatSetting::Pretty 185 } 186 } 187 188 #[cfg(test)] 189 mod tests { 190 use super::*; 191 192 #[test] verify_cli()193 fn verify_cli() { 194 use clap::CommandFactory; 195 Arguments::command().debug_assert(); 196 } 197 } 198