it: run tests in parallel
This commit is contained in:
parent
09d9f2ccbb
commit
fa8d079c72
4 changed files with 64 additions and 12 deletions
52
src/it.rs
52
src/it.rs
|
|
@ -6,17 +6,19 @@ use {
|
||||||
testrun::TestRun,
|
testrun::TestRun,
|
||||||
tests::TestCase,
|
tests::TestCase,
|
||||||
},
|
},
|
||||||
utils::errorfmt::ErrorFmt,
|
utils::{errorfmt::ErrorFmt, num_cpus::num_cpus},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
futures_util::{future, future::Either},
|
futures_util::{future, future::Either},
|
||||||
isnt::std_1::collections::IsntHashMapExt,
|
isnt::std_1::collections::IsntHashMapExt,
|
||||||
log::Level,
|
log::Level,
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::Cell,
|
||||||
|
collections::VecDeque,
|
||||||
future::pending,
|
future::pending,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
},
|
},
|
||||||
uapi::c,
|
uapi::c,
|
||||||
|
|
@ -37,23 +39,51 @@ mod test_utils;
|
||||||
mod testrun;
|
mod testrun;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
const SINGLE_THREAD: bool = false;
|
||||||
|
|
||||||
pub fn run_tests() {
|
pub fn run_tests() {
|
||||||
test_logger::install();
|
test_logger::install();
|
||||||
test_logger::set_level(Level::Trace);
|
test_logger::set_level(Level::Trace);
|
||||||
let it_run = ItRun {
|
let it_run = Arc::new(ItRun {
|
||||||
path: format!(
|
path: format!(
|
||||||
"{}/testruns/{}",
|
"{}/testruns/{}",
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
humantime::format_rfc3339_millis(SystemTime::now())
|
humantime::format_rfc3339_millis(SystemTime::now())
|
||||||
),
|
),
|
||||||
failed: Default::default(),
|
failed: Default::default(),
|
||||||
};
|
});
|
||||||
for test in tests::tests() {
|
if SINGLE_THREAD {
|
||||||
with_test_config(|cfg| {
|
for test in tests::tests() {
|
||||||
run_test(&it_run, test, cfg);
|
with_test_config(|cfg| {
|
||||||
})
|
run_test(&it_run, test, cfg);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let queue = Arc::new(Mutex::new(VecDeque::from_iter(tests::tests())));
|
||||||
|
let mut threads = vec![];
|
||||||
|
let num_cpus = match num_cpus() {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => fatal!("Could not determine the number of cpus: {}", ErrorFmt(e)),
|
||||||
|
};
|
||||||
|
log::info!("Running {} tests in parallel", num_cpus);
|
||||||
|
for _ in 0..num_cpus {
|
||||||
|
let queue = queue.clone();
|
||||||
|
let it_run = it_run.clone();
|
||||||
|
threads.push(std::thread::spawn(move || loop {
|
||||||
|
let test = match queue.lock().unwrap().pop_front() {
|
||||||
|
Some(t) => t,
|
||||||
|
_ => break,
|
||||||
|
};
|
||||||
|
with_test_config(|cfg| {
|
||||||
|
run_test(&it_run, test, cfg);
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
for thread in threads {
|
||||||
|
thread.join().unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let failed = it_run.failed.borrow_mut();
|
let failed = it_run.failed.lock().unwrap();
|
||||||
if failed.is_not_empty() {
|
if failed.is_not_empty() {
|
||||||
let mut failed: Vec<_> = failed.iter().collect();
|
let mut failed: Vec<_> = failed.iter().collect();
|
||||||
failed.sort_by_key(|f| f.0);
|
failed.sort_by_key(|f| f.0);
|
||||||
|
|
@ -70,7 +100,7 @@ pub fn run_tests() {
|
||||||
|
|
||||||
struct ItRun {
|
struct ItRun {
|
||||||
path: String,
|
path: String,
|
||||||
failed: RefCell<AHashMap<&'static str, Vec<String>>>,
|
failed: Mutex<AHashMap<&'static str, Vec<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test(it_run: &ItRun, test: &'static dyn TestCase, cfg: Rc<TestConfig>) {
|
fn run_test(it_run: &ItRun, test: &'static dyn TestCase, cfg: Rc<TestConfig>) {
|
||||||
|
|
@ -130,7 +160,7 @@ fn run_test(it_run: &ItRun, test: &'static dyn TestCase, cfg: Rc<TestConfig>) {
|
||||||
for e in &errors {
|
for e in &errors {
|
||||||
log::error!(" {}", e);
|
log::error!(" {}", e);
|
||||||
}
|
}
|
||||||
it_run.failed.borrow_mut().insert(test.name(), errors);
|
it_run.failed.lock().unwrap().insert(test.name(), errors);
|
||||||
}
|
}
|
||||||
test_logger::unset_file();
|
test_logger::unset_file();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ mod t0002_window;
|
||||||
mod t0003_multi_window;
|
mod t0003_multi_window;
|
||||||
mod t0004_quit;
|
mod t0004_quit;
|
||||||
|
|
||||||
pub trait TestCase {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn run(&self, testrun: Rc<TestRun>) -> Box<dyn Future<Output = Result<(), TestError>>>;
|
fn run(&self, testrun: Rc<TestRun>) -> Box<dyn Future<Output = Result<(), TestError>>>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ pub mod hex;
|
||||||
pub mod linkedlist;
|
pub mod linkedlist;
|
||||||
pub mod log_on_drop;
|
pub mod log_on_drop;
|
||||||
pub mod nonblock;
|
pub mod nonblock;
|
||||||
|
pub mod num_cpus;
|
||||||
pub mod numcell;
|
pub mod numcell;
|
||||||
pub mod oserror;
|
pub mod oserror;
|
||||||
pub mod ptr_ext;
|
pub mod ptr_ext;
|
||||||
|
|
|
||||||
21
src/utils/num_cpus.rs
Normal file
21
src/utils/num_cpus.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
use {
|
||||||
|
crate::utils::oserror::OsError,
|
||||||
|
smallvec::{smallvec_inline, SmallVec},
|
||||||
|
uapi::{c, Errno},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn num_cpus() -> Result<u32, OsError> {
|
||||||
|
let mut buf: SmallVec<[usize; 32]> = smallvec_inline![0; 32];
|
||||||
|
loop {
|
||||||
|
match uapi::sched_getaffinity(0, &mut buf) {
|
||||||
|
Ok(_) => return Ok(count(&buf)),
|
||||||
|
Err(Errno(c::EINVAL)) => buf.extend_from_slice(&[0; 32][..]),
|
||||||
|
Err(e) => return Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count(buf: &[usize]) -> u32 {
|
||||||
|
buf.iter().copied().map(|n| n.count_ones()).sum()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue