use super::*;
use ResolveResult::*;
#[test]
fn qname_decompose() {
let q = QName(b"pre:local");
assert_eq!(q.prefix().map(|p| p.into_inner()), Some(&b"pre"[..]));
assert_eq!(q.local_name().into_inner(), b"local");
let (local, prefix) = q.decompose();
assert_eq!(local.into_inner(), b"local");
assert_eq!(prefix.map(|p| p.into_inner()), Some(&b"pre"[..]));
let plain = QName(b"local");
assert_eq!(plain.prefix(), None);
assert_eq!(plain.local_name().into_inner(), b"local");
}
#[test]
fn prefix_special() {
assert!(QName(b"xml:lang").prefix().expect("prefix").is_xml());
assert!(QName(b"xmlns:a").prefix().expect("prefix").is_xmlns());
assert!(!QName(b"other:a").prefix().expect("prefix").is_xml());
}
#[test]
fn namespace_binding_detection() {
assert_eq!(
QName(b"xmlns").as_namespace_binding(),
Some(PrefixDeclaration::Default)
);
assert_eq!(
QName(b"xmlns:p").as_namespace_binding(),
Some(PrefixDeclaration::Named(b"p"))
);
assert_eq!(QName(b"xmlnsx").as_namespace_binding(), None);
assert_eq!(QName(b"other").as_namespace_binding(), None);
}
#[test]
fn resolve_element_vs_attribute() -> Result<(), NamespaceError> {
let mut resolver = NamespaceResolver::default();
resolver.push(&BytesStart::from_content(
"e xmlns=\"default\" xmlns:p=\"urn:p\"",
1,
))?;
assert_eq!(
resolver.resolve_element(QName(b"name")).0,
Bound(Namespace(b"default"))
);
assert_eq!(resolver.resolve_attribute(QName(b"name")).0, Unbound);
assert_eq!(
resolver.resolve_element(QName(b"p:name")).0,
Bound(Namespace(b"urn:p"))
);
assert_eq!(
resolver.resolve_attribute(QName(b"p:name")).0,
Bound(Namespace(b"urn:p"))
);
assert_eq!(
resolver.resolve_element(QName(b"q:name")).0,
Unknown(b"q".to_vec())
);
Ok(())
}
#[test]
fn scoping_push_pop() -> Result<(), NamespaceError> {
let mut resolver = NamespaceResolver::default();
resolver.push(&BytesStart::from_content("a xmlns=\"a1\"", 1))?;
assert_eq!(
resolver.resolve_element(QName(b"x")).0,
Bound(Namespace(b"a1"))
);
resolver.push(&BytesStart::from_content("b xmlns=\"b1\"", 1))?;
assert_eq!(
resolver.resolve_element(QName(b"x")).0,
Bound(Namespace(b"b1"))
);
resolver.pop();
assert_eq!(
resolver.resolve_element(QName(b"x")).0,
Bound(Namespace(b"a1"))
);
resolver.pop();
assert_eq!(resolver.resolve_element(QName(b"x")).0, Unbound);
Ok(())
}
#[test]
fn undeclaring_default() -> Result<(), NamespaceError> {
let mut resolver = NamespaceResolver::default();
resolver.add(PrefixDeclaration::Default, Namespace(b"ns"))?;
assert_eq!(
resolver.resolve_element(QName(b"x")).0,
Bound(Namespace(b"ns"))
);
resolver.add(PrefixDeclaration::Default, Namespace(b""))?;
assert_eq!(resolver.resolve_element(QName(b"x")).0, Unbound);
Ok(())
}
#[test]
fn reserved_prefix_rules() {
let mut resolver = NamespaceResolver::default();
assert!(
resolver
.add(PrefixDeclaration::Named(b"xml"), Namespace(b"other"))
.is_err()
);
assert!(
resolver
.add(
PrefixDeclaration::Named(b"xml"),
Namespace(b"http://www.w3.org/XML/1998/namespace")
)
.is_ok()
);
assert!(
resolver
.add(PrefixDeclaration::Named(b"xmlns"), Namespace(b"x"))
.is_err()
);
assert!(matches!(
resolver.add(
PrefixDeclaration::Named(b"p"),
Namespace(b"http://www.w3.org/XML/1998/namespace")
),
Err(NamespaceError::InvalidPrefixForXml(_))
));
}
#[test]
fn xml_prefix_predefined() {
let resolver = NamespaceResolver::default();
assert_eq!(
resolver.resolve_element(QName(b"xml:lang")).0,
Bound(Namespace(b"http://www.w3.org/XML/1998/namespace"))
);
}
#[test]
fn too_many_declarations() {
let mut resolver = NamespaceResolver::default();
resolver.set_max_declarations_per_element(2);
assert_eq!(
resolver.push(&BytesStart::from_content(
"e xmlns:a='' xmlns:b='' xmlns:c=''",
1
)),
Err(NamespaceError::TooManyDeclarations(2))
);
}
#[test]
fn resolve_result_try_into() {
let bound: Result<Option<Namespace>, _> = ResolveResult::Bound(Namespace(b"n")).try_into();
assert_eq!(bound, Ok(Some(Namespace(b"n"))));
let unbound: Result<Option<Namespace>, _> = ResolveResult::Unbound.try_into();
assert_eq!(unbound, Ok(None));
let unknown: Result<Option<Namespace>, _> = ResolveResult::Unknown(b"p".to_vec()).try_into();
assert_eq!(unknown, Err(NamespaceError::UnknownPrefix(b"p".to_vec())));
}
#[test]
fn resolve_event_only_element_events() {
let resolver = NamespaceResolver::default();
let (res, _) = resolver.resolve_event(Event::Text(crate::events::BytesText::new("hi")));
assert_eq!(res, ResolveResult::Unbound);
}
#[test]
fn push_past_usize_max_reports_an_error_instead_of_overflowing() {
let mut resolver = NamespaceResolver::default();
resolver.set_level(usize::MAX);
assert_eq!(resolver.level(), usize::MAX);
assert_eq!(
resolver.push(&BytesStart::from_content("e xmlns=\"ns\"", 1)),
Err(NamespaceError::TooDeeplyNested(usize::MAX)),
);
}
#[test]
fn deep_nesting_beyond_former_u16_bound_does_not_corrupt_resolution() {
let mut resolver = NamespaceResolver::default();
let depth: usize = 70_000;
for i in 0..depth {
let content = format!("e xmlns:p=\"urn:ns{i}\"");
resolver
.push(&BytesStart::from_content(content, 1))
.expect("push below any configured limit must succeed");
}
assert_eq!(resolver.level(), depth);
assert_eq!(
resolver.resolve_element(QName(b"p:x")).0,
Bound(Namespace(format!("urn:ns{}", depth - 1).as_bytes())),
);
for _ in 0..depth {
resolver.pop();
}
assert_eq!(resolver.level(), 0);
assert_eq!(
resolver.resolve_element(QName(b"p:x")).0,
Unknown(b"p".to_vec())
);
}