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><boom/></bla>", "<boom/>".to_string()),
187 ("<bla>♫</bla>", "♫".to_string()),
188 ("<bla>♫</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