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