mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-27 00:00:03 +03:00
Run solutions in parallel
This commit is contained in:
parent
98db579014
commit
42a3503906
|
@ -4,6 +4,11 @@ use std::{
|
||||||
fs::{self, read_dir, OpenOptions},
|
fs::{self, read_dir, OpenOptions},
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
sync::{
|
||||||
|
atomic::{self, AtomicBool},
|
||||||
|
Mutex,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -167,36 +172,52 @@ fn check_exercises(info_file: &InfoFile) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_solutions(require_solutions: bool, info_file: &InfoFile) -> Result<()> {
|
fn check_solutions(require_solutions: bool, info_file: &InfoFile) -> Result<()> {
|
||||||
let mut paths = hashbrown::HashSet::with_capacity(info_file.exercises.len());
|
|
||||||
let target_dir = parse_target_dir()?;
|
let target_dir = parse_target_dir()?;
|
||||||
let mut output = Vec::with_capacity(OUTPUT_CAPACITY);
|
let paths = Mutex::new(hashbrown::HashSet::with_capacity(info_file.exercises.len()));
|
||||||
|
let error_occured = AtomicBool::new(false);
|
||||||
|
|
||||||
|
println!("Running all solutions. This may take a while...\n");
|
||||||
|
thread::scope(|s| {
|
||||||
for exercise_info in &info_file.exercises {
|
for exercise_info in &info_file.exercises {
|
||||||
|
s.spawn(|| {
|
||||||
|
let error = |e| {
|
||||||
|
let mut stderr = io::stderr().lock();
|
||||||
|
stderr.write_all(e).unwrap();
|
||||||
|
stderr
|
||||||
|
.write_all(b"\nFailed to run the solution of the exercise ")
|
||||||
|
.unwrap();
|
||||||
|
stderr.write_all(exercise_info.name.as_bytes()).unwrap();
|
||||||
|
stderr.write_all(SEPARATOR).unwrap();
|
||||||
|
error_occured.store(true, atomic::Ordering::Relaxed);
|
||||||
|
};
|
||||||
|
|
||||||
let path = exercise_info.sol_path();
|
let path = exercise_info.sol_path();
|
||||||
if !Path::new(&path).exists() {
|
if !Path::new(&path).exists() {
|
||||||
if require_solutions {
|
if require_solutions {
|
||||||
bail!("Exercise {} is missing a solution", exercise_info.name);
|
error(b"Solution missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
// No solution to check.
|
// No solution to check.
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Running the solution of {}", exercise_info.name);
|
let mut output = Vec::with_capacity(OUTPUT_CAPACITY);
|
||||||
let success = exercise_info.run_solution(&mut output, &target_dir)?;
|
match exercise_info.run_solution(&mut output, &target_dir) {
|
||||||
if !success {
|
Ok(true) => {
|
||||||
io::stderr().write_all(&output)?;
|
paths.lock().unwrap().insert(PathBuf::from(path));
|
||||||
|
}
|
||||||
|
Ok(false) => error(&output),
|
||||||
|
Err(e) => error(e.to_string().as_bytes()),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
bail!(
|
if error_occured.load(atomic::Ordering::Relaxed) {
|
||||||
"Failed to run the solution of the exercise {}",
|
bail!("At least one solution failed. See the output above.");
|
||||||
exercise_info.name,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paths.insert(PathBuf::from(path));
|
check_unexpected_files("solutions", &paths.into_inner().unwrap())?;
|
||||||
}
|
|
||||||
|
|
||||||
check_unexpected_files("solutions", &paths)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -224,3 +245,6 @@ pub fn check(require_solutions: bool) -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SEPARATOR: &[u8] =
|
||||||
|
b"\n========================================================================================\n";
|
||||||
|
|
Loading…
Reference in a new issue