Skip to content

Commit

Permalink
Change expected enum representation in tests according to new policy
Browse files Browse the repository at this point in the history
New representation policy is compatible with serde>=1.0.181 and also more correct
and consistent with general mapping rules.

General rules of new policy:
- In `$value` field the representation is always the same as top-level representation;
- In `$text` field the representation is always the same as in normal field, but surrounding tags with field name are removed;
- In normal field the representation is always contains a tag with field name.

The tables below summarizes the representation policy. For examples in fields only content
at place of `...` is shown:
```
<Container>...</Container>
```

The struct which contains field looks like:
```
struct Container {
  field: Enum,

  #[serde(rename = "$text")]
  text: Enum,

  #[serde(rename = "$value")]
  value: Enum,
}
```

Normal enum variant
-------------------

### Old (before this commit) representation
|Kind   |Top-level, in normal and `$value` fields |In `$text` field|
|-------|-----------------------------------------|----------------|
|Unit   |`<Unit/>`                                |_(empty)_       |
|Newtype|`<Newtype>42</Newtype>`                  |`42`            |
|Tuple  |`<Tuple>42</Tuple><Tuple>answer</Tuple>` |`42 answer`     |
|Struct |`<Struct><q>42</q><a>answer</a></Struct>`|Err(Unsupported)|

### New (since this commit)
|Kind   |Top-level and in `$value` field          |In normal field      |In `$text` field|
|-------|-----------------------------------------|---------------------|----------------|
|Unit   |`<Unit/>`                                |`<field>Unit</field>`|`Unit`          |
|Newtype|`<Newtype>42</Newtype>`                  |Err(Unsupported)     |Err(Unsupported)|
|Tuple  |`<Tuple>42</Tuple><Tuple>answer</Tuple>` |Err(Unsupported)     |Err(Unsupported)|
|Struct |`<Struct><q>42</q><a>answer</a></Struct>`|Err(Unsupported)     |Err(Unsupported)|

`$text` enum variant
--------------------

`<field>` in top-level serialization is the name of top-level element, serialization is impossible if it is not defined in the serializer.

### Old (before this commit) representation
|Kind   |In `$value` field              |In normal field           |In `$text` field|
|-------|-------------------------------|--------------------------|----------------|
|Unit   |_(empty)_                      |`<field/>`                |_(empty)_       |
|Newtype|`42`                           |`<field>42</field>`       |`42`            |
|Tuple  |`42 answer`                    |`<field>42 answer</field>`|`42 answer`     |
|Struct |Err(Unsupported)               |Err(Unsupported)          |Err(Unsupported)|

### New (since this commit)
|Kind   |Top-level and in `$value` field|In normal field           |In `$text` field|
|-------|-------------------------------|--------------------------|----------------|
|Unit   |_(empty)_                      |`<field/>`                |_(empty)_       |
|Newtype|`42`                           |Err(Unsupported)          |Err(Unsupported)|
|Tuple  |`42 answer`                    |Err(Unsupported)          |Err(Unsupported)|
|Struct |Err(Unsupported)               |Err(Unsupported)          |Err(Unsupported)|

failures (28):
  --lib (14)
    se::element::tests::expand_empty_elements::enum_unit
    se::element::tests::expand_empty_elements::enum_unit_escaped
    se::element::tests::with_indent::attributes::enum_
    se::element::tests::with_indent::enum_newtype
    se::element::tests::with_indent::enum_struct
    se::element::tests::with_indent::enum_tuple
    se::element::tests::with_indent::enum_unit
    se::element::tests::with_indent::enum_unit_escaped
    se::element::tests::without_indent::attributes::enum_
    se::element::tests::without_indent::enum_newtype
    se::element::tests::without_indent::enum_struct
    se::element::tests::without_indent::enum_tuple
    se::element::tests::without_indent::enum_unit
    se::element::tests::without_indent::enum_unit_escaped
  serde-se (14):
    without_root::enum_::externally_tagged::normal_field2::empty_struct
    without_root::enum_::externally_tagged::normal_field2::newtype
    without_root::enum_::externally_tagged::normal_field2::struct_
    without_root::enum_::externally_tagged::normal_field2::tuple
    without_root::enum_::externally_tagged::normal_field2::unit
    without_root::enum_::externally_tagged::normal_field::empty_struct
    without_root::enum_::externally_tagged::normal_field::newtype
    without_root::enum_::externally_tagged::normal_field::struct_
    without_root::enum_::externally_tagged::normal_field::tuple
    without_root::enum_::externally_tagged::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::normal_field::newtype
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple
    without_root::enum_::externally_tagged::text_variant::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::text_field::unit
  • Loading branch information
