//! Tree module tests
//!
use libxml::parser::Parser;
use libxml::tree::{Document, Namespace, Node, NodeType};
#[test]
/// Root node and first child of root node are different
/// (There is a tiny chance this might fail for a correct program)
fn child_of_root_has_different_hash() {
let parser = Parser::default();
{
let doc_result = parser.parse_file("tests/resources/file01.xml");
assert!(doc_result.is_ok());
let doc = doc_result.unwrap();
let root = doc.get_root_element().unwrap();
assert!(!root.is_text_node());
if let Some(child) = root.get_first_child() {
assert!(root != child);
} else {
assert!(false); //test failed - child doesn't exist
}
// same check with last child
if let Some(child) = root.get_last_child() {
assert!(root != child);
} else {
assert!(false); //test failed - child doesn't exist
}
}
}
#[test]
/// Siblings basic unit tests
fn node_sibling_accessors() {
let mut doc = Document::new().unwrap();
let hello_element_result = Node::new("hello", None, &doc);
assert!(hello_element_result.is_ok());
let mut hello_element = hello_element_result.unwrap();
doc.set_root_element(&hello_element);
let mut new_sibling = Node::new("sibling", None, &doc).unwrap();
assert!(hello_element.add_prev_sibling(&mut new_sibling).is_ok());
}
#[test]
fn node_children_accessors() {
// Setup
let parser = Parser::default();
let doc_result = parser.parse_file("tests/resources/file01.xml");
assert!(doc_result.is_ok());
let doc = doc_result.unwrap();
let root = doc.get_root_element().unwrap();
// Tests
let root_children = root.get_child_nodes();
assert_eq!(root_children.len(), 5, "file01 root has five child nodes");
let mut element_children = root.get_child_elements();
assert_eq!(
element_children.len(),
2,
"file01 root has two child elements"
);
assert_eq!(element_children.pop().unwrap().get_name(), "child");
assert_eq!(element_children.pop().unwrap().get_name(), "child");
assert!(element_children.is_empty());
}
#[test]
fn node_attributes_accessor() {
// Setup
let parser = Parser::default();
let doc_result = parser.parse_file("tests/resources/file01.xml");
assert!(doc_result.is_ok());
let doc = doc_result.unwrap();
let root = doc.get_root_element().unwrap();
let mut root_elements = root.get_child_elements();
let child_opt = root_elements.first_mut();
assert!(child_opt.is_some());
let child = child_opt.unwrap();
// All attributes
let attributes = child.get_attributes();
assert_eq!(attributes.len(), 1);
assert_eq!(attributes.get("attribute"), Some(&"value".to_string()));
// Has
assert_eq!(child.has_attribute("attribute"), true);
// Get
assert_eq!(child.get_attribute("attribute"), Some("value".to_string()));
// Get as node
let attr_node_opt = child.get_attribute_node("attribute");
assert!(attr_node_opt.is_some());
let attr_node = attr_node_opt.unwrap();
assert_eq!(attr_node.get_name(), "attribute");
assert_eq!(attr_node.get_type(), Some(NodeType::AttributeNode));
// Set
assert!(child.set_attribute("attribute", "setter_value").is_ok());
assert_eq!(
child.get_attribute("attribute"),
Some("setter_value".to_string())
);
// Remove
assert!(child.remove_attribute("attribute").is_ok());
assert_eq!(child.get_attribute("attribute"), None);
assert_eq!(child.has_attribute("attribute"), false);
// Recount
let attributes = child.get_attributes();
assert_eq!(attributes.len(), 0);
}
#[test]
fn attribute_namespace_accessors() {
let mut doc = Document::new().unwrap();
let element_result = Node::new("example", None, &doc);
assert!(element_result.is_ok());
let mut element = element_result.unwrap();
doc.set_root_element(&element);
let ns_result = Namespace::new(
"myxml",
"http://www.w3.org/XML/1998/namespace",
&mut element,
);
assert!(ns_result.is_ok());
let ns = ns_result.unwrap();
assert!(element.set_attribute_ns("id", "testing", &ns).is_ok());
let id_attr = element.get_attribute_ns("id", "http://www.w3.org/XML/1998/namespace");
assert!(id_attr.is_some());
assert_eq!(id_attr.unwrap(), "testing");
let id_regular = element.get_attribute("id");
assert!(id_regular.is_some());
assert_eq!(id_regular.unwrap(), "testing");
let id_false_ns = element.get_attribute_ns("id", "http://www.foobar.org");
assert!(id_false_ns.is_none());
let fb_ns_result = Namespace::new("fb", "http://www.foobar.org", &mut element);
assert!(fb_ns_result.is_ok());
let fb_ns = fb_ns_result.unwrap();
assert!(element.set_attribute_ns("fb", "fb", &fb_ns).is_ok());
assert_eq!(
element.get_attribute_ns("fb", "http://www.foobar.org"),
Some("fb".to_string())
);
assert!(element
.remove_attribute_ns("fb", "http://www.foobar.org")
.is_ok());
assert_eq!(
element.get_attribute_ns("fb", "http://www.foobar.org"),
None
);
let ns_prefix = element.lookup_namespace_prefix("http://www.w3.org/XML/1998/namespace");
assert_eq!(ns_prefix, Some("xml".to_string())); // system ns has the global prefix when doing global lookup
let fb_prefix = element.lookup_namespace_prefix("http://www.foobar.org");
assert_eq!(fb_prefix, Some("fb".to_string())); // system ns has the global prefix when doing global lookup
let ns_uri = element.lookup_namespace_uri("myxml");
assert_eq!(
ns_uri,
Some("http://www.w3.org/XML/1998/namespace".to_string())
); // system ns has the global uri when doing global lookup
let fb_uri = element.lookup_namespace_uri("fb");
assert_eq!(fb_uri, Some("http://www.foobar.org".to_string())); // system ns has the global prefix when doing global lookup
}
#[test]
fn node_can_unbind() {
let mut doc = Document::new().unwrap();
let element_result = Node::new("example", None, &doc);
assert!(element_result.is_ok());
let mut element = element_result.unwrap();
doc.set_root_element(&element);
let mut first_child = Node::new("first", None, &doc).unwrap();
let mut second_child = Node::new("second", None, &doc).unwrap();
let mut third_child = Node::new("third", None, &doc).unwrap();
assert!(element.add_child(&mut first_child).is_ok());
assert!(element.add_child(&mut second_child).is_ok());
assert!(element.add_child(&mut third_child).is_ok());
assert_eq!(element.get_child_nodes().len(), 3);
first_child.unbind_node();
assert_eq!(element.get_child_nodes().len(), 2);
second_child.unlink_node();
assert_eq!(element.get_child_nodes().len(), 1);
third_child.unlink();
assert_eq!(element.get_child_nodes().len(), 0);
// Test reparenting via unlink
let mut transfer = Node::new("transfer", None, &doc).unwrap();
assert!(element.add_child(&mut transfer).is_ok());
assert!(transfer.append_text("test text").is_ok());
let mut receiver = Node::new("receiver", None, &doc).unwrap();
assert!(element.add_child(&mut receiver).is_ok());
assert_eq!(element.get_child_nodes().len(), 2);
assert_eq!(transfer.get_child_nodes().len(), 1);
assert_eq!(receiver.get_child_nodes().len(), 0);
transfer.unlink();
assert_eq!(element.get_child_nodes().len(), 1);
assert_eq!(receiver.get_child_nodes().len(), 0);
assert!(receiver.add_child(&mut transfer).is_ok());
assert_eq!(receiver.get_child_nodes().len(), 1);
assert_eq!(transfer.get_content(), "test text".to_owned());
assert_eq!(transfer.get_parent(), Some(receiver));
}
#[test]
/// Can mock a node object (useful for defaults that will be overridden)
fn can_mock_node() {
let doc_mock = Document::new().unwrap();
let node_mock = Node::mock(&doc_mock);
assert!(!node_mock.is_text_node());
}
#[test]
/// Can make a mock node hashable
fn can_hash_mock_node() {
let doc_mock = Document::new().unwrap();
let node_mock = Node::mock(&doc_mock);
assert!(node_mock.to_hashable() > 0);
}
#[test]
/// Can make null nodes and documents, to avoid memory allocations
fn can_null_node() {
let null_node = Node::null();
let second_null_node = Node::null();
assert!(null_node.is_null());
assert!(second_null_node.is_null());
assert_eq!(null_node, second_null_node);
}
#[test]
/// Can set and get attributes
fn can_manage_attributes() {
let mut doc = Document::new().unwrap();
let hello_element_result = Node::new("hello", None, &doc);
assert!(hello_element_result.is_ok());
let mut hello_element = hello_element_result.unwrap();
doc.set_root_element(&hello_element);
let key = "examplekey";
let value = "examplevalue";
let pre_value = hello_element.get_attribute(key);
assert_eq!(pre_value, None);
let pre_prop_check = hello_element.has_property(key);
assert_eq!(pre_prop_check, false);
let pre_prop_value = hello_element.get_property(key);
assert_eq!(pre_prop_value, None);
assert!(hello_element.set_attribute(key, value).is_ok());
let new_check = hello_element.has_attribute(key);
assert_eq!(new_check, true);
let new_value = hello_element.get_attribute(key);
assert_eq!(new_value, Some(value.to_owned()));
}
#[test]
/// Can set and get text node content
fn can_set_get_text_node_content() {
let mut doc = Document::new().unwrap();
let hello_element_result = Node::new("hello", None, &doc);
assert!(hello_element_result.is_ok());
let mut hello_element = hello_element_result.unwrap();
doc.set_root_element(&hello_element);
assert!(hello_element.get_content().is_empty());
assert!(hello_element.append_text("hello ").is_ok());
assert_eq!(hello_element.get_content(), "hello ");
assert!(hello_element.append_text("world!").is_ok());
assert_eq!(hello_element.get_content(), "hello world!");
}
#[test]
/// Basic namespace workflow
fn can_work_with_namespaces() {
let mut doc = Document::new().unwrap();
let mut root_node = Node::new("root", None, &doc).unwrap();
doc.set_root_element(&root_node);
let initial_namespace_list = root_node.get_namespaces(&doc);
assert_eq!(initial_namespace_list.len(), 0);
let mock_ns_result = Namespace::new("mock", "http://example.com/ns/mock", &mut root_node);
assert!(mock_ns_result.is_ok());
let second_ns_result = Namespace::new("second", "http://example.com/ns/second", &mut root_node);
assert!(second_ns_result.is_ok());
// try to attach this namespace to a node
assert!(root_node.get_namespace().is_none());
assert!(root_node.set_namespace(&mock_ns_result.unwrap()).is_ok());
let active_ns_opt = root_node.get_namespace();
assert!(active_ns_opt.is_some());
let active_ns = active_ns_opt.unwrap();
assert_eq!(active_ns.get_prefix(), "mock");
assert_eq!(active_ns.get_href(), "http://example.com/ns/mock");
// now get all namespaces for the node and check we have ours
let mut namespace_list = root_node.get_namespaces(&doc);
assert_eq!(namespace_list.len(), 2);
let second_ns = namespace_list.pop().unwrap();
assert_eq!(second_ns.get_prefix(), "second");
assert_eq!(second_ns.get_href(), "http://example.com/ns/second");
let first_ns = namespace_list.pop().unwrap();
assert_eq!(first_ns.get_prefix(), "mock");
assert_eq!(first_ns.get_href(), "http://example.com/ns/mock");
}
#[test]
fn can_work_with_ns_declarations() {
let mut doc = Document::new().unwrap();
let mut root_node = Node::new("root", None, &doc).unwrap();
doc.set_root_element(&root_node);
let mock_ns_result = Namespace::new("mock1", "http://example.com/ns/mock1", &mut root_node);
assert!(mock_ns_result.is_ok());
let second_ns_result = Namespace::new("mock2", "http://example.com/ns/mock2", &mut root_node);
assert!(second_ns_result.is_ok());
let declarations = root_node.get_namespace_declarations();
assert_eq!(declarations.len(), 2);
}
#[test]
/// Can view documents as nodes
fn can_cast_doc_to_node() {
// Setup
let parser = Parser::default();
let doc_result = parser.parse_file("tests/resources/file01.xml");
assert!(doc_result.is_ok());
let doc = doc_result.unwrap();
let doc_node = doc.as_node();
assert_eq!(doc_node.get_type(), Some(NodeType::DocumentNode));
let root_node_opt = doc_node.get_first_child();
assert!(root_node_opt.is_some());
let root_node = root_node_opt.unwrap();
assert_eq!(root_node.get_name(), "root");
}
#[test]
fn can_replace_child() {
let mut doc = Document::new().unwrap();
let mut root_node = Node::new("root", None, &doc).unwrap();
doc.set_root_element(&root_node);
let mut a = Node::new("a", None, &doc).unwrap();
let mut b = Node::new("b", None, &doc).unwrap();
let mut c = Node::new("c", None, &doc).unwrap();
let mut d = Node::new("d", None, &doc).unwrap();
let mut e = Node::new("e", None, &doc).unwrap();
assert!(root_node.add_child(&mut a).is_ok());
assert!(root_node.add_child(&mut b).is_ok());
assert!(root_node.add_child(&mut c).is_ok());
assert!(root_node.add_child(&mut d).is_ok());
assert!(root_node.add_child(&mut e).is_ok());
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
// replace first child with new F
let f = Node::new("F", None, &doc).unwrap();
let a_result = root_node.replace_child_node(f, a);
assert!(a_result.is_ok());
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
// replace last child with new G
let g = Node::new("G", None, &doc).unwrap();
assert!(root_node.replace_child_node(g, e).is_ok());
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
// replace middle child with new H
let h = Node::new("H", None, &doc).unwrap();
assert!(root_node.replace_child_node(h, c).is_ok());
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
// fail to replace a, as it is already removed.
let none = Node::new("none", None, &doc).unwrap();
assert!(root_node
.replace_child_node(none, a_result.unwrap())
.is_err());
// no change.
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
// replacing with self succeeds without change.
assert!(root_node.replace_child_node(b.clone(), b).is_ok());
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
// replacing with parent succeeds without change.
assert!(root_node.replace_child_node(root_node.clone(), d).is_ok());
assert_eq!(
doc.to_string(),
"\n\n",
"document initialized correctly."
);
}