• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use simple_logger::SimpleLogger;
2 use std::fmt::Debug;
3 
4 use serde::{de, ser};
5 use serde_derive::{Deserialize, Serialize};
6 use serde_xml_rs::{from_str, Error};
7 
init_logger()8 fn init_logger() {
9     let _ = SimpleLogger::new().init();
10 }
11 
12 #[derive(PartialEq, Debug, Serialize, Deserialize)]
13 enum Animal {
14     Dog,
15     Frog(String),
16     Ant(Simple),
17     Cat { age: usize, name: String },
18 }
19 
20 #[derive(PartialEq, Debug, Serialize, Deserialize)]
21 struct Simple {
22     a: (),
23     b: usize,
24     c: String,
25     d: Option<String>,
26 }
27 
28 #[derive(PartialEq, Debug, Serialize, Deserialize)]
29 struct Inner {
30     a: (),
31     b: (usize, String, i8),
32     c: Vec<String>,
33 }
34 
35 #[derive(PartialEq, Debug, Serialize, Deserialize)]
36 struct Outer {
37     inner: Option<Inner>,
38 }
39 
test_parse_ok<'de, 'a, T>(errors: &[(&'a str, T)]) where T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,40 fn test_parse_ok<'de, 'a, T>(errors: &[(&'a str, T)])
41 where
42     T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,
43 {
44     for &(s, ref value) in errors {
45         let v: T = from_str(s).unwrap();
46         assert_eq!(v, *value);
47 
48         // // Make sure we can deserialize into an `Element`.
49         // let xml_value: Element = from_str(s).unwrap();
50 
51         // // Make sure we can deserialize from an `Element`.
52         // let v: T = from_value(xml_value.clone()).unwrap();
53         // assert_eq!(v, *value);
54     }
55 }
56 
test_parse_err<'de, 'a, T>(errors: &[&'a str]) where T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,57 fn test_parse_err<'de, 'a, T>(errors: &[&'a str])
58 where
59     T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,
60 {
61     for &s in errors {
62         assert!(match from_str::<T>(s) {
63             Err(Error::Syntax { source: _ }) => true,
64             _ => false,
65         });
66     }
67 }
68 
test_parse_invalid<'de, 'a, T>(errors: &[&'a str]) where T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,69 fn test_parse_invalid<'de, 'a, T>(errors: &[&'a str])
70 where
71     T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,
72 {
73     for &s in errors {
74         assert!(match from_str::<T>(s) {
75             Err(_) => true,
76             _ => false,
77         });
78     }
79 }
80 
81 #[test]
test_namespaces()82 fn test_namespaces() {
83     init_logger();
84     #[derive(PartialEq, Serialize, Deserialize, Debug)]
85     struct Envelope {
86         subject: String,
87     }
88     let s = r#"
89     <?xml version="1.0" encoding="UTF-8"?>
90     <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
91         <gesmes:subject>Reference rates</gesmes:subject>
92     </gesmes:Envelope>"#;
93     test_parse_ok(&[(
94         s,
95         Envelope {
96             subject: "Reference rates".to_string(),
97         },
98     )]);
99 }
100 
101 #[test]
test_doctype()102 fn test_doctype() {
103     init_logger();
104     #[derive(PartialEq, Serialize, Deserialize, Debug)]
105     struct Envelope {
106         subject: String,
107     }
108 
109     test_parse_ok(&[
110         (
111             r#"
112             <?xml version="1.0" encoding="UTF-8"?>
113             <!DOCTYPE Envelope>
114             <Envelope>
115             <subject>Reference rates</subject>
116             </Envelope>"#,
117             Envelope {
118                 subject: "Reference rates".to_string(),
119             },
120         ),
121         (
122             r#"
123             <?xml version="1.0" encoding="UTF-8"?>
124             <!DOCTYPE Envelope[]>
125             <Envelope>
126             <subject>Reference rates</subject>
127             </Envelope>"#,
128             Envelope {
129                 subject: "Reference rates".to_string(),
130             },
131         ),
132         (
133             r#"
134             <?xml version="1.0" encoding="UTF-8"?>
135             <!DOCTYPE Envelope [
136                 <!ELEMENT subject (#PCDATA)>
137             ] >
138             <Envelope>
139             <subject>Reference rates</subject>
140             </Envelope>"#,
141             Envelope {
142                 subject: "Reference rates".to_string(),
143             },
144         ),
145     ]);
146 }
147 
148 #[test]
149 #[ignore] // FIXME
test_forwarded_namespace()150 fn test_forwarded_namespace() {
151     #[derive(PartialEq, Serialize, Deserialize, Debug)]
152     struct Graphml {
153         #[serde(rename = "xsi:schemaLocation")]
154         schema_location: String,
155     }
156     let s = r#"
157     <?xml version="1.0" encoding="UTF-8"?>
158     <graphml xmlns="http://graphml.graphdrawing.org/xmlns"
159         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
160         xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
161         http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
162 
163 
164     </graphml>"#;
165     test_parse_ok(&[(
166         s,
167         Graphml {
168             schema_location: "http://graphml.graphdrawing.org/xmlns
169         http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"
170                 .to_string(),
171         },
172     )]);
173 }
174 
175 #[test]
test_parse_string()176 fn test_parse_string() {
177     init_logger();
178 
179     test_parse_ok(&[
180         (
181             "<bla>This is a String</bla>",
182             "This is a String".to_string(),
183         ),
184         ("<bla></bla>", "".to_string()),
185         ("<bla>     </bla>", "".to_string()),
186         ("<bla>&lt;boom/&gt;</bla>", "<boom/>".to_string()),
187         ("<bla>&#9835;</bla>", "♫".to_string()),
188         ("<bla>&#x266B;</bla>", "♫".to_string()),
189         (
190             "<bla>♫<![CDATA[<cookies/>]]>♫</bla>",
191             "♫<cookies/>♫".to_string(),
192         ),
193     ]);
194 }
195 
196 #[test]
197 #[ignore] // FIXME
test_parse_string_not_trim()198 fn test_parse_string_not_trim() {
199     init_logger();
200 
201     test_parse_ok(&[("<bla>     </bla>", "     ".to_string())]);
202 }
203 
204 #[test]
205 #[ignore] // FIXME
test_parse_enum()206 fn test_parse_enum() {
207     use self::Animal::*;
208     init_logger();
209 
210     test_parse_ok(&[
211         ("<Animal xsi:type=\"Dog\"/>", Dog),
212         (
213             "<Animal xsi:type=\"Frog\">Quak</Animal>",
214             Frog("Quak".to_string()),
215         ),
216         (
217             "<Animal xsi:type=\"Ant\"><a/><c>bla</c><b>15</b><d>Foo</d></Animal>",
218             Ant(Simple {
219                 a: (),
220                 b: 15,
221                 c: "bla".to_string(),
222                 d: Some("Foo".to_string()),
223             }),
224         ),
225         (
226             "<Animal xsi:type=\"Ant\"><a/><c>bla</c><b>15</b></Animal>",
227             Ant(Simple {
228                 a: (),
229                 b: 15,
230                 c: "bla".to_string(),
231                 d: None,
232             }),
233         ),
234         (
235             "<Animal xsi:type=\"Cat\"><age>42</age><name>Shere Khan</name></Animal>",
236             Cat {
237                 age: 42,
238                 name: "Shere Khan".to_string(),
239             },
240         ),
241     ]);
242 
243     #[derive(PartialEq, Debug, Serialize, Deserialize)]
244     struct Helper {
245         x: Animal,
246     }
247 
248     test_parse_ok(&[
249         ("<Helper><x xsi:type=\"Dog\"/></Helper>", Helper { x: Dog }),
250         (
251             "<Helper><x xsi:type=\"Frog\">Quak</Animal></Helper>",
252             Helper {
253                 x: Frog("Quak".to_string()),
254             },
255         ),
256         (
257             "<Helper><x xsi:type=\"Cat\">
258                 <age>42</age>
259                 <name>Shere Khan</name>
260             </x></Helper>",
261             Helper {
262                 x: Cat {
263                     age: 42,
264                     name: "Shere Khan".to_string(),
265                 },
266             },
267         ),
268     ]);
269 }
270 
271 #[test]
test_parse_i64()272 fn test_parse_i64() {
273     init_logger();
274     test_parse_ok(&[
275         ("<bla>0</bla>", 0),
276         ("<bla>-2</bla>", -2),
277         ("<bla>-1234</bla>", -1234),
278         ("<bla> -1234 </bla>", -1234),
279     ]);
280 }
281 
282 #[test]
test_parse_u64()283 fn test_parse_u64() {
284     init_logger();
285     test_parse_ok(&[
286         ("<bla>0</bla>", 0),
287         ("<bla>1234</bla>", 1234),
288         ("<bla> 1234 </bla>", 1234),
289     ]);
290 }
291 
292 #[test]
test_parse_bool_element()293 fn test_parse_bool_element() {
294     init_logger();
295     test_parse_ok(&[
296         ("<bla>true</bla>", true),
297         ("<bla>false</bla>", false),
298         ("<bla> true </bla>", true),
299         ("<bla> false </bla>", false),
300         ("<bla>1</bla>", true),
301         ("<bla>0</bla>", false),
302     ]);
303 
304     test_parse_invalid::<bool>(&["<bla>verum</bla>"]);
305 }
306 
307 #[test]
test_parse_bool_attribute()308 fn test_parse_bool_attribute() {
309     #[derive(PartialEq, Debug, Deserialize, Serialize)]
310     struct Dummy {
311         foo: bool,
312     }
313 
314     init_logger();
315     test_parse_ok(&[
316         ("<bla foo=\"true\"/>", Dummy { foo: true }),
317         ("<bla foo=\"false\"/>", Dummy { foo: false }),
318         ("<bla foo=\"1\"/>", Dummy { foo: true }),
319         ("<bla foo=\"0\"/>", Dummy { foo: false }),
320     ]);
321 
322     test_parse_invalid::<Dummy>(&[
323         "<bla foo=\"bar\"/>",
324         "<bla foo=\" true \"/>",
325         "<bla foo=\"10\"/>",
326         "<bla foo=\"\"/>",
327         "<bla/>",
328     ]);
329 }
330 
331 #[test]
test_parse_unit()332 fn test_parse_unit() {
333     init_logger();
334     test_parse_ok(&[("<bla/>", ())]);
335 }
336 
337 #[test]
test_parse_f64()338 fn test_parse_f64() {
339     init_logger();
340     test_parse_ok(&[
341         ("<bla>3.0</bla>", 3.0f64),
342         ("<bla>3.1</bla>", 3.1),
343         ("<bla>-1.2</bla>", -1.2),
344         ("<bla>0.4</bla>", 0.4),
345         ("<bla>0.4e5</bla>", 0.4e5),
346         ("<bla>0.4e15</bla>", 0.4e15),
347         ("<bla>0.4e-01</bla>", 0.4e-01), // precision troubles
348         ("<bla> 0.4e-01 </bla>", 0.4e-01),
349     ]);
350 }
351 
352 #[test]
test_parse_struct()353 fn test_parse_struct() {
354     init_logger();
355 
356     test_parse_ok(&[
357         (
358             "<Simple>
359                 <c>abc</c>
360                 <a/>
361                 <b>2</b>
362             </Simple>",
363             Simple {
364                 a: (),
365                 b: 2,
366                 c: "abc".to_string(),
367                 d: None,
368             },
369         ),
370         (
371             "<Simple><!-- this is a comment -->
372                 <c>abc</c>
373                 <a/>
374                 <b>2</b>
375             </Simple>",
376             Simple {
377                 a: (),
378                 b: 2,
379                 c: "abc".to_string(),
380                 d: None,
381             },
382         ),
383         (
384             "<Simple d=\"Foo\"><!-- this is a comment -->
385                 <c>abc</c>
386                 <a/>
387                 <b>2</b>
388             </Simple>",
389             Simple {
390                 a: (),
391                 b: 2,
392                 c: "abc".to_string(),
393                 d: Some("Foo".to_string()),
394             },
395         ),
396     ]);
397 }
398 
399 #[test]
test_option()400 fn test_option() {
401     init_logger();
402     test_parse_ok(&[
403         ("<a/>", Some("".to_string())),
404         ("<a></a>", Some("".to_string())),
405         ("<a> </a>", Some("".to_string())),
406         ("<a>42</a>", Some("42".to_string())),
407     ]);
408 }
409 
410 #[test]
411 #[ignore] // FIXME
test_option_not_trim()412 fn test_option_not_trim() {
413     init_logger();
414     test_parse_ok(&[("<a> </a>", Some(" ".to_string()))]);
415 }
416 
417 #[test]
test_amoskvin()418 fn test_amoskvin() {
419     init_logger();
420     #[derive(Debug, Deserialize, PartialEq, Serialize)]
421     struct Root {
422         foo: Vec<Foo>,
423     }
424 
425     #[derive(Debug, Deserialize, PartialEq, Serialize)]
426     struct Foo {
427         a: String,
428         b: Option<String>,
429     }
430     test_parse_ok(&[(
431         "
432 <root>
433 <foo>
434  <a>Hello</a>
435  <b>World</b>
436 </foo>
437 <foo>
438  <a>Hi</a>
439 </foo>
440 </root>",
441         Root {
442             foo: vec![
443                 Foo {
444                     a: "Hello".to_string(),
445                     b: Some("World".to_string()),
446                 },
447                 Foo {
448                     a: "Hi".to_string(),
449                     b: None,
450                 },
451             ],
452         },
453     )]);
454 }
455 
456 #[test]
457 #[ignore] // FIXME
test_nicolai86()458 fn test_nicolai86() {
459     init_logger();
460     #[derive(Serialize, Deserialize, PartialEq, Debug)]
461     struct TheSender {
462         name: String,
463     }
464 
465     #[derive(Serialize, Deserialize, PartialEq, Debug)]
466     struct CurrencyCube {
467         currency: String,
468         rate: String,
469     }
470 
471     #[derive(Serialize, Deserialize, PartialEq, Debug)]
472     #[allow(non_snake_case)]
473     struct InnerCube {
474         Cube: Vec<CurrencyCube>,
475     }
476 
477     #[derive(Serialize, Deserialize, PartialEq, Debug)]
478     #[allow(non_snake_case)]
479     struct OuterCube {
480         Cube: Vec<InnerCube>,
481     }
482 
483     #[derive(Serialize, Deserialize, PartialEq, Debug)]
484     #[allow(non_snake_case)]
485     struct Envelope {
486         subject: String,
487         Sender: TheSender,
488         Cube: OuterCube,
489     }
490     test_parse_ok(&[
491         (
492             r#"
493             <?xml version="1.0" encoding="UTF-8"?>
494             <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
495                 <gesmes:subject>Reference rates</gesmes:subject>
496                 <gesmes:Sender>
497                     <gesmes:name>European Central Bank</gesmes:name>
498                 </gesmes:Sender>
499                 <Cube> </Cube>
500             </gesmes:Envelope>"#,
501             Envelope {
502                 subject: "Reference rates".to_string(),
503                 Sender: TheSender {
504                     name: "European Central Bank".to_string(),
505                 },
506                 Cube: OuterCube { Cube: vec![] },
507             },
508         ),
509         (
510             r#"
511             <?xml version="1.0" encoding="UTF-8"?>
512             <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
513                 <gesmes:subject>Reference rates</gesmes:subject>
514                 <gesmes:Sender>
515                     <gesmes:name>European Central Bank</gesmes:name>
516                 </gesmes:Sender>
517                 <Cube><Cube>
518                     <Cube currency='GBP' rate='0.81725'/>
519                     <Cube currency='Latinum' rate='999999'/>
520                 </Cube></Cube>
521             </gesmes:Envelope>"#,
522             Envelope {
523                 subject: "Reference rates".to_string(),
524                 Sender: TheSender {
525                     name: "European Central Bank".to_string(),
526                 },
527                 Cube: OuterCube {
528                     Cube: vec![InnerCube {
529                         Cube: vec![
530                             CurrencyCube {
531                                 currency: "GBP".to_string(),
532                                 rate: "0.81725".to_string(),
533                             },
534                             CurrencyCube {
535                                 currency: "Latinum".to_string(),
536                                 rate: "999999".to_string(),
537                             },
538                         ],
539                     }],
540                 },
541             },
542         ),
543     ]);
544 }
545 
546 #[test]
test_hugo_duncan2()547 fn test_hugo_duncan2() {
548     init_logger();
549     let s = r#"
550     <?xml version="1.0" encoding="UTF-8"?>
551     <DescribeVpcsResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
552         <requestId>8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1</requestId>
553         <vpcSet>
554             <item>
555                 <vpcId>vpc-ba0d18d8</vpcId>
556                 <state>available</state>
557             </item>
558         </vpcSet>
559     </DescribeVpcsResponse>"#;
560     #[derive(PartialEq, Debug, Serialize, Deserialize)]
561     #[allow(non_snake_case)]
562     struct VpcSet {
563         vpcId: String,
564         state: String,
565     }
566 
567     #[derive(PartialEq, Debug, Serialize)]
568     struct ItemVec<T>(Vec<T>);
569 
570     impl<'de, T: de::Deserialize<'de>> de::Deserialize<'de> for ItemVec<T> {
571         fn deserialize<D>(deserializer: D) -> Result<ItemVec<T>, D::Error>
572         where
573             D: de::Deserializer<'de>,
574         {
575             #[derive(PartialEq, Debug, Serialize, Deserialize)]
576             struct Helper<U> {
577                 item: Vec<U>,
578             }
579             let h: Helper<_> = de::Deserialize::deserialize(deserializer)?;
580             Ok(ItemVec(h.item))
581         }
582     }
583     #[derive(PartialEq, Debug, Serialize, Deserialize)]
584     #[allow(non_snake_case)]
585     struct DescribeVpcsResponse {
586         requestId: String,
587         vpcSet: ItemVec<VpcSet>,
588     }
589     test_parse_ok(&[(
590         s,
591         DescribeVpcsResponse {
592             requestId: "8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1".to_string(),
593             vpcSet: ItemVec(vec![VpcSet {
594                 vpcId: "vpc-ba0d18d8".to_string(),
595                 state: "available".to_string(),
596             }]),
597         },
598     )]);
599 }
600 
601 #[test]
test_hugo_duncan()602 fn test_hugo_duncan() {
603     init_logger();
604     let s = "
605         <?xml version=\"1.0\" encoding=\"UTF-8\"?>
606         <DescribeInstancesResponse xmlns=\"http://ec2.amazonaws.com/doc/2014-10-01/\">
607             <requestId>9474f558-10a5-42e8-84d1-f9ee181fe943</requestId>
608             <reservationSet/>
609         </DescribeInstancesResponse>
610     ";
611     #[derive(PartialEq, Debug, Serialize, Deserialize)]
612     #[allow(non_snake_case)]
613     struct DescribeInstancesResponse {
614         requestId: String,
615         reservationSet: (),
616     }
617     test_parse_ok(&[(
618         s,
619         DescribeInstancesResponse {
620             requestId: "9474f558-10a5-42e8-84d1-f9ee181fe943".to_string(),
621             reservationSet: (),
622         },
623     )]);
624 }
625 
626 #[test]
test_parse_xml_value()627 fn test_parse_xml_value() {
628     init_logger();
629     #[derive(Eq, Debug, PartialEq, Deserialize, Serialize)]
630     struct Test {
631         #[serde(rename = "$value")]
632         myval: String,
633     }
634     test_parse_ok(&[(
635         "<Test>abc</Test>",
636         Test {
637             myval: "abc".to_string(),
638         },
639     )]);
640 }
641 
642 #[test]
643 #[ignore] // FIXME
test_parse_complexstruct()644 fn test_parse_complexstruct() {
645     init_logger();
646 
647     test_parse_ok(&[
648         (
649             "<Outer>
650                 <inner>
651                     <b>2</b>
652                     <b>boom</b>
653                     <b>88</b>
654                 </inner>
655             </Outer>",
656             Outer {
657                 inner: Some(Inner {
658                     a: (),
659                     b: (2, "boom".to_string(), 88),
660                     c: vec![],
661                 }),
662             },
663         ),
664         (
665             "<Outer>
666                 <inner>
667                     <c>abc</c>
668                     <c>xyz</c>
669                     <a/>
670                     <b>2</b>
671                     <b>boom</b>
672                     <b>88</b>
673                 </inner>
674             </Outer>",
675             Outer {
676                 inner: Some(Inner {
677                     a: (),
678                     b: (2, "boom".to_string(), 88),
679                     c: vec!["abc".to_string(), "xyz".to_string()],
680                 }),
681             },
682         ),
683         ("<Outer/>", Outer { inner: None }),
684     ]);
685 }
686 
687 #[test]
test_parse_attributes()688 fn test_parse_attributes() {
689     init_logger();
690 
691     #[derive(PartialEq, Debug, Serialize, Deserialize)]
692     struct A {
693         a1: String,
694         #[serde(rename = "$value")]
695         a2: i32,
696     }
697 
698     test_parse_ok(&[(
699         r#"<A a1="What is the answer to the ultimate question?">42</A>"#,
700         A {
701             a1: "What is the answer to the ultimate question?".to_string(),
702             a2: 42,
703         },
704     )]);
705 
706     #[derive(PartialEq, Debug, Serialize, Deserialize)]
707     struct B {
708         b1: String,
709         b2: i32,
710     }
711 
712     test_parse_ok(&[(
713         r#"<B b1="What is the answer to the ultimate question?" b2="42"/>"#,
714         B {
715             b1: "What is the answer to the ultimate question?".to_string(),
716             b2: 42,
717         },
718     )]);
719 
720     #[derive(PartialEq, Debug, Serialize, Deserialize)]
721     struct C {
722         c1: B,
723     }
724 
725     test_parse_ok(&[
726         (
727             r#"<C><c1 b1="What is the answer to the ultimate question?" b2="42"/></C>"#,
728             C {
729                 c1: B {
730                     b1: "What is the answer to the ultimate question?".to_string(),
731                     b2: 42,
732                 },
733             },
734         ),
735         (
736             r#"<C><c1 b1="What is the answer to the ultimate question?" b2="42"/> </C>"#,
737             C {
738                 c1: B {
739                     b1: "What is the answer to the ultimate question?".to_string(),
740                     b2: 42,
741                 },
742             },
743         ),
744         (
745             r#"<C>  <c1 b1="What is the answer to the ultimate question?" b2="42">
746         </c1> </C>"#,
747             C {
748                 c1: B {
749                     b1: "What is the answer to the ultimate question?".to_string(),
750                     b2: 42,
751                 },
752             },
753         ),
754     ]);
755 
756     #[derive(PartialEq, Debug, Serialize, Deserialize)]
757     struct D {
758         d1: Option<A>,
759     }
760     test_parse_ok(&[(
761         r#"<D><d1 a1="What is the answer to the ultimate question?">42</d1></D>"#,
762         D {
763             d1: Some(A {
764                 a1: "What is the answer to the ultimate question?".to_string(),
765                 a2: 42,
766             }),
767         },
768     )]);
769 }
770 
771 #[test]
772 #[ignore] // FIXME
test_parse_hierarchies()773 fn test_parse_hierarchies() {
774     init_logger();
775     #[derive(PartialEq, Debug, Serialize, Deserialize)]
776     struct A {
777         a1: String,
778         a2: (String, String),
779     }
780     #[derive(PartialEq, Debug, Serialize, Deserialize)]
781     struct B {
782         b1: A,
783         b2: (A, A),
784     }
785     #[derive(PartialEq, Debug, Serialize, Deserialize)]
786     struct C {
787         c1: B,
788         c2: Vec<B>,
789     }
790 
791     test_parse_ok(&[
792         (
793             "<C><c1>
794             <b1>
795                 <a1>No</a1>
796                 <a2>Maybe</a2>
797                 <a2>Yes</a2>
798             </b1>
799             <b2>
800                 <a1>Red</a1>
801                 <a2>Green</a2>
802                 <a2>Blue</a2>
803             </b2>
804             <b2>
805                 <a1>London</a1>
806                 <a2>Berlin</a2>
807                 <a2>Paris</a2>
808             </b2>
809         </c1></C>",
810             C {
811                 c1: B {
812                     b1: A {
813                         a1: "No".to_string(),
814                         a2: ("Maybe".to_string(), "Yes".to_string()),
815                     },
816                     b2: (
817                         A {
818                             a1: "Red".to_string(),
819                             a2: ("Green".to_string(), "Blue".to_string()),
820                         },
821                         A {
822                             a1: "London".to_string(),
823                             a2: ("Berlin".to_string(), "Paris".to_string()),
824                         },
825                     ),
826                 },
827                 c2: vec![],
828             },
829         ),
830         (
831             "<C><c1>
832             <b2>
833                 <a2>Green</a2>
834                 <a2>Blue</a2>
835                 <a1>Red</a1>
836             </b2>
837             <b2>
838                 <a2>Berlin</a2>
839                 <a2>Paris</a2>
840                 <a1>London</a1>
841             </b2>
842             <b1>
843                 <a2>Maybe</a2>
844                 <a2>Yes</a2>
845                 <a1>No</a1>
846             </b1>
847         </c1></C>",
848             C {
849                 c1: B {
850                     b1: A {
851                         a1: "No".to_string(),
852                         a2: ("Maybe".to_string(), "Yes".to_string()),
853                     },
854                     b2: (
855                         A {
856                             a1: "Red".to_string(),
857                             a2: ("Green".to_string(), "Blue".to_string()),
858                         },
859                         A {
860                             a1: "London".to_string(),
861                             a2: ("Berlin".to_string(), "Paris".to_string()),
862                         },
863                     ),
864                 },
865                 c2: vec![],
866             },
867         ),
868     ]);
869 }
870 
871 #[test]
unknown_field()872 fn unknown_field() {
873     #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)]
874     struct A {
875         other: Vec<Other>,
876     }
877 
878     #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)]
879     struct Other {
880         d: i32,
881     }
882     test_parse_ok(&[(
883         "<a>
884                <b>
885                  <c>5</c>
886                </b>
887                <other>
888                  <d>6</d>
889                </other>
890             </a>",
891         A {
892             other: vec![Other { d: 6 }],
893         },
894     )]);
895 }
896 
897 // #[test]
898 // fn eoz() {
899 //     use std::io::Read;
900 //     let mut file = std::fs::File::open("Report_test.2.xml").unwrap();
901 //     let mut s = String::new();
902 //     file.read_to_string(&mut s).unwrap();
903 
904 //     let _xml_value: Element = from_str(&s).unwrap();
905 // }
906 
907 #[test]
test_parse_unfinished()908 fn test_parse_unfinished() {
909     test_parse_err::<Simple>(&["<Simple>
910             <c>abc</c>
911             <a/>
912             <b>2</b>
913             <d/>"]);
914 }
915 
916 #[test]
test_things_qc_found()917 fn test_things_qc_found() {
918     test_parse_err::<u32>(&["<\u{0}:/"]);
919 }
920 
921 #[test]
futile()922 fn futile() {
923     init_logger();
924     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
925     struct Object {
926         id: u8,
927         name: String,
928         x: u8,
929         y: u8,
930         width: u8,
931         height: u8,
932         ellipse: Option<()>,
933     }
934 
935     test_parse_ok(&[
936         (
937             r###"
938             <object id="11" name="testEllipse" x="102" y="38" width="21" height="14">
939               <ellipse/>
940             </object>
941             "###,
942             Object {
943                 id: 11,
944                 name: "testEllipse".to_owned(),
945                 x: 102,
946                 y: 38,
947                 width: 21,
948                 height: 14,
949                 ellipse: Some(()),
950             },
951         ),
952         (
953             r###"
954             <object id="11" name="testEllipse" x="102" y="38" width="21" height="14">
955             </object>
956             "###,
957             Object {
958                 id: 11,
959                 name: "testEllipse".to_owned(),
960                 x: 102,
961                 y: 38,
962                 width: 21,
963                 height: 14,
964                 ellipse: None,
965             },
966         ),
967     ]);
968 }
969 
970 #[test]
futile2()971 fn futile2() {
972     init_logger();
973     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
974     struct Null;
975 
976     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
977     struct Object {
978         field: Option<Null>,
979     };
980 
981     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
982     struct Stuff {
983         stuff_field: Option<Object>,
984     };
985 
986     test_parse_ok(&[
987         (
988             r###"
989             <object>
990               <field/>
991             </object>
992             "###,
993             Object { field: Some(Null) },
994         ),
995         (
996             r###"
997             <object>
998             </object>
999             "###,
1000             Object { field: None },
1001         ),
1002     ]);
1003 
1004     test_parse_ok(&[
1005         (
1006             r###"
1007             <object>
1008               <stuff_field/>
1009             </object>
1010             "###,
1011             Stuff {
1012                 stuff_field: Some(Object { field: None }),
1013             },
1014         ),
1015         (
1016             r###"
1017             <object>
1018               <stuff_field>
1019                 <field/>
1020               </stuff_field>
1021             </object>
1022             "###,
1023             Stuff {
1024                 stuff_field: Some(Object { field: Some(Null) }),
1025             },
1026         ),
1027         (
1028             r###"
1029             <object>
1030             </object>
1031             "###,
1032             Stuff { stuff_field: None },
1033         ),
1034         (
1035             r###"
1036             <object/>
1037             "###,
1038             Stuff { stuff_field: None },
1039         ),
1040     ]);
1041 }
1042 
1043 #[test]
newtype_struct()1044 fn newtype_struct() {
1045     #[derive(PartialEq, Debug, Serialize, Deserialize)]
1046     struct Wrapper(String);
1047 
1048     test_parse_ok(&[(
1049         r###"<wrapper>Content</wrapper>"###,
1050         Wrapper("Content".into()),
1051     )]);
1052 }
1053