// Copyright (c) 2020 lumi // Copyright (c) 2020 Emmanuel Gil Peyrot // Copyright (c) 2020 Bastien Orivel // Copyright (c) 2020 Astro // Copyright (c) 2020 Maxime “pep” Buquet // Copyright (c) 2020 Yue Liu // Copyright (c) 2020 Matt Bilker // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. use crate::element::Element; use crate::error::Error; const TEST_STRING: &'static [u8] = br#"meownya"#; fn build_test_tree() -> Element { let mut root = Element::builder("root", "root_ns") .attr("xml:lang", "en") .attr("a", "b") .build(); root.append_text_node("meow"); let child = Element::builder("child", "root_ns").attr("c", "d").build(); root.append_child(child); let other_child = Element::builder("child", "child_ns") .attr("d", "e") .attr("xml:lang", "fr") .build(); root.append_child(other_child); root.append_text_node("nya"); root } #[test] fn reader_works() { assert_eq!( Element::from_reader(TEST_STRING).unwrap(), build_test_tree() ); } #[test] fn reader_deduplicate_prefixes() { // The reader shouldn't complain that "child" doesn't have a namespace. It should reuse the // parent ns with the same prefix. let _: Element = r#""#.parse().unwrap(); let _: Element = r#""#.parse().unwrap(); let _: Element = r#""# .parse() .unwrap(); match r#""#.parse::() { Err(Error::MissingNamespace) => (), Err(err) => panic!("No or wrong error: {:?}", err), Ok(elem) => panic!( "Got Element: {}; was expecting Error::MissingNamespace", String::from(&elem) ), } } #[test] fn reader_no_deduplicate_sibling_prefixes() { // The reader shouldn't reuse the sibling's prefixes match r#""#.parse::() { Err(Error::MissingNamespace) => (), Err(err) => panic!("No or wrong error: {:?}", err), Ok(elem) => panic!( "Got Element:\n{:?}\n{}\n; was expecting Error::MissingNamespace", elem, String::from(&elem) ), } } #[test] fn test_real_data() { let correction = Element::builder("replace", "urn:xmpp:message-correct:0").build(); let body = Element::builder("body", "jabber:client").build(); let message = Element::builder("message", "jabber:client") .append(body) .append(correction) .build(); let stream = Element::builder("stream", "http://etherx.jabber.org/streams") .prefix( Some(String::from("stream")), "http://etherx.jabber.org/streams", ) .unwrap() .prefix(None, "jabber:client") .unwrap() .append(message) .build(); println!("{}", String::from(&stream)); let jid = Element::builder("jid", "urn:xmpp:presence:0").build(); let nick = Element::builder("nick", "urn:xmpp:presence:0").build(); let mix = Element::builder("mix", "urn:xmpp:presence:0") .append(jid) .append(nick) .build(); let show = Element::builder("show", "jabber:client").build(); let status = Element::builder("status", "jabber:client").build(); let presence = Element::builder("presence", "jabber:client") .append(show) .append(status) .append(mix) .build(); let item = Element::builder("item", "http://jabber.org/protocol/pubsub") .append(presence) .build(); let items = Element::builder("items", "http://jabber.org/protocol/pubsub") .append(item) .build(); let pubsub = Element::builder("pubsub", "http://jabber.org/protocol/pubsub") .append(items) .build(); let iq = Element::builder("iq", "jabber:client") .append(pubsub) .build(); let stream = Element::builder("stream", "http://etherx.jabber.org/streams") .prefix( Some(String::from("stream")), "http://etherx.jabber.org/streams", ) .unwrap() .prefix(None, "jabber:client") .unwrap() .append(iq) .build(); println!("{}", String::from(&stream)); } #[test] fn writer_works() { let root = build_test_tree(); let mut writer = Vec::new(); { root.write_to(&mut writer).unwrap(); } assert_eq!(writer, TEST_STRING); } #[test] fn writer_with_decl_works() { let root = build_test_tree(); let mut writer = Vec::new(); { root.write_to_decl(&mut writer).unwrap(); } let result = format!( "\n{}", String::from_utf8(TEST_STRING.to_owned()).unwrap() ); assert_eq!(String::from_utf8(writer).unwrap(), result); } #[test] fn writer_with_prefix() { let root = Element::builder("root", "ns1") .prefix(Some(String::from("p1")), "ns1") .unwrap() .prefix(None, "ns2") .unwrap() .build(); assert_eq!( String::from(&root), r#""#, ); } #[test] fn writer_no_prefix_namespace() { let root = Element::builder("root", "ns1").build(); // TODO: Note that this isn't exactly equal to a None prefix. it's just that the None prefix is // the most obvious when it's not already used. Maybe fix tests so that it only checks that the // prefix used equals the one declared for the namespace. assert_eq!(String::from(&root), r#""#); } #[test] fn writer_no_prefix_namespace_child() { let child = Element::builder("child", "ns1").build(); let root = Element::builder("root", "ns1").append(child).build(); // TODO: Same remark as `writer_no_prefix_namespace`. assert_eq!(String::from(&root), r#""#); let child = Element::builder("child", "ns2") .prefix(None, "ns3") .unwrap() .build(); let root = Element::builder("root", "ns1").append(child).build(); // TODO: Same remark as `writer_no_prefix_namespace`. assert_eq!( String::from(&root), r#""# ); } #[test] fn writer_prefix_namespace_child() { let child = Element::builder("child", "ns1").build(); let root = Element::builder("root", "ns1") .prefix(Some(String::from("p1")), "ns1") .unwrap() .append(child) .build(); assert_eq!( String::from(&root), r#""# ); } #[test] fn writer_with_prefix_deduplicate() { let child = Element::builder("child", "ns1") // .prefix(Some(String::from("p1")), "ns1") .build(); let root = Element::builder("root", "ns1") .prefix(Some(String::from("p1")), "ns1") .unwrap() .prefix(None, "ns2") .unwrap() .append(child) .build(); assert_eq!( String::from(&root), r#""#, ); // Ensure descendants don't just reuse ancestors' prefixes that have been shadowed in between let grandchild = Element::builder("grandchild", "ns1").build(); let child = Element::builder("child", "ns2").append(grandchild).build(); let root = Element::builder("root", "ns1").append(child).build(); assert_eq!( String::from(&root), r#""#, ); } #[test] fn writer_escapes_attributes() { let root = Element::builder("root", "ns1") .attr("a", "\"Air\" quotes") .build(); let mut writer = Vec::new(); { root.write_to(&mut writer).unwrap(); } assert_eq!( String::from_utf8(writer).unwrap(), r#""# ); } #[test] fn writer_escapes_text() { let root = Element::builder("root", "ns1").append("<3").build(); let mut writer = Vec::new(); { root.write_to(&mut writer).unwrap(); } assert_eq!( String::from_utf8(writer).unwrap(), r#"<3"# ); } #[test] fn builder_works() { let elem = Element::builder("a", "b") .attr("c", "d") .append(Element::builder("child", "b")) .append("e") .build(); assert_eq!(elem.name(), "a"); assert_eq!(elem.ns(), "b".to_owned()); assert_eq!(elem.attr("c"), Some("d")); assert_eq!(elem.attr("x"), None); assert_eq!(elem.text(), "e"); assert!(elem.has_child("child", "b")); assert!(elem.is("a", "b")); } #[test] fn children_iter_works() { let root = build_test_tree(); let mut iter = root.children(); assert!(iter.next().unwrap().is("child", "root_ns")); assert!(iter.next().unwrap().is("child", "child_ns")); assert_eq!(iter.next(), None); } #[test] fn get_child_works() { let root = build_test_tree(); assert_eq!(root.get_child("child", "inexistent_ns"), None); assert_eq!(root.get_child("not_a_child", "root_ns"), None); assert!(root .get_child("child", "root_ns") .unwrap() .is("child", "root_ns")); assert!(root .get_child("child", "child_ns") .unwrap() .is("child", "child_ns")); assert_eq!( root.get_child("child", "root_ns").unwrap().attr("c"), Some("d") ); assert_eq!( root.get_child("child", "child_ns").unwrap().attr("d"), Some("e") ); } #[test] fn namespace_propagation_works() { let mut root = Element::builder("root", "root_ns").build(); let mut child = Element::bare("child", "root_ns"); let grandchild = Element::bare("grandchild", "root_ns"); child.append_child(grandchild); root.append_child(child); assert_eq!(root.get_child("child", "root_ns").unwrap().ns(), root.ns()); assert_eq!( root.get_child("child", "root_ns") .unwrap() .get_child("grandchild", "root_ns") .unwrap() .ns(), root.ns() ); } #[test] fn two_elements_with_same_arguments_different_order_are_equal() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert_eq!(elem1, elem2); let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert_ne!(elem1, elem2); } #[test] fn namespace_attributes_works() { let root = Element::from_reader(TEST_STRING).unwrap(); assert_eq!("en", root.attr("xml:lang").unwrap()); assert_eq!( "fr", root.get_child("child", "child_ns") .unwrap() .attr("xml:lang") .unwrap() ); } #[test] fn wrongly_closed_elements_error() { let elem1 = "".parse::(); assert!(elem1.is_err()); let elem1 = "".parse::(); assert!(elem1.is_err()); let elem1 = "".parse::(); assert!(elem1.is_ok()); } #[test] fn namespace_simple() { let elem: Element = "".parse().unwrap(); assert_eq!(elem.name(), "message"); assert_eq!(elem.ns(), "jabber:client".to_owned()); } #[test] fn namespace_prefixed() { let elem: Element = "" .parse() .unwrap(); assert_eq!(elem.name(), "features"); assert_eq!(elem.ns(), "http://etherx.jabber.org/streams".to_owned(),); } #[test] fn namespace_inherited_simple() { let elem: Element = "" .parse() .unwrap(); assert_eq!(elem.name(), "stream"); assert_eq!(elem.ns(), "jabber:client".to_owned()); let child = elem.children().next().unwrap(); assert_eq!(child.name(), "message"); assert_eq!(child.ns(), "jabber:client".to_owned()); } #[test] fn namespace_inherited_prefixed1() { let elem: Element = "" .parse().unwrap(); assert_eq!(elem.name(), "features"); assert_eq!(elem.ns(), "http://etherx.jabber.org/streams".to_owned(),); let child = elem.children().next().unwrap(); assert_eq!(child.name(), "message"); assert_eq!(child.ns(), "jabber:client".to_owned()); } #[test] fn namespace_inherited_prefixed2() { let elem: Element = "" .parse().unwrap(); assert_eq!(elem.name(), "stream"); assert_eq!(elem.ns(), "http://etherx.jabber.org/streams".to_owned(),); let child = elem.children().next().unwrap(); assert_eq!(child.name(), "message"); assert_eq!(child.ns(), "jabber:client".to_owned()); } #[test] fn fail_comments() { let elem: Result = "".parse(); match elem { Err(_) => (), _ => panic!(), }; } #[test] fn xml_error() { match "".parse::() { Err(crate::error::Error::XmlError(rxml::Error::ElementMismatch)) => (), err => panic!("No or wrong error: {:?}", err), } match "() { Err(crate::error::Error::XmlError(rxml::Error::InvalidEof(_))) => (), err => panic!("No or wrong error: {:?}", err), } } #[test] fn missing_namespace_error() { match "".parse::() { Err(crate::error::Error::MissingNamespace) => (), err => panic!("No or wrong error: {:?}", err), } } #[test] fn misserialisation() { let xml = "vp9"; //let elem = xml.parse::().unwrap(); let elem = Element::builder("jitsi_participant_codecType", "jabber:client") .append("vp9") .build(); let data = String::from(&elem); assert_eq!(xml, data); }