use std::time::SystemTime; use git_date::{time::Sign, Time}; #[test] fn special_time_is_ok_for_now() { assert_eq!( git_date::parse("1979-02-26 18:30:00", Some(SystemTime::now())).unwrap(), Time { seconds_since_unix_epoch: 42, offset_in_seconds: 1800, sign: Sign::Plus, } ); } #[test] fn short() { assert_eq!( git_date::parse("1979-02-26", Some(SystemTime::now())).unwrap(), Time { seconds_since_unix_epoch: 288835200, offset_in_seconds: 0, sign: Sign::Plus, }, "could not parse with SHORT format" ); } #[test] fn rfc2822() { assert_eq!( git_date::parse("Thu, 18 Aug 2022 12:45:06 +0800", None).unwrap(), Time { seconds_since_unix_epoch: 1660797906, offset_in_seconds: 28800, sign: Sign::Plus, }, ); } #[test] fn git_rfc2822() { let expected = Time { seconds_since_unix_epoch: 1659329106, offset_in_seconds: 28800, sign: Sign::Plus, }; assert_eq!( git_date::parse("Thu, 1 Aug 2022 12:45:06 +0800", None).unwrap(), expected, ); assert_eq!( git_date::parse("Thu, 1 Aug 2022 12:45:06 +0800", None).unwrap(), expected, ); } #[test] fn raw() { assert_eq!( git_date::parse("1660874655 +0800", None).unwrap(), Time { seconds_since_unix_epoch: 1660874655, offset_in_seconds: 28800, sign: Sign::Plus, }, ); let expected = Time { seconds_since_unix_epoch: 1660874655, offset_in_seconds: -28800, sign: Sign::Minus, }; for date_str in [ "1660874655 -0800", "1660874655 -0800 ", " 1660874655 -0800", " 1660874655 -0800 ", " 1660874655 -0800 ", "1660874655\t-0800", ] { assert_eq!(git_date::parse(date_str, None).unwrap(), expected); } } #[test] fn bad_raw() { for bad_date_str in [ "123456 !0600", "123456 +060", "123456 -060", "123456 +06000", "123456 06000", "123456 0600", "123456 +0600 extra", "-123456 +0600", "123456+0600", "123456 + 600", ] { assert!(git_date::parse(bad_date_str, None).is_err()); } } #[test] fn git_default() { assert_eq!( git_date::parse("Thu Aug 8 12:45:06 2022 +0800", None).unwrap(), Time { seconds_since_unix_epoch: 1659933906, offset_in_seconds: 28800, sign: Sign::Plus, }, ); } #[test] fn invalid_dates_can_be_produced_without_current_time() { assert!(matches!( git_date::parse("foobar", None).unwrap_err(), git_date::parse::Error::InvalidDateString { input } if input == "foobar" )); } mod relative { use std::time::SystemTime; use git_date::{parse::Error, time::Sign}; use time::{Duration, OffsetDateTime}; #[test] fn large_offsets() { git_date::parse("999999999999999 weeks ago", Some(std::time::UNIX_EPOCH)).ok(); } #[test] fn large_offsets_do_not_panic() { assert!(matches!( git_date::parse("9999999999 weeks ago", Some(std::time::UNIX_EPOCH)), Err(git_date::parse::Error::RelativeTimeConversion) )); } #[test] fn offset_leading_to_before_unix_epoch_cannot_be_represented() { let err = git_date::parse("1 second ago", Some(std::time::UNIX_EPOCH)).unwrap_err(); assert!(matches!(err, Error::TooEarly{timestamp} if timestamp == -1)); } #[test] fn various() { let now = Some(SystemTime::now()); let two_weeks_ago = git_date::parse("2 weeks ago", now).unwrap(); assert_eq!(Sign::Plus, two_weeks_ago.sign); assert_eq!(0, two_weeks_ago.offset_in_seconds); let expected = OffsetDateTime::from(now.unwrap()).saturating_sub(Duration::weeks(2)); // account for the loss of precision when creating `Time` with seconds let expected = expected.replace_nanosecond(0).unwrap(); assert_eq!( OffsetDateTime::from_unix_timestamp(two_weeks_ago.seconds_since_unix_epoch as i64).unwrap(), expected, "relative times differ" ); } } /// Various cases the fuzzer found mod fuzz { #[test] fn invalid_but_does_not_cause_panic() { for input in ["7 -𬞋", "5 ڜ-09", "-4 week ago Z"] { let _ = git_date::parse(input, Some(std::time::UNIX_EPOCH)).unwrap_err(); } } }