1 //! This crate provides a convenient concise way to write unit tests for 2 //! implementations of [`Serialize`] and [`Deserialize`]. 3 //! 4 //! [`Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html 5 //! [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html 6 //! 7 //! The `Serialize` impl for a value can be characterized by the sequence of 8 //! [`Serializer`] calls that are made in the course of serializing the value, 9 //! so `serde_test` provides a [`Token`] abstraction which corresponds roughly 10 //! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to 11 //! test that a value serializes to a particular sequence of method calls, an 12 //! [`assert_de_tokens`] function to test that a value can be deserialized from 13 //! a particular sequence of method calls, and an [`assert_tokens`] function to 14 //! test both directions. There are also functions to test expected failure 15 //! conditions. 16 //! 17 //! [`Serializer`]: https://docs.serde.rs/serde/ser/trait.Serializer.html 18 //! [`Token`]: https://docs.serde.rs/serde_test/enum.Token.html 19 //! [`assert_ser_tokens`]: https://docs.serde.rs/serde_test/fn.assert_ser_tokens.html 20 //! [`assert_de_tokens`]: https://docs.serde.rs/serde_test/fn.assert_de_tokens.html 21 //! [`assert_tokens`]: https://docs.serde.rs/serde_test/fn.assert_tokens.html 22 //! 23 //! Here is an example from the [`linked-hash-map`] crate. 24 //! 25 //! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map 26 //! 27 //! ```edition2018 28 //! # const IGNORE: &str = stringify! { 29 //! use linked_hash_map::LinkedHashMap; 30 //! # }; 31 //! use serde_test::{Token, assert_tokens}; 32 //! 33 //! # use std::fmt; 34 //! # use std::marker::PhantomData; 35 //! # 36 //! # use serde::ser::{Serialize, Serializer, SerializeMap}; 37 //! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess}; 38 //! # 39 //! # // Dumb imitation of LinkedHashMap. 40 //! # #[derive(PartialEq, Debug)] 41 //! # struct LinkedHashMap<K, V>(Vec<(K, V)>); 42 //! # 43 //! # impl<K, V> LinkedHashMap<K, V> { 44 //! # fn new() -> Self { 45 //! # LinkedHashMap(Vec::new()) 46 //! # } 47 //! # 48 //! # fn insert(&mut self, k: K, v: V) { 49 //! # self.0.push((k, v)); 50 //! # } 51 //! # } 52 //! # 53 //! # impl<K, V> Serialize for LinkedHashMap<K, V> 54 //! # where 55 //! # K: Serialize, 56 //! # V: Serialize, 57 //! # { 58 //! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 59 //! # where 60 //! # S: Serializer, 61 //! # { 62 //! # let mut map = serializer.serialize_map(Some(self.0.len()))?; 63 //! # for &(ref k, ref v) in &self.0 { 64 //! # map.serialize_entry(k, v)?; 65 //! # } 66 //! # map.end() 67 //! # } 68 //! # } 69 //! # 70 //! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>); 71 //! # 72 //! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V> 73 //! # where 74 //! # K: Deserialize<'de>, 75 //! # V: Deserialize<'de>, 76 //! # { 77 //! # type Value = LinkedHashMap<K, V>; 78 //! # 79 //! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result { 80 //! # unimplemented!() 81 //! # } 82 //! # 83 //! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> 84 //! # where 85 //! # M: MapAccess<'de>, 86 //! # { 87 //! # let mut map = LinkedHashMap::new(); 88 //! # while let Some((key, value)) = access.next_entry()? { 89 //! # map.insert(key, value); 90 //! # } 91 //! # Ok(map) 92 //! # } 93 //! # } 94 //! # 95 //! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V> 96 //! # where 97 //! # K: Deserialize<'de>, 98 //! # V: Deserialize<'de>, 99 //! # { 100 //! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 101 //! # where 102 //! # D: Deserializer<'de>, 103 //! # { 104 //! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData)) 105 //! # } 106 //! # } 107 //! # 108 //! #[test] 109 //! # fn not_a_test_ser_de_empty() {} 110 //! fn test_ser_de_empty() { 111 //! let map = LinkedHashMap::<char, u32>::new(); 112 //! 113 //! assert_tokens(&map, &[ 114 //! Token::Map { len: Some(0) }, 115 //! Token::MapEnd, 116 //! ]); 117 //! } 118 //! 119 //! #[test] 120 //! # fn not_a_test_ser_de() {} 121 //! fn test_ser_de() { 122 //! let mut map = LinkedHashMap::new(); 123 //! map.insert('b', 20); 124 //! map.insert('a', 10); 125 //! map.insert('c', 30); 126 //! 127 //! assert_tokens(&map, &[ 128 //! Token::Map { len: Some(3) }, 129 //! Token::Char('b'), 130 //! Token::I32(20), 131 //! 132 //! Token::Char('a'), 133 //! Token::I32(10), 134 //! 135 //! Token::Char('c'), 136 //! Token::I32(30), 137 //! Token::MapEnd, 138 //! ]); 139 //! } 140 //! # 141 //! # fn main() { 142 //! # test_ser_de_empty(); 143 //! # test_ser_de(); 144 //! # } 145 //! ``` 146 147 #![doc(html_root_url = "https://docs.rs/serde_test/1.0.123")] 148 #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] 149 #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] 150 // Ignored clippy lints 151 #![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))] 152 // Ignored clippy_pedantic lints 153 #![cfg_attr( 154 feature = "cargo-clippy", 155 allow( 156 empty_line_after_outer_attr, 157 missing_docs_in_private_items, 158 module_name_repetitions, 159 must_use_candidate, 160 redundant_field_names, 161 too_many_lines, 162 use_debug, 163 use_self 164 ) 165 )] 166 167 #[macro_use] 168 extern crate serde; 169 170 mod de; 171 mod error; 172 mod ser; 173 174 mod assert; 175 mod configure; 176 mod token; 177 178 pub use assert::{ 179 assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error, 180 assert_tokens, 181 }; 182 pub use token::Token; 183 184 pub use configure::{Compact, Configure, Readable}; 185 186 // Not public API. 187 #[doc(hidden)] 188 pub use de::Deserializer; 189