1 #![allow(clippy::cast_lossless, clippy::cast_possible_wrap)]
2 
3 use indoc::indoc;
4 use serde_derive::Deserialize;
5 use serde_yaml::Value;
6 use std::collections::BTreeMap;
7 use std::fmt::Debug;
8 
test_de<T>(yaml: &str, expected: &T) where T: serde::de::DeserializeOwned + PartialEq + Debug,9 fn test_de<T>(yaml: &str, expected: &T)
10 where
11     T: serde::de::DeserializeOwned + PartialEq + Debug,
12 {
13     let deserialized: T = serde_yaml::from_str(yaml).unwrap();
14     assert_eq!(*expected, deserialized);
15 
16     serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
17     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
18 }
19 
test_de_seed<T, S>(yaml: &str, seed: S, expected: &T) where T: PartialEq + Debug, S: for<'de> serde::de::DeserializeSeed<'de, Value = T>,20 fn test_de_seed<T, S>(yaml: &str, seed: S, expected: &T)
21 where
22     T: PartialEq + Debug,
23     S: for<'de> serde::de::DeserializeSeed<'de, Value = T>,
24 {
25     let deserialized: T = serde_yaml::seed::from_str_seed(yaml, seed).unwrap();
26     assert_eq!(*expected, deserialized);
27 
28     serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
29     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
30 }
31 
32 #[test]
test_alias()33 fn test_alias() {
34     let yaml = indoc! {"
35         ---
36         first:
37           &alias
38           1
39         second:
40           *alias
41         third: 3
42     "};
43     let mut expected = BTreeMap::new();
44     {
45         expected.insert(String::from("first"), 1);
46         expected.insert(String::from("second"), 1);
47         expected.insert(String::from("third"), 3);
48     }
49     test_de(yaml, &expected);
50 }
51 
52 #[test]
test_option()53 fn test_option() {
54     #[derive(Deserialize, PartialEq, Debug)]
55     struct Data {
56         a: Option<f64>,
57         b: Option<String>,
58         c: Option<bool>,
59     }
60     let yaml = indoc! {"
61         ---
62         b:
63         c: true
64     "};
65     let expected = Data {
66         a: None,
67         b: None,
68         c: Some(true),
69     };
70     test_de(yaml, &expected);
71 }
72 
73 #[test]
test_option_alias()74 fn test_option_alias() {
75     #[derive(Deserialize, PartialEq, Debug)]
76     struct Data {
77         a: Option<f64>,
78         b: Option<String>,
79         c: Option<bool>,
80         d: Option<f64>,
81         e: Option<String>,
82         f: Option<bool>,
83     }
84     let yaml = indoc! {"
85         ---
86         none_f:
87           &none_f
88           ~
89         none_s:
90           &none_s
91           ~
92         none_b:
93           &none_b
94           ~
95 
96         some_f:
97           &some_f
98           1.0
99         some_s:
100           &some_s
101           x
102         some_b:
103           &some_b
104           true
105 
106         a: *none_f
107         b: *none_s
108         c: *none_b
109         d: *some_f
110         e: *some_s
111         f: *some_b
112     "};
113     let expected = Data {
114         a: None,
115         b: None,
116         c: None,
117         d: Some(1.0),
118         e: Some("x".to_owned()),
119         f: Some(true),
120     };
121     test_de(yaml, &expected);
122 }
123 
124 #[test]
test_enum_alias()125 fn test_enum_alias() {
126     #[derive(Deserialize, PartialEq, Debug)]
127     enum E {
128         A,
129         B(u8, u8),
130     }
131     #[derive(Deserialize, PartialEq, Debug)]
132     struct Data {
133         a: E,
134         b: E,
135     }
136     let yaml = indoc! {"
137         ---
138         aref:
139           &aref
140           A
141         bref:
142           &bref
143           B:
144             - 1
145             - 2
146 
147         a: *aref
148         b: *bref
149     "};
150     let expected = Data {
151         a: E::A,
152         b: E::B(1, 2),
153     };
154     test_de(yaml, &expected);
155 }
156 
157 #[test]
test_enum_tag()158 fn test_enum_tag() {
159     #[derive(Deserialize, PartialEq, Debug)]
160     enum E {
161         A(String),
162         B(String),
163     }
164     #[derive(Deserialize, PartialEq, Debug)]
165     struct Data {
166         a: E,
167         b: E,
168     }
169     let yaml = indoc! {"
170         ---
171         a: !A foo
172         b: !B bar
173     "};
174     let expected = Data {
175         a: E::A("foo".into()),
176         b: E::B("bar".into()),
177     };
178     test_de(yaml, &expected);
179 }
180 
181 #[test]
test_number_as_string()182 fn test_number_as_string() {
183     #[derive(Deserialize, PartialEq, Debug)]
184     struct Num {
185         value: String,
186     }
187     let yaml = indoc! {"
188         ---
189         # Cannot be represented as u128
190         value: 340282366920938463463374607431768211457
191     "};
192     let expected = Num {
193         value: "340282366920938463463374607431768211457".to_owned(),
194     };
195     test_de(yaml, &expected);
196 }
197 
198 #[test]
test_i128_big()199 fn test_i128_big() {
200     let expected: i128 = ::std::i64::MIN as i128 - 1;
201     let yaml = indoc! {"
202         ---
203         -9223372036854775809
204     "};
205     assert_eq!(expected, serde_yaml::from_str::<i128>(yaml).unwrap());
206 }
207 
208 #[test]
test_u128_big()209 fn test_u128_big() {
210     let expected: u128 = ::std::u64::MAX as u128 + 1;
211     let yaml = indoc! {"
212         ---
213         18446744073709551616
214     "};
215     assert_eq!(expected, serde_yaml::from_str::<u128>(yaml).unwrap());
216 }
217 
218 #[test]
test_number_alias_as_string()219 fn test_number_alias_as_string() {
220     #[derive(Deserialize, PartialEq, Debug)]
221     struct Num {
222         version: String,
223         value: String,
224     }
225     let yaml = indoc! {"
226         ---
227         version: &a 1.10
228         value: *a
229     "};
230     let expected = Num {
231         version: "1.10".to_owned(),
232         value: "1.10".to_owned(),
233     };
234     test_de(yaml, &expected);
235 }
236 
237 #[test]
test_de_mapping()238 fn test_de_mapping() {
239     #[derive(Debug, Deserialize, PartialEq)]
240     struct Data {
241         pub substructure: serde_yaml::Mapping,
242     }
243     let yaml = indoc! {"
244         ---
245         substructure:
246           a: 'foo'
247           b: 'bar'
248     "};
249 
250     let mut expected = Data {
251         substructure: serde_yaml::Mapping::new(),
252     };
253     expected.substructure.insert(
254         serde_yaml::Value::String("a".to_owned()),
255         serde_yaml::Value::String("foo".to_owned()),
256     );
257     expected.substructure.insert(
258         serde_yaml::Value::String("b".to_owned()),
259         serde_yaml::Value::String("bar".to_owned()),
260     );
261 
262     test_de(yaml, &expected);
263 }
264 
265 #[test]
test_bomb()266 fn test_bomb() {
267     #[derive(Debug, Deserialize, PartialEq)]
268     struct Data {
269         expected: String,
270     }
271 
272     // This would deserialize an astronomical number of elements if we were
273     // vulnerable.
274     let yaml = indoc! {"
275         ---
276         a: &a ~
277         b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
278         c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
279         d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
280         e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
281         f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
282         g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
283         h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
284         i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
285         j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i]
286         k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j]
287         l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k]
288         m: &m [*l,*l,*l,*l,*l,*l,*l,*l,*l]
289         n: &n [*m,*m,*m,*m,*m,*m,*m,*m,*m]
290         o: &o [*n,*n,*n,*n,*n,*n,*n,*n,*n]
291         p: &p [*o,*o,*o,*o,*o,*o,*o,*o,*o]
292         q: &q [*p,*p,*p,*p,*p,*p,*p,*p,*p]
293         r: &r [*q,*q,*q,*q,*q,*q,*q,*q,*q]
294         s: &s [*r,*r,*r,*r,*r,*r,*r,*r,*r]
295         t: &t [*s,*s,*s,*s,*s,*s,*s,*s,*s]
296         u: &u [*t,*t,*t,*t,*t,*t,*t,*t,*t]
297         v: &v [*u,*u,*u,*u,*u,*u,*u,*u,*u]
298         w: &w [*v,*v,*v,*v,*v,*v,*v,*v,*v]
299         x: &x [*w,*w,*w,*w,*w,*w,*w,*w,*w]
300         y: &y [*x,*x,*x,*x,*x,*x,*x,*x,*x]
301         z: &z [*y,*y,*y,*y,*y,*y,*y,*y,*y]
302         expected: string
303     "};
304 
305     let expected = Data {
306         expected: "string".to_owned(),
307     };
308 
309     assert_eq!(expected, serde_yaml::from_str::<Data>(yaml).unwrap());
310 }
311 
312 #[test]
test_numbers()313 fn test_numbers() {
314     let cases = [
315         ("0xF0", "240"),
316         ("+0xF0", "240"),
317         ("-0xF0", "-240"),
318         ("0o70", "56"),
319         ("+0o70", "56"),
320         ("-0o70", "-56"),
321         ("0b10", "2"),
322         ("+0b10", "2"),
323         ("-0b10", "-2"),
324         ("127", "127"),
325         ("+127", "127"),
326         ("-127", "-127"),
327         (".inf", ".inf"),
328         (".Inf", ".inf"),
329         (".INF", ".inf"),
330         ("-.inf", "-.inf"),
331         ("-.Inf", "-.inf"),
332         ("-.INF", "-.inf"),
333         (".nan", ".nan"),
334         (".NaN", ".nan"),
335         (".NAN", ".nan"),
336         ("0.1", "0.1"),
337     ];
338     for &(yaml, expected) in &cases {
339         let value = serde_yaml::from_str::<Value>(yaml).unwrap();
340         match value {
341             Value::Number(number) => assert_eq!(number.to_string(), expected),
342             _ => panic!("expected number"),
343         }
344     }
345 }
346 
347 #[test]
test_stateful()348 fn test_stateful() {
349     struct Seed(i64);
350 
351     impl<'de> serde::de::DeserializeSeed<'de> for Seed {
352         type Value = i64;
353         fn deserialize<D>(self, deserializer: D) -> Result<i64, D::Error>
354         where
355             D: serde::de::Deserializer<'de>,
356         {
357             struct Visitor(i64);
358             impl<'de> serde::de::Visitor<'de> for Visitor {
359                 type Value = i64;
360 
361                 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
362                     write!(formatter, "an integer")
363                 }
364 
365                 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<i64, E> {
366                     Ok(v * self.0)
367                 }
368 
369                 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> {
370                     Ok(v as i64 * self.0)
371                 }
372             }
373 
374             deserializer.deserialize_any(Visitor(self.0))
375         }
376     }
377 
378     let cases = [("3", 5, 15), ("6", 7, 42), ("-5", 9, -45)];
379     for &(yaml, seed, expected) in &cases {
380         test_de_seed(yaml, Seed(seed), &expected);
381     }
382 }
383