use stet::{ExecWarningKind, Interpreter};
const NO_SHOWPAGE: &[u8] = b"%!PS-Adobe-3.0\n0 0 1 setrgbcolor 20 20 100 100 rectfill\n";
const WITH_SHOWPAGE: &[u8] =
b"%!PS-Adobe-3.0\n0 0 1 setrgbcolor 20 20 100 100 rectfill\nshowpage\n";
const TRAILING_PAGE: &[u8] = b"%!PS-Adobe-3.0\n\
0 0 1 setrgbcolor 20 20 100 100 rectfill showpage\n\
1 0 0 setrgbcolor 20 20 100 100 rectfill\n";
fn dropped(interp: &Interpreter) -> Option<(usize, i32)> {
interp.warnings().iter().find_map(|w| match w.kind {
ExecWarningKind::DroppedFinalPage {
objects,
pages_emitted,
} => Some((objects, pages_emitted)),
_ => None,
})
}
#[test]
fn missing_showpage_yields_no_pages_and_a_warning() {
let mut interp = Interpreter::new();
let pages = interp.render_to_display_list(NO_SHOWPAGE, 72.0).unwrap();
assert!(pages.is_empty(), "a program with no showpage emits no page");
let (objects, pages_emitted) = dropped(&interp).expect("expected a DroppedFinalPage warning");
assert!(objects > 0, "the discarded page had marks on it");
assert_eq!(pages_emitted, 0, "nothing was emitted before the drop");
}
#[test]
fn nulldevice_suppresses_the_dropped_page_warning() {
let mut interp = Interpreter::new();
let src = b"%!PS-Adobe-3.0\nnulldevice\n0 0 1 setrgbcolor 20 20 100 100 rectfill\n";
let _ = interp.render_to_display_list(src, 72.0).unwrap();
assert!(
interp.warnings().is_empty(),
"a nulldevice program must not warn: {:?}",
interp.warnings()
);
}
#[test]
fn nulldevice_suppression_survives_grestore() {
let mut interp = Interpreter::new();
let src =
b"%!PS-Adobe-3.0\ngsave nulldevice\n0 0 1 setrgbcolor 20 20 100 100 rectfill\ngrestore\n";
let _ = interp.render_to_display_list(src, 72.0).unwrap();
assert!(
interp.warnings().is_empty(),
"grestore must not resurrect the warning: {:?}",
interp.warnings()
);
}
#[test]
fn nulldevice_suppression_does_not_leak_to_the_next_render() {
let mut interp = Interpreter::new();
let nulled = b"%!PS-Adobe-3.0\nnulldevice\n0 0 1 setrgbcolor 20 20 100 100 rectfill\n";
let _ = interp.render_to_display_list(nulled, 72.0).unwrap();
assert!(interp.warnings().is_empty());
let _ = interp.render_to_display_list(NO_SHOWPAGE, 72.0).unwrap();
assert!(
dropped(&interp).is_some(),
"the nulldevice flag must reset per render call"
);
}
#[test]
fn proper_showpage_is_silent() {
let mut interp = Interpreter::new();
let pages = interp.render_to_display_list(WITH_SHOWPAGE, 72.0).unwrap();
assert_eq!(pages.len(), 1);
assert!(
interp.warnings().is_empty(),
"a well-formed program must not warn: {:?}",
interp.warnings()
);
}
#[test]
fn trailing_marks_after_a_showpage_report_the_earlier_pages() {
let mut interp = Interpreter::new();
let pages = interp.render_to_display_list(TRAILING_PAGE, 72.0).unwrap();
assert_eq!(pages.len(), 1, "only the shown page comes out");
let (_, pages_emitted) = dropped(&interp).expect("expected a DroppedFinalPage warning");
assert_eq!(
pages_emitted, 1,
"the message must distinguish partial loss from total loss"
);
}
#[test]
fn warnings_are_cleared_between_calls() {
let mut interp = Interpreter::new();
let _ = interp.render_to_display_list(NO_SHOWPAGE, 72.0).unwrap();
assert!(dropped(&interp).is_some());
let _ = interp.render_to_display_list(WITH_SHOWPAGE, 72.0).unwrap();
assert!(
interp.warnings().is_empty(),
"warnings describe the latest call only: {:?}",
interp.warnings()
);
}
#[test]
fn eps_gets_an_implicit_showpage_and_does_not_warn() {
let mut interp = Interpreter::new();
let eps = b"%!PS-Adobe-3.0 EPSF-3.0\n\
%%BoundingBox: 0 0 200 200\n\
%%EndComments\n\
0 0 1 setrgbcolor 20 20 100 100 rectfill\n";
let pages = interp.render_to_display_list(eps, 72.0).unwrap();
assert_eq!(pages.len(), 1, "EPS renders without an explicit showpage");
assert!(
interp.warnings().is_empty(),
"the implicit showpage means nothing was dropped: {:?}",
interp.warnings()
);
}
#[cfg(feature = "render")]
#[test]
fn render_surfaces_the_warning_too() {
let mut interp = Interpreter::new();
let pages = interp.render(NO_SHOWPAGE, 72.0).unwrap();
assert!(pages.is_empty());
assert!(
dropped(&interp).is_some(),
"render() delegates to render_to_display_list, so it must warn as well"
);
}
#[cfg(feature = "pdf-output")]
#[test]
fn pdf_output_warns_on_a_dropped_page() {
let mut interp = Interpreter::new();
let _ = interp.render_to_pdf(NO_SHOWPAGE, 72.0).unwrap();
assert!(
dropped(&interp).is_some(),
"the PDF path drops the final page the same way the raster path does"
);
}