Skip to content

Commit f6cc0fc

Browse files
committed
Add test to ensure, that entities which expands to the XML fragments are parsed
Remove previous test because it is covered by the new one
1 parent 3fde5c4 commit f6cc0fc

3 files changed

Lines changed: 99 additions & 81 deletions

File tree

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ name = "serde-de-enum"
233233
required-features = ["serialize"]
234234
path = "tests/serde-de-enum.rs"
235235

236+
[[test]]
237+
name = "serde-de-references"
238+
required-features = ["serialize"]
239+
path = "tests/serde-de-references.rs"
240+
236241
[[test]]
237242
name = "serde-de-seq"
238243
required-features = ["serialize"]

tests/serde-de-references.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::borrow::Cow;
2+
use std::convert::Infallible;
3+
4+
use quick_xml::de::Deserializer;
5+
use quick_xml::events::BytesText;
6+
use quick_xml::reader::{EntityResolver, EntityResolverFactory, ReplacementText};
7+
8+
use pretty_assertions::assert_eq;
9+
use serde::Deserialize;
10+
11+
#[derive(Clone, Copy)]
12+
struct TestEntityResolver {
13+
capture_called: bool,
14+
}
15+
16+
impl<'i> EntityResolverFactory<'i> for TestEntityResolver {
17+
type CaptureError = Infallible;
18+
type Resolver = Self;
19+
20+
fn new_resolver(&mut self) -> Self::Resolver {
21+
*self
22+
}
23+
}
24+
25+
impl<'i> EntityResolver<'i> for TestEntityResolver {
26+
type CaptureError = Infallible;
27+
28+
fn capture(&mut self, _doctype: BytesText) -> Result<(), Self::CaptureError> {
29+
self.capture_called = true;
30+
Ok(())
31+
}
32+
33+
fn resolve<'e>(&self, entity: &str) -> Option<ReplacementText<'i, 'e>> {
34+
assert!(
35+
self.capture_called,
36+
"`EntityResolver::capture` should be called before `EntityResolver::resolve(\"{}\")`",
37+
entity,
38+
);
39+
40+
match dbg!(entity) {
41+
"text" => Some(ReplacementText::Internal(Cow::Borrowed(
42+
b"&#x20;<![CDATA[second text]]>&#32;",
43+
))),
44+
_ => Some(ReplacementText::Internal(Cow::Borrowed(
45+
b"
46+
<child1 attribute = '&lt;attribute value&gt;'>&text;</child1>
47+
<child2/>
48+
",
49+
))),
50+
}
51+
}
52+
}
53+
54+
#[derive(Debug, PartialEq, Deserialize)]
55+
struct Root {
56+
child1: Child1,
57+
child2: (),
58+
}
59+
60+
#[derive(Debug, PartialEq, Deserialize)]
61+
struct Child1 {
62+
#[serde(rename = "@attribute")]
63+
attribute: String,
64+
65+
#[serde(rename = "$text")]
66+
text: String,
67+
}
68+
69+
#[test]
70+
fn entities() {
71+
let mut de = Deserializer::from_str_with_resolver(
72+
"
73+
<!DOCTYPE root>
74+
<root>&entity;</root>
75+
",
76+
TestEntityResolver {
77+
capture_called: false,
78+
},
79+
);
80+
81+
let data = Root::deserialize(&mut de).unwrap();
82+
83+
de.check_eof_reached();
84+
assert_eq!(
85+
data,
86+
Root {
87+
child1: Child1 {
88+
attribute: "<attribute value>".to_string(),
89+
text: " second text ".to_string(),
90+
},
91+
child2: (),
92+
}
93+
);
94+
}

tests/serde-de.rs

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use quick_xml::de::Deserializer;
21
use quick_xml::utils::{ByteBuf, Bytes};
32
use quick_xml::DeError;
43

@@ -1827,86 +1826,6 @@ mod borrow {
18271826
}
18281827
}
18291828

1830-
/// Test for entity resolver
1831-
mod resolve {
1832-
use super::*;
1833-
use pretty_assertions::assert_eq;
1834-
use quick_xml::events::BytesText;
1835-
use quick_xml::reader::{EntityResolver, EntityResolverFactory, ReplacementText};
1836-
use std::borrow::Cow;
1837-
use std::collections::BTreeMap;
1838-
use std::convert::Infallible;
1839-
use std::iter::FromIterator;
1840-
1841-
#[derive(Clone, Copy)]
1842-
struct TestEntityResolver {
1843-
capture_called: bool,
1844-
}
1845-
1846-
impl<'i> EntityResolverFactory<'i> for TestEntityResolver {
1847-
type CaptureError = Infallible;
1848-
type Resolver = Self;
1849-
1850-
fn new_resolver(&mut self) -> Self::Resolver {
1851-
*self
1852-
}
1853-
}
1854-
1855-
impl<'i> EntityResolver<'i> for TestEntityResolver {
1856-
type CaptureError = Infallible;
1857-
1858-
fn capture(&mut self, doctype: BytesText) -> Result<(), Self::CaptureError> {
1859-
self.capture_called = true;
1860-
1861-
assert_eq!(doctype.as_ref(), br#"dict[ <!ENTITY unc "unclassified"> ]"#);
1862-
1863-
Ok(())
1864-
}
1865-
1866-
fn resolve<'e>(&self, entity: &str) -> Option<ReplacementText<'i, 'e>> {
1867-
assert!(
1868-
self.capture_called,
1869-
"`EntityResolver::capture` should be called before `EntityResolver::resolve`"
1870-
);
1871-
match entity {
1872-
"t1" => Some(ReplacementText::Internal(Cow::Borrowed(b"test_one"))),
1873-
"t2" => Some(ReplacementText::Internal(Cow::Borrowed(b"test_two"))),
1874-
_ => None,
1875-
}
1876-
}
1877-
}
1878-
1879-
#[test]
1880-
fn resolve_custom_entity() {
1881-
let resolver = TestEntityResolver {
1882-
capture_called: false,
1883-
};
1884-
let mut de = Deserializer::with_resolver(
1885-
br#"
1886-
<!DOCTYPE dict[ <!ENTITY unc "unclassified"> ]>
1887-
1888-
<root>
1889-
<entity_one>&t1;</entity_one>
1890-
<entity_two>&t2;</entity_two>
1891-
<entity_three>non-entity</entity_three>
1892-
</root>
1893-
"#
1894-
.as_ref(),
1895-
resolver,
1896-
);
1897-
1898-
let data: BTreeMap<String, String> = BTreeMap::deserialize(&mut de).unwrap();
1899-
assert_eq!(
1900-
data,
1901-
BTreeMap::from_iter([
1902-
(String::from("entity_one"), String::from("test_one")),
1903-
(String::from("entity_two"), String::from("test_two")),
1904-
(String::from("entity_three"), String::from("non-entity")),
1905-
])
1906-
);
1907-
}
1908-
}
1909-
19101829
/// Tests for https://github.com/tafia/quick-xml/pull/603.
19111830
///
19121831
/// According to <https://www.w3.org/TR/xml11/#NT-prolog> comments,

0 commit comments

Comments
 (0)