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