From cf604ff98b5d23c803252b4e7fa67ffb305f3133 Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Fri, 30 Aug 2024 21:13:54 +0200 Subject: [PATCH] Fixed missing validation for given day or task in benchmakr files --- Cargo.lock | 1 + Cargo.toml | 3 ++ crates/cli/Cargo.toml | 4 ++ crates/cli/src/benchmarking.rs | 43 ++++++++++--------- .../cli/src/benchmarking/file_to_benchmark.rs | 29 +++++++++++++ ...chmark__testing__deserlize_with_error.snap | 15 +++++++ ..._testing__deserlize_with_invalid_task.snap | 15 +++++++ ...enchmark__testing__deserlize_with_ron.snap | 28 ++++++++++++ .../test_benchmark_as_correct.ron | 14 ++++++ .../test_benchmark_with_invalid_day.ron | 14 ++++++ .../test_benchmark_with_invalid_task.ron | 14 ++++++ crates/cli/src/cli/given_day.rs | 14 +++++- crates/cli/src/cli/given_task.rs | 11 ++++- crates/solutions/Cargo.toml | 2 +- real_benchmark.ron | 24 +++++------ 15 files changed, 196 insertions(+), 35 deletions(-) create mode 100644 crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_error.snap create mode 100644 crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_invalid_task.snap create mode 100644 crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_ron.snap create mode 100644 crates/cli/src/benchmarking/test_benchmark_as_correct.ron create mode 100644 crates/cli/src/benchmarking/test_benchmark_with_invalid_day.ron create mode 100644 crates/cli/src/benchmarking/test_benchmark_with_invalid_task.ron diff --git a/Cargo.lock b/Cargo.lock index 05c86e7..8133229 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,6 +10,7 @@ dependencies = [ "clap", "derive_more", "env_logger", + "insta", "log", "prettytable-rs", "ron", diff --git a/Cargo.toml b/Cargo.toml index 870ac71..b4efd0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,6 @@ default-members = ["crates/cli"] [workspace.dependencies] derive_more = { version = "1", features = ["full"] } thiserror = "1.0.63" +insta = "1.39.0" + + diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 232596b..9eb48f2 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -8,6 +8,7 @@ solutions_advent_of_code_2023 = { path = "../solutions" } derive_more = { workspace = true } thiserror = { workspace = true } + serde = { version = "1.0.209", features = ["derive"] } clap = { version = "4.5.15", features = ["derive"] } @@ -16,3 +17,6 @@ log = "0.4.22" anyhow = "1.0.86" ron = "0.8.1" prettytable-rs = "0.10.0" + +[dev-dependencies] +insta = { workspace = true } diff --git a/crates/cli/src/benchmarking.rs b/crates/cli/src/benchmarking.rs index eb555eb..0670509 100644 --- a/crates/cli/src/benchmarking.rs +++ b/crates/cli/src/benchmarking.rs @@ -11,7 +11,7 @@ mod row_building; use crate::{ cli::BenchmarkCli, solving_given::{solve_given, NoSolutionFound}, - AppError, AppResult, + AppResult, }; use anyhow::anyhow; use std::time::{Duration, Instant}; @@ -59,27 +59,30 @@ fn solve_and_keep_track_of_runtime( } fn load_benchmarks(args: &BenchmarkCli) -> AppResult> { - args.files() - .iter() - .flat_map(|path| { - let content = std::fs::read_to_string(path).map_err(|error| { - anyhow!( - "Could not read benchmark file at {:?}\n\ + let mut parsed_benchmarks = Vec::new(); + for next_paths in args.files() { + let content = std::fs::read_to_string(next_paths).map_err(|error| { + anyhow!( + "Could not read benchmark file at {:?}\n\ Details: {}", - path, - error - ) - })?; - let parsed: Vec = ron::from_str(&content).map_err(|error| { - anyhow!( - "Content of benchmark file at ({:?}) is in an invalid ron format\n\ + next_paths, + error + ) + })?; + let parsed: Vec = ron::from_str(&content).map_err(|error| { + dbg!(); + anyhow!( + "Content of benchmark file at ({:?}) is in an invalid ron format\n\ Details of invalid format: {}", - path, - error - ) - })?; - Ok::<_, AppError>(parsed) - }) + next_paths, + error + ) + })?; + parsed_benchmarks.push(parsed); + } + + parsed_benchmarks + .into_iter() .flatten() .map(|benchmark| { let where_to_look = benchmark.where_to_look(); diff --git a/crates/cli/src/benchmarking/file_to_benchmark.rs b/crates/cli/src/benchmarking/file_to_benchmark.rs index 4107d05..274927c 100644 --- a/crates/cli/src/benchmarking/file_to_benchmark.rs +++ b/crates/cli/src/benchmarking/file_to_benchmark.rs @@ -74,3 +74,32 @@ impl FileToBenchmark { &self.expected_output } } + +#[cfg(test)] +mod testing { + + use ron::error::SpannedResult; + + use crate::benchmarking::FileToBenchmark; + + #[test] + fn deserlize_with_error() { + const INPUT: &str = include_str!("test_benchmark_with_invalid_day.ron"); + let actual: SpannedResult> = ron::from_str(INPUT); + insta::assert_debug_snapshot!(actual); + } + + #[test] + fn deserlize_with_invalid_task() { + const INPUT: &str = include_str!("test_benchmark_with_invalid_task.ron"); + let actual: SpannedResult> = ron::from_str(INPUT); + insta::assert_debug_snapshot!(actual); + } + + #[test] + fn deserlize_with_ron() { + const INPUT: &str = include_str!("test_benchmark_as_correct.ron"); + let actual: SpannedResult> = ron::from_str(INPUT); + insta::assert_debug_snapshot!(actual); + } +} diff --git a/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_error.snap b/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_error.snap new file mode 100644 index 0000000..154d77c --- /dev/null +++ b/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_error.snap @@ -0,0 +1,15 @@ +--- +source: crates/cli/src/benchmarking/file_to_benchmark.rs +expression: actual +--- +Err( + SpannedError { + code: Message( + "(30) is not within the valid range between 0 and 25", + ), + position: Position { + line: 3, + col: 22, + }, + }, +) diff --git a/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_invalid_task.snap b/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_invalid_task.snap new file mode 100644 index 0000000..f9f6126 --- /dev/null +++ b/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_invalid_task.snap @@ -0,0 +1,15 @@ +--- +source: crates/cli/src/benchmarking/file_to_benchmark.rs +expression: actual +--- +Err( + SpannedError { + code: Message( + "(3) is not within the valid range between 1 and 2", + ), + position: Position { + line: 4, + col: 22, + }, + }, +) diff --git a/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_ron.snap b/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_ron.snap new file mode 100644 index 0000000..fbb6e13 --- /dev/null +++ b/crates/cli/src/benchmarking/snapshots/advent_of_code_2023__benchmarking__file_to_benchmark__testing__deserlize_with_ron.snap @@ -0,0 +1,28 @@ +--- +source: crates/cli/src/benchmarking/file_to_benchmark.rs +expression: actual +--- +Ok( + [ + FileToBenchmark { + given_day: GivenDay( + 5, + ), + given_task: GivenTask( + 2, + ), + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + }, + FileToBenchmark { + given_day: GivenDay( + 5, + ), + given_task: GivenTask( + 1, + ), + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + }, + ], +) diff --git a/crates/cli/src/benchmarking/test_benchmark_as_correct.ron b/crates/cli/src/benchmarking/test_benchmark_as_correct.ron new file mode 100644 index 0000000..624bbda --- /dev/null +++ b/crates/cli/src/benchmarking/test_benchmark_as_correct.ron @@ -0,0 +1,14 @@ +[ + ( + given_day: 5, + given_task: 2, + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ), + ( + given_day: 5, + given_task: 1, + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ) +] diff --git a/crates/cli/src/benchmarking/test_benchmark_with_invalid_day.ron b/crates/cli/src/benchmarking/test_benchmark_with_invalid_day.ron new file mode 100644 index 0000000..274cfc5 --- /dev/null +++ b/crates/cli/src/benchmarking/test_benchmark_with_invalid_day.ron @@ -0,0 +1,14 @@ +[ + ( + given_day: 30, + given_task: 2, + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ), + ( + given_day: 5, + given_task: 1, + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ) +] diff --git a/crates/cli/src/benchmarking/test_benchmark_with_invalid_task.ron b/crates/cli/src/benchmarking/test_benchmark_with_invalid_task.ron new file mode 100644 index 0000000..2730be7 --- /dev/null +++ b/crates/cli/src/benchmarking/test_benchmark_with_invalid_task.ron @@ -0,0 +1,14 @@ +[ + ( + given_day: 10, + given_task: 3, + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ), + ( + given_day: 5, + given_task: 1, + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ) +] diff --git a/crates/cli/src/cli/given_day.rs b/crates/cli/src/cli/given_day.rs index 9fa8ac4..4efb43f 100644 --- a/crates/cli/src/cli/given_day.rs +++ b/crates/cli/src/cli/given_day.rs @@ -13,13 +13,25 @@ pub enum InvalidGivenDayError { constants::MAX_DAY )] InvalidFormat(Arc), - #[error("({0}) is within the valid range between 0 and {}", constants::MAX_DAY)] + #[error( + "({0}) is not within the valid range between 0 and {}", + constants::MAX_DAY + )] InvalidRange(u32), } #[derive(Debug, Copy, Clone, Into, PartialEq, Eq, Serialize, Deserialize, Display)] +#[serde(try_from = "u32")] pub struct GivenDay(u32); +impl TryFrom for GivenDay { + type Error = InvalidGivenDayError; + + fn try_from(value: u32) -> Result { + Self::new(value) + } +} + impl GivenDay { pub fn new(value: u32) -> Result { if (1..=constants::MAX_DAY).contains(&value) { diff --git a/crates/cli/src/cli/given_task.rs b/crates/cli/src/cli/given_task.rs index 2a4fe59..914a834 100644 --- a/crates/cli/src/cli/given_task.rs +++ b/crates/cli/src/cli/given_task.rs @@ -13,15 +13,24 @@ pub enum InvalidGivenTaskError { )] InvalidFormat(Arc), #[error( - "({0}) is within the valid range between 1 and {}", + "({0}) is not within the valid range between 1 and {}", constants::MAX_TASK )] InvalidRange(u32), } #[derive(Debug, Copy, Into, Clone, PartialEq, Eq, Serialize, Deserialize, Display)] +#[serde(try_from = "u32")] pub struct GivenTask(u32); +impl TryFrom for GivenTask { + type Error = InvalidGivenTaskError; + + fn try_from(value: u32) -> Result { + Self::new(value) + } +} + impl GivenTask { pub fn new(value: u32) -> Result { if (1..=constants::MAX_TASK).contains(&value) { diff --git a/crates/solutions/Cargo.toml b/crates/solutions/Cargo.toml index a127a94..93a6d06 100644 --- a/crates/solutions/Cargo.toml +++ b/crates/solutions/Cargo.toml @@ -12,4 +12,4 @@ thiserror = { workspace = true } regex = "1.10.6" [dev-dependencies] -insta = "1.39.0" +insta = { workspace = true } diff --git a/real_benchmark.ron b/real_benchmark.ron index fa7408f..9805dc8 100644 --- a/real_benchmark.ron +++ b/real_benchmark.ron @@ -1,37 +1,37 @@ [ ( - given_day: GivenDay(5), - given_task: GivenTask(2), + given_day: 5, + given_task: 2, where_to_look: "real_puzzel_input/day5_real.txt", expected_output: "42", ), ( - given_day: GivenDay(5), - given_task: GivenTask(1), + given_day: 5, + given_task: 1, where_to_look: "real_puzzel_input/day5_real.txt", expected_output: "42", ), ( - given_day: GivenDay(6), - given_task: GivenTask(1), + given_day: 6, + given_task: 1, where_to_look: "real_puzzel_input/day6_real.txt", expected_output: "42", ), ( - given_day: GivenDay(6), - given_task: GivenTask(2), + given_day: 6, + given_task: 2, where_to_look: "real_puzzel_input/day6_real.txt", expected_output: "42", ), ( - given_day: GivenDay(7), - given_task: GivenTask(1), + given_day: 7, + given_task: 1, where_to_look: "real_puzzel_input/day7_real.txt", expected_output: "42", ), ( - given_day: GivenDay(7), - given_task: GivenTask(2), + given_day: 7, + given_task: 2, where_to_look: "real_puzzel_input/day7_real.txt", expected_output: "42", ),