Fixed missing validation for given day or task in benchmakr files

This commit is contained in:
BoolPurist 2024-08-30 21:13:54 +02:00
parent 603ee1827d
commit cf604ff98b
15 changed files with 196 additions and 35 deletions

1
Cargo.lock generated
View file

@ -10,6 +10,7 @@ dependencies = [
"clap", "clap",
"derive_more", "derive_more",
"env_logger", "env_logger",
"insta",
"log", "log",
"prettytable-rs", "prettytable-rs",
"ron", "ron",

View file

@ -7,3 +7,6 @@ default-members = ["crates/cli"]
[workspace.dependencies] [workspace.dependencies]
derive_more = { version = "1", features = ["full"] } derive_more = { version = "1", features = ["full"] }
thiserror = "1.0.63" thiserror = "1.0.63"
insta = "1.39.0"

View file

@ -8,6 +8,7 @@ solutions_advent_of_code_2023 = { path = "../solutions" }
derive_more = { workspace = true } derive_more = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
serde = { version = "1.0.209", features = ["derive"] } serde = { version = "1.0.209", features = ["derive"] }
clap = { version = "4.5.15", features = ["derive"] } clap = { version = "4.5.15", features = ["derive"] }
@ -16,3 +17,6 @@ log = "0.4.22"
anyhow = "1.0.86" anyhow = "1.0.86"
ron = "0.8.1" ron = "0.8.1"
prettytable-rs = "0.10.0" prettytable-rs = "0.10.0"
[dev-dependencies]
insta = { workspace = true }

View file

@ -11,7 +11,7 @@ mod row_building;
use crate::{ use crate::{
cli::BenchmarkCli, cli::BenchmarkCli,
solving_given::{solve_given, NoSolutionFound}, solving_given::{solve_given, NoSolutionFound},
AppError, AppResult, AppResult,
}; };
use anyhow::anyhow; use anyhow::anyhow;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -59,27 +59,30 @@ fn solve_and_keep_track_of_runtime(
} }
fn load_benchmarks(args: &BenchmarkCli) -> AppResult<Vec<(FileToBenchmark, String)>> { fn load_benchmarks(args: &BenchmarkCli) -> AppResult<Vec<(FileToBenchmark, String)>> {
args.files() let mut parsed_benchmarks = Vec::new();
.iter() for next_paths in args.files() {
.flat_map(|path| { let content = std::fs::read_to_string(next_paths).map_err(|error| {
let content = std::fs::read_to_string(path).map_err(|error| { anyhow!(
anyhow!( "Could not read benchmark file at {:?}\n\
"Could not read benchmark file at {:?}\n\
Details: {}", Details: {}",
path, next_paths,
error error
) )
})?; })?;
let parsed: Vec<FileToBenchmark> = ron::from_str(&content).map_err(|error| { let parsed: Vec<FileToBenchmark> = ron::from_str(&content).map_err(|error| {
anyhow!( dbg!();
"Content of benchmark file at ({:?}) is in an invalid ron format\n\ anyhow!(
"Content of benchmark file at ({:?}) is in an invalid ron format\n\
Details of invalid format: {}", Details of invalid format: {}",
path, next_paths,
error error
) )
})?; })?;
Ok::<_, AppError>(parsed) parsed_benchmarks.push(parsed);
}) }
parsed_benchmarks
.into_iter()
.flatten() .flatten()
.map(|benchmark| { .map(|benchmark| {
let where_to_look = benchmark.where_to_look(); let where_to_look = benchmark.where_to_look();

View file

@ -74,3 +74,32 @@ impl FileToBenchmark {
&self.expected_output &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<Vec<FileToBenchmark>> = 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<Vec<FileToBenchmark>> = 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<Vec<FileToBenchmark>> = ron::from_str(INPUT);
insta::assert_debug_snapshot!(actual);
}
}

View file

@ -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,
},
},
)

View file

@ -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,
},
},
)

View file

@ -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",
},
],
)

View file

@ -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",
)
]

View file

@ -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",
)
]

View file

@ -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",
)
]

View file

