1 #![allow(clippy::zero_sized_map_values)]
2
3 use indoc::indoc;
4 use serde::de::Deserialize;
5 #[cfg(not(miri))]
6 use serde::de::{SeqAccess, Visitor};
7 use serde_derive::{Deserialize, Serialize};
8 use serde_yaml::value::{Tag, TaggedValue};
9 use serde_yaml::{Deserializer, Value};
10 #[cfg(not(miri))]
11 use std::collections::BTreeMap;
12 #[cfg(not(miri))]
13 use std::fmt;
14 use std::fmt::Debug;
15
test_error<'de, T>(yaml: &'de str, expected: &str) where T: Deserialize<'de> + Debug,16 fn test_error<'de, T>(yaml: &'de str, expected: &str)
17 where
18 T: Deserialize<'de> + Debug,
19 {
20 let result = serde_yaml::from_str::<T>(yaml);
21 assert_eq!(expected, result.unwrap_err().to_string());
22
23 let mut deserializer = Deserializer::from_str(yaml);
24 if let Some(first_document) = deserializer.next() {
25 if deserializer.next().is_none() {
26 let result = T::deserialize(first_document);
27 assert_eq!(expected, result.unwrap_err().to_string());
28 }
29 }
30 }
31
32 #[test]
test_scan_error()33 fn test_scan_error() {
34 let yaml = ">\n@";
35 let expected = "found character that cannot start any token at line 2 column 1, while scanning for the next token";
36 test_error::<Value>(yaml, expected);
37 }
38
39 #[test]
test_incorrect_type()40 fn test_incorrect_type() {
41 let yaml = indoc! {"
42 ---
43 str
44 "};
45 let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
46 test_error::<i16>(yaml, expected);
47 }
48
49 #[test]
test_incorrect_nested_type()50 fn test_incorrect_nested_type() {
51 #[derive(Deserialize, Debug)]
52 pub struct A {
53 pub b: Vec<B>,
54 }
55 #[derive(Deserialize, Debug)]
56 pub enum B {
57 C(C),
58 }
59 #[derive(Deserialize, Debug)]
60 pub struct C {
61 pub d: bool,
62 }
63 let yaml = indoc! {"
64 b:
65 - !C
66 d: fase
67 "};
68 let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8";
69 test_error::<A>(yaml, expected);
70 }
71
72 #[test]
test_empty()73 fn test_empty() {
74 let expected = "EOF while parsing a value";
75 test_error::<String>("", expected);
76 }
77
78 #[test]
test_missing_field()79 fn test_missing_field() {
80 #[derive(Deserialize, Debug)]
81 pub struct Basic {
82 pub v: bool,
83 pub w: bool,
84 }
85 let yaml = indoc! {"
86 ---
87 v: true
88 "};
89 let expected = "missing field `w` at line 2 column 1";
90 test_error::<Basic>(yaml, expected);
91 }
92
93 #[test]
test_unknown_anchor()94 fn test_unknown_anchor() {
95 let yaml = indoc! {"
96 ---
97 *some
98 "};
99 let expected = "unknown anchor at line 2 column 1";
100 test_error::<String>(yaml, expected);
101 }
102
103 #[test]
test_ignored_unknown_anchor()104 fn test_ignored_unknown_anchor() {
105 #[derive(Deserialize, Debug)]
106 pub struct Wrapper {
107 pub c: (),
108 }
109 let yaml = indoc! {"
110 b: [*a]
111 c: ~
112 "};
113 let expected = "unknown anchor at line 1 column 5";
114 test_error::<Wrapper>(yaml, expected);
115 }
116
117 #[test]
test_bytes()118 fn test_bytes() {
119 let expected = "serialization and deserialization of bytes in YAML is not implemented";
120 test_error::<&[u8]>("...", expected);
121 }
122
123 #[test]
test_two_documents()124 fn test_two_documents() {
125 let yaml = indoc! {"
126 ---
127 0
128 ---
129 1
130 "};
131 let expected = "deserializing from YAML containing more than one document is not supported";
132 test_error::<usize>(yaml, expected);
133 }
134
135 #[test]
test_second_document_syntax_error()136 fn test_second_document_syntax_error() {
137 let yaml = indoc! {"
138 ---
139 0
140 ---
141 ]
142 "};
143
144 let mut de = Deserializer::from_str(yaml);
145 let first_doc = de.next().unwrap();
146 let result = <usize as serde::Deserialize>::deserialize(first_doc);
147 assert_eq!(0, result.unwrap());
148
149 let second_doc = de.next().unwrap();
150 let result = <usize as serde::Deserialize>::deserialize(second_doc);
151 let expected =
152 "did not find expected node content at line 4 column 1, while parsing a block node";
153 assert_eq!(expected, result.unwrap_err().to_string());
154 }
155
156 #[test]
test_missing_enum_tag()157 fn test_missing_enum_tag() {
158 #[derive(Deserialize, Debug)]
159 pub enum E {
160 V(usize),
161 }
162 let yaml = indoc! {r#"
163 "V": 16
164 "other": 32
165 "#};
166 let expected = "invalid type: map, expected a YAML tag starting with '!'";
167 test_error::<E>(yaml, expected);
168 }
169
170 #[test]
test_serialize_nested_enum()171 fn test_serialize_nested_enum() {
172 #[derive(Serialize, Debug)]
173 pub enum Outer {
174 Inner(Inner),
175 }
176 #[derive(Serialize, Debug)]
177 pub enum Inner {
178 Newtype(usize),
179 Tuple(usize, usize),
180 Struct { x: usize },
181 }
182
183 let expected = "serializing nested enums in YAML is not supported yet";
184
185 let e = Outer::Inner(Inner::Newtype(0));
186 let error = serde_yaml::to_string(&e).unwrap_err();
187 assert_eq!(error.to_string(), expected);
188
189 let e = Outer::Inner(Inner::Tuple(0, 0));
190 let error = serde_yaml::to_string(&e).unwrap_err();
191 assert_eq!(error.to_string(), expected);
192
193 let e = Outer::Inner(Inner::Struct { x: 0 });
194 let error = serde_yaml::to_string(&e).unwrap_err();
195 assert_eq!(error.to_string(), expected);
196
197 let e = Value::Tagged(Box::new(TaggedValue {
198 tag: Tag::new("Outer"),
199 value: Value::Tagged(Box::new(TaggedValue {
200 tag: Tag::new("Inner"),
201 value: Value::Null,
202 })),
203 }));
204 let error = serde_yaml::to_string(&e).unwrap_err();
205 assert_eq!(error.to_string(), expected);
206 }
207
208 #[test]
test_deserialize_nested_enum()209 fn test_deserialize_nested_enum() {
210 #[derive(Deserialize, Debug)]
211 pub enum Outer {
212 Inner(Inner),
213 }
214 #[derive(Deserialize, Debug)]
215 pub enum Inner {
216 Variant(Vec<usize>),
217 }
218
219 let yaml = indoc! {"
220 ---
221 !Inner []
222 "};
223 let expected = "deserializing nested enum in Outer::Inner from YAML is not supported yet at line 2 column 1";
224 test_error::<Outer>(yaml, expected);
225
226 let yaml = indoc! {"
227 ---
228 !Variant []
229 "};
230 let expected = "unknown variant `Variant`, expected `Inner`";
231 test_error::<Outer>(yaml, expected);
232
233 let yaml = indoc! {"
234 ---
235 !Inner !Variant []
236 "};
237 let expected = "deserializing nested enum in Outer::Inner from YAML is not supported yet at line 2 column 1";
238 test_error::<Outer>(yaml, expected);
239 }
240
241 #[test]
test_variant_not_a_seq()242 fn test_variant_not_a_seq() {
243 #[derive(Deserialize, Debug)]
244 pub enum E {
245 V(usize),
246 }
247 let yaml = indoc! {"
248 ---
249 !V
250 value: 0
251 "};
252 let expected = "invalid type: map, expected usize at line 2 column 1";
253 test_error::<E>(yaml, expected);
254 }
255
256 #[test]
test_struct_from_sequence()257 fn test_struct_from_sequence() {
258 #[derive(Deserialize, Debug)]
259 pub struct Struct {
260 pub x: usize,
261 pub y: usize,
262 }
263 let yaml = indoc! {"
264 [0, 0]
265 "};
266 let expected = "invalid type: sequence, expected struct Struct";
267 test_error::<Struct>(yaml, expected);
268 }
269
270 #[test]
test_bad_bool()271 fn test_bad_bool() {
272 let yaml = indoc! {"
273 ---
274 !!bool str
275 "};
276 let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1";
277 test_error::<bool>(yaml, expected);
278 }
279
280 #[test]
test_bad_int()281 fn test_bad_int() {
282 let yaml = indoc! {"
283 ---
284 !!int str
285 "};
286 let expected = "invalid value: string \"str\", expected an integer at line 2 column 1";
287 test_error::<i64>(yaml, expected);
288 }
289
290 #[test]
test_bad_float()291 fn test_bad_float() {
292 let yaml = indoc! {"
293 ---
294 !!float str
295 "};
296 let expected = "invalid value: string \"str\", expected a float at line 2 column 1";
297 test_error::<f64>(yaml, expected);
298 }
299
300 #[test]
test_bad_null()301 fn test_bad_null() {
302 let yaml = indoc! {"
303 ---
304 !!null str
305 "};
306 let expected = "invalid value: string \"str\", expected null at line 2 column 1";
307 test_error::<()>(yaml, expected);
308 }
309
310 #[test]
test_short_tuple()311 fn test_short_tuple() {
312 let yaml = indoc! {"
313 ---
314 [0, 0]
315 "};
316 let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
317 test_error::<(u8, u8, u8)>(yaml, expected);
318 }
319
320 #[test]
test_long_tuple()321 fn test_long_tuple() {
322 let yaml = indoc! {"
323 ---
324 [0, 0, 0]
325 "};
326 let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
327 test_error::<(u8, u8)>(yaml, expected);
328 }
329
330 #[test]
test_invalid_scalar_type()331 fn test_invalid_scalar_type() {
332 #[derive(Deserialize, Debug)]
333 pub struct S {
334 pub x: [i32; 1],
335 }
336
337 let yaml = "x: ''\n";
338 let expected = "x: invalid type: string \"\", expected an array of length 1 at line 1 column 4";
339 test_error::<S>(yaml, expected);
340 }
341
342 #[cfg(not(miri))]
343 #[test]
test_infinite_recursion_objects()344 fn test_infinite_recursion_objects() {
345 #[derive(Deserialize, Debug)]
346 pub struct S {
347 pub x: Option<Box<S>>,
348 }
349
350 let yaml = "&a {'x': *a}";
351 let expected = "recursion limit exceeded";
352 test_error::<S>(yaml, expected);
353 }
354
355 #[cfg(not(miri))]
356 #[test]
test_infinite_recursion_arrays()357 fn test_infinite_recursion_arrays() {
358 #[derive(Deserialize, Debug)]
359 pub struct S(pub usize, pub Option<Box<S>>);
360
361 let yaml = "&a [0, *a]";
362 let expected = "recursion limit exceeded";
363 test_error::<S>(yaml, expected);
364 }
365
366 #[cfg(not(miri))]
367 #[test]
test_infinite_recursion_newtype()368 fn test_infinite_recursion_newtype() {
369 #[derive(Deserialize, Debug)]
370 pub struct S(pub Option<Box<S>>);
371
372 let yaml = "&a [*a]";
373 let expected = "recursion limit exceeded";
374 test_error::<S>(yaml, expected);
375 }
376
377 #[cfg(not(miri))]
378 #[test]
test_finite_recursion_objects()379 fn test_finite_recursion_objects() {
380 #[derive(Deserialize, Debug)]
381 pub struct S {
382 pub x: Option<Box<S>>,
383 }
384
385 let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
386 let expected = "recursion limit exceeded at line 1 column 641";
387 test_error::<S>(&yaml, expected);
388 }
389
390 #[cfg(not(miri))]
391 #[test]
test_finite_recursion_arrays()392 fn test_finite_recursion_arrays() {
393 #[derive(Deserialize, Debug)]
394 pub struct S(pub usize, pub Option<Box<S>>);
395
396 let yaml = "[0, ".repeat(1_000) + &"]".repeat(1_000);
397 let expected = "recursion limit exceeded at line 1 column 513";
398 test_error::<S>(&yaml, expected);
399 }
400
401 #[cfg(not(miri))]
402 #[test]
test_billion_laughs()403 fn test_billion_laughs() {
404 #[derive(Debug)]
405 struct X;
406
407 impl<'de> Deserialize<'de> for X {
408 fn deserialize<D>(deserializer: D) -> Result<X, D::Error>
409 where
410 D: serde::Deserializer<'de>,
411 {
412 impl<'de> Visitor<'de> for X {
413 type Value = X;
414
415 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
416 formatter.write_str("exponential blowup")
417 }
418
419 fn visit_unit<E>(self) -> Result<X, E> {
420 Ok(X)
421 }
422
423 fn visit_seq<S>(self, mut seq: S) -> Result<X, S::Error>
424 where
425 S: SeqAccess<'de>,
426 {
427 while let Some(X) = seq.next_element()? {}
428 Ok(X)
429 }
430 }
431
432 deserializer.deserialize_any(X)
433 }
434 }
435
436 let yaml = indoc! {"
437 a: &a ~
438 b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
439 c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
440 d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
441 e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
442 f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
443 g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
444 h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
445 i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
446 "};
447 let expected = "repetition limit exceeded";
448 test_error::<BTreeMap<String, X>>(yaml, expected);
449 }
450
451 #[test]
test_duplicate_keys()452 fn test_duplicate_keys() {
453 let yaml = indoc! {"
454 ---
455 thing: true
456 thing: false
457 "};
458 let expected = "duplicate entry with key \"thing\" at line 2 column 1";
459 test_error::<Value>(yaml, expected);
460
461 let yaml = indoc! {"
462 ---
463 null: true
464 ~: false
465 "};
466 let expected = "duplicate entry with null key at line 2 column 1";
467 test_error::<Value>(yaml, expected);
468
469 let yaml = indoc! {"
470 ---
471 99: true
472 99: false
473 "};
474 let expected = "duplicate entry with key 99 at line 2 column 1";
475 test_error::<Value>(yaml, expected);
476
477 let yaml = indoc! {"
478 ---
479 {}: true
480 {}: false
481 "};
482 let expected = "duplicate entry in YAML map at line 2 column 1";
483 test_error::<Value>(yaml, expected);
484 }
485