1 #![allow(
2     clippy::decimal_literal_representation,
3     clippy::derive_partial_eq_without_eq,
4     clippy::unreadable_literal,
5     clippy::shadow_unrelated
6 )]
7 
8 use indoc::indoc;
9 use serde::ser::SerializeMap;
10 use serde_derive::{Deserialize, Serialize};
11 use serde_yaml::{Mapping, Number, Value};
12 use std::collections::BTreeMap;
13 use std::fmt::Debug;
14 use std::iter;
15 
test_serde<T>(thing: &T, yaml: &str) where T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug,16 fn test_serde<T>(thing: &T, yaml: &str)
17 where
18     T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug,
19 {
20     let serialized = serde_yaml::to_string(&thing).unwrap();
21     assert_eq!(yaml, serialized);
22 
23     let value = serde_yaml::to_value(thing).unwrap();
24     let serialized = serde_yaml::to_string(&value).unwrap();
25     assert_eq!(yaml, serialized);
26 
27     let deserialized: T = serde_yaml::from_str(yaml).unwrap();
28     assert_eq!(*thing, deserialized);
29 
30     let value: Value = serde_yaml::from_str(yaml).unwrap();
31     let deserialized = T::deserialize(&value).unwrap();
32     assert_eq!(*thing, deserialized);
33 
34     let deserialized: T = serde_yaml::from_value(value).unwrap();
35     assert_eq!(*thing, deserialized);
36 
37     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
38 }
39 
40 #[test]
test_default()41 fn test_default() {
42     assert_eq!(Value::default(), Value::Null);
43 }
44 
45 #[test]
test_int()46 fn test_int() {
47     let thing = 256;
48     let yaml = indoc! {"
49         256
50     "};
51     test_serde(&thing, yaml);
52 }
53 
54 #[test]
test_int_max_u64()55 fn test_int_max_u64() {
56     let thing = u64::MAX;
57     let yaml = indoc! {"
58         18446744073709551615
59     "};
60     test_serde(&thing, yaml);
61 }
62 
63 #[test]
test_int_min_i64()64 fn test_int_min_i64() {
65     let thing = i64::MIN;
66     let yaml = indoc! {"
67         -9223372036854775808
68     "};
69     test_serde(&thing, yaml);
70 }
71 
72 #[test]
test_int_max_i64()73 fn test_int_max_i64() {
74     let thing = i64::MAX;
75     let yaml = indoc! {"
76         9223372036854775807
77     "};
78     test_serde(&thing, yaml);
79 }
80 
81 #[test]
test_i128_small()82 fn test_i128_small() {
83     let thing: i128 = -256;
84     let yaml = indoc! {"
85         -256
86     "};
87     test_serde(&thing, yaml);
88 }
89 
90 #[test]
test_u128_small()91 fn test_u128_small() {
92     let thing: u128 = 256;
93     let yaml = indoc! {"
94         256
95     "};
96     test_serde(&thing, yaml);
97 }
98 
99 #[test]
test_float()100 fn test_float() {
101     let thing = 25.6;
102     let yaml = indoc! {"
103         25.6
104     "};
105     test_serde(&thing, yaml);
106 
107     let thing = 25.;
108     let yaml = indoc! {"
109         25.0
110     "};
111     test_serde(&thing, yaml);
112 
113     let thing = f64::INFINITY;
114     let yaml = indoc! {"
115         .inf
116     "};
117     test_serde(&thing, yaml);
118 
119     let thing = f64::NEG_INFINITY;
120     let yaml = indoc! {"
121         -.inf
122     "};
123     test_serde(&thing, yaml);
124 
125     let float: f64 = serde_yaml::from_str(indoc! {"
126         .nan
127     "})
128     .unwrap();
129     assert!(float.is_nan());
130 }
131 
132 #[test]
test_float32()133 fn test_float32() {
134     let thing: f32 = 25.5;
135     let yaml = indoc! {"
136         25.5
137     "};
138     test_serde(&thing, yaml);
139 
140     let thing = f32::INFINITY;
141     let yaml = indoc! {"
142         .inf
143     "};
144     test_serde(&thing, yaml);
145 
146     let thing = f32::NEG_INFINITY;
147     let yaml = indoc! {"
148         -.inf
149     "};
150     test_serde(&thing, yaml);
151 
152     let single_float: f32 = serde_yaml::from_str(indoc! {"
153         .nan
154     "})
155     .unwrap();
156     assert!(single_float.is_nan());
157 }
158 
159 #[test]
test_char()160 fn test_char() {
161     let ch = '.';
162     let yaml = indoc! {"
163         '.'
164     "};
165     assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap());
166 
167     let ch = '#';
168     let yaml = indoc! {"
169         '#'
170     "};
171     assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap());
172 
173     let ch = '-';
174     let yaml = indoc! {"
175         '-'
176     "};
177     assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap());
178 }
179 
180 #[test]
test_vec()181 fn test_vec() {
182     let thing = vec![1, 2, 3];
183     let yaml = indoc! {"
184         - 1
185         - 2
186         - 3
187     "};
188     test_serde(&thing, yaml);
189 }
190 
191 #[test]
test_map()192 fn test_map() {
193     let mut thing = BTreeMap::new();
194     thing.insert("x".to_owned(), 1);
195     thing.insert("y".to_owned(), 2);
196     let yaml = indoc! {"
197         x: 1
198         y: 2
199     "};
200     test_serde(&thing, yaml);
201 }
202 
203 #[test]
test_map_key_value()204 fn test_map_key_value() {
205     struct Map;
206 
207     impl serde::Serialize for Map {
208         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
209         where
210             S: serde::Serializer,
211         {
212             // Test maps which do not serialize using serialize_entry.
213             let mut map = serializer.serialize_map(Some(1))?;
214             map.serialize_key("k")?;
215             map.serialize_value("v")?;
216             map.end()
217         }
218     }
219 
220     let yaml = indoc! {"
221         k: v
222     "};
223     assert_eq!(yaml, serde_yaml::to_string(&Map).unwrap());
224 }
225 
226 #[test]
test_basic_struct()227 fn test_basic_struct() {
228     #[derive(Serialize, Deserialize, PartialEq, Debug)]
229     struct Basic {
230         x: isize,
231         y: String,
232         z: bool,
233     }
234     let thing = Basic {
235         x: -4,
236         y: "hi\tquoted".to_owned(),
237         z: true,
238     };
239     let yaml = indoc! {r#"
240         x: -4
241         y: "hi\tquoted"
242         z: true
243     "#};
244     test_serde(&thing, yaml);
245 }
246 
247 #[test]
test_string_escapes()248 fn test_string_escapes() {
249     let yaml = indoc! {"
250         ascii
251     "};
252     test_serde(&"ascii".to_owned(), yaml);
253 
254     let yaml = indoc! {r#"
255         "\0\a\b\t\n\v\f\r\e\"\\\N\L\P"
256     "#};
257     test_serde(
258         &"\0\u{7}\u{8}\t\n\u{b}\u{c}\r\u{1b}\"\\\u{85}\u{2028}\u{2029}".to_owned(),
259         yaml,
260     );
261 
262     let yaml = indoc! {r#"
263         "\x1F\uFEFF"
264     "#};
265     test_serde(&"\u{1f}\u{feff}".to_owned(), yaml);
266 
267     let yaml = indoc! {"
268         ��
269     "};
270     test_serde(&"\u{1f389}".to_owned(), yaml);
271 }
272 
273 #[test]
test_multiline_string()274 fn test_multiline_string() {
275     #[derive(Serialize, Deserialize, PartialEq, Debug)]
276     struct Struct {
277         trailing_newline: String,
278         no_trailing_newline: String,
279     }
280     let thing = Struct {
281         trailing_newline: "aaa\nbbb\n".to_owned(),
282         no_trailing_newline: "aaa\nbbb".to_owned(),
283     };
284     let yaml = indoc! {"
285         trailing_newline: |
286           aaa
287           bbb
288         no_trailing_newline: |-
289           aaa
290           bbb
291     "};
292     test_serde(&thing, yaml);
293 }
294 
295 #[test]
test_strings_needing_quote()296 fn test_strings_needing_quote() {
297     #[derive(Serialize, Deserialize, PartialEq, Debug)]
298     struct Struct {
299         boolean: String,
300         integer: String,
301         void: String,
302         leading_zeros: String,
303     }
304     let thing = Struct {
305         boolean: "true".to_owned(),
306         integer: "1".to_owned(),
307         void: "null".to_owned(),
308         leading_zeros: "007".to_owned(),
309     };
310     let yaml = indoc! {"
311         boolean: 'true'
312         integer: '1'
313         void: 'null'
314         leading_zeros: '007'
315     "};
316     test_serde(&thing, yaml);
317 }
318 
319 #[test]
test_nested_vec()320 fn test_nested_vec() {
321     let thing = vec![vec![1, 2, 3], vec![4, 5, 6]];
322     let yaml = indoc! {"
323         - - 1
324           - 2
325           - 3
326         - - 4
327           - 5
328           - 6
329     "};
330     test_serde(&thing, yaml);
331 }
332 
333 #[test]
test_nested_struct()334 fn test_nested_struct() {
335     #[derive(Serialize, Deserialize, PartialEq, Debug)]
336     struct Outer {
337         inner: Inner,
338     }
339     #[derive(Serialize, Deserialize, PartialEq, Debug)]
340     struct Inner {
341         v: u16,
342     }
343     let thing = Outer {
344         inner: Inner { v: 512 },
345     };
346     let yaml = indoc! {"
347         inner:
348           v: 512
349     "};
350     test_serde(&thing, yaml);
351 }
352 
353 #[test]
test_nested_enum()354 fn test_nested_enum() {
355     #[derive(Serialize, Deserialize, PartialEq, Debug)]
356     enum Outer {
357         Inner(Inner),
358     }
359     #[derive(Serialize, Deserialize, PartialEq, Debug)]
360     enum Inner {
361         Unit,
362     }
363     let thing = Outer::Inner(Inner::Unit);
364     let yaml = indoc! {"
365         !Inner Unit
366     "};
367     test_serde(&thing, yaml);
368 }
369 
370 #[test]
test_option()371 fn test_option() {
372     let thing = vec![Some(1), None, Some(3)];
373     let yaml = indoc! {"
374         - 1
375         - null
376         - 3
377     "};
378     test_serde(&thing, yaml);
379 }
380 
381 #[test]
test_unit()382 fn test_unit() {
383     let thing = vec![(), ()];
384     let yaml = indoc! {"
385         - null
386         - null
387     "};
388     test_serde(&thing, yaml);
389 }
390 
391 #[test]
test_unit_struct()392 fn test_unit_struct() {
393     #[derive(Serialize, Deserialize, PartialEq, Debug)]
394     struct Foo;
395     let thing = Foo;
396     let yaml = indoc! {"
397         null
398     "};
399     test_serde(&thing, yaml);
400 }
401 
402 #[test]
test_unit_variant()403 fn test_unit_variant() {
404     #[derive(Serialize, Deserialize, PartialEq, Debug)]
405     enum Variant {
406         First,
407         Second,
408     }
409     let thing = Variant::First;
410     let yaml = indoc! {"
411         First
412     "};
413     test_serde(&thing, yaml);
414 }
415 
416 #[test]
test_newtype_struct()417 fn test_newtype_struct() {
418     #[derive(Serialize, Deserialize, PartialEq, Debug)]
419     struct OriginalType {
420         v: u16,
421     }
422     #[derive(Serialize, Deserialize, PartialEq, Debug)]
423     struct NewType(OriginalType);
424     let thing = NewType(OriginalType { v: 1 });
425     let yaml = indoc! {"
426         v: 1
427     "};
428     test_serde(&thing, yaml);
429 }
430 
431 #[test]
test_newtype_variant()432 fn test_newtype_variant() {
433     #[derive(Serialize, Deserialize, PartialEq, Debug)]
434     enum Variant {
435         Size(usize),
436     }
437     let thing = Variant::Size(127);
438     let yaml = indoc! {"
439         !Size 127
440     "};
441     test_serde(&thing, yaml);
442 }
443 
444 #[test]
test_tuple_variant()445 fn test_tuple_variant() {
446     #[derive(Serialize, Deserialize, PartialEq, Debug)]
447     enum Variant {
448         Rgb(u8, u8, u8),
449     }
450     let thing = Variant::Rgb(32, 64, 96);
451     let yaml = indoc! {"
452         !Rgb
453         - 32
454         - 64
455         - 96
456     "};
457     test_serde(&thing, yaml);
458 }
459 
460 #[test]
test_struct_variant()461 fn test_struct_variant() {
462     #[derive(Serialize, Deserialize, PartialEq, Debug)]
463     enum Variant {
464         Color { r: u8, g: u8, b: u8 },
465     }
466     let thing = Variant::Color {
467         r: 32,
468         g: 64,
469         b: 96,
470     };
471     let yaml = indoc! {"
472         !Color
473         r: 32
474         g: 64
475         b: 96
476     "};
477     test_serde(&thing, yaml);
478 }
479 
480 #[test]
test_tagged_map_value()481 fn test_tagged_map_value() {
482     #[derive(Serialize, Deserialize, PartialEq, Debug)]
483     struct Bindings {
484         profile: Profile,
485     }
486     #[derive(Serialize, Deserialize, PartialEq, Debug)]
487     enum Profile {
488         ClassValidator { class_name: String },
489     }
490     let thing = Bindings {
491         profile: Profile::ClassValidator {
492             class_name: "ApplicationConfig".to_owned(),
493         },
494     };
495     let yaml = indoc! {"
496         profile: !ClassValidator
497           class_name: ApplicationConfig
498     "};
499     test_serde(&thing, yaml);
500 }
501 
502 #[test]
test_value()503 fn test_value() {
504     #[derive(Serialize, Deserialize, PartialEq, Debug)]
505     pub struct GenericInstructions {
506         #[serde(rename = "type")]
507         pub typ: String,
508         pub config: Value,
509     }
510     let thing = GenericInstructions {
511         typ: "primary".to_string(),
512         config: Value::Sequence(vec![
513             Value::Null,
514             Value::Bool(true),
515             Value::Number(Number::from(65535)),
516             Value::Number(Number::from(0.54321)),
517             Value::String("s".into()),
518             Value::Mapping(Mapping::new()),
519         ]),
520     };
521     let yaml = indoc! {"
522         type: primary
523         config:
524         - null
525         - true
526         - 65535
527         - 0.54321
528         - s
529         - {}
530     "};
531     test_serde(&thing, yaml);
532 }
533 
534 #[test]
test_mapping()535 fn test_mapping() {
536     #[derive(Serialize, Deserialize, PartialEq, Debug)]
537     struct Data {
538         pub substructure: Mapping,
539     }
540 
541     let mut thing = Data {
542         substructure: Mapping::new(),
543     };
544     thing.substructure.insert(
545         Value::String("a".to_owned()),
546         Value::String("foo".to_owned()),
547     );
548     thing.substructure.insert(
549         Value::String("b".to_owned()),
550         Value::String("bar".to_owned()),
551     );
552 
553     let yaml = indoc! {"
554         substructure:
555           a: foo
556           b: bar
557     "};
558 
559     test_serde(&thing, yaml);
560 }
561 
562 #[test]
test_long_string()563 fn test_long_string() {
564     #[derive(Serialize, Deserialize, PartialEq, Debug)]
565     struct Data {
566         pub string: String,
567     }
568 
569     let thing = Data {
570         string: iter::repeat(["word", " "]).flatten().take(69).collect(),
571     };
572 
573     let yaml = indoc! {"
574         string: word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word
575     "};
576 
577     test_serde(&thing, yaml);
578 }
579