diff options
Diffstat (limited to 'third_party/rust/serde_with/tests/indexmap.rs')
-rw-r--r-- | third_party/rust/serde_with/tests/indexmap.rs | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/third_party/rust/serde_with/tests/indexmap.rs b/third_party/rust/serde_with/tests/indexmap.rs new file mode 100644 index 0000000000..7e46b9c5c5 --- /dev/null +++ b/third_party/rust/serde_with/tests/indexmap.rs @@ -0,0 +1,285 @@ +#![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 core::iter::FromIterator; +use expect_test::expect; +use indexmap_crate::{IndexMap, IndexSet}; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr, Same}; +use std::net::IpAddr; + +#[test] +fn test_indexmap() { + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct S(#[serde_as(as = "IndexMap<DisplayFromStr, DisplayFromStr>")] IndexMap<u8, u32>); + + // Normal + is_equal( + S([(1, 1), (3, 3), (111, 111)].iter().cloned().collect()), + expect![[r#" + { + "1": "1", + "3": "3", + "111": "111" + }"#]], + ); + is_equal(S(IndexMap::default()), expect![[r#"{}"#]]); +} + +#[test] +fn test_indexset() { + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct S(#[serde_as(as = "IndexSet<DisplayFromStr>")] IndexSet<u32>); + + // Normal + is_equal( + S([1, 2, 3, 4, 5].iter().cloned().collect()), + expect![[r#" + [ + "1", + "2", + "3", + "4", + "5" + ]"#]], + ); + is_equal(S(IndexSet::default()), expect![[r#"[]"#]]); +} + +#[test] +fn test_map_as_tuple_list() { + let ip = "1.2.3.4".parse().unwrap(); + let ip2 = "255.255.255.255".parse().unwrap(); + + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct SI(#[serde_as(as = "Vec<(DisplayFromStr, DisplayFromStr)>")] IndexMap<u32, IpAddr>); + + let map: IndexMap<_, _> = vec![(1, ip), (10, ip), (200, ip2)].into_iter().collect(); + is_equal( + SI(map.clone()), + expect![[r#" + [ + [ + "1", + "1.2.3.4" + ], + [ + "10", + "1.2.3.4" + ], + [ + "200", + "255.255.255.255" + ] + ]"#]], + ); + + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct SI2(#[serde_as(as = "Vec<(Same, DisplayFromStr)>")] IndexMap<u32, IpAddr>); + + is_equal( + SI2(map), + expect![[r#" + [ + [ + 1, + "1.2.3.4" + ], + [ + 10, + "1.2.3.4" + ], + [ + 200, + "255.255.255.255" + ] + ]"#]], + ); +} + +#[test] +fn test_tuple_list_as_map() { + let ip = "1.2.3.4".parse().unwrap(); + let ip2 = "255.255.255.255".parse().unwrap(); + + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct SI( + #[serde_as(as = "std::collections::HashMap<DisplayFromStr, DisplayFromStr>")] + IndexSet<(u32, IpAddr)>, + ); + + is_equal( + SI(IndexSet::from_iter(vec![(1, ip), (10, ip), (200, ip2)])), + expect![[r#" + { + "1": "1.2.3.4", + "10": "1.2.3.4", + "200": "255.255.255.255" + }"#]], + ); +} + +#[test] +fn duplicate_key_first_wins_indexmap() { + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct S(#[serde(with = "::serde_with::rust::maps_first_key_wins")] IndexMap<usize, usize>); + + // Different value and key always works + is_equal( + S(IndexMap::from_iter(vec![(1, 1), (2, 2), (3, 3)])), + expect![[r#" + { + "1": 1, + "2": 2, + "3": 3 + }"#]], + ); + + // Same value for different keys is ok + is_equal( + S(IndexMap::from_iter(vec![(1, 1), (2, 1), (3, 1)])), + expect![[r#" + { + "1": 1, + "2": 1, + "3": 1 + }"#]], + ); + + // Duplicate keys, the first one is used + check_deserialization( + S(IndexMap::from_iter(vec![(1, 1), (2, 2)])), + r#"{"1": 1, "2": 2, "1": 3}"#, + ); +} + +#[test] +fn prohibit_duplicate_key_indexmap() { + #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)] + struct S( + #[serde(with = "::serde_with::rust::maps_duplicate_key_is_error")] IndexMap<usize, usize>, + ); + + // Different value and key always works + is_equal( + S(IndexMap::from_iter(vec![(1, 1), (2, 2), (3, 3)])), + expect![[r#" + { + "1": 1, + "2": 2, + "3": 3 + }"#]], + ); + + // Same value for different keys is ok + is_equal( + S(IndexMap::from_iter(vec![(1, 1), (2, 1), (3, 1)])), + expect![[r#" + { + "1": 1, + "2": 1, + "3": 1 + }"#]], + ); + + // Duplicate keys are an error + check_error_deserialization::<S>( + r#"{"1": 1, "2": 2, "1": 3}"#, + expect![[r#"invalid entry: found duplicate key at line 1 column 24"#]], + ); +} + +#[test] +fn duplicate_value_last_wins_indexset() { + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct S(#[serde(with = "::serde_with::rust::sets_last_value_wins")] IndexSet<W>); + + #[derive(Debug, Eq, Deserialize, Serialize)] + struct W(i32, bool); + impl PartialEq for W { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + impl std::hash::Hash for W { + fn hash<H>(&self, state: &mut H) + where + H: std::hash::Hasher, + { + self.0.hash(state) + } + } + + // Different values always work + is_equal( + S(IndexSet::from_iter(vec![ + W(1, true), + W(2, false), + W(3, true), + ])), + expect![[r#" + [ + [ + 1, + true + ], + [ + 2, + false + ], + [ + 3, + true + ] + ]"#]], + ); + + let value: S = serde_json::from_str( + r#"[ + [1, false], + [1, true], + [2, true], + [2, false] + ]"#, + ) + .unwrap(); + let entries: Vec<_> = value.0.into_iter().collect(); + assert_eq!(1, entries[0].0); + assert!(entries[0].1); + assert_eq!(2, entries[1].0); + assert!(!entries[1].1); +} + +#[test] +fn prohibit_duplicate_value_indexset() { + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct S(#[serde(with = "::serde_with::rust::sets_duplicate_value_is_error")] IndexSet<usize>); + + is_equal( + S(IndexSet::from_iter(vec![1, 2, 3, 4])), + expect![[r#" + [ + 1, + 2, + 3, + 4 + ]"#]], + ); + check_error_deserialization::<S>( + r#"[1, 2, 3, 4, 1]"#, + expect![[r#"invalid entry: found duplicate value at line 1 column 15"#]], + ); +} |