in src/lib.rs [178:230]
fn run_tests(&self, memory: &mut [usize], deadline: Instant) -> Vec<TestReport> {
let mut reports = Vec::new();
let mut timed_out = false;
for test_kind in &self.test_kinds {
let test_result = if timed_out {
Err(memtest::Error::Observer(RuntimeError::Timeout))
} else if self.allow_multithread {
std::thread::scope(|scope| {
let num_threads = num_cpus::get();
let chunk_size = memory.len() / num_threads;
let mut handles = vec![];
for chunk in memory.chunks_exact_mut(chunk_size) {
handles.push(scope.spawn(|| self.run_test(*test_kind, chunk, deadline)));
}
#[allow(clippy::manual_try_fold)]
handles
.into_iter()
.map(|handle| {
handle
.join()
.unwrap_or(Err(memtest::Error::Other(anyhow!("Thread panicked"))))
})
.fold(Ok(Outcome::Pass), |acc, result| {
use {memtest::Error::*, Outcome::*};
match (acc, result) {
(Err(Other(e)), _) | (_, Err(Other(e))) => Err(Other(e)),
(Ok(Fail(f)), _) | (_, Ok(Fail(f))) => Ok(Fail(f)),
(Err(Observer(e)), _) | (_, Err(Observer(e))) => Err(Observer(e)),
_ => Ok(Pass),
}
})
})
} else {
self.run_test(*test_kind, memory, deadline)
};
timed_out = matches!(
test_result,
Err(memtest::Error::Observer(RuntimeError::Timeout))
);
if matches!(test_result, Ok(Outcome::Fail(_))) && self.allow_early_termination {
reports.push(TestReport::new(*test_kind, test_result));
warn!("Test failed, terminating early");
break;
}
reports.push(TestReport::new(*test_kind, test_result));
}
reports
}