Skip to content

Commit

Permalink
test: verify serde YAML compatibility
Browse files Browse the repository at this point in the history
Deserializing `jiff` types from YAML is not
currently possible.

Neither `serde_yaml` nor its maintained fork
`serde_yml` support deserializing from bytes.

These tests serve in both

- proving the current incompatibility
- verifying the fix in the following commit,
  which migrates `Deserialize` implementations
  to `deserializer.deserialize_str`.

Related to BurntSushi#148, BurntSushi#138
  • Loading branch information
LeoniePhiline committed Oct 31, 2024
1 parent d3e0a16 commit ec3d98f
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ jiff = { path = "./", features = ["serde"] }
quickcheck = { version = "1.0.3", default-features = false }
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.117"
serde_yml = "0.0.12"
tabwriter = "1.4.0"
time = { version = "0.3.36", features = ["local-offset", "macros", "parsing"] }
tzfile = "0.1.3"
Expand Down
28 changes: 28 additions & 0 deletions src/civil/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3651,6 +3651,8 @@ fn day_of_year(year: Year, day: i16) -> Result<Date, Error> {

#[cfg(test)]
mod tests {
use std::io::Cursor;

use crate::{civil::date, tz::TimeZone, Timestamp, ToSpan};

use super::*;
Expand Down Expand Up @@ -4006,4 +4008,30 @@ mod tests {
d1 == got
}
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn civil_date_deserialize_yaml() {
let expected = date(2024, 10, 31);

let deserialized: Date = serde_yml::from_str("2024-10-31").unwrap();

assert_eq!(deserialized, expected);

let deserialized: Date =
serde_yml::from_slice("2024-10-31".as_bytes()).unwrap();

assert_eq!(deserialized, expected);

let cursor = Cursor::new(b"2024-10-31");
let deserialized: Date = serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}
30 changes: 30 additions & 0 deletions src/civil/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4134,6 +4134,8 @@ impl DateTimeWith {

#[cfg(test)]
mod tests {
use std::io::Cursor;

use crate::{
civil::{date, time},
RoundMode, ToSpan, Unit,
Expand Down Expand Up @@ -4277,4 +4279,32 @@ mod tests {
assert_eq!(12, core::mem::size_of::<DateTime>());
}
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn civil_datetime_deserialize_yaml() {
let expected = datetime(2024, 10, 31, 16, 33, 53, 123456789);

let deserialized: DateTime =
serde_yml::from_str("2024-10-31 16:33:53.123456789").unwrap();

assert_eq!(deserialized, expected);

let deserialized: DateTime =
serde_yml::from_slice("2024-10-31 16:33:53.123456789".as_bytes())
.unwrap();

assert_eq!(deserialized, expected);

let cursor = Cursor::new(b"2024-10-31 16:33:53.123456789");
let deserialized: DateTime = serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}
29 changes: 29 additions & 0 deletions src/civil/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3144,6 +3144,8 @@ impl TimeWith {

#[cfg(test)]
mod tests {
use std::io::Cursor;

use crate::{civil::time, ToSpan};

use super::*;
Expand Down Expand Up @@ -3360,4 +3362,31 @@ mod tests {
let expected = max.rem_euclid(t::NANOS_PER_CIVIL_DAY.bound());
assert_eq!(got, expected);
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn civil_time_deserialize_yaml() {
let expected = time(16, 35, 4, 987654321);

let deserialized: Time =
serde_yml::from_str("16:35:04.987654321").unwrap();

assert_eq!(deserialized, expected);

let deserialized: Time =
serde_yml::from_slice("16:35:04.987654321".as_bytes()).unwrap();

assert_eq!(deserialized, expected);

let cursor = Cursor::new(b"16:35:04.987654321");
let deserialized: Time = serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}
30 changes: 30 additions & 0 deletions src/signed_duration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2069,6 +2069,8 @@ impl<'de> serde::Deserialize<'de> for SignedDuration {

#[cfg(test)]
mod tests {
use std::io::Cursor;

use super::*;

#[test]
Expand Down Expand Up @@ -2186,4 +2188,32 @@ mod tests {
assert_eq!(None, add((i64::MAX, 1), (0, 999_999_999)));
assert_eq!(None, add((i64::MIN, -1), (0, -999_999_999)));
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn signed_duration_deserialize_yaml() {
let expected = SignedDuration::from_secs(123456789);

let deserialized: SignedDuration =
serde_yml::from_str("PT34293h33m9s").unwrap();

assert_eq!(deserialized, expected);

let deserialized: SignedDuration =
serde_yml::from_slice("PT34293h33m9s".as_bytes()).unwrap();

assert_eq!(deserialized, expected);

let cursor = Cursor::new(b"PT34293h33m9s");
let deserialized: SignedDuration =
serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}
36 changes: 36 additions & 0 deletions src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5998,6 +5998,8 @@ fn clamp_relative_span(

#[cfg(test)]
mod tests {
use std::io::Cursor;

use crate::{civil::date, RoundMode};

use super::*;
Expand Down Expand Up @@ -6359,4 +6361,38 @@ mod tests {
quickcheck::TestResult::from_bool(nanos == got.to_invariant_nanoseconds())
}
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn span_deserialize_yaml() {
let expected = Span::new()
.years(1)
.months(2)
.weeks(3)
.days(4)
.hours(5)
.minutes(6)
.seconds(7);

let deserialized: Span =
serde_yml::from_str("P1y2m3w4dT5h6m7s").unwrap();

assert_eq!(deserialized, expected);

let deserialized: Span =
serde_yml::from_slice("P1y2m3w4dT5h6m7s".as_bytes()).unwrap();

assert_eq!(deserialized, expected);

let cursor = Cursor::new(b"P1y2m3w4dT5h6m7s");
let deserialized: Span = serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}
42 changes: 41 additions & 1 deletion src/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3513,7 +3513,12 @@ impl From<(Unit, i64)> for TimestampRound {

#[cfg(test)]
mod tests {
use crate::{civil, tz::Offset};
use std::io::Cursor;

use crate::{
civil::{self, datetime},
tz::Offset,
};

use super::*;

Expand Down Expand Up @@ -3687,4 +3692,39 @@ mod tests {
t == got
}
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn timestamp_deserialize_yaml() {
let expected = datetime(2024, 10, 31, 16, 33, 53, 123456789)
.intz("Europe/Berlin")
.unwrap()
.timestamp();

let deserialized: Timestamp = serde_yml::from_str(
"2024-10-31T16:33:53.123456789+01:00[Europe/Berlin]",
)
.unwrap();

assert_eq!(deserialized, expected);

let deserialized: Timestamp = serde_yml::from_slice(
"2024-10-31T16:33:53.123456789+01:00[Europe/Berlin]".as_bytes(),
)
.unwrap();

assert_eq!(deserialized, expected);

let cursor =
Cursor::new(b"2024-10-31T16:33:53.123456789+01:00[Europe/Berlin]");
let deserialized: Timestamp = serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}
41 changes: 40 additions & 1 deletion src/zoned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5146,7 +5146,12 @@ fn day_length(

#[cfg(test)]
mod tests {
use crate::{civil::date, ToSpan};
use std::io::Cursor;

use crate::{
civil::{date, datetime},
ToSpan,
};

use super::*;

Expand Down Expand Up @@ -5238,4 +5243,38 @@ mod tests {
assert_eq!(40, core::mem::size_of::<Zoned>());
}
}

/// # `serde` deserializer compatibility test
///
/// Serde YAML used to be unable to deserialize `jiff` types,
/// as deserializing from bytes is not supported by the deserializer.
///
/// - <https://github.com/BurntSushi/jiff/issues/138>
/// - <https://github.com/BurntSushi/jiff/discussions/148>
#[test]
fn zoned_deserialize_yaml() {
let expected = datetime(2024, 10, 31, 16, 33, 53, 123456789)
.intz("Europe/Berlin")
.unwrap();

let deserialized: Zoned = serde_yml::from_str(
"2024-10-31T16:33:53.123456789+01:00[Europe/Berlin]",
)
.unwrap();

assert_eq!(deserialized, expected);

let deserialized: Zoned = serde_yml::from_slice(
"2024-10-31T16:33:53.123456789+01:00[Europe/Berlin]".as_bytes(),
)
.unwrap();

assert_eq!(deserialized, expected);

let cursor =
Cursor::new(b"2024-10-31T16:33:53.123456789+01:00[Europe/Berlin]");
let deserialized: Zoned = serde_yml::from_reader(cursor).unwrap();

assert_eq!(deserialized, expected);
}
}

0 comments on commit ec3d98f

Please sign in to comment.