use libxml::parser::Parser;
use libxml::tree::{Document, Node};
#[test]
fn rust_owned_default_is_false() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a/></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
assert!(!root.is_rust_owned());
let a = root.get_first_element_child().expect("a");
assert!(!a.is_rust_owned());
}
#[test]
fn rust_owned_idempotent() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a/></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
let mut a = root.get_first_element_child().expect("a");
a.unlink_node();
a.set_rust_owned();
a.set_rust_owned(); assert!(a.is_rust_owned());
drop(a);
drop(doc);
}
#[test]
fn rust_owned_flag_visible_through_clones() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a/></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
let mut a = root.get_first_element_child().expect("a");
a.unlink_node();
let a_clone1 = a.clone();
let a_clone2 = a.clone();
a_clone1.set_rust_owned();
assert!(a.is_rust_owned());
assert!(a_clone1.is_rust_owned());
assert!(a_clone2.is_rust_owned());
drop(a);
drop(a_clone1);
drop(a_clone2);
drop(doc);
}
#[test]
fn rust_owned_drops_before_source_doc() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a><b/></a></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
let mut a = root.get_first_element_child().expect("a");
a.unlink_node();
a.set_rust_owned();
drop(a);
drop(doc);
}
#[test]
fn rust_owned_after_dup_node_into_new_doc() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a id=\"a1\"><b>hello</b></a><c/></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
let mut a = root.get_first_element_child().expect("a");
a.unlink_node();
let sub = Document::dup_node_into_new_doc(&a).expect("dup");
a.set_rust_owned();
drop(a);
let sub_root = sub.get_root_element().expect("sub root");
assert_eq!(sub_root.get_name(), "a");
let sub_b = sub_root.get_first_element_child().expect("sub b");
assert_eq!(sub_b.get_name(), "b");
assert_eq!(sub_b.get_content(), "hello");
let c = root.get_last_element_child().expect("c");
assert_eq!(c.get_name(), "c");
drop(sub);
drop(doc);
}
#[test]
fn rust_owned_split_extract_stress() {
let parser = Parser::default();
let mut xml = String::from("<book>");
for i in 0..16 {
xml.push_str(&format!(
"<section id=\"s{}\"><h>title {}</h><p>body {}</p></section>",
i, i, i
));
}
xml.push_str("</book>");
let doc = parser.parse_string(xml.as_bytes()).expect("parse");
let root = doc.get_root_element().expect("root");
let mut sections: Vec<Node> = root.get_child_elements();
let mut subdocs: Vec<Document> = Vec::new();
for n in sections.iter_mut() {
n.unlink_node();
let sub = Document::dup_node_into_new_doc(n).expect("dup");
n.set_rust_owned();
subdocs.push(sub);
}
drop(sections);
let root2 = doc.get_root_element().expect("root still there");
assert_eq!(root2.get_name(), "book");
for (i, sub) in subdocs.iter().enumerate() {
let sub_root = sub.get_root_element().expect("sub root");
assert_eq!(sub_root.get_name(), "section");
assert_eq!(
sub_root.get_attribute("id"),
Some(format!("s{}", i))
);
}
drop(subdocs);
drop(doc);
}
#[test]
fn rust_owned_descendant_wrappers_drop_before_parent() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a><b><c/><d/></b><e/></a></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
let mut a = root.get_first_element_child().expect("a");
a.unlink_node();
a.set_rust_owned();
let b = a.get_first_element_child().expect("b");
let c = b.get_first_element_child().expect("c");
let d = c.get_next_element_sibling().expect("d");
let e = a.get_last_element_child().expect("e");
assert_eq!(b.get_name(), "b");
assert_eq!(c.get_name(), "c");
assert_eq!(d.get_name(), "d");
assert_eq!(e.get_name(), "e");
drop(c);
drop(d);
drop(b);
drop(e);
drop(a);
drop(doc);
}
#[test]
fn import_node_rejects_rust_owned_source() {
let parser = Parser::default();
let src = parser
.parse_string("<r><a/></r>".as_bytes())
.expect("parse src");
let mut dest = parser
.parse_string("<root/>".as_bytes())
.expect("parse dest");
let src_root = src.get_root_element().expect("src root");
let mut a = src_root.get_first_element_child().expect("a");
a.unlink_node();
a.set_rust_owned();
let result = dest.import_node(&mut a);
assert!(result.is_err(), "import_node must reject RustOwned source");
assert!(a.is_rust_owned());
drop(a);
drop(dest);
drop(src);
}
#[test]
#[should_panic(expected = "set_rust_owned called on a Linked node")]
#[cfg(debug_assertions)]
fn rust_owned_panics_on_linked_node() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a/></r>".as_bytes())
.expect("parse");
let root = doc.get_root_element().expect("root");
let a = root.get_first_element_child().expect("a");
a.set_rust_owned();
drop(doc);
}
#[test]
#[should_panic(expected = "set_linked called on a RustOwned node")]
#[cfg(debug_assertions)]
fn rust_owned_relink_via_add_child_panics_in_debug() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a/></r>".as_bytes())
.expect("parse");
let mut root = doc.get_root_element().expect("root");
let mut a = root.get_first_element_child().expect("a");
a.unlink_node();
a.set_rust_owned();
let _ = root.add_child(&mut a);
drop(doc);
}
#[test]
fn rust_owned_mixed_with_reattach() {
let parser = Parser::default();
let doc = parser
.parse_string("<r><a/><b/><c/><d/></r>".as_bytes())
.expect("parse");
let mut root = doc.get_root_element().expect("root");
let kids: Vec<Node> = root.get_child_elements();
let mut a = kids[0].clone();
let mut b = kids[1].clone();
let mut c = kids[2].clone();
let mut d = kids[3].clone();
drop(kids);
a.unlink_node();
b.unlink_node();
c.unlink_node();
d.unlink_node();
root.add_child(&mut a).expect("re-attach a");
root.add_child(&mut c).expect("re-attach c");
b.set_rust_owned();
d.set_rust_owned();
drop(b);
drop(d);
let names: Vec<String> = root
.get_child_elements()
.iter()
.map(|n| n.get_name())
.collect();
assert_eq!(names, vec!["a", "c"]);
drop(a);
drop(c);
drop(root);
drop(doc);
}