use super::*;
#[test]
fn parse_daily() {
let interval: Interval = "1d".parse().expect("'1d' is a valid Interval literal");
assert_eq!(interval, Interval::Day);
}
#[test]
fn parse_hourly() {
let interval: Interval = "1h".parse().expect("'1h' is a valid Interval literal");
assert_eq!(interval, Interval::Hour);
}
#[test]
fn parse_weekly() {
let interval: Interval = "1w".parse().expect("'1w' is a valid Interval literal");
assert_eq!(interval, Interval::Week);
}
#[test]
fn parse_unknown_returns_error() {
let result: Result<Interval, _> = "xyz".parse();
assert!(matches!(result, Err(IntervalError::Unknown(s)) if s == "xyz"));
}
#[test]
fn parse_empty_returns_error() {
let result: Result<Interval, _> = "".parse();
assert!(matches!(result, Err(IntervalError::Unknown(_))));
}
#[test]
fn parse_alternative_formats() {
assert_eq!(
"h".parse::<Interval>()
.expect("'h' is a valid Interval alias"),
Interval::Hour
);
assert_eq!(
"hour"
.parse::<Interval>()
.expect("'hour' is a valid Interval alias"),
Interval::Hour
);
assert_eq!(
"hourly"
.parse::<Interval>()
.expect("'hourly' is a valid Interval alias"),
Interval::Hour
);
assert_eq!(
"d".parse::<Interval>()
.expect("'d' is a valid Interval alias"),
Interval::Day
);
assert_eq!(
"day"
.parse::<Interval>()
.expect("'day' is a valid Interval alias"),
Interval::Day
);
assert_eq!(
"daily"
.parse::<Interval>()
.expect("'daily' is a valid Interval alias"),
Interval::Day
);
assert_eq!(
"w".parse::<Interval>()
.expect("'w' is a valid Interval alias"),
Interval::Week
);
assert_eq!(
"week"
.parse::<Interval>()
.expect("'week' is a valid Interval alias"),
Interval::Week
);
assert_eq!(
"weekly"
.parse::<Interval>()
.expect("'weekly' is a valid Interval alias"),
Interval::Week
);
}
#[test]
fn as_str_roundtrips_with_parse() {
for interval in [
Interval::Minute,
Interval::Hour,
Interval::Day,
Interval::Week,
] {
let s = interval.as_str();
let parsed: Interval = s
.parse()
.expect("as_str() output must roundtrip through parse()");
assert_eq!(parsed, interval);
}
}
#[test]
fn parse_case_insensitive() {
assert_eq!(
"1H".parse::<Interval>()
.expect("'1H' is a valid case-insensitive Interval"),
Interval::Hour
);
assert_eq!(
"1D".parse::<Interval>()
.expect("'1D' is a valid case-insensitive Interval"),
Interval::Day
);
assert_eq!(
"DAY"
.parse::<Interval>()
.expect("'DAY' is a valid case-insensitive Interval"),
Interval::Day
);
assert_eq!(
"WEEKLY"
.parse::<Interval>()
.expect("'WEEKLY' is a valid case-insensitive Interval"),
Interval::Week
);
}
#[test]
fn interval_duration_minute() {
let d = super::interval_duration(Interval::Minute);
assert_eq!(d.num_seconds(), 60);
}
#[test]
fn interval_duration_hour() {
let d = super::interval_duration(Interval::Hour);
assert_eq!(d.num_seconds(), 3600);
}
#[test]
fn interval_duration_day() {
let d = super::interval_duration(Interval::Day);
assert_eq!(d.num_seconds(), 86400);
}
#[test]
fn interval_duration_week() {
let d = super::interval_duration(Interval::Week);
assert_eq!(d.num_seconds(), 604800);
}
#[test]
fn serde_roundtrip() {
for variant in [
Interval::Minute,
Interval::Hour,
Interval::Day,
Interval::Week,
] {
let json = serde_json::to_string(&variant).expect("valid json");
let parsed: Interval = serde_json::from_str(&json).expect("valid json");
assert_eq!(parsed, variant);
}
}
#[test]
fn lower_intervals_minute_is_empty() {
assert!(Interval::Minute.lower_intervals().is_empty());
}
#[test]
fn lower_intervals_hour_contains_minute() {
let lower = Interval::Hour.lower_intervals();
assert_eq!(lower, &[Interval::Minute]);
}
#[test]
fn lower_intervals_day_ordered_by_preference() {
let lower = Interval::Day.lower_intervals();
assert_eq!(lower, &[Interval::Hour, Interval::Minute]);
}
#[test]
fn lower_intervals_week_ordered_by_preference() {
let lower = Interval::Week.lower_intervals();
assert_eq!(lower, &[Interval::Day, Interval::Hour, Interval::Minute]);
}
#[test]
fn crypto_daily_uses_365_not_252() {
assert_eq!(Interval::Day.periods_per_year(true), 365);
}
#[test]
fn equity_daily_uses_252() {
assert_eq!(Interval::Day.periods_per_year(false), 252);
}
#[test]
fn crypto_hourly_uses_8760() {
assert_eq!(Interval::Hour.periods_per_year(true), 8760);
}
#[test]
fn equity_hourly_uses_1638() {
assert_eq!(Interval::Hour.periods_per_year(false), 1638);
}
#[test]
fn crypto_weekly_uses_52() {
assert_eq!(Interval::Week.periods_per_year(true), 52);
}
#[test]
fn equity_weekly_uses_52() {
assert_eq!(Interval::Week.periods_per_year(false), 52);
}
#[test]
fn crypto_minute_uses_525600() {
assert_eq!(Interval::Minute.periods_per_year(true), 525_600);
}
#[test]
fn equity_minute_uses_98280() {
assert_eq!(Interval::Minute.periods_per_year(false), 98_280);
}
#[test]
fn interval_error_display_contains_input() {
let err = IntervalError::Unknown("3x".to_string());
assert!(err.to_string().contains("3x"));
}