| mod common; |
| |
| use common::init_logger; |
| use serde::{de, ser, Deserialize, Serialize}; |
| use serde_xml_rs::{from_str, Error}; |
| use std::fmt::Debug; |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| enum Animal { |
| Dog, |
| Frog(String), |
| Ant(Simple), |
| Cat { age: usize, name: String }, |
| } |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct Simple { |
| a: (), |
| b: usize, |
| c: String, |
| d: Option<String>, |
| } |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct Inner { |
| a: (), |
| b: (usize, String, i8), |
| c: Vec<String>, |
| } |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct Outer { |
| inner: Option<Inner>, |
| } |
| |
| fn test_parse_ok<'de, 'a, T>(errors: &[(&'a str, T)]) |
| where |
| T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>, |
| { |
| for &(s, ref value) in errors { |
| let v: T = from_str(s).unwrap(); |
| assert_eq!(v, *value); |
| |
| // // Make sure we can deserialize into an `Element`. |
| // let xml_value: Element = from_str(s).unwrap(); |
| |
| // // Make sure we can deserialize from an `Element`. |
| // let v: T = from_value(xml_value.clone()).unwrap(); |
| // assert_eq!(v, *value); |
| } |
| } |
| |
| fn test_parse_err<'de, 'a, T>(errors: &[&'a str]) |
| where |
| T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>, |
| { |
| for &s in errors { |
| assert!(match from_str::<T>(s) { |
| Err(Error::Syntax { source: _ }) => true, |
| _ => false, |
| }); |
| } |
| } |
| |
| #[test] |
| fn test_namespaces() { |
| init_logger(); |
| #[derive(PartialEq, Serialize, Deserialize, Debug)] |
| struct Envelope { |
| subject: String, |
| } |
| let s = r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> |
| <gesmes:subject>Reference rates</gesmes:subject> |
| </gesmes:Envelope>"#; |
| test_parse_ok(&[( |
| s, |
| Envelope { |
| subject: "Reference rates".to_string(), |
| }, |
| )]); |
| } |
| |
| #[test] |
| fn test_doctype() { |
| init_logger(); |
| #[derive(PartialEq, Serialize, Deserialize, Debug)] |
| struct Envelope { |
| subject: String, |
| } |
| |
| test_parse_ok(&[ |
| ( |
| r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Envelope> |
| <Envelope> |
| <subject>Reference rates</subject> |
| </Envelope>"#, |
| Envelope { |
| subject: "Reference rates".to_string(), |
| }, |
| ), |
| ( |
| r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Envelope[]> |
| <Envelope> |
| <subject>Reference rates</subject> |
| </Envelope>"#, |
| Envelope { |
| subject: "Reference rates".to_string(), |
| }, |
| ), |
| ( |
| r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Envelope [ |
| <!ELEMENT subject (#PCDATA)> |
| ] > |
| <Envelope> |
| <subject>Reference rates</subject> |
| </Envelope>"#, |
| Envelope { |
| subject: "Reference rates".to_string(), |
| }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_forwarded_namespace() { |
| #[derive(PartialEq, Serialize, Deserialize, Debug)] |
| struct Graphml { |
| #[serde(rename = "xsi:schemaLocation")] |
| schema_location: String, |
| } |
| let s = r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <graphml xmlns="http://graphml.graphdrawing.org/xmlns" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns |
| http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> |
| |
| |
| </graphml>"#; |
| test_parse_ok(&[( |
| s, |
| Graphml { |
| schema_location: "http://graphml.graphdrawing.org/xmlns |
| http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd" |
| .to_string(), |
| }, |
| )]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_parse_string_not_trim() { |
| init_logger(); |
| |
| test_parse_ok(&[("<bla> </bla>", " ".to_string())]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_parse_enum() { |
| use self::Animal::*; |
| init_logger(); |
| |
| test_parse_ok(&[ |
| ("<Animal xsi:type=\"Dog\"/>", Dog), |
| ( |
| "<Animal xsi:type=\"Frog\">Quak</Animal>", |
| Frog("Quak".to_string()), |
| ), |
| ( |
| "<Animal xsi:type=\"Ant\"><a/><c>bla</c><b>15</b><d>Foo</d></Animal>", |
| Ant(Simple { |
| a: (), |
| b: 15, |
| c: "bla".to_string(), |
| d: Some("Foo".to_string()), |
| }), |
| ), |
| ( |
| "<Animal xsi:type=\"Ant\"><a/><c>bla</c><b>15</b></Animal>", |
| Ant(Simple { |
| a: (), |
| b: 15, |
| c: "bla".to_string(), |
| d: None, |
| }), |
| ), |
| ( |
| "<Animal xsi:type=\"Cat\"><age>42</age><name>Shere Khan</name></Animal>", |
| Cat { |
| age: 42, |
| name: "Shere Khan".to_string(), |
| }, |
| ), |
| ]); |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct Helper { |
| x: Animal, |
| } |
| |
| test_parse_ok(&[ |
| ("<Helper><x xsi:type=\"Dog\"/></Helper>", Helper { x: Dog }), |
| ( |
| "<Helper><x xsi:type=\"Frog\">Quak</Animal></Helper>", |
| Helper { |
| x: Frog("Quak".to_string()), |
| }, |
| ), |
| ( |
| "<Helper><x xsi:type=\"Cat\"> |
| <age>42</age> |
| <name>Shere Khan</name> |
| </x></Helper>", |
| Helper { |
| x: Cat { |
| age: 42, |
| name: "Shere Khan".to_string(), |
| }, |
| }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| fn test_parse_struct() { |
| init_logger(); |
| |
| test_parse_ok(&[ |
| ( |
| "<Simple> |
| <c>abc</c> |
| <a/> |
| <b>2</b> |
| </Simple>", |
| Simple { |
| a: (), |
| b: 2, |
| c: "abc".to_string(), |
| d: None, |
| }, |
| ), |
| ( |
| "<Simple><!-- this is a comment --> |
| <c>abc</c> |
| <a/> |
| <b>2</b> |
| </Simple>", |
| Simple { |
| a: (), |
| b: 2, |
| c: "abc".to_string(), |
| d: None, |
| }, |
| ), |
| ( |
| "<Simple d=\"Foo\"><!-- this is a comment --> |
| <c>abc</c> |
| <a/> |
| <b>2</b> |
| </Simple>", |
| Simple { |
| a: (), |
| b: 2, |
| c: "abc".to_string(), |
| d: Some("Foo".to_string()), |
| }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_option_not_trim() { |
| init_logger(); |
| test_parse_ok(&[("<a> </a>", Some(" ".to_string()))]); |
| } |
| |
| #[test] |
| fn test_amoskvin() { |
| init_logger(); |
| #[derive(Debug, Deserialize, PartialEq, Serialize)] |
| struct Root { |
| foo: Vec<Foo>, |
| } |
| |
| #[derive(Debug, Deserialize, PartialEq, Serialize)] |
| struct Foo { |
| a: String, |
| b: Option<String>, |
| } |
| test_parse_ok(&[( |
| " |
| <root> |
| <foo> |
| <a>Hello</a> |
| <b>World</b> |
| </foo> |
| <foo> |
| <a>Hi</a> |
| </foo> |
| </root>", |
| Root { |
| foo: vec![ |
| Foo { |
| a: "Hello".to_string(), |
| b: Some("World".to_string()), |
| }, |
| Foo { |
| a: "Hi".to_string(), |
| b: None, |
| }, |
| ], |
| }, |
| )]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_nicolai86() { |
| init_logger(); |
| #[derive(Serialize, Deserialize, PartialEq, Debug)] |
| struct TheSender { |
| name: String, |
| } |
| |
| #[derive(Serialize, Deserialize, PartialEq, Debug)] |
| struct CurrencyCube { |
| currency: String, |
| rate: String, |
| } |
| |
| #[derive(Serialize, Deserialize, PartialEq, Debug)] |
| #[allow(non_snake_case)] |
| struct InnerCube { |
| Cube: Vec<CurrencyCube>, |
| } |
| |
| #[derive(Serialize, Deserialize, PartialEq, Debug)] |
| #[allow(non_snake_case)] |
| struct OuterCube { |
| Cube: Vec<InnerCube>, |
| } |
| |
| #[derive(Serialize, Deserialize, PartialEq, Debug)] |
| #[allow(non_snake_case)] |
| struct Envelope { |
| subject: String, |
| Sender: TheSender, |
| Cube: OuterCube, |
| } |
| test_parse_ok(&[ |
| ( |
| r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> |
| <gesmes:subject>Reference rates</gesmes:subject> |
| <gesmes:Sender> |
| <gesmes:name>European Central Bank</gesmes:name> |
| </gesmes:Sender> |
| <Cube> </Cube> |
| </gesmes:Envelope>"#, |
| Envelope { |
| subject: "Reference rates".to_string(), |
| Sender: TheSender { |
| name: "European Central Bank".to_string(), |
| }, |
| Cube: OuterCube { Cube: vec![] }, |
| }, |
| ), |
| ( |
| r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> |
| <gesmes:subject>Reference rates</gesmes:subject> |
| <gesmes:Sender> |
| <gesmes:name>European Central Bank</gesmes:name> |
| </gesmes:Sender> |
| <Cube><Cube> |
| <Cube currency='GBP' rate='0.81725'/> |
| <Cube currency='Latinum' rate='999999'/> |
| </Cube></Cube> |
| </gesmes:Envelope>"#, |
| Envelope { |
| subject: "Reference rates".to_string(), |
| Sender: TheSender { |
| name: "European Central Bank".to_string(), |
| }, |
| Cube: OuterCube { |
| Cube: vec![InnerCube { |
| Cube: vec![ |
| CurrencyCube { |
| currency: "GBP".to_string(), |
| rate: "0.81725".to_string(), |
| }, |
| CurrencyCube { |
| currency: "Latinum".to_string(), |
| rate: "999999".to_string(), |
| }, |
| ], |
| }], |
| }, |
| }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| fn test_hugo_duncan2() { |
| init_logger(); |
| let s = r#" |
| <?xml version="1.0" encoding="UTF-8"?> |
| <DescribeVpcsResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/"> |
| <requestId>8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1</requestId> |
| <vpcSet> |
| <item> |
| <vpcId>vpc-ba0d18d8</vpcId> |
| <state>available</state> |
| </item> |
| </vpcSet> |
| </DescribeVpcsResponse>"#; |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| #[allow(non_snake_case)] |
| struct VpcSet { |
| vpcId: String, |
| state: String, |
| } |
| |
| #[derive(PartialEq, Debug, Serialize)] |
| struct ItemVec<T>(Vec<T>); |
| |
| impl<'de, T: de::Deserialize<'de>> de::Deserialize<'de> for ItemVec<T> { |
| fn deserialize<D>(deserializer: D) -> Result<ItemVec<T>, D::Error> |
| where |
| D: de::Deserializer<'de>, |
| { |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct Helper<U> { |
| item: Vec<U>, |
| } |
| let h: Helper<_> = de::Deserialize::deserialize(deserializer)?; |
| Ok(ItemVec(h.item)) |
| } |
| } |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| #[allow(non_snake_case)] |
| struct DescribeVpcsResponse { |
| requestId: String, |
| vpcSet: ItemVec<VpcSet>, |
| } |
| test_parse_ok(&[( |
| s, |
| DescribeVpcsResponse { |
| requestId: "8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1".to_string(), |
| vpcSet: ItemVec(vec![VpcSet { |
| vpcId: "vpc-ba0d18d8".to_string(), |
| state: "available".to_string(), |
| }]), |
| }, |
| )]); |
| } |
| |
| #[test] |
| fn test_hugo_duncan() { |
| init_logger(); |
| let s = " |
| <?xml version=\"1.0\" encoding=\"UTF-8\"?> |
| <DescribeInstancesResponse xmlns=\"http://ec2.amazonaws.com/doc/2014-10-01/\"> |
| <requestId>9474f558-10a5-42e8-84d1-f9ee181fe943</requestId> |
| <reservationSet/> |
| </DescribeInstancesResponse> |
| "; |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| #[allow(non_snake_case)] |
| struct DescribeInstancesResponse { |
| requestId: String, |
| reservationSet: (), |
| } |
| test_parse_ok(&[( |
| s, |
| DescribeInstancesResponse { |
| requestId: "9474f558-10a5-42e8-84d1-f9ee181fe943".to_string(), |
| reservationSet: (), |
| }, |
| )]); |
| } |
| |
| #[test] |
| fn test_parse_xml_value() { |
| init_logger(); |
| #[derive(Eq, Debug, PartialEq, Deserialize, Serialize)] |
| struct Test { |
| #[serde(rename = "$value")] |
| myval: String, |
| } |
| test_parse_ok(&[( |
| "<Test>abc</Test>", |
| Test { |
| myval: "abc".to_string(), |
| }, |
| )]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_parse_complexstruct() { |
| init_logger(); |
| |
| test_parse_ok(&[ |
| ( |
| "<Outer> |
| <inner> |
| <b>2</b> |
| <b>boom</b> |
| <b>88</b> |
| </inner> |
| </Outer>", |
| Outer { |
| inner: Some(Inner { |
| a: (), |
| b: (2, "boom".to_string(), 88), |
| c: vec![], |
| }), |
| }, |
| ), |
| ( |
| "<Outer> |
| <inner> |
| <c>abc</c> |
| <c>xyz</c> |
| <a/> |
| <b>2</b> |
| <b>boom</b> |
| <b>88</b> |
| </inner> |
| </Outer>", |
| Outer { |
| inner: Some(Inner { |
| a: (), |
| b: (2, "boom".to_string(), 88), |
| c: vec!["abc".to_string(), "xyz".to_string()], |
| }), |
| }, |
| ), |
| ("<Outer/>", Outer { inner: None }), |
| ]); |
| } |
| |
| #[test] |
| fn test_parse_attributes() { |
| init_logger(); |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct A { |
| a1: String, |
| #[serde(rename = "$value")] |
| a2: i32, |
| } |
| |
| test_parse_ok(&[( |
| r#"<A a1="What is the answer to the ultimate question?">42</A>"#, |
| A { |
| a1: "What is the answer to the ultimate question?".to_string(), |
| a2: 42, |
| }, |
| )]); |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct B { |
| b1: String, |
| b2: i32, |
| } |
| |
| test_parse_ok(&[( |
| r#"<B b1="What is the answer to the ultimate question?" b2="42"/>"#, |
| B { |
| b1: "What is the answer to the ultimate question?".to_string(), |
| b2: 42, |
| }, |
| )]); |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct C { |
| c1: B, |
| } |
| |
| test_parse_ok(&[ |
| ( |
| r#"<C><c1 b1="What is the answer to the ultimate question?" b2="42"/></C>"#, |
| C { |
| c1: B { |
| b1: "What is the answer to the ultimate question?".to_string(), |
| b2: 42, |
| }, |
| }, |
| ), |
| ( |
| r#"<C><c1 b1="What is the answer to the ultimate question?" b2="42"/> </C>"#, |
| C { |
| c1: B { |
| b1: "What is the answer to the ultimate question?".to_string(), |
| b2: 42, |
| }, |
| }, |
| ), |
| ( |
| r#"<C> <c1 b1="What is the answer to the ultimate question?" b2="42"> |
| </c1> </C>"#, |
| C { |
| c1: B { |
| b1: "What is the answer to the ultimate question?".to_string(), |
| b2: 42, |
| }, |
| }, |
| ), |
| ]); |
| |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct D { |
| d1: Option<A>, |
| } |
| test_parse_ok(&[( |
| r#"<D><d1 a1="What is the answer to the ultimate question?">42</d1></D>"#, |
| D { |
| d1: Some(A { |
| a1: "What is the answer to the ultimate question?".to_string(), |
| a2: 42, |
| }), |
| }, |
| )]); |
| } |
| |
| #[test] |
| #[ignore] // FIXME |
| fn test_parse_hierarchies() { |
| init_logger(); |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct A { |
| a1: String, |
| a2: (String, String), |
| } |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct B { |
| b1: A, |
| b2: (A, A), |
| } |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct C { |
| c1: B, |
| c2: Vec<B>, |
| } |
| |
| test_parse_ok(&[ |
| ( |
| "<C><c1> |
| <b1> |
| <a1>No</a1> |
| <a2>Maybe</a2> |
| <a2>Yes</a2> |
| </b1> |
| <b2> |
| <a1>Red</a1> |
| <a2>Green</a2> |
| <a2>Blue</a2> |
| </b2> |
| <b2> |
| <a1>London</a1> |
| <a2>Berlin</a2> |
| <a2>Paris</a2> |
| </b2> |
| </c1></C>", |
| C { |
| c1: B { |
| b1: A { |
| a1: "No".to_string(), |
| a2: ("Maybe".to_string(), "Yes".to_string()), |
| }, |
| b2: ( |
| A { |
| a1: "Red".to_string(), |
| a2: ("Green".to_string(), "Blue".to_string()), |
| }, |
| A { |
| a1: "London".to_string(), |
| a2: ("Berlin".to_string(), "Paris".to_string()), |
| }, |
| ), |
| }, |
| c2: vec![], |
| }, |
| ), |
| ( |
| "<C><c1> |
| <b2> |
| <a2>Green</a2> |
| <a2>Blue</a2> |
| <a1>Red</a1> |
| </b2> |
| <b2> |
| <a2>Berlin</a2> |
| <a2>Paris</a2> |
| <a1>London</a1> |
| </b2> |
| <b1> |
| <a2>Maybe</a2> |
| <a2>Yes</a2> |
| <a1>No</a1> |
| </b1> |
| </c1></C>", |
| C { |
| c1: B { |
| b1: A { |
| a1: "No".to_string(), |
| a2: ("Maybe".to_string(), "Yes".to_string()), |
| }, |
| b2: ( |
| A { |
| a1: "Red".to_string(), |
| a2: ("Green".to_string(), "Blue".to_string()), |
| }, |
| A { |
| a1: "London".to_string(), |
| a2: ("Berlin".to_string(), "Paris".to_string()), |
| }, |
| ), |
| }, |
| c2: vec![], |
| }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| fn unknown_field() { |
| #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)] |
| struct A { |
| other: Vec<Other>, |
| } |
| |
| #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)] |
| struct Other { |
| d: i32, |
| } |
| test_parse_ok(&[( |
| "<a> |
| <b> |
| <c>5</c> |
| </b> |
| <other> |
| <d>6</d> |
| </other> |
| </a>", |
| A { |
| other: vec![Other { d: 6 }], |
| }, |
| )]); |
| } |
| |
| // #[test] |
| // fn eoz() { |
| // use std::io::Read; |
| // let mut file = std::fs::File::open("Report_test.2.xml").unwrap(); |
| // let mut s = String::new(); |
| // file.read_to_string(&mut s).unwrap(); |
| |
| // let _xml_value: Element = from_str(&s).unwrap(); |
| // } |
| |
| #[test] |
| fn test_parse_unfinished() { |
| test_parse_err::<Simple>(&["<Simple> |
| <c>abc</c> |
| <a/> |
| <b>2</b> |
| <d/>"]); |
| } |
| |
| #[test] |
| fn test_things_qc_found() { |
| test_parse_err::<u32>(&["<\u{0}:/"]); |
| } |
| |
| #[test] |
| fn futile() { |
| init_logger(); |
| #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] |
| struct Object { |
| id: u8, |
| name: String, |
| x: u8, |
| y: u8, |
| width: u8, |
| height: u8, |
| ellipse: Option<()>, |
| } |
| |
| test_parse_ok(&[ |
| ( |
| r###" |
| <object id="11" name="testEllipse" x="102" y="38" width="21" height="14"> |
| <ellipse/> |
| </object> |
| "###, |
| Object { |
| id: 11, |
| name: "testEllipse".to_owned(), |
| x: 102, |
| y: 38, |
| width: 21, |
| height: 14, |
| ellipse: Some(()), |
| }, |
| ), |
| ( |
| r###" |
| <object id="11" name="testEllipse" x="102" y="38" width="21" height="14"> |
| </object> |
| "###, |
| Object { |
| id: 11, |
| name: "testEllipse".to_owned(), |
| x: 102, |
| y: 38, |
| width: 21, |
| height: 14, |
| ellipse: None, |
| }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| fn futile2() { |
| init_logger(); |
| #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] |
| struct Null; |
| |
| #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] |
| struct Object { |
| field: Option<Null>, |
| } |
| |
| #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] |
| struct Stuff { |
| stuff_field: Option<Object>, |
| } |
| |
| test_parse_ok(&[ |
| ( |
| r###" |
| <object> |
| <field/> |
| </object> |
| "###, |
| Object { field: Some(Null) }, |
| ), |
| ( |
| r###" |
| <object> |
| </object> |
| "###, |
| Object { field: None }, |
| ), |
| ]); |
| |
| test_parse_ok(&[ |
| ( |
| r###" |
| <object> |
| <stuff_field/> |
| </object> |
| "###, |
| Stuff { |
| stuff_field: Some(Object { field: None }), |
| }, |
| ), |
| ( |
| r###" |
| <object> |
| <stuff_field> |
| <field/> |
| </stuff_field> |
| </object> |
| "###, |
| Stuff { |
| stuff_field: Some(Object { field: Some(Null) }), |
| }, |
| ), |
| ( |
| r###" |
| <object> |
| </object> |
| "###, |
| Stuff { stuff_field: None }, |
| ), |
| ( |
| r###" |
| <object/> |
| "###, |
| Stuff { stuff_field: None }, |
| ), |
| ]); |
| } |
| |
| #[test] |
| fn newtype_struct() { |
| #[derive(PartialEq, Debug, Serialize, Deserialize)] |
| struct Wrapper(String); |
| |
| test_parse_ok(&[( |
| r###"<wrapper>Content</wrapper>"###, |
| Wrapper("Content".into()), |
| )]); |
| } |