230 lines
11 KiB
Rust
230 lines
11 KiB
Rust
#![allow(
|
|
// clippy is broken and shows wrong warnings
|
|
// clippy on stable does not know yet about the lint name
|
|
unknown_lints,
|
|
// https://github.com/rust-lang/rust-clippy/issues/8867
|
|
clippy::derive_partial_eq_without_eq,
|
|
)]
|
|
|
|
mod utils;
|
|
|
|
use crate::utils::{check_deserialization, check_error_deserialization, is_equal};
|
|
use expect_test::expect;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_with::{
|
|
serde_as, DurationMicroSeconds, DurationMicroSecondsWithFrac, DurationMilliSeconds,
|
|
DurationMilliSecondsWithFrac, DurationNanoSeconds, DurationNanoSecondsWithFrac,
|
|
DurationSeconds, DurationSecondsWithFrac, TimestampMicroSeconds, TimestampMicroSecondsWithFrac,
|
|
TimestampMilliSeconds, TimestampMilliSecondsWithFrac, TimestampNanoSeconds,
|
|
TimestampNanoSecondsWithFrac, TimestampSeconds, TimestampSecondsWithFrac,
|
|
};
|
|
use time_0_3::{Duration, OffsetDateTime, PrimitiveDateTime, UtcOffset};
|
|
|
|
/// Create a [`PrimitiveDateTime`] for the Unix Epoch
|
|
fn unix_epoch_primitive() -> PrimitiveDateTime {
|
|
PrimitiveDateTime::new(
|
|
time_0_3::Date::from_ordinal_date(1970, 1).unwrap(),
|
|
time_0_3::Time::from_hms_nano(0, 0, 0, 0).unwrap(),
|
|
)
|
|
}
|
|
|
|
macro_rules! smoketest {
|
|
($($valuety:ty, $adapter:literal, $value:expr, $expect:tt;)*) => {
|
|
$({
|
|
#[serde_as]
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
|
struct S(#[serde_as(as = $adapter)] $valuety);
|
|
#[allow(unused_braces)]
|
|
is_equal(S($value), $expect);
|
|
})*
|
|
};
|
|
}
|
|
|
|
#[test]
|
|
fn test_duration_smoketest() {
|
|
let zero = Duration::seconds(0);
|
|
let one_second = Duration::seconds(1);
|
|
|
|
smoketest! {
|
|
Duration, "DurationSeconds<i64>", one_second, {expect![[r#"1"#]]};
|
|
Duration, "DurationSeconds<f64>", one_second, {expect![[r#"1.0"#]]};
|
|
Duration, "DurationMilliSeconds<i64>", one_second, {expect![[r#"1000"#]]};
|
|
Duration, "DurationMilliSeconds<f64>", one_second, {expect![[r#"1000.0"#]]};
|
|
Duration, "DurationMicroSeconds<i64>", one_second, {expect![[r#"1000000"#]]};
|
|
Duration, "DurationMicroSeconds<f64>", one_second, {expect![[r#"1000000.0"#]]};
|
|
Duration, "DurationNanoSeconds<i64>", one_second, {expect![[r#"1000000000"#]]};
|
|
Duration, "DurationNanoSeconds<f64>", one_second, {expect![[r#"1000000000.0"#]]};
|
|
};
|
|
|
|
smoketest! {
|
|
Duration, "DurationSecondsWithFrac", one_second, {expect![[r#"1.0"#]]};
|
|
Duration, "DurationSecondsWithFrac<String>", one_second, {expect![[r#""1""#]]};
|
|
Duration, "DurationMilliSecondsWithFrac", one_second, {expect![[r#"1000.0"#]]};
|
|
Duration, "DurationMilliSecondsWithFrac<String>", one_second, {expect![[r#""1000""#]]};
|
|
Duration, "DurationMicroSecondsWithFrac", one_second, {expect![[r#"1000000.0"#]]};
|
|
Duration, "DurationMicroSecondsWithFrac<String>", one_second, {expect![[r#""1000000""#]]};
|
|
Duration, "DurationNanoSecondsWithFrac", one_second, {expect![[r#"1000000000.0"#]]};
|
|
Duration, "DurationNanoSecondsWithFrac<String>", one_second, {expect![[r#""1000000000""#]]};
|
|
};
|
|
|
|
smoketest! {
|
|
Duration, "DurationSecondsWithFrac", zero, {expect![[r#"0.0"#]]};
|
|
Duration, "DurationSecondsWithFrac", zero + Duration::nanoseconds(500_000_000), {expect![[r#"0.5"#]]};
|
|
Duration, "DurationSecondsWithFrac", zero + Duration::seconds(1), {expect![[r#"1.0"#]]};
|
|
Duration, "DurationSecondsWithFrac", zero - Duration::nanoseconds(500_000_000), {expect![[r#"-0.5"#]]};
|
|
Duration, "DurationSecondsWithFrac", zero - Duration::seconds(1), {expect![[r#"-1.0"#]]};
|
|
};
|
|
}
|
|
|
|
#[test]
|
|
fn test_datetime_utc_smoketest() {
|
|
let zero = OffsetDateTime::UNIX_EPOCH;
|
|
let one_second = zero + Duration::seconds(1);
|
|
|
|
smoketest! {
|
|
OffsetDateTime, "TimestampSeconds<i64>", one_second, {expect![[r#"1"#]]};
|
|
OffsetDateTime, "TimestampSeconds<f64>", one_second, {expect![[r#"1.0"#]]};
|
|
OffsetDateTime, "TimestampMilliSeconds<i64>", one_second, {expect![[r#"1000"#]]};
|
|
OffsetDateTime, "TimestampMilliSeconds<f64>", one_second, {expect![[r#"1000.0"#]]};
|
|
OffsetDateTime, "TimestampMicroSeconds<i64>", one_second, {expect![[r#"1000000"#]]};
|
|
OffsetDateTime, "TimestampMicroSeconds<f64>", one_second, {expect![[r#"1000000.0"#]]};
|
|
OffsetDateTime, "TimestampNanoSeconds<i64>", one_second, {expect![[r#"1000000000"#]]};
|
|
OffsetDateTime, "TimestampNanoSeconds<f64>", one_second, {expect![[r#"1000000000.0"#]]};
|
|
};
|
|
|
|
smoketest! {
|
|
OffsetDateTime, "TimestampSecondsWithFrac", one_second, {expect![[r#"1.0"#]]};
|
|
OffsetDateTime, "TimestampSecondsWithFrac<String>", one_second, {expect![[r#""1""#]]};
|
|
OffsetDateTime, "TimestampMilliSecondsWithFrac", one_second, {expect![[r#"1000.0"#]]};
|
|
OffsetDateTime, "TimestampMilliSecondsWithFrac<String>", one_second, {expect![[r#""1000""#]]};
|
|
OffsetDateTime, "TimestampMicroSecondsWithFrac", one_second, {expect![[r#"1000000.0"#]]};
|
|
OffsetDateTime, "TimestampMicroSecondsWithFrac<String>", one_second, {expect![[r#""1000000""#]]};
|
|
OffsetDateTime, "TimestampNanoSecondsWithFrac", one_second, {expect![[r#"1000000000.0"#]]};
|
|
OffsetDateTime, "TimestampNanoSecondsWithFrac<String>", one_second, {expect![[r#""1000000000""#]]};
|
|
};
|
|
|
|
smoketest! {
|
|
OffsetDateTime, "TimestampSecondsWithFrac", zero, {expect![[r#"0.0"#]]};
|
|
OffsetDateTime, "TimestampSecondsWithFrac", zero + Duration::nanoseconds(500_000_000), {expect![[r#"0.5"#]]};
|
|
OffsetDateTime, "TimestampSecondsWithFrac", zero + Duration::seconds(1), {expect![[r#"1.0"#]]};
|
|
OffsetDateTime, "TimestampSecondsWithFrac", zero - Duration::nanoseconds(500_000_000), {expect![[r#"-0.5"#]]};
|
|
OffsetDateTime, "TimestampSecondsWithFrac", zero - Duration::seconds(1), {expect![[r#"-1.0"#]]};
|
|
};
|
|
}
|
|
|
|
#[test]
|
|
fn test_naive_datetime_smoketest() {
|
|
let zero = unix_epoch_primitive();
|
|
let one_second = zero + Duration::seconds(1);
|
|
|
|
smoketest! {
|
|
PrimitiveDateTime, "TimestampSeconds<i64>", one_second, {expect![[r#"1"#]]};
|
|
PrimitiveDateTime, "TimestampSeconds<f64>", one_second, {expect![[r#"1.0"#]]};
|
|
PrimitiveDateTime, "TimestampMilliSeconds<i64>", one_second, {expect![[r#"1000"#]]};
|
|
PrimitiveDateTime, "TimestampMilliSeconds<f64>", one_second, {expect![[r#"1000.0"#]]};
|
|
PrimitiveDateTime, "TimestampMicroSeconds<i64>", one_second, {expect![[r#"1000000"#]]};
|
|
PrimitiveDateTime, "TimestampMicroSeconds<f64>", one_second, {expect![[r#"1000000.0"#]]};
|
|
PrimitiveDateTime, "TimestampNanoSeconds<i64>", one_second, {expect![[r#"1000000000"#]]};
|
|
PrimitiveDateTime, "TimestampNanoSeconds<f64>", one_second, {expect![[r#"1000000000.0"#]]};
|
|
};
|
|
|
|
smoketest! {
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac", one_second, {expect![[r#"1.0"#]]};
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac<String>", one_second, {expect![[r#""1""#]]};
|
|
PrimitiveDateTime, "TimestampMilliSecondsWithFrac", one_second, {expect![[r#"1000.0"#]]};
|
|
PrimitiveDateTime, "TimestampMilliSecondsWithFrac<String>", one_second, {expect![[r#""1000""#]]};
|
|
PrimitiveDateTime, "TimestampMicroSecondsWithFrac", one_second, {expect![[r#"1000000.0"#]]};
|
|
PrimitiveDateTime, "TimestampMicroSecondsWithFrac<String>", one_second, {expect![[r#""1000000""#]]};
|
|
PrimitiveDateTime, "TimestampNanoSecondsWithFrac", one_second, {expect![[r#"1000000000.0"#]]};
|
|
PrimitiveDateTime, "TimestampNanoSecondsWithFrac<String>", one_second, {expect![[r#""1000000000""#]]};
|
|
};
|
|
|
|
smoketest! {
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac", zero, {expect![[r#"0.0"#]]};
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac", zero + Duration::nanoseconds(500_000_000), {expect![[r#"0.5"#]]};
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac", zero + Duration::seconds(1), {expect![[r#"1.0"#]]};
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac", zero - Duration::nanoseconds(500_000_000), {expect![[r#"-0.5"#]]};
|
|
PrimitiveDateTime, "TimestampSecondsWithFrac", zero - Duration::seconds(1), {expect![[r#"-1.0"#]]};
|
|
};
|
|
}
|
|
|
|
#[test]
|
|
fn test_offset_datetime_rfc2822() {
|
|
#[serde_as]
|
|
#[derive(Debug, PartialEq, Deserialize, Serialize)]
|
|
struct S(#[serde_as(as = "time_0_3::format_description::well_known::Rfc2822")] OffsetDateTime);
|
|
|
|
is_equal(
|
|
S(OffsetDateTime::UNIX_EPOCH),
|
|
expect![[r#""Thu, 01 Jan 1970 00:00:00 +0000""#]],
|
|
);
|
|
|
|
check_error_deserialization::<S>(
|
|
r#""Foobar""#,
|
|
expect![[r#"the 'weekday' component could not be parsed at line 1 column 8"#]],
|
|
);
|
|
check_error_deserialization::<S>(
|
|
r#""Fri, 2000""#,
|
|
expect![[r#"a character literal was not valid at line 1 column 11"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_offset_datetime_rfc3339() {
|
|
#[serde_as]
|
|
#[derive(Debug, PartialEq, Deserialize, Serialize)]
|
|
struct S(#[serde_as(as = "time_0_3::format_description::well_known::Rfc3339")] OffsetDateTime);
|
|
|
|
is_equal(
|
|
S(OffsetDateTime::UNIX_EPOCH),
|
|
expect![[r#""1970-01-01T00:00:00Z""#]],
|
|
);
|
|
check_deserialization::<S>(
|
|
S(
|
|
OffsetDateTime::from_unix_timestamp_nanos(482_196_050_520_000_000)
|
|
.unwrap()
|
|
.to_offset(UtcOffset::from_hms(0, 0, 0).unwrap()),
|
|
),
|
|
r#""1985-04-12T23:20:50.52Z""#,
|
|
);
|
|
check_deserialization::<S>(
|
|
S(OffsetDateTime::from_unix_timestamp(851_042_397)
|
|
.unwrap()
|
|
.to_offset(UtcOffset::from_hms(-8, 0, 0).unwrap())),
|
|
r#""1996-12-19T16:39:57-08:00""#,
|
|
);
|
|
check_deserialization::<S>(
|
|
S(
|
|
OffsetDateTime::from_unix_timestamp_nanos(662_687_999_999_999_999)
|
|
.unwrap()
|
|
.to_offset(UtcOffset::from_hms(0, 0, 0).unwrap()),
|
|
),
|
|
r#""1990-12-31T23:59:60Z""#,
|
|
);
|
|
check_deserialization::<S>(
|
|
S(
|
|
OffsetDateTime::from_unix_timestamp_nanos(662_687_999_999_999_999)
|
|
.unwrap()
|
|
.to_offset(UtcOffset::from_hms(-8, 0, 0).unwrap()),
|
|
),
|
|
r#""1990-12-31T15:59:60-08:00""#,
|
|
);
|
|
check_deserialization::<S>(
|
|
S(
|
|
OffsetDateTime::from_unix_timestamp_nanos(-1_041_337_172_130_000_000)
|
|
.unwrap()
|
|
.to_offset(UtcOffset::from_hms(0, 20, 0).unwrap()),
|
|
),
|
|
r#""1937-01-01T12:00:27.87+00:20""#,
|
|
);
|
|
|
|
check_error_deserialization::<S>(
|
|
r#""Foobar""#,
|
|
expect![[r#"the 'year' component could not be parsed at line 1 column 8"#]],
|
|
);
|
|
check_error_deserialization::<S>(
|
|
r#""2000-AA""#,
|
|
expect![[r#"the 'month' component could not be parsed at line 1 column 9"#]],
|
|
);
|
|
}
|