This commit is contained in:
Dirkjan Ochtman 2022-09-03 14:01:33 +02:00
parent 3ad6917ba0
commit cf4e1d4e55
5 changed files with 514 additions and 14 deletions

509
instant-xml/tests/all.rs Normal file
View File

@ -0,0 +1,509 @@
use std::borrow::Cow;
use similar_asserts::assert_eq;
use instant_xml::{Error, FromXml, ToXml};
#[derive(Debug, Eq, PartialEq, ToXml)]
struct Unit;
#[test]
fn unit() {
assert_eq!(Unit.to_xml().unwrap(), "<Unit></Unit>");
//assert_eq!(Unit::from_xml("<Unit/>").unwrap(), Unit);
}
#[derive(Debug, Eq, PartialEq, ToXml)]
#[xml(ns(bar = "BAZ", foo = "BAR"))]
struct StructWithNamedFields {
flag: bool,
#[xml(ns("BAZ"))]
string: String,
#[xml(ns("typo"))]
number: i32,
}
// Tests:
// - Empty default namespace
// - Prefix namespace
// - Direct namespace
#[test]
fn struct_with_named_fields() {
assert_eq!(
StructWithNamedFields {
flag: true,
string: "test".to_string(),
number: 1,
}
.to_xml()
.unwrap(),
"<StructWithNamedFields xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><flag>true</flag><bar:string>test</bar:string><number xmlns=\"typo\">1</number></StructWithNamedFields>"
);
}
#[derive(Debug, Eq, PartialEq, ToXml)]
#[xml(ns("URI", dar = "BAZ", internal = "INTERNAL"))]
struct Nested {
#[xml(ns(internal))]
flag_internal_prefix: bool,
}
#[derive(Debug, Eq, PartialEq, ToXml)]
#[xml(ns("URI", bar = "BAZ", foo = "BAR"))]
struct StructWithCustomField {
#[xml(attribute)]
int_attribute: i32,
#[xml(ns("BAZ"))]
flag_direct_namespace_same_the_same_as_prefix: bool,
#[xml(ns("DIFFERENT"))]
flag_direct_namespace: bool,
test: Nested,
}
// Tests:
// - The same direct namespace as the one from prefix
// - Attribute handling
// - Omitting redeclared child default namespace
// - Omitting redeclared child namespace with different prefix
// - Unique direct namespace
// - Child unique prefix
// - Child repeated prefix
// - Child default namespace the same as parent
#[test]
fn struct_with_custom_field() {
assert_eq!(
StructWithCustomField {
int_attribute: 42,
flag_direct_namespace_same_the_same_as_prefix: true,
flag_direct_namespace: true,
test: Nested {
flag_internal_prefix: false,
},
}
.to_xml()
.unwrap(),
"<StructWithCustomField xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" int_attribute=\"42\"><flag_direct_namespace_same_the_same_as_prefix xmlns=\"BAZ\">true</flag_direct_namespace_same_the_same_as_prefix><flag_direct_namespace xmlns=\"DIFFERENT\">true</flag_direct_namespace><Nested xmlns:internal=\"INTERNAL\"><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructWithCustomField>"
);
}
#[derive(Debug, Eq, PartialEq, ToXml)]
struct NestedDifferentNamespace {
#[xml(ns("INTERNAL"))]
flag_internal_prefix: bool,
}
#[derive(Debug, Eq, PartialEq, ToXml)]
#[xml(ns("URI", bar = "BAZ", foo = "BAR"))]
struct StructChildNamespaces {
different_child_namespace: NestedDifferentNamespace,
same_child_namespace: Nested,
}
// Tests:
// - Different child namespace
// - The same child namespace
#[test]
fn struct_child_namespaces() {
assert_eq!(
StructChildNamespaces {
different_child_namespace: NestedDifferentNamespace {
flag_internal_prefix: false,
},
same_child_namespace: Nested {
flag_internal_prefix: false,
},
}
.to_xml()
.unwrap(),
"<StructChildNamespaces xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><NestedDifferentNamespace xmlns=\"\"><flag_internal_prefix>false</internal:flag_internal_prefix></NestedDifferentNamespace><Nested xmlns:internal=\"INTERNAL\"><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructChildNamespaces>"
);
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct NestedDe {
#[xml(ns("BAZ"))]
flag: bool,
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ", foo = "BAR"))]
struct StructWithCustomFieldFromXml {
#[xml(ns("BAZ"))]
flag: bool,
#[xml(attribute)]
flag_attribute: bool,
test: NestedDe,
}
#[test]
fn struct_with_custom_field_from_xml() {
assert_eq!(
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml flag_attribute=\"true\" xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><bar:flag>false</bar:flag><NestedDe><bar:flag>true</bar:flag></NestedDe></StructWithCustomFieldFromXml>").unwrap(),
StructWithCustomFieldFromXml {
flag: false,
flag_attribute: true,
test: NestedDe { flag: true }
}
);
// Different order
assert_eq!(
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" flag_attribute=\"true\"><NestedDe><bar:flag>true</bar:flag></NestedDe><bar:flag>false</bar:flag></StructWithCustomFieldFromXml>").unwrap(),
StructWithCustomFieldFromXml {
flag: false,
flag_attribute: true,
test: NestedDe { flag: true }
}
);
// Different prefixes then in definition
assert_eq!(
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml flag_attribute=\"true\" xmlns=\"URI\" xmlns:grr=\"BAZ\" xmlns:foo=\"BAR\"><grr:flag>false</grr:flag><NestedDe><grr:flag>true</grr:flag></NestedDe></StructWithCustomFieldFromXml>").unwrap(),
StructWithCustomFieldFromXml {
flag: false,
flag_attribute: true,
test: NestedDe { flag: true }
}
);
assert_eq!(
NestedDe::from_xml(
"<NestedDe xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe>"
)
.unwrap(),
NestedDe { flag: true }
);
}
#[derive(Debug, Eq, PartialEq, FromXml)]
struct NestedWrongNamespace {
flag: bool,
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct StructWithCorrectNestedNamespace {
test: NestedDe,
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct StructWithWrongNestedNamespace {
test: NestedWrongNamespace,
}
#[test]
fn default_namespaces() {
// Default namespace not-nested
assert_eq!(
NestedDe::from_xml(
"<NestedDe xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe>"
)
.unwrap(),
NestedDe { flag: true }
);
// Default namespace not-nested - wrong namespace
assert_eq!(
NestedDe::from_xml(
"<NestedDe xmlns=\"WRONG\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe>"
)
.unwrap_err(),
Error::WrongNamespace
);
// Correct child namespace
assert_eq!(
StructWithCorrectNestedNamespace::from_xml("<StructWithCorrectNestedNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedDe xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe></StructWithCorrectNestedNamespace>").unwrap(),
StructWithCorrectNestedNamespace {
test: NestedDe { flag: true }
}
);
// Correct child namespace - without child redefinition
assert_eq!(
StructWithCorrectNestedNamespace::from_xml("<StructWithCorrectNestedNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedDe><bar:flag>true</bar:flag></NestedDe></StructWithCorrectNestedNamespace>").unwrap(),
StructWithCorrectNestedNamespace {
test: NestedDe { flag: true }
}
);
// Different child namespace
assert_eq!(
StructWithWrongNestedNamespace::from_xml("<StructWithWrongNestedNamespace xmlns=\"URI\" xmlns:dar=\"BAZ\"><NestedWrongNamespace xmlns=\"\"><flag>true</flag></NestedWrongNamespace></StructWithWrongNestedNamespace>").unwrap(),
StructWithWrongNestedNamespace {
test: NestedWrongNamespace {
flag: true
}
}
);
// Wrong child namespace
assert_eq!(
StructWithWrongNestedNamespace::from_xml("<StructWithWrongNestedNamespace xmlns=\"URI\" xmlns:dar=\"BAZ\"><NestedWrongNamespace><flag>true</flag></NestedWrongNamespace></StructWithWrongNestedNamespace>").unwrap_err(),
Error::WrongNamespace
);
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct NestedOtherNamespace {
#[xml(ns("BAZ"))]
flag: bool,
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct StructOtherNamespace {
test: NestedOtherNamespace,
}
#[test]
fn other_namespaces() {
// Other namespace not-nested
assert_eq!(
NestedOtherNamespace::from_xml(
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedOtherNamespace>"
)
.unwrap(),
NestedOtherNamespace { flag: true }
);
// Other namespace not-nested - wrong defined namespace
assert_eq!(
NestedOtherNamespace::from_xml(
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><wrong:flag>true</wrong:flag></NestedOtherNamespace>"
)
.unwrap_err(),
Error::WrongNamespace
);
// Other namespace not-nested - wrong parser namespace
assert_eq!(
NestedOtherNamespace::from_xml(
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"WRONG\"><bar:flag>true</bar:flag></NestedOtherNamespace>"
)
.unwrap_err(),
Error::WrongNamespace
);
// Other namespace not-nested - missing parser prefix
assert_eq!(
NestedOtherNamespace::from_xml(
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAR\"><flag>true</flag></NestedOtherNamespace>"
)
.unwrap_err(),
Error::WrongNamespace
);
// Correct child other namespace
assert_eq!(
StructOtherNamespace::from_xml(
"<StructOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedOtherNamespace></StructOtherNamespace>"
)
.unwrap(),
StructOtherNamespace {
test: NestedOtherNamespace {
flag: true,
}
}
);
// Correct child other namespace - without child redefinition
assert_eq!(
StructOtherNamespace::from_xml(
"<StructOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedOtherNamespace><bar:flag>true</bar:flag></NestedOtherNamespace></StructOtherNamespace>"
)
.unwrap(),
StructOtherNamespace {
test: NestedOtherNamespace {
flag: true,
}
}
);
// Wrong child other namespace - without child redefinition
assert_eq!(
StructOtherNamespace::from_xml(
"<StructOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedOtherNamespace><wrong:flag>true</wrong:flag></NestedOtherNamespace></StructOtherNamespace>"
)
.unwrap_err(),
Error::WrongNamespace
);
}
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI"))]
struct StructDirectNamespace {
#[xml(ns("BAZ"))]
flag: bool,
}
#[test]
fn direct_namespaces() {
// Correct direct namespace
assert_eq!(
StructDirectNamespace::from_xml(
"<StructDirectNamespace xmlns=\"URI\"><flag xmlns=\"BAZ\">true</flag></StructDirectNamespace>"
)
.unwrap(),
StructDirectNamespace { flag: true }
);
// Wrong direct namespace
assert_eq!(
StructDirectNamespace::from_xml(
"<StructDirectNamespace xmlns=\"URI\"><flag xmlns=\"WRONG\">true</flag></StructDirectNamespace>"
)
.unwrap_err(),
Error::WrongNamespace
);
// Wrong direct namespace - missing namespace
assert_eq!(
StructDirectNamespace::from_xml(
"<StructDirectNamespace xmlns=\"URI\"><flag>true</flag></StructDirectNamespace>"
)
.unwrap_err(),
Error::WrongNamespace
);
}
#[derive(Debug, PartialEq, Eq, FromXml, ToXml)]
#[xml(ns("URI"))]
struct NestedLifetimes<'a> {
flag: bool,
str_type_a: &'a str,
}
#[derive(Debug, PartialEq, FromXml, ToXml)]
#[xml(ns("URI"))]
struct StructDeserializerScalars<'a, 'b> {
bool_type: bool,
i8_type: i8,
u32_type: u32,
string_type: String,
str_type_a: &'a str,
str_type_b: &'b str,
char_type: char,
f32_type: f32,
nested: NestedLifetimes<'a>,
cow: Cow<'a, str>,
option: Option<&'a str>,
}
#[test]
fn scalars() {
assert_eq!(
StructDeserializerScalars::from_xml(
"<StructDeserializerScalars xmlns=\"URI\"><bool_type>true</bool_type><i8_type>1</i8_type><u32_type>42</u32_type><string_type>string</string_type><str_type_a>lifetime a</str_type_a><str_type_b>lifetime b</str_type_b><char_type>c</char_type><f32_type>1.20</f32_type><NestedLifetimes><flag>true</flag><str_type_a>asd</str_type_a></NestedLifetimes><cow>123</cow></StructDeserializerScalars>"
)
.unwrap(),
StructDeserializerScalars{
bool_type: true,
i8_type: 1,
u32_type: 42,
string_type: "string".to_string(),
str_type_a: "lifetime a",
str_type_b: "lifetime b",
char_type: 'c',
f32_type: 1.20,
nested: NestedLifetimes {
flag: true,
str_type_a: "asd"
},
cow: Cow::from("123"),
option: None,
}
);
// Option none
assert_eq!(
StructDeserializerScalars::from_xml(
"<StructDeserializerScalars xmlns=\"URI\"><bool_type>true</bool_type><i8_type>1</i8_type><u32_type>42</u32_type><string_type>string</string_type><str_type_a>lifetime a</str_type_a><str_type_b>lifetime b</str_type_b><char_type>c</char_type><f32_type>1.2</f32_type><NestedLifetimes><flag>true</flag><str_type_a>asd</str_type_a></NestedLifetimes><cow>123</cow><option>asd</option></StructDeserializerScalars>"
).unwrap(),
StructDeserializerScalars{
bool_type: true,
i8_type: 1,
u32_type: 42,
string_type: "string".to_string(),
str_type_a: "lifetime a",
str_type_b: "lifetime b",
char_type: 'c',
f32_type: 1.20,
nested: NestedLifetimes {
flag: true,
str_type_a: "asd"
},
cow: Cow::from("123"),
option: Some("asd"),
}
);
}
#[derive(Debug, PartialEq, Eq, FromXml, ToXml)]
#[xml(ns("URI"))]
struct StructSpecialEntities<'a> {
string: String,
str: &'a str,
cow: Cow<'a, str>,
}
#[test]
fn escape_back() {
assert_eq!(
StructSpecialEntities::from_xml(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str&amp;</cow></StructSpecialEntities>"
)
.unwrap(),
StructSpecialEntities {
string: String::from("<>&\"'adsad\""),
str: "str",
cow: Cow::Owned("str&".to_string()),
}
);
// Wrong str char
assert_eq!(
StructSpecialEntities::from_xml(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str&amp;</str></StructSpecialEntities>"
)
.unwrap_err(),
Error::Other("Unsupported char: str&".to_string())
);
// Borrowed
let escape_back = StructSpecialEntities::from_xml(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str</cow></StructSpecialEntities>"
)
.unwrap();
if let Cow::Owned(_) = escape_back.cow {
panic!("Should be Borrowed")
}
// Owned
let escape_back = StructSpecialEntities::from_xml(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str&amp;</cow></StructSpecialEntities>"
)
.unwrap();
if let Cow::Borrowed(_) = escape_back.cow {
panic!("Should be Owned")
}
}
#[test]
fn special_entities() {
assert_eq!(
StructSpecialEntities{
string: "&\"<>\'aa".to_string(),
str: "&\"<>\'bb",
cow: Cow::from("&\"<>\'cc"),
}
.to_xml()
.unwrap(),
"<StructSpecialEntities xmlns=\"URI\"><string>&amp;&quot;&lt;&gt;&apos;aa</string><str>&amp;&quot;&lt;&gt;&apos;bb</str><cow>&amp;&quot;&lt;&gt;&apos;cc</cow></StructSpecialEntities>"
);
}

View File

@ -10,7 +10,7 @@ struct NestedWrongNamespace {
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct NestedDe {
#[xml(ns(bar))]
#[xml(ns("BAZ"))]
flag: bool,
}
@ -78,7 +78,7 @@ fn default_namespaces() {
#[derive(Debug, Eq, PartialEq, FromXml)]
#[xml(ns("URI", bar = "BAZ"))]
struct NestedOtherNamespace {
#[xml(ns(bar))]
#[xml(ns("BAZ"))]
flag: bool,
}

View File

@ -5,8 +5,6 @@ use instant_xml::{to_string, ToXml};
#[derive(Debug, Eq, PartialEq, ToXml)]
#[xml(ns(dar = "BAZ", internal = "INTERNAL"))]
struct NestedDifferentNamespace {
#[xml(ns(dar))]
flag_parent_prefix: bool,
#[xml(ns(internal))]
flag_internal_prefix: bool,
}
@ -35,7 +33,6 @@ fn struct_child_namespaces() {
assert_eq!(
to_string(&StructChildNamespaces {
different_child_namespace: NestedDifferentNamespace {
flag_parent_prefix: true,
flag_internal_prefix: false,
},
same_child_namespace: Nested {
@ -44,6 +41,6 @@ fn struct_child_namespaces() {
},
})
.unwrap(),
"<StructChildNamespaces xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><NestedDifferentNamespace xmlns=\"\" xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></NestedDifferentNamespace><Nested xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructChildNamespaces>"
"<StructChildNamespaces xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><NestedDifferentNamespace xmlns=\"\" xmlns:internal=\"INTERNAL\"><internal:flag_internal_prefix>false</internal:flag_internal_prefix></NestedDifferentNamespace><Nested xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructChildNamespaces>"
);
}

View File

@ -6,7 +6,7 @@ use instant_xml::{to_string, ToXml};
#[xml(ns(bar = "BAZ", foo = "BAR"))]
struct StructWithNamedFields {
flag: bool,
#[xml(ns(bar))]
#[xml(ns("BAZ"))]
string: String,
#[xml(ns("typo"))]
number: i32,

View File

@ -5,8 +5,6 @@ use instant_xml::{to_string, ToXml};
#[derive(Debug, Eq, PartialEq, ToXml)]
#[xml(ns("URI", dar = "BAZ", internal = "INTERNAL"))]
struct Nested {
#[xml(ns(dar))]
flag_parent_prefix: bool,
#[xml(ns(internal))]
flag_internal_prefix: bool,
}
@ -18,8 +16,6 @@ struct StructWithCustomField {
int_attribute: i32,
#[xml(ns("BAZ"))]
flag_direct_namespace_same_the_same_as_prefix: bool,
#[xml(ns(bar))]
flag_prefix: bool,
#[xml(ns("DIFFERENT"))]
flag_direct_namespace: bool,
test: Nested,
@ -40,14 +36,12 @@ fn struct_with_custom_field() {
to_string(&StructWithCustomField {
int_attribute: 42,
flag_direct_namespace_same_the_same_as_prefix: true,
flag_prefix: false,
flag_direct_namespace: true,
test: Nested {
flag_parent_prefix: true,
flag_internal_prefix: false,
},
})
.unwrap(),
"<StructWithCustomField xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" int_attribute=\"42\"><flag_direct_namespace_same_the_same_as_prefix xmlns=\"BAZ\">true</flag_direct_namespace_same_the_same_as_prefix><bar:flag_prefix>false</bar:flag_prefix><flag_direct_namespace xmlns=\"DIFFERENT\">true</flag_direct_namespace><Nested xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructWithCustomField>"
"<StructWithCustomField xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" int_attribute=\"42\"><flag_direct_namespace_same_the_same_as_prefix xmlns=\"BAZ\">true</flag_direct_namespace_same_the_same_as_prefix><flag_direct_namespace xmlns=\"DIFFERENT\">true</flag_direct_namespace><Nested xmlns:internal=\"INTERNAL\"><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructWithCustomField>"
);
}