Mingun committed Oct 17, 2023
1 parent 3b21d28 commit 01650ee
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 224 deletions.
100 changes: 22 additions & 78 deletions src/se/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,12 +670,12 @@ mod tests {
serialize_as!(unit_struct: Unit => "<root/>");
serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");

serialize_as!(enum_unit: Enum::Unit => "<Unit/>");
err!(enum_unit_escaped: Enum::UnitEscaped
=> Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root>&lt;&quot;&amp;&apos;&gt;</root>");

serialize_as!(newtype: Newtype(42) => "<root>42</root>");
serialize_as!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
err!(enum_newtype: Enum::Newtype(42)
=> Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));

serialize_as!(seq: vec![1, 2, 3]
=> "<root>1</root>\
Expand All @@ -689,9 +689,8 @@ mod tests {
serialize_as!(tuple_struct: Tuple("first", 42)
=> "<root>first</root>\
<root>42</root>");
serialize_as!(enum_tuple: Enum::Tuple("first", 42)
=> "<Tuple>first</Tuple>\
<Tuple>42</Tuple>");
err!(enum_tuple: Enum::Tuple("first", 42)
=> Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));

serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
=> "<root>\
Expand All @@ -704,12 +703,8 @@ mod tests {
<val>42</val>\
<val>42</val>\
</root>");
serialize_as!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
=> "<Struct>\
<key>answer</key>\
<val>42</val>\
<val>42</val>\
</Struct>");
err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
=> Unsupported("cannot serialize enum struct variant `Enum::Struct`"));

/// Special field name `$text` should be serialized as text content.
/// Sequences serialized as an `xs:list` content
Expand Down Expand Up @@ -1216,12 +1211,8 @@ mod tests {
serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
=> r#"<root val="42"><key>answer</key></root>"#);

serialize_as!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
=> r#"<Attributes key="answer" val="42 42"/>"#);
serialize_as!(enum_before: Enum::AttributesBefore { key: "answer", val: 42 }
=> r#"<AttributesBefore key="answer"><val>42</val></AttributesBefore>"#);
serialize_as!(enum_after: Enum::AttributesAfter { key: "answer", val: 42 }
=> r#"<AttributesAfter val="42"><key>answer</key></AttributesAfter>"#);
err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
=> Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));

/// Test for https://github.com/tafia/quick-xml/issues/252
mod optional {
Expand Down Expand Up @@ -1385,12 +1376,12 @@ mod tests {
serialize_as!(unit_struct: Unit => "<root/>");
serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");

serialize_as!(enum_unit: Enum::Unit => "<Unit/>");
err!(enum_unit_escaped: Enum::UnitEscaped
=> Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root>&lt;&quot;&amp;&apos;&gt;</root>");

serialize_as!(newtype: Newtype(42) => "<root>42</root>");
serialize_as!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
err!(enum_newtype: Enum::Newtype(42)
=> Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));

serialize_as!(seq: vec![1, 2, 3]
=> "<root>1</root>\n\
Expand All @@ -1404,9 +1395,8 @@ mod tests {
serialize_as!(tuple_struct: Tuple("first", 42)
=> "<root>first</root>\n\
<root>42</root>");
serialize_as!(enum_tuple: Enum::Tuple("first", 42)
=> "<Tuple>first</Tuple>\n\
<Tuple>42</Tuple>");
err!(enum_tuple: Enum::Tuple("first", 42)
=> Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));

serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
=> "<root>\n \
Expand All @@ -1419,12 +1409,8 @@ mod tests {
<val>42</val>\n \
<val>42</val>\n\
</root>");
serialize_as!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
=> "<Struct>\n \
<key>answer</key>\n \
<val>42</val>\n \
<val>42</val>\n\
</Struct>");
err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
=> Unsupported("cannot serialize enum struct variant `Enum::Struct`"));

/// Special field name `$text` should be serialized as text content.
/// Sequences serialized as an `xs:list` content
Expand Down Expand Up @@ -1960,16 +1946,8 @@ mod tests {
<key>answer</key>\n\
</root>");

serialize_as!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
=> r#"<Attributes key="answer" val="42 42"/>"#);
serialize_as!(enum_before: Enum::AttributesBefore { key: "answer", val: 42 }
=> "<AttributesBefore key=\"answer\">\n \
<val>42</val>\n\
</AttributesBefore>");
serialize_as!(enum_after: Enum::AttributesAfter { key: "answer", val: 42 }
=> "<AttributesAfter val=\"42\">\n \
<key>answer</key>\n\
</AttributesAfter>");
err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
=> Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));

/// Test for https://github.com/tafia/quick-xml/issues/252
mod optional {
Expand Down Expand Up @@ -2052,48 +2030,14 @@ mod tests {
};
}

/// Checks that attempt to serialize given `$data` results to a
/// serialization error `$kind` with `$reason`
macro_rules! err {
($name:ident: $data:expr => $kind:ident($reason:literal)) => {
#[test]
fn $name() {
let mut buffer = String::new();
let ser = ElementSerializer {
ser: ContentSerializer {
writer: &mut buffer,
level: QuoteLevel::Full,
indent: Indent::None,
write_indent: false,
expand_empty_elements: false,
},
key: XmlName("root"),
};

match $data.serialize(ser).unwrap_err() {
DeError::$kind(e) => assert_eq!(e, $reason),
e => panic!(
"Expected `{}({})`, found `{:?}`",
stringify!($kind),
$reason,
e
),
}
// We can write something before fail
// assert_eq!(buffer, "");
}
};
}

serialize_as!(option_some_empty: Some("") => "<root></root>");
serialize_as!(option_some_empty_str: Some("") => "<root></root>");

serialize_as!(unit: () => "<root></root>");
serialize_as!(unit_struct: Unit => "<root></root>");
serialize_as!(unit_struct_escaped: UnitEscaped => "<root></root>");

serialize_as!(enum_unit: Enum::Unit => "<Unit></Unit>");
err!(enum_unit_escaped: Enum::UnitEscaped
=> Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root>&lt;&quot;&amp;&apos;&gt;</root>");
}
}
Loading

0 comments on commit 01650ee

Please sign in to comment.