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