1 pub use rstest::{fixture, rstest};
2 use simple_logger::SimpleLogger;
3 use std::fmt::Debug;
4 
5 #[fixture]
logger()6 fn logger() {
7     let _ = SimpleLogger::new().init();
8 }
9 
10 mod de {
11     use super::*;
12     use serde::Deserialize;
13     use serde_xml_rs::from_str;
14 
15     #[rstest]
16     #[case::string("<bla>This is a String</bla>", "This is a String".to_string())]
17     #[case::string("<bla></bla>", "".to_string())]
18     #[case::string("<bla>    </bla>", "".to_string())]
19     #[case::string("<bla>&lt;boom/&gt;</bla>", "<boom/>".to_string())]
20     #[case::string("<bla>&#9835;</bla>", "♫".to_string())]
21     #[case::string("<bla>&#x266B;</bla>", "♫".to_string())]
22     #[case::string("<bla>♫<![CDATA[<cookies/>]]>♫</bla>", "♫<cookies/>♫".to_string())]
23     #[case::i64("<bla>0</bla>", 0i64)]
24     #[case::i64("<bla>-2</bla>", -2i64)]
25     #[case::i64("<bla>-1234</bla>", -1234i64)]
26     #[case::i64("<bla> -1234 </bla>", -1234i64)]
27     #[case::u64("<bla>0</bla>", 0u64)]
28     #[case::u64("<bla>1234</bla>", 1234u64)]
29     #[case::u64("<bla> 1234 </bla>", 1234u64)]
30     #[case::bool("<bla>true</bla>", true)]
31     #[case::bool("<bla>false</bla>", false)]
32     #[case::unit("<bla/>", ())]
33     #[case::f64("<bla>3.0</bla>", 3.0f64)]
34     #[case::f64("<bla>3.1</bla>", 3.1f64)]
35     #[case::f64("<bla>-1.2</bla>", -1.2f64)]
36     #[case::f64("<bla>0.4</bla>", 0.4f64)]
37     #[case::f64("<bla>0.4e5</bla>", 0.4e5f64)]
38     #[case::f64("<bla>0.4e15</bla>", 0.4e15f64)]
39     #[case::f64_precision_troubles("<bla>0.4e-01</bla>", 0.4e-01f64)]
40     #[case::f64("<bla> 0.4e-01 </bla>", 0.4e-01f64)]
41     #[case::option("<bla/>", Some("".to_string()))]
42     #[case::option("<bla></bla>", Some("".to_string()))]
43     #[case::option("<bla> </bla>", Some("".to_string()))]
44     #[case::option("<bla>42</bla>", Some("42".to_string()))]
element_ok<T, 'de>(_logger: (), #[case] document: &str, #[case] expected: T) where T: Deserialize<'de> + Debug + PartialEq,45     fn element_ok<T, 'de>(_logger: (), #[case] document: &str, #[case] expected: T)
46     where
47         T: Deserialize<'de> + Debug + PartialEq,
48     {
49         let actual: T = from_str(document).unwrap();
50         assert_eq!(actual, expected);
51     }
52 
53     #[rstest]
54     #[case("<bla>verum</bla>", Some(true))]
element_ko<T, 'de>(_logger: (), #[case] document: &str, #[case] _type: Option<T>) where T: Deserialize<'de> + Debug + PartialEq,55     fn element_ko<T, 'de>(_logger: (), #[case] document: &str, #[case] _type: Option<T>)
56     where
57         T: Deserialize<'de> + Debug + PartialEq,
58     {
59         let actual: Result<T, _> = from_str(document);
60         assert!(actual.is_err());
61     }
62 
63     #[derive(PartialEq, Debug, Deserialize)]
64     struct DummyAttribute<T> {
65         foo: T,
66     }
67 
68     #[rstest]
69     #[case(r#"<bla foo="true"/>"#, DummyAttribute { foo: true })]
70     #[case(r#"<bla foo="false"/>"#, DummyAttribute { foo: false })]
71     #[case(r#"<bla foo="1"/>"#, DummyAttribute { foo: true })]
72     #[case(r#"<bla foo="0"/>"#, DummyAttribute { foo: false })]
attribute_ok<T, 'de>(_logger: (), #[case] document: &str, #[case] expected: T) where T: Deserialize<'de> + Debug + PartialEq,73     fn attribute_ok<T, 'de>(_logger: (), #[case] document: &str, #[case] expected: T)
74     where
75         T: Deserialize<'de> + Debug + PartialEq,
76     {
77         let actual: T = from_str(document).unwrap();
78         assert_eq!(actual, expected);
79     }
80 }
81 
82 mod ser {
83     use super::*;
84     use serde::{self, Serialize};
85     use serde_xml_rs::to_string;
86 
87     #[derive(Serialize, Debug)]
88     #[serde(rename = "bla")]
89     struct Dummy<T> {
90         #[serde(rename = "$value")]
91         value: T,
92     }
93 
94     #[rstest]
95     #[case::string("<bla>This is a String</bla>", "This is a String".to_string())]
96     #[case::string("<bla></bla>", "".to_string())]
97     #[case::string("<bla>&lt;boom/></bla>", "<boom/>".to_string())]
98     #[case::string("<bla>♫</bla>", "♫".to_string())]
99     #[case::string("<bla>♫&lt;cookies/>♫</bla>", "♫<cookies/>♫".to_string())]
100     #[case::i64("<bla>0</bla>", 0i64)]
101     #[case::i64("<bla>-2</bla>", -2i64)]
102     #[case::i64("<bla>-1234</bla>", -1234i64)]
103     #[case::u64("<bla>0</bla>", 0u64)]
104     #[case::u64("<bla>1234</bla>", 1234u64)]
105     #[case::bool("<bla>true</bla>", true)]
106     #[case::bool("<bla>false</bla>", false)]
107     #[case::unit("<bla />", ())]
108     #[case::f64("<bla>3</bla>", 3.0f64)]
109     #[case::f64("<bla>3.1</bla>", 3.1f64)]
110     #[case::f64("<bla>-1.2</bla>", -1.2f64)]
111     #[case::f64("<bla>0.4</bla>", 0.4f64)]
112     #[case::f64("<bla>40000</bla>", 0.4e5f64)]
113     #[case::f64("<bla>400000000000000</bla>", 0.4e15f64)]
114     #[case::f64_precision_troubles("<bla>0.04</bla>", 0.4e-01f64)]
115     #[case::option("<bla></bla>", Some("".to_string()))]
116     #[case::option("<bla>42</bla>", Some("42".to_string()))]
element_ok<T>(_logger: (), #[case] expected: &str, #[case] value: T) where T: Serialize + Debug,117     fn element_ok<T>(_logger: (), #[case] expected: &str, #[case] value: T)
118     where
119         T: Serialize + Debug,
120     {
121         let actual = to_string(&Dummy { value }).unwrap();
122         assert_eq!(
123             actual,
124             format!(r#"<?xml version="1.0" encoding="UTF-8"?>{}"#, expected)
125         );
126     }
127 
128     #[derive(Serialize, Debug)]
129     #[serde(rename = "bla")]
130     struct DummyAttribute<T> {
131         #[serde(rename = "@value")]
132         value: T,
133     }
134 
135     #[rstest]
136     #[case::string(r#"<bla value="" />"#, "".to_string())]
137     #[case::bool(r#"<bla value="true" />"#, true)]
138     #[case::bool(r#"<bla value="false" />"#, false)]
attribute_ok<T>(_logger: (), #[case] expected: &str, #[case] value: T) where T: Serialize + Debug,139     fn attribute_ok<T>(_logger: (), #[case] expected: &str, #[case] value: T)
140     where
141         T: Serialize + Debug,
142     {
143         let actual = to_string(&DummyAttribute { value }).unwrap();
144         assert_eq!(
145             actual,
146             format!(r#"<?xml version="1.0" encoding="UTF-8"?>{}"#, expected)
147         );
148     }
149 }
150