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