summaryrefslogtreecommitdiffstats
path: root/vendor/ui_test/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ui_test/src')
-rw-r--r--vendor/ui_test/src/config.rs9
-rw-r--r--vendor/ui_test/src/lib.rs152
-rw-r--r--vendor/ui_test/src/parser.rs37
3 files changed, 123 insertions, 75 deletions
diff --git a/vendor/ui_test/src/config.rs b/vendor/ui_test/src/config.rs
index 6f24cce90..8d92fe8d8 100644
--- a/vendor/ui_test/src/config.rs
+++ b/vendor/ui_test/src/config.rs
@@ -82,7 +82,10 @@ impl Config {
dependencies_crate_manifest_path: None,
dependency_builder: CommandBuilder::cargo(),
num_test_threads: std::thread::available_parallelism().unwrap(),
- out_dir: std::env::current_dir().unwrap().join("target/ui"),
+ out_dir: std::env::var_os("CARGO_TARGET_DIR")
+ .map(PathBuf::from)
+ .unwrap_or_else(|| std::env::current_dir().unwrap().join("target"))
+ .join("ui"),
edition: Some("2021".into()),
}
}
@@ -128,7 +131,9 @@ impl Config {
.push((Regex::new(pattern).unwrap().into(), replacement.as_ref()));
}
- pub(crate) fn build_dependencies_and_link_them(&mut self) -> Result<()> {
+ /// Compile dependencies and make sure `Config::program` contains the right flags
+ /// to find the dependencies.
+ pub fn build_dependencies_and_link_them(&mut self) -> Result<()> {
let dependencies = build_dependencies(self)?;
for (name, artifacts) in dependencies.dependencies {
for dependency in artifacts {
diff --git a/vendor/ui_test/src/lib.rs b/vendor/ui_test/src/lib.rs
index 7837d0e62..1420e2881 100644
--- a/vendor/ui_test/src/lib.rs
+++ b/vendor/ui_test/src/lib.rs
@@ -11,7 +11,7 @@
use bstr::ByteSlice;
pub use color_eyre;
use color_eyre::eyre::{eyre, Result};
-use crossbeam_channel::unbounded;
+use crossbeam_channel::{unbounded, Receiver, Sender};
use parser::{ErrorMatch, Revisioned};
use regex::bytes::Regex;
use rustc_stderr::{Diagnostics, Level, Message};
@@ -179,15 +179,11 @@ pub fn run_tests_generic(
config.build_dependencies_and_link_them()?;
- // A channel for files to process
- let (submit, receive) = unbounded();
-
let mut results = vec![];
- thread::scope(|s| -> Result<()> {
- // Create a thread that is in charge of walking the directory and submitting jobs.
- // It closes the channel when it is done.
- s.spawn(|| {
+ run_and_collect(
+ config.num_test_threads.get(),
+ |submit| {
let mut todo = VecDeque::new();
todo.push_back(config.root_dir.clone());
while let Some(path) = todo.pop_front() {
@@ -210,73 +206,51 @@ pub fn run_tests_generic(
submit.send(path).unwrap();
}
}
- // There will be no more jobs. This signals the workers to quit.
- // (This also ensures `submit` is moved into this closure.)
- drop(submit);
- });
-
- // A channel for the messages emitted by the individual test threads.
- // Used to produce live updates while running the tests.
- let (finished_files_sender, finished_files_recv) = unbounded::<TestRun>();
-
- s.spawn(|| {
+ },
+ |receive, finished_files_sender| -> Result<()> {
+ for path in receive {
+ let maybe_config;
+ let config = match per_file_config(&config, &path) {
+ None => &config,
+ Some(config) => {
+ maybe_config = config;
+ &maybe_config
+ }
+ };
+ let result = match std::panic::catch_unwind(|| parse_and_test_file(&path, config)) {
+ Ok(res) => res,
+ Err(err) => {
+ finished_files_sender.send(TestRun {
+ result: TestResult::Errored {
+ command: Command::new("<unknown>"),
+ errors: vec![Error::Bug(
+ *Box::<dyn std::any::Any + Send + 'static>::downcast::<String>(
+ err,
+ )
+ .unwrap(),
+ )],
+ stderr: vec![],
+ },
+ path,
+ revision: String::new(),
+ })?;
+ continue;
+ }
+ };
+ for result in result {
+ finished_files_sender.send(result)?;
+ }
+ }
+ Ok(())
+ },
+ |finished_files_recv| {
for run in finished_files_recv {
status_emitter.test_result(&run.path, &run.revision, &run.result);
results.push(run);
}
- });
-
- let mut threads = vec![];
-
- // Create N worker threads that receive files to test.
- for _ in 0..config.num_test_threads.get() {
- let finished_files_sender = finished_files_sender.clone();
- threads.push(s.spawn(|| -> Result<()> {
- let finished_files_sender = finished_files_sender;
- for path in &receive {
- let maybe_config;
- let config = match per_file_config(&config, &path) {
- None => &config,
- Some(config) => {
- maybe_config = config;
- &maybe_config
- }
- };
- let result =
- match std::panic::catch_unwind(|| parse_and_test_file(&path, config)) {
- Ok(res) => res,
- Err(err) => {
- finished_files_sender.send(TestRun {
- result: TestResult::Errored {
- command: Command::new("<unknown>"),
- errors: vec![Error::Bug(
- *Box::<dyn std::any::Any + Send + 'static>::downcast::<
- String,
- >(err)
- .unwrap(),
- )],
- stderr: vec![],
- },
- path,
- revision: String::new(),
- })?;
- continue;
- }
- };
- for result in result {
- finished_files_sender.send(result)?;
- }
- }
- Ok(())
- }));
- }
-
- for thread in threads {
- thread.join().unwrap()?;
- }
- Ok(())
- })?;
+ },
+ )?;
let mut failures = vec![];
let mut succeeded = 0;
@@ -309,6 +283,43 @@ pub fn run_tests_generic(
}
}
+/// A generic multithreaded runner that has a thread for producing work,
+/// a thread for collecting work, and `num_threads` threads for doing the work.
+pub fn run_and_collect<SUBMISSION: Send, RESULT: Send>(
+ num_threads: usize,
+ submitter: impl FnOnce(Sender<SUBMISSION>) + Send,
+ runner: impl Sync + Fn(&Receiver<SUBMISSION>, Sender<RESULT>) -> Result<()>,
+ collector: impl FnOnce(Receiver<RESULT>) + Send,
+) -> Result<()> {
+ // A channel for files to process
+ let (submit, receive) = unbounded();
+
+ thread::scope(|s| {
+ // Create a thread that is in charge of walking the directory and submitting jobs.
+ // It closes the channel when it is done.
+ s.spawn(|| submitter(submit));
+
+ // A channel for the messages emitted by the individual test threads.
+ // Used to produce live updates while running the tests.
+ let (finished_files_sender, finished_files_recv) = unbounded();
+
+ s.spawn(|| collector(finished_files_recv));
+
+ let mut threads = vec![];
+
+ // Create N worker threads that receive files to test.
+ for _ in 0..num_threads {
+ let finished_files_sender = finished_files_sender.clone();
+ threads.push(s.spawn(|| runner(&receive, finished_files_sender)));
+ }
+
+ for thread in threads {
+ thread.join().unwrap()?;
+ }
+ Ok(())
+ })
+}
+
fn parse_and_test_file(path: &Path, config: &Config) -> Vec<TestRun> {
let comments = match parse_comments_in_file(path) {
Ok(comments) => comments,
@@ -696,6 +707,7 @@ fn run_rustfix(
revisioned: std::iter::once((
vec![],
Revisioned {
+ line: 0,
ignore: vec![],
only: vec![],
stderr_per_bitwidth: false,
diff --git a/vendor/ui_test/src/parser.rs b/vendor/ui_test/src/parser.rs
index d2b510e1b..b041fb812 100644
--- a/vendor/ui_test/src/parser.rs
+++ b/vendor/ui_test/src/parser.rs
@@ -18,7 +18,7 @@ mod tests;
/// get processed by their respective use sites.
#[derive(Default, Debug)]
pub(crate) struct Comments {
- /// List of revision names to execute. Can only be speicified once
+ /// List of revision names to execute. Can only be specified once
pub revisions: Option<Vec<String>>,
/// Comments that are only available under specific revisions.
/// The defaults are in key `vec![]`
@@ -78,6 +78,9 @@ impl Comments {
#[derive(Default, Debug)]
/// Comments that can be filtered for specific revisions.
pub(crate) struct Revisioned {
+ /// The line in which this revisioned item was first added.
+ /// Used for reporting errors on unknown revisions.
+ pub line: usize,
/// Don't run this test if any of these filters apply
pub ignore: Vec<Condition>,
/// Only run this test if all of these filters apply
@@ -210,6 +213,27 @@ impl Comments {
}),
}
}
+ if let Some(revisions) = &parser.comments.revisions {
+ for (key, revisioned) in &parser.comments.revisioned {
+ for rev in key {
+ if !revisions.contains(rev) {
+ parser.errors.push(Error::InvalidComment {
+ msg: format!("the revision `{rev}` is not known"),
+ line: revisioned.line,
+ })
+ }
+ }
+ }
+ } else {
+ for (key, revisioned) in &parser.comments.revisioned {
+ if !key.is_empty() {
+ parser.errors.push(Error::InvalidComment {
+ msg: "there are no revisions in this test".into(),
+ line: revisioned.line,
+ })
+ }
+ }
+ }
if parser.errors.is_empty() {
Ok(parser.comments)
} else {
@@ -332,10 +356,17 @@ impl CommentParser<Comments> {
revisions: Vec<String>,
f: impl FnOnce(&mut CommentParser<&mut Revisioned>),
) {
+ let line = self.line;
let mut this = CommentParser {
errors: std::mem::take(&mut self.errors),
- line: self.line,
- comments: self.revisioned.entry(revisions).or_default(),
+ line,
+ comments: self
+ .revisioned
+ .entry(revisions)
+ .or_insert_with(|| Revisioned {
+ line,
+ ..Default::default()
+ }),
};
f(&mut this);
self.errors = this.errors;