diff --git a/aoc/src/run.rs b/aoc/src/run.rs index 9394cfd..f99ed1b 100644 --- a/aoc/src/run.rs +++ b/aoc/src/run.rs @@ -1,6 +1,6 @@ use chrono::{Datelike, Duration}; use clap::Parser; -use itertools::Itertools; +use std::fmt::Write; #[derive(Parser)] #[clap(version, author)] @@ -46,6 +46,44 @@ fn pretty_duration(duration: Duration) -> String { } } +#[allow(clippy::module_name_repetitions)] +pub fn run_tests( + register: F, + single_day: Option, + main_only: bool, + timings: bool, +) -> eyre::Result +where + F: Fn(), +{ + register(); + let mut results = String::new(); + let mut runners = super::runners::RUNNERS.lock().unwrap(); + let keys = runners.keys().copied().collect::>(); + for (day, part) in keys { + if single_day.map_or(true, |d| d == day) { + for (version, runner) in runners.remove(&(day, part)).unwrap() { + if main_only && version.is_some() { + continue; + } + write!(&mut results, "Day {day} - part {part}")?; + if let Some(version) = version { + write!(&mut results, " — {version}")?; + } + let before = chrono::Utc::now(); + let result = runner()?; + let after = chrono::Utc::now(); + write!(&mut results, ": {result}")?; + if timings { + write!(&mut results, " ({})", pretty_duration(after - before))?; + } + writeln!(&mut results)?; + } + } + } + Ok(results) +} + pub fn run(register: F) -> eyre::Result<()> where F: Fn(), @@ -62,35 +100,14 @@ where super::input::OVERRIDE_INPUT = opts.input; } let current_day = opts.day.unwrap_or(chrono::Utc::now().day() as usize); - register(); - let mut runners = super::runners::RUNNERS.lock().unwrap(); - let keys = runners.keys().copied().collect::>(); - for (day, part) in keys { - if day == current_day || opts.all { - for (version, runner) in runners.remove(&(day, part)).unwrap() { - if opts.main_only && version.is_some() { - continue; - } - let before = chrono::Utc::now(); - let result = runner(); - let after = chrono::Utc::now(); - let version = version - .clone() - .map_or_else(String::new, |v| format!(" — {v}")); - let elapsed = if opts.timing { - format!(" ({})", pretty_duration(after - before)) - } else { - String::new() - }; - let header = format!("Day {day} - part {part}{version}: "); - let sep = format!("\n{}", " ".repeat(header.len())); - let result = match result { - Ok(e) => e.lines().join(&sep), - Err(e) => format!(""), - }; - println!("{header}{result}{elapsed}"); - } - } - } + println!( + "{}", + run_tests( + register, + (!opts.all).then_some(current_day), + opts.main_only, + opts.timing + )? + ); Ok(()) } diff --git a/aoc/src/test.rs b/aoc/src/test.rs index 2c8e66a..c6c42c1 100644 --- a/aoc/src/test.rs +++ b/aoc/src/test.rs @@ -4,14 +4,6 @@ use std::process::Command; const ENV_VAR: &str = "RECORD_RESULTS"; -fn run_with(args: &[&str]) -> eyre::Result { - let output = Command::new("cargo") - .args(["run", "--release", "--", "-a"]) - .args(args) - .output()?; - Ok(String::from_utf8(output.stdout)?) -} - fn equal_content>(actual: &str, expected: P, show_diff: bool) -> eyre::Result { let expected_content = std::fs::read_to_string(expected.as_ref()).context(format!( "cannot read {}", @@ -41,12 +33,12 @@ fn equal_content>(actual: &str, expected: P, show_diff: bool) -> } } -pub fn check_results>(expected: P, main_only: bool) -> eyre::Result { - let actual = if main_only { - run_with(&["-m"])? - } else { - run_with(&[])? - }; +pub fn check_results>( + register: F, + expected: P, + main_only: bool, +) -> eyre::Result { + let actual = super::run::run_tests(register, None, false, main_only)?; let update = std::env::var(ENV_VAR).is_ok(); if update { if !matches!(equal_content(&actual, &expected, false), Ok(true)) { diff --git a/aoc/tests/dummy-year.rs b/aoc/tests/dummy-year.rs index 1be54ee..fb4f09d 100644 --- a/aoc/tests/dummy-year.rs +++ b/aoc/tests/dummy-year.rs @@ -65,21 +65,3 @@ fn all_days_main() { Day 2 - part 2: 3842356 "###); } - -#[test] -#[serial] -fn check_expected_main() { - let dir = std::env::current_dir().unwrap(); - std::env::set_current_dir("../dummy-year").unwrap(); - assert!(aoc::test::check_results("expected.txt", true).unwrap()); - std::env::set_current_dir(dir).unwrap(); -} - -#[test] -#[serial] -fn check_expected() { - let dir = std::env::current_dir().unwrap(); - std::env::set_current_dir("../dummy-year").unwrap(); - assert!(aoc::test::check_results("expected-all.txt", false).unwrap()); - std::env::set_current_dir(dir).unwrap(); -} diff --git a/dummy-year/expected-all.txt b/dummy-year/expected-all.txt deleted file mode 100644 index d64c47f..0000000 --- a/dummy-year/expected-all.txt +++ /dev/null @@ -1,7 +0,0 @@ -Day 1 - part 1: 232 -Day 1 - part 1 — str_slice: 232 -Day 1 - part 2: 1783 -Day 1 - part 2 — result: 1783 -Day 1 - part 2 — result_string: 1783 -Day 2 - part 1: 1606483 -Day 2 - part 2: 3842356 diff --git a/dummy-year/expected.txt b/dummy-year/expected.txt index 0ee80ec..d64c47f 100644 --- a/dummy-year/expected.txt +++ b/dummy-year/expected.txt @@ -1,4 +1,7 @@ Day 1 - part 1: 232 +Day 1 - part 1 — str_slice: 232 Day 1 - part 2: 1783 +Day 1 - part 2 — result: 1783 +Day 1 - part 2 — result_string: 1783 Day 2 - part 1: 1606483 Day 2 - part 2: 3842356 diff --git a/dummy-year/src/day1.rs b/dummy-year/src/day1.rs index 38b5f8b..a57410c 100644 --- a/dummy-year/src/day1.rs +++ b/dummy-year/src/day1.rs @@ -7,7 +7,7 @@ fn part1(input: &str) -> usize { #[aoc(day1, part1, str_slice)] fn part1_string_slice(input: &[&str]) -> usize { - input.iter().cloned().map(part1).sum() + input.iter().copied().map(part1).sum() } #[aoc(day1, part2)] diff --git a/dummy-year/tests/check-expected.rs b/dummy-year/tests/check-expected.rs new file mode 100644 index 0000000..7019b81 --- /dev/null +++ b/dummy-year/tests/check-expected.rs @@ -0,0 +1,9 @@ +#[test] +fn check_expected() { + assert!(aoc::test::check_results( + dummy_year::register::register_runners, + "expected.txt", + false + ) + .unwrap()); +}