1 #![allow(clippy::cast_lossless, clippy::cast_possible_wrap)]
2
3 use indoc::indoc;
4 use serde::serde_if_integer128;
5 use serde_derive::Deserialize;
6 use serde_yaml::Value;
7 use std::collections::BTreeMap;
8 use std::fmt::Debug;
9
test_de<T>(yaml: &str, expected: &T) where T: serde::de::DeserializeOwned + PartialEq + Debug,10 fn test_de<T>(yaml: &str, expected: &T)
11 where
12 T: serde::de::DeserializeOwned + PartialEq + Debug,
13 {
14 let deserialized: T = serde_yaml::from_str(yaml).unwrap();
15 assert_eq!(*expected, deserialized);
16
17 serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
18 serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
19 }
20
test_de_seed<T, S>(yaml: &str, seed: S, expected: &T) where T: PartialEq + Debug, S: for<'de> serde::de::DeserializeSeed<'de, Value = T>,21 fn test_de_seed<T, S>(yaml: &str, seed: S, expected: &T)
22 where
23 T: PartialEq + Debug,
24 S: for<'de> serde::de::DeserializeSeed<'de, Value = T>,
25 {
26 let deserialized: T = serde_yaml::seed::from_str_seed(yaml, seed).unwrap();
27 assert_eq!(*expected, deserialized);
28
29 serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
30 serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
31 }
32
33 #[test]
test_alias()34 fn test_alias() {
35 let yaml = indoc! {"
36 ---
37 first:
38 &alias
39 1
40 second:
41 *alias
42 third: 3
43 "};
44 let mut expected = BTreeMap::new();
45 {
46 expected.insert(String::from("first"), 1);
47 expected.insert(String::from("second"), 1);
48 expected.insert(String::from("third"), 3);
49 }
50 test_de(&yaml, &expected);
51 }
52
53 #[test]
test_option()54 fn test_option() {
55 #[derive(Deserialize, PartialEq, Debug)]
56 struct Data {
57 a: Option<f64>,
58 b: Option<String>,
59 c: Option<bool>,
60 }
61 let yaml = indoc! {"
62 ---
63 b:
64 c: true
65 "};
66 let expected = Data {
67 a: None,
68 b: None,
69 c: Some(true),
70 };
71 test_de(&yaml, &expected);
72 }
73
74 #[test]
test_option_alias()75 fn test_option_alias() {
76 #[derive(Deserialize, PartialEq, Debug)]
77 struct Data {
78 a: Option<f64>,
79 b: Option<String>,
80 c: Option<bool>,
81 d: Option<f64>,
82 e: Option<String>,
83 f: Option<bool>,
84 }
85 let yaml = indoc! {"
86 ---
87 none_f:
88 &none_f
89 ~
90 none_s:
91 &none_s
92 ~
93 none_b:
94 &none_b
95 ~
96
97 some_f:
98 &some_f
99 1.0
100 some_s:
101 &some_s
102 x
103 some_b:
104 &some_b
105 true
106
107 a: *none_f
108 b: *none_s
109 c: *none_b
110 d: *some_f
111 e: *some_s
112 f: *some_b
113 "};
114 let expected = Data {
115 a: None,
116 b: None,
117 c: None,
118 d: Some(1.0),
119 e: Some("x".to_owned()),
120 f: Some(true),
121 };
122 test_de(&yaml, &expected);
123 }
124
125 #[test]
test_enum_alias()126 fn test_enum_alias() {
127 #[derive(Deserialize, PartialEq, Debug)]
128 enum E {
129 A,
130 B(u8, u8),
131 }
132 #[derive(Deserialize, PartialEq, Debug)]
133 struct Data {
134 a: E,
135 b: E,
136 }
137 let yaml = indoc! {"
138 ---
139 aref:
140 &aref
141 A
142 bref:
143 &bref
144 B:
145 - 1
146 - 2
147
148 a: *aref
149 b: *bref
150 "};
151 let expected = Data {
152 a: E::A,
153 b: E::B(1, 2),
154 };
155 test_de(&yaml, &expected);
156 }
157
158 #[test]
test_enum_tag()159 fn test_enum_tag() {
160 #[derive(Deserialize, PartialEq, Debug)]
161 enum E {
162 A(String),
163 B(String),
164 }
165 #[derive(Deserialize, PartialEq, Debug)]
166 struct Data {
167 a: E,
168 b: E,
169 }
170 let yaml = indoc! {"
171 ---
172 a: !A foo
173 b: !B bar
174 "};
175 let expected = Data {
176 a: E::A("foo".into()),
177 b: E::B("bar".into()),
178 };
179 test_de(&yaml, &expected);
180 }
181
182 #[test]
test_number_as_string()183 fn test_number_as_string() {
184 #[derive(Deserialize, PartialEq, Debug)]
185 struct Num {
186 value: String,
187 }
188 let yaml = indoc! {"
189 ---
190 # Cannot be represented as u128
191 value: 340282366920938463463374607431768211457
192 "};
193 let expected = Num {
194 value: "340282366920938463463374607431768211457".to_owned(),
195 };
196 test_de(&yaml, &expected);
197 }
198
199 serde_if_integer128! {
200 #[test]
201 fn test_i128_big() {
202 let expected: i128 = ::std::i64::MIN as i128 - 1;
203 let yaml = indoc! {"
204 ---
205 -9223372036854775809
206 "};
207 assert_eq!(expected, serde_yaml::from_str::<i128>(&yaml).unwrap());
208 }
209
210 #[test]
211 fn test_u128_big() {
212 let expected: u128 = ::std::u64::MAX as u128 + 1;
213 let yaml = indoc! {"
214 ---
215 18446744073709551616
216 "};
217 assert_eq!(expected, serde_yaml::from_str::<u128>(&yaml).unwrap());
218 }
219 }
220
221 #[test]
test_number_alias_as_string()222 fn test_number_alias_as_string() {
223 #[derive(Deserialize, PartialEq, Debug)]
224 struct Num {
225 version: String,
226 value: String,
227 }
228 let yaml = indoc! {"
229 ---
230 version: &a 1.10
231 value: *a
232 "};
233 let expected = Num {
234 version: "1.10".to_owned(),
235 value: "1.10".to_owned(),
236 };
237 test_de(&yaml, &expected);
238 }
239
240 #[test]
test_de_mapping()241 fn test_de_mapping() {
242 #[derive(Debug, Deserialize, PartialEq)]
243 struct Data {
244 pub substructure: serde_yaml::Mapping,
245 }
246 let yaml = indoc! {"
247 ---
248 substructure:
249 a: 'foo'
250 b: 'bar'
251 "};
252
253 let mut expected = Data {
254 substructure: serde_yaml::Mapping::new(),
255 };
256 expected.substructure.insert(
257 serde_yaml::Value::String("a".to_owned()),
258 serde_yaml::Value::String("foo".to_owned()),
259 );
260 expected.substructure.insert(
261 serde_yaml::Value::String("b".to_owned()),
262 serde_yaml::Value::String("bar".to_owned()),
263 );
264
265 test_de(&yaml, &expected);
266 }
267
268 #[test]
test_bomb()269 fn test_bomb() {
270 #[derive(Debug, Deserialize, PartialEq)]
271 struct Data {
272 expected: String,
273 }
274
275 // This would deserialize an astronomical number of elements if we were
276 // vulnerable.
277 let yaml = indoc! {"
278 ---
279 a: &a ~
280 b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
281 c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
282 d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
283 e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
284 f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
285 g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
286 h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
287 i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
288 j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i]
289 k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j]
290 l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k]
291 m: &m [*l,*l,*l,*l,*l,*l,*l,*l,*l]
292 n: &n [*m,*m,*m,*m,*m,*m,*m,*m,*m]
293 o: &o [*n,*n,*n,*n,*n,*n,*n,*n,*n]
294 p: &p [*o,*o,*o,*o,*o,*o,*o,*o,*o]
295 q: &q [*p,*p,*p,*p,*p,*p,*p,*p,*p]
296 r: &r [*q,*q,*q,*q,*q,*q,*q,*q,*q]
297 s: &s [*r,*r,*r,*r,*r,*r,*r,*r,*r]
298 t: &t [*s,*s,*s,*s,*s,*s,*s,*s,*s]
299 u: &u [*t,*t,*t,*t,*t,*t,*t,*t,*t]
300 v: &v [*u,*u,*u,*u,*u,*u,*u,*u,*u]
301 w: &w [*v,*v,*v,*v,*v,*v,*v,*v,*v]
302 x: &x [*w,*w,*w,*w,*w,*w,*w,*w,*w]
303 y: &y [*x,*x,*x,*x,*x,*x,*x,*x,*x]
304 z: &z [*y,*y,*y,*y,*y,*y,*y,*y,*y]
305 expected: string
306 "};
307
308 let expected = Data {
309 expected: "string".to_owned(),
310 };
311
312 assert_eq!(expected, serde_yaml::from_str::<Data>(&yaml).unwrap());
313 }
314
315 #[test]
test_numbers()316 fn test_numbers() {
317 let cases = [
318 ("0xF0", "240"),
319 ("+0xF0", "240"),
320 ("-0xF0", "-240"),
321 ("0o70", "56"),
322 ("+0o70", "56"),
323 ("-0o70", "-56"),
324 ("0b10", "2"),
325 ("+0b10", "2"),
326 ("-0b10", "-2"),
327 ("127", "127"),
328 ("+127", "127"),
329 ("-127", "-127"),
330 (".inf", ".inf"),
331 (".Inf", ".inf"),
332 (".INF", ".inf"),
333 ("-.inf", "-.inf"),
334 ("-.Inf", "-.inf"),
335 ("-.INF", "-.inf"),
336 (".nan", ".nan"),
337 (".NaN", ".nan"),
338 (".NAN", ".nan"),
339 ("0.1", "0.1"),
340 ];
341 for &(yaml, expected) in &cases {
342 let value = serde_yaml::from_str::<Value>(yaml).unwrap();
343 match value {
344 Value::Number(number) => assert_eq!(number.to_string(), expected),
345 _ => panic!("expected number"),
346 }
347 }
348 }
349
350 #[test]
test_stateful()351 fn test_stateful() {
352 struct Seed(i64);
353
354 impl<'de> serde::de::DeserializeSeed<'de> for Seed {
355 type Value = i64;
356 fn deserialize<D>(self, deserializer: D) -> Result<i64, D::Error>
357 where
358 D: serde::de::Deserializer<'de>,
359 {
360 struct Visitor(i64);
361 impl<'de> serde::de::Visitor<'de> for Visitor {
362 type Value = i64;
363
364 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
365 write!(formatter, "an integer")
366 }
367
368 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<i64, E> {
369 Ok(v * self.0)
370 }
371
372 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> {
373 Ok(v as i64 * self.0)
374 }
375 }
376
377 deserializer.deserialize_any(Visitor(self.0))
378 }
379 }
380
381 let cases = [("3", 5, 15), ("6", 7, 42), ("-5", 9, -45)];
382 for &(yaml, seed, expected) in &cases {
383 test_de_seed(yaml, Seed(seed), &expected);
384 }
385 }
386