diff options
| author | mo8it <mo8it@proton.me> | 2024-08-01 15:53:32 +0200 |
|---|---|---|
| committer | mo8it <mo8it@proton.me> | 2024-08-01 15:53:32 +0200 |
| commit | e0f0944bffe607af9e6059df7a65d4b9b0b99e4f (patch) | |
| tree | 712f2533ff5fed1ee511b7f2d964b075ebb96573 /src/dev/check.rs | |
| parent | c7590dd752ab35d06a85f016e88921f10934e6aa (diff) | |
Refactor check_solutions
Diffstat (limited to 'src/dev/check.rs')
| -rw-r--r-- | src/dev/check.rs | 99 |
1 files changed, 58 insertions, 41 deletions
diff --git a/src/dev/check.rs b/src/dev/check.rs index db5b21f..0d1e587 100644 --- a/src/dev/check.rs +++ b/src/dev/check.rs @@ -1,13 +1,10 @@ -use anyhow::{anyhow, bail, Context, Result}; +use anyhow::{anyhow, bail, Context, Error, Result}; use std::{ cmp::Ordering, fs::{self, read_dir, OpenOptions}, io::{self, Read, Write}, path::{Path, PathBuf}, - sync::{ - atomic::{self, AtomicBool}, - Mutex, - }, + sync::atomic::{self, AtomicBool}, thread, }; @@ -213,56 +210,76 @@ fn check_exercises(info_file: &InfoFile, cmd_runner: &CmdRunner) -> Result<()> { check_exercises_unsolved(info_file, cmd_runner) } +enum SolutionCheck { + Success { sol_path: String }, + MissingRequired, + MissingOptional, + RunFailure { output: Vec<u8> }, + Err(Error), +} + fn check_solutions( require_solutions: bool, info_file: &InfoFile, cmd_runner: &CmdRunner, ) -> Result<()> { - let paths = Mutex::new(hashbrown::HashSet::with_capacity(info_file.exercises.len())); - let error_occurred = AtomicBool::new(false); - println!("Running all solutions. This may take a while…\n"); - thread::scope(|s| { - 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_occurred.store(true, atomic::Ordering::Relaxed); - }; + let sol_paths = thread::scope(|s| { + let handles = info_file + .exercises + .iter() + .map(|exercise_info| { + s.spawn(|| { + let sol_path = exercise_info.sol_path(); + if !Path::new(&sol_path).exists() { + if require_solutions { + return SolutionCheck::MissingRequired; + } + + return SolutionCheck::MissingOptional; + } - let path = exercise_info.sol_path(); - if !Path::new(&path).exists() { - if require_solutions { - error(b"Solution missing"); + let mut output = Vec::with_capacity(OUTPUT_CAPACITY); + match exercise_info.run_solution(Some(&mut output), cmd_runner) { + Ok(true) => SolutionCheck::Success { sol_path }, + Ok(false) => SolutionCheck::RunFailure { output }, + Err(e) => SolutionCheck::Err(e), } + }) + }) + .collect::<Vec<_>>(); - // No solution to check. - return; - } + let mut sol_paths = hashbrown::HashSet::with_capacity(info_file.exercises.len()); - let mut output = Vec::with_capacity(OUTPUT_CAPACITY); - match exercise_info.run_solution(Some(&mut output), cmd_runner) { - Ok(true) => { - paths.lock().unwrap().insert(PathBuf::from(path)); - } - Ok(false) => error(&output), - Err(e) => error(e.to_string().as_bytes()), + for (exercise_name, handle) in info_file + .exercises + .iter() + .map(|exercise_info| &exercise_info.name) + .zip(handles) + { + match handle.join() { + Ok(SolutionCheck::Success { sol_path }) => { + sol_paths.insert(PathBuf::from(sol_path)); } - }); + Ok(SolutionCheck::MissingRequired) => { + bail!("The solution of the exercise {exercise_name} is missing"); + } + Ok(SolutionCheck::MissingOptional) => (), + Ok(SolutionCheck::RunFailure { output }) => { + io::stderr().lock().write_all(&output)?; + bail!("Running the solution of the exercise {exercise_name} failed with the error above"); + } + Ok(SolutionCheck::Err(e)) => return Err(e), + Err(_) => { + bail!("Panic while trying to run the solution of the exericse {exercise_name}"); + } + } } - }); - if error_occurred.load(atomic::Ordering::Relaxed) { - bail!("At least one solution failed. See the output above."); - } + Ok(sol_paths) + })?; - check_unexpected_files("solutions", &paths.into_inner().unwrap())?; + check_unexpected_files("solutions", &sol_paths)?; Ok(()) } |
