diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/jobserver/tests/client.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | third_party/rust/jobserver/tests/client.rs | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/third_party/rust/jobserver/tests/client.rs b/third_party/rust/jobserver/tests/client.rs new file mode 100644 index 0000000000..2516b8ccf7 --- /dev/null +++ b/third_party/rust/jobserver/tests/client.rs @@ -0,0 +1,198 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc; +use std::sync::Arc; +use std::thread; + +use futures::future::{self, Future}; +use futures::stream::{self, Stream}; +use jobserver::Client; +use tokio_core::reactor::Core; +use tokio_process::CommandExt; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +struct Test { + name: &'static str, + f: &'static dyn Fn(), + make_args: &'static [&'static str], + rule: &'static dyn Fn(&str) -> String, +} + +const TESTS: &[Test] = &[ + Test { + name: "no j args", + make_args: &[], + rule: &|me| me.to_string(), + f: &|| { + assert!(unsafe { Client::from_env().is_none() }); + }, + }, + Test { + name: "no j args with plus", + make_args: &[], + rule: &|me| format!("+{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_none() }); + }, + }, + Test { + name: "j args with plus", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_some() }); + }, + }, + Test { + name: "acquire", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + drop(c.acquire().unwrap()); + drop(c.acquire().unwrap()); + }, + }, + Test { + name: "acquire3", + make_args: &["-j3"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + let a = c.acquire().unwrap(); + let b = c.acquire().unwrap(); + drop((a, b)); + }, + }, + Test { + name: "acquire blocks", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + let a = c.acquire().unwrap(); + let hit = Arc::new(AtomicBool::new(false)); + let hit2 = hit.clone(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + tx.send(()).unwrap(); + let _b = c.acquire().unwrap(); + hit2.store(true, Ordering::SeqCst); + }); + rx.recv().unwrap(); + assert!(!hit.load(Ordering::SeqCst)); + drop(a); + t.join().unwrap(); + assert!(hit.load(Ordering::SeqCst)); + }, + }, + Test { + name: "acquire_raw", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + c.acquire_raw().unwrap(); + c.release_raw().unwrap(); + }, + }, +]; + +fn main() { + if let Ok(test) = env::var("TEST_TO_RUN") { + return (TESTS.iter().find(|t| t.name == test).unwrap().f)(); + } + + let me = t!(env::current_exe()); + let me = me.to_str().unwrap(); + let filter = env::args().nth(1); + + let mut core = t!(Core::new()); + + let futures = TESTS + .iter() + .filter(|test| match filter { + Some(ref s) => test.name.contains(s), + None => true, + }) + .map(|test| { + let td = t!(tempfile::tempdir()); + let makefile = format!( + "\ +all: export TEST_TO_RUN={} +all: +\t{} +", + test.name, + (test.rule)(me) + ); + t!(t!(File::create(td.path().join("Makefile"))).write_all(makefile.as_bytes())); + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); + let mut cmd = Command::new(prog); + cmd.args(test.make_args); + cmd.current_dir(td.path()); + future::lazy(move || { + cmd.output_async().map(move |e| { + drop(td); + (test, e) + }) + }) + }) + .collect::<Vec<_>>(); + + println!("\nrunning {} tests\n", futures.len()); + + let stream = stream::iter(futures.into_iter().map(Ok)).buffer_unordered(num_cpus::get()); + + let mut failures = Vec::new(); + t!(core.run(stream.for_each(|(test, output)| { + if output.status.success() { + println!("test {} ... ok", test.name); + } else { + println!("test {} ... FAIL", test.name); + failures.push((test, output)); + } + Ok(()) + }))); + + if failures.is_empty() { + println!("\ntest result: ok\n"); + return; + } + + println!("\n----------- failures"); + + for (test, output) in failures { + println!("test {}", test.name); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + + println!("\texit status: {}", output.status); + if !stdout.is_empty() { + println!("\tstdout ==="); + for line in stdout.lines() { + println!("\t\t{}", line); + } + } + + if !stderr.is_empty() { + println!("\tstderr ==="); + for line in stderr.lines() { + println!("\t\t{}", line); + } + } + } + + std::process::exit(4); +} |