tests.rs

  1// Copyright (c) 2020 lumi <lumi@pew.im>
  2// Copyright (c) 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  3// Copyright (c) 2020 Bastien Orivel <eijebong+minidom@bananium.fr>
  4// Copyright (c) 2020 Astro <astro@spaceboyz.net>
  5// Copyright (c) 2020 Maxime “pep” Buquet <pep@bouah.net>
  6// Copyright (c) 2020 Yue Liu <amznyue@amazon.com>
  7// Copyright (c) 2020 Matt Bilker <me@mbilker.us>
  8//
  9// This Source Code Form is subject to the terms of the Mozilla Public
 10// License, v. 2.0. If a copy of the MPL was not distributed with this
 11// file, You can obtain one at http://mozilla.org/MPL/2.0/.
 12
 13use crate::element::Element;
 14use crate::error::Error;
 15
 16const TEST_STRING: &'static [u8] = br#"<root xmlns='root_ns' a="b" xml:lang="en">meow<child c="d"/><child xmlns='child_ns' d="e" xml:lang="fr"/>nya</root>"#;
 17
 18fn build_test_tree() -> Element {
 19    let mut root = Element::builder("root", "root_ns")
 20        .attr("xml:lang", "en")
 21        .attr("a", "b")
 22        .build();
 23    root.append_text_node("meow");
 24    let child = Element::builder("child", "root_ns").attr("c", "d").build();
 25    root.append_child(child);
 26    let other_child = Element::builder("child", "child_ns")
 27        .attr("d", "e")
 28        .attr("xml:lang", "fr")
 29        .build();
 30    root.append_child(other_child);
 31    root.append_text_node("nya");
 32    root
 33}
 34
 35#[test]
 36fn reader_works() {
 37    assert_eq!(
 38        Element::from_reader(TEST_STRING).unwrap(),
 39        build_test_tree()
 40    );
 41}
 42
 43#[test]
 44fn reader_deduplicate_prefixes() {
 45    // The reader shouldn't complain that "child" doesn't have a namespace. It should reuse the
 46    // parent ns with the same prefix.
 47    let _: Element = r#"<root xmlns="ns1"><child/></root>"#.parse().unwrap();
 48    let _: Element = r#"<p1:root xmlns:p1="ns1"><p1:child/></p1:root>"#.parse().unwrap();
 49    let _: Element = r#"<root xmlns="ns1"><child xmlns:p1="ns2"><p1:grandchild/></child></root>"#
 50        .parse()
 51        .unwrap();
 52
 53    match r#"<p1:root xmlns:p1="ns1"><child/></p1:root>"#.parse::<Element>() {
 54        Err(Error::MissingNamespace) => (),
 55        Err(err) => panic!("No or wrong error: {:?}", err),
 56        Ok(elem) => panic!(
 57            "Got Element: {}; was expecting Error::MissingNamespace",
 58            String::from(&elem)
 59        ),
 60    }
 61}
 62
 63#[test]
 64fn reader_no_deduplicate_sibling_prefixes() {
 65    // The reader shouldn't reuse the sibling's prefixes
 66    match r#"<root xmlns="ns1"><p1:child1 xmlns:p1="ns2"/><p1:child2/></root>"#.parse::<Element>() {
 67        Err(Error::MissingNamespace) => (),
 68        Err(err) => panic!("No or wrong error: {:?}", err),
 69        Ok(elem) => panic!(
 70            "Got Element:\n{:?}\n{}\n; was expecting Error::MissingNamespace",
 71            elem,
 72            String::from(&elem)
 73        ),
 74    }
 75}
 76
 77#[test]
 78fn test_real_data() {
 79    let correction = Element::builder("replace", "urn:xmpp:message-correct:0").build();
 80    let body = Element::builder("body", "jabber:client").build();
 81    let message = Element::builder("message", "jabber:client")
 82        .append(body)
 83        .append(correction)
 84        .build();
 85    let stream = Element::builder("stream", "http://etherx.jabber.org/streams")
 86        .prefix(
 87            Some(String::from("stream")),
 88            "http://etherx.jabber.org/streams",
 89        )
 90        .unwrap()
 91        .prefix(None, "jabber:client")
 92        .unwrap()
 93        .append(message)
 94        .build();
 95    println!("{}", String::from(&stream));
 96
 97    let jid = Element::builder("jid", "urn:xmpp:presence:0").build();
 98    let nick = Element::builder("nick", "urn:xmpp:presence:0").build();
 99    let mix = Element::builder("mix", "urn:xmpp:presence:0")
100        .append(jid)
101        .append(nick)
102        .build();
103    let show = Element::builder("show", "jabber:client").build();
104    let status = Element::builder("status", "jabber:client").build();
105    let presence = Element::builder("presence", "jabber:client")
106        .append(show)
107        .append(status)
108        .append(mix)
109        .build();
110    let item = Element::builder("item", "http://jabber.org/protocol/pubsub")
111        .append(presence)
112        .build();
113    let items = Element::builder("items", "http://jabber.org/protocol/pubsub")
114        .append(item)
115        .build();
116    let pubsub = Element::builder("pubsub", "http://jabber.org/protocol/pubsub")
117        .append(items)
118        .build();
119    let iq = Element::builder("iq", "jabber:client")
120        .append(pubsub)
121        .build();
122    let stream = Element::builder("stream", "http://etherx.jabber.org/streams")
123        .prefix(
124            Some(String::from("stream")),
125            "http://etherx.jabber.org/streams",
126        )
127        .unwrap()
128        .prefix(None, "jabber:client")
129        .unwrap()
130        .append(iq)
131        .build();
132
133    println!("{}", String::from(&stream));
134}
135
136#[test]
137fn writer_works() {
138    let root = build_test_tree();
139    let mut writer = Vec::new();
140    {
141        root.write_to(&mut writer).unwrap();
142    }
143    assert_eq!(writer, TEST_STRING);
144}
145
146#[test]
147fn writer_with_decl_works() {
148    let root = build_test_tree();
149    let mut writer = Vec::new();
150    {
151        root.write_to_decl(&mut writer).unwrap();
152    }
153    let result = format!(
154        "<?xml version='1.0' encoding='utf-8'?>\n{}",
155        String::from_utf8(TEST_STRING.to_owned()).unwrap()
156    );
157    assert_eq!(String::from_utf8(writer).unwrap(), result);
158}
159
160#[test]
161fn writer_with_prefix() {
162    let root = Element::builder("root", "ns1")
163        .prefix(Some(String::from("p1")), "ns1")
164        .unwrap()
165        .prefix(None, "ns2")
166        .unwrap()
167        .build();
168    assert_eq!(
169        String::from(&root),
170        r#"<p1:root xmlns='ns2' xmlns:p1='ns1'/>"#,
171    );
172}
173
174#[test]
175fn writer_no_prefix_namespace() {
176    let root = Element::builder("root", "ns1").build();
177    // TODO: Note that this isn't exactly equal to a None prefix. it's just that the None prefix is
178    // the most obvious when it's not already used. Maybe fix tests so that it only checks that the
179    // prefix used equals the one declared for the namespace.
180    assert_eq!(String::from(&root), r#"<root xmlns='ns1'/>"#);
181}
182
183#[test]
184fn writer_no_prefix_namespace_child() {
185    let child = Element::builder("child", "ns1").build();
186    let root = Element::builder("root", "ns1").append(child).build();
187    // TODO: Same remark as `writer_no_prefix_namespace`.
188    assert_eq!(String::from(&root), r#"<root xmlns='ns1'><child/></root>"#);
189
190    let child = Element::builder("child", "ns2")
191        .prefix(None, "ns3")
192        .unwrap()
193        .build();
194    let root = Element::builder("root", "ns1").append(child).build();
195    // TODO: Same remark as `writer_no_prefix_namespace`.
196    assert_eq!(
197        String::from(&root),
198        r#"<root xmlns='ns1'><tns0:child xmlns='ns3' xmlns:tns0='ns2'/></root>"#
199    );
200}
201
202#[test]
203fn writer_prefix_namespace_child() {
204    let child = Element::builder("child", "ns1").build();
205    let root = Element::builder("root", "ns1")
206        .prefix(Some(String::from("p1")), "ns1")
207        .unwrap()
208        .append(child)
209        .build();
210    assert_eq!(
211        String::from(&root),
212        r#"<p1:root xmlns:p1='ns1'><p1:child/></p1:root>"#
213    );
214}
215
216#[test]
217fn writer_with_prefix_deduplicate() {
218    let child = Element::builder("child", "ns1")
219        // .prefix(Some(String::from("p1")), "ns1")
220        .build();
221    let root = Element::builder("root", "ns1")
222        .prefix(Some(String::from("p1")), "ns1")
223        .unwrap()
224        .prefix(None, "ns2")
225        .unwrap()
226        .append(child)
227        .build();
228    assert_eq!(
229        String::from(&root),
230        r#"<p1:root xmlns='ns2' xmlns:p1='ns1'><p1:child/></p1:root>"#,
231    );
232
233    // Ensure descendants don't just reuse ancestors' prefixes that have been shadowed in between
234    let grandchild = Element::builder("grandchild", "ns1").build();
235    let child = Element::builder("child", "ns2").append(grandchild).build();
236    let root = Element::builder("root", "ns1").append(child).build();
237    assert_eq!(
238        String::from(&root),
239        r#"<root xmlns='ns1'><child xmlns='ns2'><grandchild xmlns='ns1'/></child></root>"#,
240    );
241}
242
243#[test]
244fn writer_escapes_attributes() {
245    let root = Element::builder("root", "ns1")
246        .attr("a", "\"Air\" quotes")
247        .build();
248    let mut writer = Vec::new();
249    {
250        root.write_to(&mut writer).unwrap();
251    }
252    assert_eq!(
253        String::from_utf8(writer).unwrap(),
254        r#"<root xmlns='ns1' a="&#34;Air&#34; quotes"/>"#
255    );
256}
257
258#[test]
259fn writer_escapes_text() {
260    let root = Element::builder("root", "ns1").append("<3").build();
261    let mut writer = Vec::new();
262    {
263        root.write_to(&mut writer).unwrap();
264    }
265    assert_eq!(
266        String::from_utf8(writer).unwrap(),
267        r#"<root xmlns='ns1'>&lt;3</root>"#
268    );
269}
270
271#[test]
272fn builder_works() {
273    let elem = Element::builder("a", "b")
274        .attr("c", "d")
275        .append(Element::builder("child", "b"))
276        .append("e")
277        .build();
278    assert_eq!(elem.name(), "a");
279    assert_eq!(elem.ns(), "b".to_owned());
280    assert_eq!(elem.attr("c"), Some("d"));
281    assert_eq!(elem.attr("x"), None);
282    assert_eq!(elem.text(), "e");
283    assert!(elem.has_child("child", "b"));
284    assert!(elem.is("a", "b"));
285}
286
287#[test]
288fn children_iter_works() {
289    let root = build_test_tree();
290    let mut iter = root.children();
291    assert!(iter.next().unwrap().is("child", "root_ns"));
292    assert!(iter.next().unwrap().is("child", "child_ns"));
293    assert_eq!(iter.next(), None);
294}
295
296#[test]
297fn get_child_works() {
298    let root = build_test_tree();
299    assert_eq!(root.get_child("child", "inexistent_ns"), None);
300    assert_eq!(root.get_child("not_a_child", "root_ns"), None);
301    assert!(root
302        .get_child("child", "root_ns")
303        .unwrap()
304        .is("child", "root_ns"));
305    assert!(root
306        .get_child("child", "child_ns")
307        .unwrap()
308        .is("child", "child_ns"));
309    assert_eq!(
310        root.get_child("child", "root_ns").unwrap().attr("c"),
311        Some("d")
312    );
313    assert_eq!(
314        root.get_child("child", "child_ns").unwrap().attr("d"),
315        Some("e")
316    );
317}
318
319#[test]
320fn namespace_propagation_works() {
321    let mut root = Element::builder("root", "root_ns").build();
322    let mut child = Element::bare("child", "root_ns");
323    let grandchild = Element::bare("grandchild", "root_ns");
324    child.append_child(grandchild);
325    root.append_child(child);
326
327    assert_eq!(root.get_child("child", "root_ns").unwrap().ns(), root.ns());
328    assert_eq!(
329        root.get_child("child", "root_ns")
330            .unwrap()
331            .get_child("grandchild", "root_ns")
332            .unwrap()
333            .ns(),
334        root.ns()
335    );
336}
337
338#[test]
339fn two_elements_with_same_arguments_different_order_are_equal() {
340    let elem1: Element = "<a b='a' c='' xmlns='ns1'/>".parse().unwrap();
341    let elem2: Element = "<a c='' b='a' xmlns='ns1'/>".parse().unwrap();
342    assert_eq!(elem1, elem2);
343
344    let elem1: Element = "<a b='a' c='' xmlns='ns1'/>".parse().unwrap();
345    let elem2: Element = "<a c='d' b='a' xmlns='ns1'/>".parse().unwrap();
346    assert_ne!(elem1, elem2);
347}
348
349#[test]
350fn namespace_attributes_works() {
351    let root = Element::from_reader(TEST_STRING).unwrap();
352    assert_eq!("en", root.attr("xml:lang").unwrap());
353    assert_eq!(
354        "fr",
355        root.get_child("child", "child_ns")
356            .unwrap()
357            .attr("xml:lang")
358            .unwrap()
359    );
360}
361
362#[test]
363fn wrongly_closed_elements_error() {
364    let elem1 = "<a xmlns='ns1'></b>".parse::<Element>();
365    assert!(elem1.is_err());
366    let elem1 = "<a xmlns='ns1'></c></a>".parse::<Element>();
367    assert!(elem1.is_err());
368    let elem1 = "<a xmlns='ns1'><c xmlns='ns1'><d xmlns='ns1'/></c></a>".parse::<Element>();
369    assert!(elem1.is_ok());
370}
371
372#[test]
373fn namespace_simple() {
374    let elem: Element = "<message xmlns='jabber:client'/>".parse().unwrap();
375    assert_eq!(elem.name(), "message");
376    assert_eq!(elem.ns(), "jabber:client".to_owned());
377}
378
379#[test]
380fn namespace_prefixed() {
381    let elem: Element = "<stream:features xmlns:stream='http://etherx.jabber.org/streams'/>"
382        .parse()
383        .unwrap();
384    assert_eq!(elem.name(), "features");
385    assert_eq!(elem.ns(), "http://etherx.jabber.org/streams".to_owned(),);
386}
387
388#[test]
389fn namespace_inherited_simple() {
390    let elem: Element = "<stream xmlns='jabber:client'><message xmlns='jabber:client' /></stream>"
391        .parse()
392        .unwrap();
393    assert_eq!(elem.name(), "stream");
394    assert_eq!(elem.ns(), "jabber:client".to_owned());
395    let child = elem.children().next().unwrap();
396    assert_eq!(child.name(), "message");
397    assert_eq!(child.ns(), "jabber:client".to_owned());
398}
399
400#[test]
401fn namespace_inherited_prefixed1() {
402    let elem: Element = "<stream:features xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'><message xmlns='jabber:client' /></stream:features>"
403        .parse().unwrap();
404    assert_eq!(elem.name(), "features");
405    assert_eq!(elem.ns(), "http://etherx.jabber.org/streams".to_owned(),);
406    let child = elem.children().next().unwrap();
407    assert_eq!(child.name(), "message");
408    assert_eq!(child.ns(), "jabber:client".to_owned());
409}
410
411#[test]
412fn namespace_inherited_prefixed2() {
413    let elem: Element = "<stream xmlns='http://etherx.jabber.org/streams' xmlns:jabber='jabber:client'><jabber:message xmlns:jabber='jabber:client' /></stream>"
414        .parse().unwrap();
415    assert_eq!(elem.name(), "stream");
416    assert_eq!(elem.ns(), "http://etherx.jabber.org/streams".to_owned(),);
417    let child = elem.children().next().unwrap();
418    assert_eq!(child.name(), "message");
419    assert_eq!(child.ns(), "jabber:client".to_owned());
420}
421
422#[test]
423fn fail_comments() {
424    let elem: Result<Element, Error> = "<foo xmlns='ns1'><!-- bar --></foo>".parse();
425    match elem {
426        Err(_) => (),
427        _ => panic!(),
428    };
429}
430
431#[test]
432fn xml_error() {
433    match "<a xmlns='ns1'></b>".parse::<Element>() {
434        Err(crate::error::Error::XmlError(rxml::Error::Xml(
435            rxml::error::XmlError::ElementMismatch,
436        ))) => (),
437        err => panic!("No or wrong error: {:?}", err),
438    }
439
440    match "<a xmlns='ns1'></".parse::<Element>() {
441        Err(crate::error::Error::XmlError(rxml::Error::Xml(
442            rxml::error::XmlError::InvalidEof(_),
443        ))) => (),
444        err => panic!("No or wrong error: {:?}", err),
445    }
446}
447
448#[test]
449fn missing_namespace_error() {
450    match "<a/>".parse::<Element>() {
451        Err(crate::error::Error::MissingNamespace) => (),
452        err => panic!("No or wrong error: {:?}", err),
453    }
454}
455
456#[test]
457fn misserialisation() {
458    let xml =
459        "<jitsi_participant_codecType xmlns='jabber:client'>vp9</jitsi_participant_codecType>";
460    //let elem = xml.parse::<Element>().unwrap();
461    let elem = Element::builder("jitsi_participant_codecType", "jabber:client")
462        .append("vp9")
463        .build();
464    let data = String::from(&elem);
465    assert_eq!(xml, data);
466}