Skip to main content

forma_test/
lib.rs

1//! Token-based test framework for forma_core.
2//!
3//! Provides [`assert_ser_tokens`], [`assert_de_tokens`], and
4//! [`assert_tokens`] for verifying that Serialize/Deserialize impls
5//! produce and consume the expected token streams.
6
7pub mod de;
8pub mod error;
9pub mod ser;
10pub mod token;
11
12pub use error::Error;
13pub use token::Token;
14
15use de::TokenDeserializer;
16use ser::TokenSerializer;
17
18use forma_core::de::Deserialize;
19use forma_core::ser::Serialize;
20
21/// Assert that serializing `value` produces exactly `expected` tokens.
22///
23/// Panics with a diff if the token streams don't match.
24pub fn assert_ser_tokens<T: Serialize + ?Sized>(value: &T, expected: &[Token]) {
25    let mut s = TokenSerializer::new();
26    value.serialize(&mut s).expect("serialization failed");
27    let actual = s.into_tokens();
28    assert!(
29        actual == expected,
30        "serialization mismatch:\n  actual:   {actual:?}\n  expected: {expected:?}"
31    );
32}
33
34/// Assert that deserializing `tokens` produces a value equal to `expected`.
35///
36/// `T` must implement `PartialEq` and `Debug` for the assertion.
37pub fn assert_de_tokens<'de, T>(expected: &T, tokens: &'de [Token])
38where
39    T: Deserialize<'de> + PartialEq + std::fmt::Debug,
40{
41    let mut de = TokenDeserializer::new(tokens);
42    let actual = T::deserialize(&mut de).expect("deserialization failed");
43    assert_eq!(
44        de.remaining(),
45        0,
46        "not all tokens consumed ({} remaining)",
47        de.remaining()
48    );
49    assert!(
50        actual == *expected,
51        "deserialization mismatch:\n  actual:   {actual:?}\n  expected: {expected:?}"
52    );
53}
54
55/// Assert that `value` round-trips through serialization and deserialization
56/// via the given token stream.
57///
58/// Equivalent to calling [`assert_ser_tokens`] then [`assert_de_tokens`].
59pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
60where
61    T: Serialize + Deserialize<'de> + PartialEq + std::fmt::Debug,
62{
63    assert_ser_tokens(value, tokens);
64    assert_de_tokens(value, tokens);
65}
66
67/// Assert that deserialization from `tokens` fails with an error whose
68/// `Display` output contains `expected_msg`.
69pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], expected_msg: &str)
70where
71    T: Deserialize<'de> + std::fmt::Debug,
72{
73    let mut de = TokenDeserializer::new(tokens);
74    match T::deserialize(&mut de) {
75        Ok(v) => panic!("expected error containing {expected_msg:?}, but deserialization succeeded with {v:?}"),
76        Err(e) => {
77            let msg = e.0;
78            assert!(
79                msg.contains(expected_msg),
80                "error message mismatch:\n  actual:   {msg:?}\n  expected to contain: {expected_msg:?}"
81            );
82        }
83    }
84}