mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-03 01:00:48 +00:00
print: the live driver test compares the vendor prefixes instead of re-running respell
Review follow-up. The test asserted `respell(validated, driver_default) == None`. respell also returns None when it refuses a ticket, and in_drivers_spelling then keeps the ticket as it is, so a ticket still spelled `ns0000` passed. The test now compares the vendor namespace declarations of the ticket driver_ticket returns with those of the driver's own default ticket and fails when a namespace the driver declares is under another prefix. The comparison is `ticket::prefixes_unlike_the_drivers` (test-only), unit-tested here: it flags the ticket as the merge returns it, passes the respelled one and the driver's own, and flags a ticket respell refused, where `respell(..) == None` can't tell it from a correct one. Checked against a Brother HL-L2390DW: the test passes, and fails with `(brother namespace, "ns0000", "brpsk")` when in_drivers_spelling is made to return the merged ticket. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQ5PzHVUcntEHU97zniM5U
This commit is contained in:
2 files changed
+62
-1
No files matched your search
@@ -376,6 +376,29 @@ pub(crate) fn respell(ticket: &str, driver: &str) -> Option<String> {
|
||||
(now == wanted && prefixes_resolve(&check)).then_some(out)
|
||||
}
|
||||
|
||||
/// Each vendor namespace that `ticket` declares under a prefix the driver does not declare it with,
|
||||
/// as (namespace, prefix in the ticket, prefix of the driver); empty when the ticket is spelled the
|
||||
/// way the driver spells it. `driver` is the driver's own ticket ([`empty_ticket`] validated).
|
||||
/// `None` when either does not parse.
|
||||
///
|
||||
/// For checking the ticket a job ends up with. [`respell`] returning `None` for it does not: that
|
||||
/// is also what it returns when it refused to change a ticket, which then stays as it is.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn prefixes_unlike_the_drivers(ticket: &str, driver: &str) -> Option<Vec<(String, String, String)>> {
|
||||
let own = vendor_prefixes(&roxmltree::Document::parse(driver).ok()?);
|
||||
let declared = vendor_prefixes(&roxmltree::Document::parse(ticket).ok()?);
|
||||
Some(
|
||||
declared
|
||||
.into_iter()
|
||||
.filter(|pair| !own.contains(pair))
|
||||
.filter_map(|(prefix, uri)| {
|
||||
let (theirs, _) = own.iter().find(|(_, u)| *u == uri)?;
|
||||
Some((uri, prefix, theirs.clone()))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// The widest unprintable margin of the paper, in micrometres, from PrintCapabilities computed
|
||||
/// for the job's ticket (`PageImageableSize`). The largest of the four, so content centred inside
|
||||
/// it is clear of every edge whichever way the driver measures. `None` when the driver doesn't say.
|
||||
@@ -552,6 +575,41 @@ mod tests {
|
||||
assert_eq!(refused("<psf:Feature brpsk:flag=\"1\"/>"), None, "attribute");
|
||||
}
|
||||
|
||||
/// What the live driver test checks. A ticket `respell` refused keeps the prefix the merge gave
|
||||
/// it, but `respell` says `None` for it, as it does for a ticket that is already right: only the
|
||||
/// prefixes tell the two apart.
|
||||
#[test]
|
||||
fn the_prefixes_tell_a_refused_ticket_from_one_in_the_drivers_spelling() {
|
||||
let driver = brother("brpsk");
|
||||
let unlike = |ticket: &str| prefixes_unlike_the_drivers(ticket, &driver).expect("both tickets parse");
|
||||
let merged = brother("ns0000");
|
||||
let mismatch = (BROTHER.to_string(), "ns0000".to_string(), "brpsk".to_string());
|
||||
|
||||
assert_eq!(unlike(&merged), std::slice::from_ref(&mismatch), "as the merge returns it");
|
||||
assert_eq!(unlike(&respell(&merged, &driver).unwrap()), [], "respelled");
|
||||
assert_eq!(unlike(&driver), [], "already the driver's");
|
||||
|
||||
// `respell` refuses this one (`ns0000` is declared again below the root), so it stays as the
|
||||
// merge left it, and `respell` says `None` for it just as it does for the driver's own.
|
||||
let refused = merged.replace(
|
||||
"<psf:Feature name=\"ns0000:JobPrintSpeed\">",
|
||||
"<psf:Feature name=\"ns0000:JobPrintSpeed\" xmlns:ns0000=\"http://example.com/nested\">",
|
||||
);
|
||||
assert_ne!(refused, merged);
|
||||
assert_eq!(respell(&refused, &driver), None);
|
||||
assert_eq!(respell(&driver, &driver), None);
|
||||
assert_eq!(unlike(&refused), [mismatch], "refused, and still wrong");
|
||||
|
||||
// Two namespaces that trade prefixes are both reported.
|
||||
let traded = prefixes_unlike_the_drivers(&two_namespaces("ns0000", "ns0001", ""), &two_namespaces("ns0001", "ns0000", "")).unwrap();
|
||||
assert_eq!(traded.len(), 2, "{traded:?}");
|
||||
// A namespace the driver doesn't declare has no prefix of the driver's to differ from.
|
||||
assert_eq!(unlike(&empty_ticket()), [], "no vendor namespace to compare");
|
||||
assert_eq!(unlike(&two_namespaces("ns0000", "ns0001", "")).len(), 1, "only BROTHER is the driver's");
|
||||
assert_eq!(prefixes_unlike_the_drivers("<not xml", &driver), None);
|
||||
assert_eq!(prefixes_unlike_the_drivers(&merged, "<not xml"), None);
|
||||
}
|
||||
|
||||
/// Only names in a namespace whose prefix changes block the respelling.
|
||||
#[test]
|
||||
fn names_in_a_namespace_that_keeps_its_prefix_do_not_block_the_respelling() {
|
||||
|
||||
@@ -217,10 +217,13 @@ mod tests {
|
||||
ticket::verify_job_options(std::str::from_utf8(ticket.get_xml()).unwrap(), &job, 1).unwrap();
|
||||
assert_eq!(paper, (215_900, 279_400));
|
||||
// The ticket names the driver's vendor namespaces as the driver does (the merge renamed them).
|
||||
// `respell` returning `None` would not show it: it also does when it refused the ticket.
|
||||
let mut own = PrintTicketBuilder::new(&device).unwrap();
|
||||
own.merge(PrintTicket::from_xml(ticket::empty_ticket())).unwrap();
|
||||
let own = own.build().unwrap();
|
||||
assert_eq!(ticket::respell(std::str::from_utf8(ticket.get_xml()).unwrap(), std::str::from_utf8(own.get_xml()).unwrap()), None);
|
||||
let unlike =
|
||||
ticket::prefixes_unlike_the_drivers(std::str::from_utf8(ticket.get_xml()).unwrap(), std::str::from_utf8(own.get_xml()).unwrap()).unwrap();
|
||||
assert!(unlike.is_empty(), "vendor namespaces under another prefix than the driver's (namespace, ticket, driver): {unlike:?}");
|
||||
eprintln!("unprintable margin: {} pt", imageable_margin(&device, &ticket));
|
||||
if let Ok(path) = std::env::var("CRAFT_PRINT_TEST_TICKET_OUTPUT") {
|
||||
std::fs::write(path, ticket.get_xml()).unwrap();
|
||||
|
||||
Reference in new issue
Block a user