@ -13,13 +13,25 @@ pub enum InvalidGivenDayError {
constants::MAX_DAY constants::MAX_DAY
)] )]
InvalidFormat(Arc<str>), InvalidFormat(Arc<str>),
#[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), InvalidRange(u32),
} }
#[derive(Debug, Copy, Clone, Into, PartialEq, Eq, Serialize, Deserialize, Display)] #[derive(Debug, Copy, Clone, Into, PartialEq, Eq, Serialize, Deserialize, Display)]
#[serde(try_from = "u32")]
pub struct GivenDay(u32); pub struct GivenDay(u32);
impl TryFrom<u32> for GivenDay {
type Error = InvalidGivenDayError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
Self::new(value)
}
}
impl GivenDay { impl GivenDay {
pub fn new(value: u32) -> Result<Self, InvalidGivenDayError> { pub fn new(value: u32) -> Result<Self, InvalidGivenDayError> {
if (1..=constants::MAX_DAY).contains(&value) { if (1..=constants::MAX_DAY).contains(&value) {

View file

@ -13,15 +13,24 @@ pub enum InvalidGivenTaskError {
)] )]
InvalidFormat(Arc<str>), InvalidFormat(Arc<str>),
#[error( #[error(
"({0}) is within the valid range between 1 and {}", "({0}) is not within the valid range between 1 and {}",
constants::MAX_TASK constants::MAX_TASK
)] )]
InvalidRange(u32), InvalidRange(u32),
} }
#[derive(Debug, Copy, Into, Clone, PartialEq, Eq, Serialize, Deserialize, Display)] #[derive(Debug, Copy, Into, Clone, PartialEq, Eq, Serialize, Deserialize, Display)]
#[serde(try_from = "u32")]
pub struct GivenTask(u32); pub struct GivenTask(u32);
impl TryFrom<u32> for GivenTask {
type Error = InvalidGivenTaskError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
Self::new(value)
}
}
impl GivenTask { impl GivenTask {
pub fn new(value: u32) -> Result<Self, InvalidGivenTaskError> { pub fn new(value: u32) -> Result<Self, InvalidGivenTaskError> {
if (1..=constants::MAX_TASK).contains(&value) { if (1..=constants::MAX_TASK).contains(&value) {

View file

@ -12,4 +12,4 @@ thiserror = { workspace = true }
regex = "1.10.6" regex = "1.10.6"
[dev-dependencies] [dev-dependencies]
insta = "1.39.0" insta = { workspace = true }

View file

@ -1,37 +1,37 @@
[ [
( (
given_day: GivenDay(5), given_day: 5,
given_task: GivenTask(2), given_task: 2,
where_to_look: "real_puzzel_input/day5_real.txt", where_to_look: "real_puzzel_input/day5_real.txt",
expected_output: "42", expected_output: "42",
), ),
( (
given_day: GivenDay(5), given_day: 5,
given_task: GivenTask(1), given_task: 1,
where_to_look: "real_puzzel_input/day5_real.txt", where_to_look: "real_puzzel_input/day5_real.txt",
expected_output: "42", expected_output: "42",
), ),
( (
given_day: GivenDay(6), given_day: 6,
given_task: GivenTask(1), given_task: 1,
where_to_look: "real_puzzel_input/day6_real.txt", where_to_look: "real_puzzel_input/day6_real.txt",
expected_output: "42", expected_output: "42",
), ),
( (
given_day: GivenDay(6), given_day: 6,
given_task: GivenTask(2), given_task: 2,
where_to_look: "real_puzzel_input/day6_real.txt", where_to_look: "real_puzzel_input/day6_real.txt",
expected_output: "42", expected_output: "42",
), ),
( (
given_day: GivenDay(7), given_day: 7,
given_task: GivenTask(1), given_task: 1,
where_to_look: "real_puzzel_input/day7_real.txt", where_to_look: "real_puzzel_input/day7_real.txt",
expected_output: "42", expected_output: "42",
), ),
( (
given_day: GivenDay(7), given_day: 7,
given_task: GivenTask(2), given_task: 2,
where_to_look: "real_puzzel_input/day7_real.txt", where_to_look: "real_puzzel_input/day7_real.txt",
expected_output: "42", expected_output: "42",
), ),