use jiff::civil::{Date, Time};
use proptest::property_test;
use crate::{
parser::error_regex,
types::error::{DataError, ExtendedDataField},
};
#[test]
fn missing_data() {
assert_eq!(
error_regex("Invalid data format []"),
None,
"error_regex should return None for an empty data format"
);
}
#[test]
fn date_time_edge_cases() {
assert_eq!(error_regex("Invalid date: [test]"), Some(DataError::InvalidDate(String::from("[test]"))));
assert_eq!(error_regex("Invalid Date [test]"), Some(DataError::InvalidDate(String::from("test"))));
assert_eq!(error_regex("Invalid time: [test]"), Some(DataError::InvalidTime(String::from("[test]"))));
assert_eq!(error_regex("Invalid Time [test]"), Some(DataError::InvalidTime(String::from("test"))));
}
#[property_test]
#[test]
fn invalid_date(#[strategy = ".+"] date: String) {
let error = DataError::InvalidDate(date.clone());
assert_eq!(error_regex(&format!("Date [{date}] invalid")), Some(error.clone()));
assert_eq!(error_regex(&format!("Invalid Date [{date}]")), Some(error.clone()));
assert_eq!(error_regex(&format!("Date is invalid [{date}]")), Some(error.clone()));
assert_eq!(error_regex(&format!("Invalid date: {date}")), Some(error));
}
#[property_test]
#[test]
fn invalid_time(#[strategy = ".+"] time: String) {
let error = DataError::InvalidTime(time.clone());
assert_eq!(error_regex(&format!("Invalid Time [{time}]")), Some(error.clone()));
assert_eq!(error_regex(&format!("Time is invalid [{time}]")), Some(error.clone()));
assert_eq!(error_regex(&format!("Invalid time: {time}")), Some(error));
}
#[property_test]
#[test]
fn future_date(#[strategy = 0..=9999i16] year: i16, #[strategy = 1..=12i8] month: i8, #[strategy = 1..=28i8] day: i8) {
let date = Date::new(year, month, day).unwrap();
let error = DataError::DateTooNew(date);
let date_str = format!("{year:04}{month:02}{day:02}");
assert_eq!(error_regex(&format!("Date [{date_str}] too new")), Some(error.clone()));
assert_eq!(error_regex(&format!("Invalid future date [{date_str}]")), Some(error.clone()));
assert_eq!(error_regex(&format!("Date is in the future [{date_str}]")), Some(error));
}
#[property_test]
#[test]
fn date_too_old(
#[strategy = 0..=9999i16] year: i16,
#[strategy = 1..=12i8] month: i8,
#[strategy = 1..=28i8] day: i8,
number: u64,
) {
let date = Date::new(year, month, day).unwrap();
let error = DataError::DateTooOld(date);
let date_str = format!("{year:04}{month:02}{day:02}");
assert_eq!(error_regex(&format!("Date [{date_str}] too old")), Some(error.clone()));
assert_eq!(error_regex(&format!("Date is older than {number} days [{date_str}]")), Some(error));
}
#[property_test]
#[test]
fn missing_temperature(
which: bool,
#[strategy = 0..=9999i16] year: i16,
#[strategy = 1..=12i8] month: i8,
#[strategy = 1..=28i8] day: i8,
) {
let date = Date::new(year, month, day).unwrap();
let (which, error) = if which {
("Max", DataError::MinTemperatureWithoutMax(date))
} else {
("Min", DataError::MaxTemperatureWithoutMin(date))
};
assert_eq!(error_regex(&format!("{which} temp missing on [{year:04}{month:02}{day:02}]")), Some(error));
}
#[property_test]
#[test]
fn production_too_high(which: bool, value: u32, system_size: u32) {
let (which, error) = if which {
(
"Power",
DataError::ExcessivePowerGeneration {
power: value,
system_size,
},
)
} else {
(
"Energy",
DataError::ExcessiveEnergyGeneration {
energy: value,
system_size,
},
)
};
assert_eq!(
error_regex(&format!("{which} value [{value}] too high for system size [{system_size}]")),
Some(error)
);
}
#[property_test]
#[test]
fn energy_too_high(energy: u32, #[strategy = 1..=23i8] hour: i8, #[strategy = 0..=59i8] minute: i8) {
assert_eq!(
error_regex(&format!("Energy value [{energy}] too high for [{hour:02}:{minute:02}]")),
Some(DataError::EnergyTooHighForTime(energy, Time::new(hour, minute, 0, 0).unwrap()))
);
}
#[property_test]
#[test]
fn invalid_data_format(#[strategy = ".+"] data: String) {
assert_eq!(error_regex(&format!("Invalid data format [{data}]")), Some(DataError::InvalidDataFormat(data)));
}
#[test]
fn generation_too_high() {
let error = include_str!("../../../cases/errors/generation_too_high.txt").trim();
assert_eq!(
error_regex(error.trim_start_matches("Bad request 400: ")),
Some(DataError::GenerationTooHigh {
generation: 10_000_000_000.0,
system_size: 6200,
date: Date::constant(2025, 9, 22)
})
);
}
#[test]
fn invalid_colour() {
let error = include_str!("../../../cases/errors/invalid_extended_colour.txt").trim();
assert_eq!(
error_regex(error.trim_start_matches("Bad Request 400: ")),
Some(DataError::InvalidExtendedDataField(7, ExtendedDataField::Colour))
);
}