diff --git a/src/config.rs b/src/config.rs index 6779bab7..ef72de9b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,7 +10,7 @@ use std::{ }; mod args; -pub use args::Args; +pub use args::{Args, Format}; #[derive(Debug, Clone)] /// Central datastructure containing all information to run the tests. @@ -53,6 +53,12 @@ pub struct Config { pub filter_files: Vec, /// Override the number of threads to use. pub threads: Option, + /// Nextest emulation: only list the test itself, not its components. + pub list: bool, + /// Only run the tests that are ignored. + pub run_only_ignored: bool, + /// Filters must match exactly instead of just checking for substrings. + pub filter_exact: bool, } impl Config { @@ -94,6 +100,9 @@ impl Config { skip_files: Vec::new(), filter_files: Vec::new(), threads: None, + list: false, + run_only_ignored: false, + filter_exact: false, } } @@ -119,9 +128,12 @@ impl Config { pub fn with_args(&mut self, args: &Args, default_bless: bool) { let Args { ref filters, - quiet: _, check, bless, + list, + exact, + ignored, + format: _, threads, ref skip, } = *args; @@ -130,6 +142,10 @@ impl Config { self.filter_files.extend_from_slice(filters); self.skip_files.extend_from_slice(skip); + self.run_only_ignored = ignored; + self.filter_exact = exact; + + self.list = list; let bless = match (bless, check) { (_, true) => false, diff --git a/src/config/args.rs b/src/config/args.rs index 2d65dc7d..101c77d0 100644 --- a/src/config/args.rs +++ b/src/config/args.rs @@ -11,9 +11,6 @@ pub struct Args { /// Filters that will be used to match on individual tests pub filters: Vec, - /// Whether to minimize output given to the user. - pub quiet: bool, - /// Whether to error on mismatches between `.stderr` files and actual /// output. pub check: bool, @@ -22,6 +19,18 @@ pub struct Args { /// output. pub bless: bool, + /// Only run the test matching the filters exactly. + pub exact: bool, + + /// Whether to only run ignored tests. + pub ignored: bool, + + /// List the tests that can be run. + pub list: bool, + + /// Choose an output format + pub format: Format, + /// The number of threads to use pub threads: Option, @@ -29,6 +38,16 @@ pub struct Args { pub skip: Vec, } +/// Possible choices for styling the output. +#[derive(Debug, Copy, Clone, Default)] +pub enum Format { + /// Print one line per test + #[default] + Pretty, + /// Remove test lines once the test finishes and show a progress bar. + Terse, +} + impl Args { /// Parse the program arguments. /// This is meant to be used if `ui_test` is used as a `harness=false` test, called from `cargo test`. @@ -43,11 +62,25 @@ impl Args { continue; } if arg == "--quiet" { - self.quiet = true; + self.format = Format::Terse; } else if arg == "--check" { self.check = true; } else if arg == "--bless" { self.bless = true; + } else if arg == "--list" { + self.list = true; + } else if arg == "--exact" { + self.exact = true; + } else if arg == "--ignored" { + self.ignored = true; + } else if arg == "--nocapture" { + // We ignore this flag for now. + } else if let Some(format) = parse_value("--format", &arg, &mut iter)? { + self.format = match &*format { + "terse" => Format::Terse, + "pretty" => Format::Pretty, + _ => bail!("unsupported format `{format}`"), + }; } else if let Some(skip) = parse_value("--skip", &arg, &mut iter)? { self.skip.push(skip.into_owned()); } else if arg == "--help" { diff --git a/src/lib.rs b/src/lib.rs index 6e9152ef..c6f8fd1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,16 +116,15 @@ pub type Filter = Vec<(Match, &'static [u8])>; /// Will additionally process command line arguments. pub fn run_tests(mut config: Config) -> Result<()> { let args = Args::test()?; - if !args.quiet { + if let Format::Pretty = args.format { println!("Compiler: {}", config.program.display()); } let name = config.root_dir.display().to_string(); - let text = if args.quiet { - status_emitter::Text::quiet() - } else { - status_emitter::Text::verbose() + let text = match args.format { + Format::Terse => status_emitter::Text::quiet(), + Format::Pretty => status_emitter::Text::verbose(), }; config.with_args(&args, true); @@ -149,7 +148,15 @@ pub fn default_file_filter(path: &Path, config: &Config) -> bool { /// To only include rust files see [`default_file_filter`]. pub fn default_any_file_filter(path: &Path, config: &Config) -> bool { let path = path.display().to_string(); - let contains_path = |files: &[String]| files.iter().any(|f| path.contains(f)); + let contains_path = |files: &[String]| { + files.iter().any(|f| { + if config.filter_exact { + *f == path + } else { + path.contains(f) + } + }) + }; if contains_path(&config.skip_files) { return false; @@ -229,6 +236,23 @@ pub fn run_tests_generic( per_file_config: impl Fn(&mut Config, &Path, &[u8]) + Sync, status_emitter: impl StatusEmitter + Send, ) -> Result<()> { + // Nexttest emulation: we act as if we are one single test. + if configs.iter().any(|c| c.list) { + if configs.iter().any(|c| !c.run_only_ignored) { + println!("ui_test: test"); + } + return Ok(()); + } + for config in &mut configs { + if config.filter_exact + && config.filter_files.len() == 1 + && config.filter_files[0] == "ui_test" + { + config.filter_exact = false; + config.filter_files.clear(); + } + } + for config in &mut configs { config.fill_host_and_target()?; } @@ -1188,18 +1212,19 @@ impl dyn TestStatus { .flat_map(|r| r.ignore.iter()) .any(|c| test_condition(c, config)) { - return false; + return config.run_only_ignored; } if comments .for_revision(revision) .any(|r| r.needs_asm_support && !config.has_asm_support()) { - return false; + return config.run_only_ignored; } comments .for_revision(revision) .flat_map(|r| r.only.iter()) .all(|c| test_condition(c, config)) + ^ config.run_only_ignored } } diff --git a/src/status_emitter.rs b/src/status_emitter.rs index 224b8d90..167b9994 100644 --- a/src/status_emitter.rs +++ b/src/status_emitter.rs @@ -13,7 +13,7 @@ use crate::{ github_actions, parser::Pattern, rustc_stderr::{Message, Span}, - Error, Errored, Errors, TestOk, TestResult, + Error, Errored, Errors, Format, TestOk, TestResult, }; use std::{ collections::HashMap, @@ -184,6 +184,15 @@ impl Text { } } +impl From for Text { + fn from(format: Format) -> Self { + match format { + Format::Terse => Text::quiet(), + Format::Pretty => Text::verbose(), + } + } +} + struct TextTest { text: Text, path: PathBuf, diff --git a/tests/integration.rs b/tests/integration.rs index 8321d9e3..59384079 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -70,11 +70,7 @@ fn main() -> Result<()> { config.filter("program not found", "No such file or directory"); config.filter(" \\(os error [0-9]+\\)", ""); - let text = if args.quiet { - ui_test::status_emitter::Text::quiet() - } else { - ui_test::status_emitter::Text::verbose() - }; + let text = ui_test::status_emitter::Text::from(args.format); run_tests_generic( vec![