1 #![allow(
2     clippy::cast_lossless,
3     clippy::cast_possible_wrap,
4     clippy::derive_partial_eq_without_eq,
5     clippy::similar_names,
6     clippy::uninlined_format_args
7 )]
8 
9 use indoc::indoc;
10 use serde_derive::Deserialize;
11 use serde_yaml::{Deserializer, Number, Value};
12 use std::collections::BTreeMap;
13 use std::fmt::Debug;
14 
test_de<T>(yaml: &str, expected: &T) where T: serde::de::DeserializeOwned + PartialEq + Debug,15 fn test_de<T>(yaml: &str, expected: &T)
16 where
17     T: serde::de::DeserializeOwned + PartialEq + Debug,
18 {
19     let deserialized: T = serde_yaml::from_str(yaml).unwrap();
20     assert_eq!(*expected, deserialized);
21 
22     let value: Value = serde_yaml::from_str(yaml).unwrap();
23     let deserialized = T::deserialize(&value).unwrap();
24     assert_eq!(*expected, deserialized);
25 
26     let deserialized: T = serde_yaml::from_value(value).unwrap();
27     assert_eq!(*expected, deserialized);
28 
29     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
30 
31     let mut deserializer = Deserializer::from_str(yaml);
32     let document = deserializer.next().unwrap();
33     let deserialized = T::deserialize(document).unwrap();
34     assert_eq!(*expected, deserialized);
35     assert!(deserializer.next().is_none());
36 }
37 
test_de_no_value<'de, T>(yaml: &'de str, expected: &T) where T: serde::de::Deserialize<'de> + PartialEq + Debug,38 fn test_de_no_value<'de, T>(yaml: &'de str, expected: &T)
39 where
40     T: serde::de::Deserialize<'de> + PartialEq + Debug,
41 {
42     let deserialized: T = serde_yaml::from_str(yaml).unwrap();
43     assert_eq!(*expected, deserialized);
44 
45     serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
46     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
47 }
48 
test_de_seed<'de, T, S>(yaml: &'de str, seed: S, expected: &T) where T: PartialEq + Debug, S: serde::de::DeserializeSeed<'de, Value = T>,49 fn test_de_seed<'de, T, S>(yaml: &'de str, seed: S, expected: &T)
50 where
51     T: PartialEq + Debug,
52     S: serde::de::DeserializeSeed<'de, Value = T>,
53 {
54     let deserialized: T = seed.deserialize(Deserializer::from_str(yaml)).unwrap();
55     assert_eq!(*expected, deserialized);
56 
57     serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
58     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
59 }
60 
61 #[test]
test_borrowed()62 fn test_borrowed() {
63     let yaml = indoc! {"
64         - plain nonàscii
65         - 'single quoted'
66         - \"double quoted\"
67     "};
68     let expected = vec!["plain nonàscii", "single quoted", "double quoted"];
69     test_de_no_value(yaml, &expected);
70 }
71 
72 #[test]
test_alias()73 fn test_alias() {
74     let yaml = indoc! {"
75         first:
76           &alias
77           1
78         second:
79           *alias
80         third: 3
81     "};
82     let mut expected = BTreeMap::new();
83     expected.insert("first".to_owned(), 1);
84     expected.insert("second".to_owned(), 1);
85     expected.insert("third".to_owned(), 3);
86     test_de(yaml, &expected);
87 }
88 
89 #[test]
test_option()90 fn test_option() {
91     #[derive(Deserialize, PartialEq, Debug)]
92     struct Data {
93         a: Option<f64>,
94         b: Option<String>,
95         c: Option<bool>,
96     }
97     let yaml = indoc! {"
98         b:
99         c: true
100     "};
101     let expected = Data {
102         a: None,
103         b: None,
104         c: Some(true),
105     };
106     test_de(yaml, &expected);
107 }
108 
109 #[test]
test_option_alias()110 fn test_option_alias() {
111     #[derive(Deserialize, PartialEq, Debug)]
112     struct Data {
113         a: Option<f64>,
114         b: Option<String>,
115         c: Option<bool>,
116         d: Option<f64>,
117         e: Option<String>,
118         f: Option<bool>,
119     }
120     let yaml = indoc! {"
121         none_f:
122           &none_f
123           ~
124         none_s:
125           &none_s
126           ~
127         none_b:
128           &none_b
129           ~
130 
131         some_f:
132           &some_f
133           1.0
134         some_s:
135           &some_s
136           x
137         some_b:
138           &some_b
139           true
140 
141         a: *none_f
142         b: *none_s
143         c: *none_b
144         d: *some_f
145         e: *some_s
146         f: *some_b
147     "};
148     let expected = Data {
149         a: None,
150         b: None,
151         c: None,
152         d: Some(1.0),
153         e: Some("x".to_owned()),
154         f: Some(true),
155     };
156     test_de(yaml, &expected);
157 }
158 
159 #[test]
test_enum_alias()160 fn test_enum_alias() {
161     #[derive(Deserialize, PartialEq, Debug)]
162     enum E {
163         A,
164         B(u8, u8),
165     }
166     #[derive(Deserialize, PartialEq, Debug)]
167     struct Data {
168         a: E,
169         b: E,
170     }
171     let yaml = indoc! {"
172         aref:
173           &aref
174           A
175         bref:
176           &bref
177           !B
178             - 1
179             - 2
180 
181         a: *aref
182         b: *bref
183     "};
184     let expected = Data {
185         a: E::A,
186         b: E::B(1, 2),
187     };
188     test_de(yaml, &expected);
189 }
190 
191 #[test]
test_enum_representations()192 fn test_enum_representations() {
193     #[derive(Deserialize, PartialEq, Debug)]
194     enum Enum {
195         Unit,
196         Tuple(i32, i32),
197         Struct { x: i32, y: i32 },
198         String(String),
199         Number(f64),
200     }
201 
202     let yaml = indoc! {"
203         - Unit
204         - 'Unit'
205         - !Unit
206         - !Unit ~
207         - !Unit null
208         - !Tuple [0, 0]
209         - !Tuple
210           - 0
211           - 0
212         - !Struct {x: 0, y: 0}
213         - !Struct
214           x: 0
215           y: 0
216         - !String '...'
217         - !String ...
218         - !Number 0
219     "};
220 
221     let expected = vec![
222         Enum::Unit,
223         Enum::Unit,
224         Enum::Unit,
225         Enum::Unit,
226         Enum::Unit,
227         Enum::Tuple(0, 0),
228         Enum::Tuple(0, 0),
229         Enum::Struct { x: 0, y: 0 },
230         Enum::Struct { x: 0, y: 0 },
231         Enum::String("...".to_owned()),
232         Enum::String("...".to_owned()),
233         Enum::Number(0.0),
234     ];
235 
236     test_de(yaml, &expected);
237 
238     let yaml = indoc! {"
239         - !String
240     "};
241     let expected = vec![Enum::String(String::new())];
242     test_de_no_value(yaml, &expected);
243 }
244 
245 #[test]
test_number_as_string()246 fn test_number_as_string() {
247     #[derive(Deserialize, PartialEq, Debug)]
248     struct Num {
249         value: String,
250     }
251     let yaml = indoc! {"
252         # Cannot be represented as u128
253         value: 340282366920938463463374607431768211457
254     "};
255     let expected = Num {
256         value: "340282366920938463463374607431768211457".to_owned(),
257     };
258     test_de_no_value(yaml, &expected);
259 }
260 
261 #[test]
test_empty_string()262 fn test_empty_string() {
263     #[derive(Deserialize, PartialEq, Debug)]
264     struct Struct {
265         empty: String,
266         tilde: String,
267     }
268     let yaml = indoc! {"
269         empty:
270         tilde: ~
271     "};
272     let expected = Struct {
273         empty: String::new(),
274         tilde: "~".to_owned(),
275     };
276     test_de_no_value(yaml, &expected);
277 }
278 
279 #[test]
test_i128_big()280 fn test_i128_big() {
281     let expected: i128 = i64::MIN as i128 - 1;
282     let yaml = indoc! {"
283         -9223372036854775809
284     "};
285     assert_eq!(expected, serde_yaml::from_str::<i128>(yaml).unwrap());
286 
287     let octal = indoc! {"
288         -0o1000000000000000000001
289     "};
290     assert_eq!(expected, serde_yaml::from_str::<i128>(octal).unwrap());
291 }
292 
293 #[test]
test_u128_big()294 fn test_u128_big() {
295     let expected: u128 = u64::MAX as u128 + 1;
296     let yaml = indoc! {"
297         18446744073709551616
298     "};
299     assert_eq!(expected, serde_yaml::from_str::<u128>(yaml).unwrap());
300 
301     let octal = indoc! {"
302         0o2000000000000000000000
303     "};
304     assert_eq!(expected, serde_yaml::from_str::<u128>(octal).unwrap());
305 }
306 
307 #[test]
test_number_alias_as_string()308 fn test_number_alias_as_string() {
309     #[derive(Deserialize, PartialEq, Debug)]
310     struct Num {
311         version: String,
312         value: String,
313     }
314     let yaml = indoc! {"
315         version: &a 1.10
316         value: *a
317     "};
318     let expected = Num {
319         version: "1.10".to_owned(),
320         value: "1.10".to_owned(),
321     };
322     test_de_no_value(yaml, &expected);
323 }
324 
325 #[test]
test_de_mapping()326 fn test_de_mapping() {
327     #[derive(Debug, Deserialize, PartialEq)]
328     struct Data {
329         pub substructure: serde_yaml::Mapping,
330     }
331     let yaml = indoc! {"
332         substructure:
333           a: 'foo'
334           b: 'bar'
335     "};
336 
337     let mut expected = Data {
338         substructure: serde_yaml::Mapping::new(),
339     };
340     expected.substructure.insert(
341         serde_yaml::Value::String("a".to_owned()),
342         serde_yaml::Value::String("foo".to_owned()),
343     );
344     expected.substructure.insert(
345         serde_yaml::Value::String("b".to_owned()),
346         serde_yaml::Value::String("bar".to_owned()),
347     );
348 
349     test_de(yaml, &expected);
350 }
351 
352 #[test]
test_byte_order_mark()353 fn test_byte_order_mark() {
354     let yaml = "\u{feff}- 0\n";
355     let expected = vec![0];
356     test_de(yaml, &expected);
357 }
358 
359 #[test]
test_bomb()360 fn test_bomb() {
361     #[derive(Debug, Deserialize, PartialEq)]
362     struct Data {
363         expected: String,
364     }
365 
366     // This would deserialize an astronomical number of elements if we were
367     // vulnerable.
368     let yaml = indoc! {"
369         a: &a ~
370         b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
371         c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
372         d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
373         e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
374         f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
375         g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
376         h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
377         i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
378         j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i]
379         k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j]
380         l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k]
381         m: &m [*l,*l,*l,*l,*l,*l,*l,*l,*l]
382         n: &n [*m,*m,*m,*m,*m,*m,*m,*m,*m]
383         o: &o [*n,*n,*n,*n,*n,*n,*n,*n,*n]
384         p: &p [*o,*o,*o,*o,*o,*o,*o,*o,*o]
385         q: &q [*p,*p,*p,*p,*p,*p,*p,*p,*p]
386         r: &r [*q,*q,*q,*q,*q,*q,*q,*q,*q]
387         s: &s [*r,*r,*r,*r,*r,*r,*r,*r,*r]
388         t: &t [*s,*s,*s,*s,*s,*s,*s,*s,*s]
389         u: &u [*t,*t,*t,*t,*t,*t,*t,*t,*t]
390         v: &v [*u,*u,*u,*u,*u,*u,*u,*u,*u]
391         w: &w [*v,*v,*v,*v,*v,*v,*v,*v,*v]
392         x: &x [*w,*w,*w,*w,*w,*w,*w,*w,*w]
393         y: &y [*x,*x,*x,*x,*x,*x,*x,*x,*x]
394         z: &z [*y,*y,*y,*y,*y,*y,*y,*y,*y]
395         expected: string
396     "};
397 
398     let expected = Data {
399         expected: "string".to_owned(),
400     };
401 
402     assert_eq!(expected, serde_yaml::from_str::<Data>(yaml).unwrap());
403 }
404 
405 #[test]
test_numbers()406 fn test_numbers() {
407     let cases = [
408         ("0xF0", "240"),
409         ("+0xF0", "240"),
410         ("-0xF0", "-240"),
411         ("0o70", "56"),
412         ("+0o70", "56"),
413         ("-0o70", "-56"),
414         ("0b10", "2"),
415         ("+0b10", "2"),
416         ("-0b10", "-2"),
417         ("127", "127"),
418         ("+127", "127"),
419         ("-127", "-127"),
420         (".inf", ".inf"),
421         (".Inf", ".inf"),
422         (".INF", ".inf"),
423         ("-.inf", "-.inf"),
424         ("-.Inf", "-.inf"),
425         ("-.INF", "-.inf"),
426         (".nan", ".nan"),
427         (".NaN", ".nan"),
428         (".NAN", ".nan"),
429         ("0.1", "0.1"),
430     ];
431     for &(yaml, expected) in &cases {
432         let value = serde_yaml::from_str::<Value>(yaml).unwrap();
433         match value {
434             Value::Number(number) => assert_eq!(number.to_string(), expected),
435             _ => panic!("expected number. input={:?}, result={:?}", yaml, value),
436         }
437     }
438 
439     // NOT numbers.
440     let cases = [
441         "0127", "+0127", "-0127", "++.inf", "+-.inf", "++1", "+-1", "-+1", "--1", "0x+1", "0x-1",
442         "-0x+1", "-0x-1", "++0x1", "+-0x1", "-+0x1", "--0x1",
443     ];
444     for yaml in &cases {
445         let value = serde_yaml::from_str::<Value>(yaml).unwrap();
446         match value {
447             Value::String(string) => assert_eq!(string, *yaml),
448             _ => panic!("expected string. input={:?}, result={:?}", yaml, value),
449         }
450     }
451 }
452 
453 #[test]
test_nan()454 fn test_nan() {
455     // There is no negative NaN in YAML.
456     assert!(serde_yaml::from_str::<f32>(".nan")
457         .unwrap()
458         .is_sign_positive());
459     assert!(serde_yaml::from_str::<f64>(".nan")
460         .unwrap()
461         .is_sign_positive());
462 }
463 
464 #[test]
test_stateful()465 fn test_stateful() {
466     struct Seed(i64);
467 
468     impl<'de> serde::de::DeserializeSeed<'de> for Seed {
469         type Value = i64;
470         fn deserialize<D>(self, deserializer: D) -> Result<i64, D::Error>
471         where
472             D: serde::de::Deserializer<'de>,
473         {
474             struct Visitor(i64);
475             impl<'de> serde::de::Visitor<'de> for Visitor {
476                 type Value = i64;
477 
478                 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
479                     write!(formatter, "an integer")
480                 }
481 
482                 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<i64, E> {
483                     Ok(v * self.0)
484                 }
485 
486                 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> {
487                     Ok(v as i64 * self.0)
488                 }
489             }
490 
491             deserializer.deserialize_any(Visitor(self.0))
492         }
493     }
494 
495     let cases = [("3", 5, 15), ("6", 7, 42), ("-5", 9, -45)];
496     for &(yaml, seed, expected) in &cases {
497         test_de_seed(yaml, Seed(seed), &expected);
498     }
499 }
500 
501 #[test]
test_ignore_tag()502 fn test_ignore_tag() {
503     #[derive(Deserialize, Debug, PartialEq)]
504     struct Data {
505         struc: Struc,
506         tuple: Tuple,
507         newtype: Newtype,
508         map: BTreeMap<char, usize>,
509         vec: Vec<usize>,
510     }
511 
512     #[derive(Deserialize, Debug, PartialEq)]
513     struct Struc {
514         x: usize,
515     }
516 
517     #[derive(Deserialize, Debug, PartialEq)]
518     struct Tuple(usize, usize);
519 
520     #[derive(Deserialize, Debug, PartialEq)]
521     struct Newtype(usize);
522 
523     let yaml = indoc! {"
524         struc: !wat
525           x: 0
526         tuple: !wat
527           - 0
528           - 0
529         newtype: !wat 0
530         map: !wat
531           x: 0
532         vec: !wat
533           - 0
534     "};
535 
536     let expected = Data {
537         struc: Struc { x: 0 },
538         tuple: Tuple(0, 0),
539         newtype: Newtype(0),
540         map: {
541             let mut map = BTreeMap::new();
542             map.insert('x', 0);
543             map
544         },
545         vec: vec![0],
546     };
547 
548     test_de(yaml, &expected);
549 }
550 
551 #[test]
test_no_required_fields()552 fn test_no_required_fields() {
553     #[derive(Deserialize, PartialEq, Debug)]
554     pub struct NoRequiredFields {
555         optional: Option<usize>,
556     }
557 
558     for document in ["", "# comment\n"] {
559         let expected = NoRequiredFields { optional: None };
560         let deserialized: NoRequiredFields = serde_yaml::from_str(document).unwrap();
561         assert_eq!(expected, deserialized);
562 
563         let expected = Vec::<String>::new();
564         let deserialized: Vec<String> = serde_yaml::from_str(document).unwrap();
565         assert_eq!(expected, deserialized);
566 
567         let expected = BTreeMap::new();
568         let deserialized: BTreeMap<char, usize> = serde_yaml::from_str(document).unwrap();
569         assert_eq!(expected, deserialized);
570 
571         let expected = None;
572         let deserialized: Option<String> = serde_yaml::from_str(document).unwrap();
573         assert_eq!(expected, deserialized);
574 
575         let expected = Value::Null;
576         let deserialized: Value = serde_yaml::from_str(document).unwrap();
577         assert_eq!(expected, deserialized);
578     }
579 }
580 
581 #[test]
test_empty_scalar()582 fn test_empty_scalar() {
583     #[derive(Deserialize, PartialEq, Debug)]
584     struct Struct<T> {
585         thing: T,
586     }
587 
588     let yaml = "thing:\n";
589     let expected = Struct {
590         thing: serde_yaml::Sequence::new(),
591     };
592     test_de(yaml, &expected);
593 
594     let expected = Struct {
595         thing: serde_yaml::Mapping::new(),
596     };
597     test_de(yaml, &expected);
598 }
599 
600 #[test]
test_python_safe_dump()601 fn test_python_safe_dump() {
602     #[derive(Deserialize, PartialEq, Debug)]
603     struct Frob {
604         foo: u32,
605     }
606 
607     // This matches output produced by PyYAML's `yaml.safe_dump` when using the
608     // default_style parameter.
609     //
610     //    >>> import yaml
611     //    >>> d = {"foo": 7200}
612     //    >>> print(yaml.safe_dump(d, default_style="|"))
613     //    "foo": !!int |-
614     //      7200
615     //
616     let yaml = indoc! {r#"
617         "foo": !!int |-
618             7200
619     "#};
620 
621     let expected = Frob { foo: 7200 };
622     test_de(yaml, &expected);
623 }
624 
625 #[test]
test_tag_resolution()626 fn test_tag_resolution() {
627     // https://yaml.org/spec/1.2.2/#1032-tag-resolution
628     let yaml = indoc! {"
629         - null
630         - Null
631         - NULL
632         - ~
633         -
634         - true
635         - True
636         - TRUE
637         - false
638         - False
639         - FALSE
640         - y
641         - Y
642         - yes
643         - Yes
644         - YES
645         - n
646         - N
647         - no
648         - No
649         - NO
650         - on
651         - On
652         - ON
653         - off
654         - Off
655         - OFF
656     "};
657 
658     let expected = vec![
659         Value::Null,
660         Value::Null,
661         Value::Null,
662         Value::Null,
663         Value::Null,
664         Value::Bool(true),
665         Value::Bool(true),
666         Value::Bool(true),
667         Value::Bool(false),
668         Value::Bool(false),
669         Value::Bool(false),
670         Value::String("y".to_owned()),
671         Value::String("Y".to_owned()),
672         Value::String("yes".to_owned()),
673         Value::String("Yes".to_owned()),
674         Value::String("YES".to_owned()),
675         Value::String("n".to_owned()),
676         Value::String("N".to_owned()),
677         Value::String("no".to_owned()),
678         Value::String("No".to_owned()),
679         Value::String("NO".to_owned()),
680         Value::String("on".to_owned()),
681         Value::String("On".to_owned()),
682         Value::String("ON".to_owned()),
683         Value::String("off".to_owned()),
684         Value::String("Off".to_owned()),
685         Value::String("OFF".to_owned()),
686     ];
687 
688     test_de(yaml, &expected);
689 }
690 
691 #[test]
test_parse_number()692 fn test_parse_number() {
693     let n = "111".parse::<Number>().unwrap();
694     assert_eq!(n, Number::from(111));
695 
696     let n = "-111".parse::<Number>().unwrap();
697     assert_eq!(n, Number::from(-111));
698 
699     let n = "-1.1".parse::<Number>().unwrap();
700     assert_eq!(n, Number::from(-1.1));
701 
702     let n = ".nan".parse::<Number>().unwrap();
703     assert_eq!(n, Number::from(f64::NAN));
704     assert!(n.as_f64().unwrap().is_sign_positive());
705 
706     let n = ".inf".parse::<Number>().unwrap();
707     assert_eq!(n, Number::from(f64::INFINITY));
708 
709     let n = "-.inf".parse::<Number>().unwrap();
710     assert_eq!(n, Number::from(f64::NEG_INFINITY));
711 
712     let err = "null".parse::<Number>().unwrap_err();
713     assert_eq!(err.to_string(), "failed to parse YAML number");
714 
715     let err = " 1 ".parse::<Number>().unwrap_err();
716     assert_eq!(err.to_string(), "failed to parse YAML number");
717 }
718