use crate::abi::structs::*;
use crate::abi::types::xmlChar;
use crate::xml::parser::helpers;
use core::ptr;
unsafe fn parse_bytes(bytes: &[u8]) -> *mut _xmlDoc {
let ctxt = helpers::create_parser_ctxt();
assert!(!ctxt.is_null(), "parser context should not be null");
let input = helpers::input_from_memory(bytes.as_ptr() as *const i8, bytes.len() as i32);
helpers::setup_parser_input(ctxt, input);
let ret = helpers::parse_document(ctxt);
let doc = (*ctxt).myDoc;
helpers::free_parser_ctxt(ctxt);
if ret != 0 {
return ptr::null_mut();
}
doc
}
#[test]
fn test_parse_empty_document() {
unsafe {
let xml = b"<?xml version=\"1.0\"?>\n<root/>\n";
let doc = parse_bytes(xml);
assert!(!doc.is_null(), "should parse empty doc");
assert!(
(*doc).children != ptr::null_mut(),
"should have root element"
);
let root = (*doc).children;
assert_eq!(
(*root).type_,
crate::abi::types::xmlElementType::XML_ELEMENT_NODE as i32
);
let name = crate::xml::string::xmlstr_to_bytes((*root).name as *const xmlChar);
assert_eq!(name, b"root");
}
}
#[test]
fn test_parse_element_with_text() {
unsafe {
let xml = b"<?xml version=\"1.0\"?>\n<root>Hello, World!</root>\n";
let doc = parse_bytes(xml);
assert!(!doc.is_null(), "should parse doc with text");
let root = (*doc).children;
assert!(!root.is_null());
let text = (*root).children;
assert!(!text.is_null(), "root should have text child");
assert_eq!(
(*text).type_,
crate::abi::types::xmlElementType::XML_TEXT_NODE as i32
);
let content = crate::xml::string::xmlstr_to_bytes((*text).content as *const xmlChar);
assert_eq!(content, b"Hello, World!");
}
}
#[test]
fn test_parse_element_with_attributes() {
unsafe {
let xml = b"<root id=\"123\" name=\"test\"/>";
let doc = parse_bytes(xml);
assert!(!doc.is_null(), "should parse doc with attributes");
let root = (*doc).children;
assert!(!root.is_null());
let attr = (*root).properties;
assert!(!attr.is_null(), "root should have attributes");
let attr_name = crate::xml::string::xmlstr_to_bytes((*attr).name as *const xmlChar);
assert_eq!(attr_name, b"id");
let attr_val =
crate::xml::string::xmlstr_to_bytes((*(*attr).children).content as *const xmlChar);
assert_eq!(attr_val, b"123");
let attr2 = (*attr).next as *mut _xmlAttr;
assert!(!attr2.is_null(), "should have second attribute");
let attr2_name = crate::xml::string::xmlstr_to_bytes((*attr2).name as *const xmlChar);
assert_eq!(attr2_name, b"name");
let attr2_val =
crate::xml::string::xmlstr_to_bytes((*(*attr2).children).content as *const xmlChar);
assert_eq!(attr2_val, b"test");
}
}
#[test]
fn test_parse_nested_elements() {
unsafe {
let xml = b"<root><child1><grandchild/></child1><child2/></root>";
let doc = parse_bytes(xml);
assert!(!doc.is_null());
let root = (*doc).children;
assert!(!root.is_null());
let name = crate::xml::string::xmlstr_to_bytes((*root).name as *const xmlChar);
assert_eq!(name, b"root");
let child1 = (*root).children;
assert!(!child1.is_null());
let child1_name = crate::xml::string::xmlstr_to_bytes((*child1).name as *const xmlChar);
assert_eq!(child1_name, b"child1");
let grandchild = (*child1).children;
assert!(!grandchild.is_null(), "child1 should have grandchild");
let grandchild_name =
crate::xml::string::xmlstr_to_bytes((*grandchild).name as *const xmlChar);
assert_eq!(grandchild_name, b"grandchild");
let child2 = (*child1).next;
assert!(!child2.is_null(), "should have child2 sibling");
let child2_name = crate::xml::string::xmlstr_to_bytes((*child2).name as *const xmlChar);
assert_eq!(child2_name, b"child2");
}
}
#[test]
fn test_parse_comments() {
unsafe {
let xml = b"<root><!-- this is a comment --></root>";
let doc = parse_bytes(xml);
assert!(!doc.is_null());
let root = (*doc).children;
assert!(!root.is_null());
let comment = (*root).children;
assert!(!comment.is_null());
assert_eq!(
(*comment).type_,
crate::abi::types::xmlElementType::XML_COMMENT_NODE as i32
);
let content = crate::xml::string::xmlstr_to_bytes((*comment).content as *const xmlChar);
assert_eq!(content, b" this is a comment ");
}
}
#[test]
fn test_parse_processing_instruction() {
unsafe {
let xml = b"<?mypi data?><root/>";
let doc = parse_bytes(xml);
assert!(!doc.is_null());
let pi = (*doc).children;
assert!(!pi.is_null());
if (*pi).type_ == crate::abi::types::xmlElementType::XML_PI_NODE as i32 {
let content = crate::xml::string::xmlstr_to_bytes((*pi).content as *const xmlChar);
assert_eq!(content, b"data");
}
}
}
#[test]
fn test_parse_with_entities() {
unsafe {
let xml = b"<root>AT&T</root>";
let doc = parse_bytes(xml);
assert!(!doc.is_null());
let root = (*doc).children;
assert!(!root.is_null());
let text = (*root).children;
assert!(!text.is_null());
if (*text).type_ == crate::abi::types::xmlElementType::XML_TEXT_NODE as i32 {
let content = crate::xml::string::xmlstr_to_bytes((*text).content as *const xmlChar);
assert!(!content.is_empty());
}
}
}
#[test]
fn test_parse_cdata_section() {
unsafe {
let xml = b"<root><![CDATA[Hello <world>]]></root>";
let doc = parse_bytes(xml);
assert!(!doc.is_null());
let root = (*doc).children;
assert!(!root.is_null());
let cdata = (*root).children;
assert!(!cdata.is_null());
assert!(
(*cdata).type_ == crate::abi::types::xmlElementType::XML_CDATA_SECTION_NODE as i32
|| (*cdata).type_ == crate::abi::types::xmlElementType::XML_TEXT_NODE as i32,
"CDATA should be CDATA or text node"
);
}
}
#[test]
fn test_parse_xml_declaration() {
unsafe {
let xml = b"<?xml version=\"1.0\" encoding=\"UTF-8\"?><root/>";
let doc = parse_bytes(xml);
assert!(!doc.is_null(), "should parse with XML declaration");
let version = crate::xml::string::xmlstr_to_bytes((*doc).version as *const xmlChar);
assert_eq!(version, b"1.0");
let encoding = crate::xml::string::xmlstr_to_bytes((*doc).encoding as *const xmlChar);
assert_eq!(encoding, b"UTF-8");
}
}
#[test]
fn test_parse_invalid_xml() {
unsafe {
let xml = b"<root><child>";
let ctxt = helpers::create_parser_ctxt();
assert!(!ctxt.is_null());
let input = helpers::input_from_memory(xml.as_ptr() as *const i8, xml.len() as i32);
helpers::setup_parser_input(ctxt, input);
let ret = helpers::parse_document(ctxt);
let doc = (*ctxt).myDoc;
helpers::free_parser_ctxt(ctxt);
if !doc.is_null() {
assert!(
!doc.is_null(),
"even partial doc should not be null if wellFormed"
);
}
}
}
#[test]
fn test_xml_read_memory_export() {
unsafe {
let xml = b"<root attr=\"val\"/>";
let doc = crate::abi::exports_xml2::xmlReadMemory(
xml.as_ptr() as *const i8,
xml.len() as i32,
core::ptr::null(),
core::ptr::null(),
0,
);
assert!(!doc.is_null(), "xmlReadMemory should return a doc");
let root = (*doc).children;
assert!(!root.is_null());
let name = crate::xml::string::xmlstr_to_bytes((*root).name as *const xmlChar);
assert_eq!(name, b"root");
let attr = (*root).properties;
assert!(!attr.is_null());
let attr_name = crate::xml::string::xmlstr_to_bytes((*attr).name as *const xmlChar);
assert_eq!(attr_name, b"attr");
let attr_val =
crate::xml::string::xmlstr_to_bytes((*(*attr).children).content as *const xmlChar);
assert_eq!(attr_val, b"val");
}
}