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, } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Inner { a: (), b: (usize, String, i8), c: Vec, } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Outer { inner: Option, } 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::(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#" Reference rates "#; 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#" Reference rates "#, Envelope { subject: "Reference rates".to_string(), }, ), ( r#" Reference rates "#, Envelope { subject: "Reference rates".to_string(), }, ), ( r#" ] > Reference rates "#, 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#" "#; 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(&[(" ", " ".to_string())]); } #[test] #[ignore] // FIXME fn test_parse_enum() { use self::Animal::*; init_logger(); test_parse_ok(&[ ("", Dog), ( "Quak", Frog("Quak".to_string()), ), ( "bla15Foo", Ant(Simple { a: (), b: 15, c: "bla".to_string(), d: Some("Foo".to_string()), }), ), ( "bla15", Ant(Simple { a: (), b: 15, c: "bla".to_string(), d: None, }), ), ( "42Shere Khan", Cat { age: 42, name: "Shere Khan".to_string(), }, ), ]); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Helper { x: Animal, } test_parse_ok(&[ ("", Helper { x: Dog }), ( "Quak", Helper { x: Frog("Quak".to_string()), }, ), ( " 42 Shere Khan ", Helper { x: Cat { age: 42, name: "Shere Khan".to_string(), }, }, ), ]); } #[test] fn test_parse_struct() { init_logger(); test_parse_ok(&[ ( " abc 2 ", Simple { a: (), b: 2, c: "abc".to_string(), d: None, }, ), ( " abc 2 ", Simple { a: (), b: 2, c: "abc".to_string(), d: None, }, ), ( " abc 2 ", 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(&[(" ", Some(" ".to_string()))]); } #[test] fn test_amoskvin() { init_logger(); #[derive(Debug, Deserialize, PartialEq, Serialize)] struct Root { foo: Vec, } #[derive(Debug, Deserialize, PartialEq, Serialize)] struct Foo { a: String, b: Option, } test_parse_ok(&[( " Hello World Hi ", 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, } #[derive(Serialize, Deserialize, PartialEq, Debug)] #[allow(non_snake_case)] struct OuterCube { Cube: Vec, } #[derive(Serialize, Deserialize, PartialEq, Debug)] #[allow(non_snake_case)] struct Envelope { subject: String, Sender: TheSender, Cube: OuterCube, } test_parse_ok(&[ ( r#" Reference rates European Central Bank "#, Envelope { subject: "Reference rates".to_string(), Sender: TheSender { name: "European Central Bank".to_string(), }, Cube: OuterCube { Cube: vec![] }, }, ), ( r#" Reference rates European Central Bank "#, 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#" 8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1 vpc-ba0d18d8 available "#; #[derive(PartialEq, Debug, Serialize, Deserialize)] #[allow(non_snake_case)] struct VpcSet { vpcId: String, state: String, } #[derive(PartialEq, Debug, Serialize)] struct ItemVec(Vec); impl<'de, T: de::Deserialize<'de>> de::Deserialize<'de> for ItemVec { fn deserialize(deserializer: D) -> Result, D::Error> where D: de::Deserializer<'de>, { #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Helper { item: Vec, } 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, } 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 = " 9474f558-10a5-42e8-84d1-f9ee181fe943 "; #[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(&[( "abc", Test { myval: "abc".to_string(), }, )]); } #[test] #[ignore] // FIXME fn test_parse_complexstruct() { init_logger(); test_parse_ok(&[ ( " 2 boom 88 ", Outer { inner: Some(Inner { a: (), b: (2, "boom".to_string(), 88), c: vec![], }), }, ), ( " abc xyz 2 boom 88 ", Outer { inner: Some(Inner { a: (), b: (2, "boom".to_string(), 88), c: vec!["abc".to_string(), "xyz".to_string()], }), }, ), ("", 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#"42"#, 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?".to_string(), b2: 42, }, )]); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct C { c1: B, } test_parse_ok(&[ ( r#""#, C { c1: B { b1: "What is the answer to the ultimate question?".to_string(), b2: 42, }, }, ), ( r#" "#, C { c1: B { b1: "What is the answer to the ultimate question?".to_string(), b2: 42, }, }, ), ( r#" "#, 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, } test_parse_ok(&[( r#"42"#, 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, } test_parse_ok(&[ ( " No Maybe Yes Red Green Blue London Berlin Paris ", 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![], }, ), ( " Green Blue Red Berlin Paris London Maybe Yes No ", 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, } #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)] struct Other { d: i32, } test_parse_ok(&[( " 5 6 ", 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::(&[" abc 2 "]); } #[test] fn test_things_qc_found() { test_parse_err::(&["<\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".to_owned(), x: 102, y: 38, width: 21, height: 14, ellipse: Some(()), }, ), ( r###" "###, 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, } #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] struct Stuff { stuff_field: Option, } test_parse_ok(&[ ( r###" "###, Object { field: Some(Null) }, ), ( r###" "###, Object { field: None }, ), ]); test_parse_ok(&[ ( r###" "###, Stuff { stuff_field: Some(Object { field: None }), }, ), ( r###" "###, Stuff { stuff_field: Some(Object { field: Some(Null) }), }, ), ( r###" "###, Stuff { stuff_field: None }, ), ( r###" "###, Stuff { stuff_field: None }, ), ]); } #[test] fn newtype_struct() { #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Wrapper(String); test_parse_ok(&[( r###"Content"###, Wrapper("Content".into()), )]); }