sabaridsnfuji's picture
download
raw
8.65 kB
"""verify-final tests: --canvas vs --from-html mutual-exclusion +
missing-input behaviour, plus pdfinfo parsing / dimension-and-rotation
logic via a monkeypatched pdfinfo (no Poppler needed). The end-to-end
pdfinfo round-trip on a real PDF is covered by a Poppler-gated
integration test against the hello_world example."""
from __future__ import annotations
import argparse
import shutil
import pytest
from _posterly import verify_final
def _args(**over):
base = argparse.Namespace(
pdf="nonexistent.pdf",
canvas=None,
from_html=None,
dim_tol_in=0.05,
max_size_mb=20.0,
allow_rotated=False,
)
for k, v in over.items():
setattr(base, k, v)
return base
def test_missing_pdf_returns_2(tmp_path) -> None:
rc = verify_final.cmd_verify_final(_args(pdf=str(tmp_path / "missing.pdf")))
assert rc == 2
def test_missing_pdf_unicode_path_stays_ascii(tmp_path, capsys) -> None:
"""Round-13: a PDF under a Unicode directory must not leak non-ASCII
into the not-found error (Windows cmd / CI logs mojibake)."""
d = tmp_path / "张三" # Unicode dir
d.mkdir()
rc = verify_final.cmd_verify_final(_args(pdf=str(d / "missing.pdf")))
capsys.readouterr().err.encode("ascii") # raises if path leaked
assert rc == 2
def test_neither_canvas_nor_from_html_returns_2(tmp_path) -> None:
"""The old default was --canvas=60x36in, which silently passed
a 24x36in poster as wrong-sized. Now both are None → exit 2 with a
clear message."""
pdf = tmp_path / "x.pdf"
pdf.write_bytes(b"not really a pdf")
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf)))
assert rc == 2
def test_both_canvas_and_from_html_returns_2(tmp_path) -> None:
"""Mutually exclusive — supplying both should fail-fast rather
than silently preferring one."""
pdf = tmp_path / "x.pdf"
pdf.write_bytes(b"not really a pdf")
html = tmp_path / "y.html"
html.write_text(
"<html><head><style>@page { size: 36in 47in }</style>"
"</head></html>", encoding="utf-8",
)
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), canvas=(36.0, 47.0), from_html=str(html))
)
assert rc == 2
def test_from_html_missing_path_returns_2(tmp_path) -> None:
pdf = tmp_path / "x.pdf"
pdf.write_bytes(b"not really a pdf")
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), from_html=str(tmp_path / "missing.html"))
)
assert rc == 2
def test_from_html_with_no_page_returns_2(tmp_path) -> None:
"""When --from-html points to a file without an @page rule, fail
cleanly rather than silently fall back to a default canvas."""
pdf = tmp_path / "x.pdf"
pdf.write_bytes(b"not really a pdf")
html = tmp_path / "y.html"
html.write_text("<html><body>no @page here</body></html>",
encoding="utf-8")
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), from_html=str(html))
)
assert rc == 2
# --- pdfinfo parsing / dimension comparison (monkeypatched, no Poppler) ---
def _pdfinfo(pages=1, w_pts=1728.0, h_pts=2592.0, rot=0):
"""Canned `pdfinfo` stdout. 1728x2592 pts == 24x36 in."""
return (
f"Pages: {pages}\n"
f"Page size: {w_pts} x {h_pts} pts\n"
f"Page rot: {rot}\n"
)
def _real_pdf(tmp_path, nbytes=1024):
pdf = tmp_path / "poster.pdf"
pdf.write_bytes(b"%PDF-1.7\n" + b"0" * max(0, nbytes - 9))
return pdf
def _patch_pdfinfo(monkeypatch, text=None, exc=None):
def fake(*a, **k):
if exc is not None:
raise exc
return text
monkeypatch.setattr(verify_final.subprocess, "check_output", fake)
def test_from_html_unicode_basename_output_ascii(
tmp_path, monkeypatch, capsys
) -> None:
"""Round-13: the `(from --from-html (<name>))` label must stay ASCII
even when the HTML basename is Unicode (it leaked through `src`)."""
pdf = _real_pdf(tmp_path)
html = tmp_path / "张三.html" # Unicode basename
html.write_text(
"<html><head><style>@page { size: 24in 36in }</style></head></html>",
encoding="utf-8",
)
_patch_pdfinfo(monkeypatch, text=_pdfinfo(w_pts=1728.0, h_pts=2592.0))
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), from_html=str(html))
)
capsys.readouterr().out.encode("ascii") # raises if basename leaked
assert rc == 0
def test_correct_dimensions_pass(tmp_path, monkeypatch) -> None:
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo()) # 24x36in, 1 page, rot 0
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 0
def test_dimension_mismatch_fails(tmp_path, monkeypatch) -> None:
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo(h_pts=2000.0)) # wrong height
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 1
def test_swapped_dims_rejected_without_rotation(tmp_path, monkeypatch) -> None:
"""36x24 PDF vs 24x36 canvas, page rot 0, no --allow-rotated → FAIL."""
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo(w_pts=2592.0, h_pts=1728.0))
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 1
def test_swapped_dims_accepted_with_allow_rotated(tmp_path, monkeypatch) -> None:
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo(w_pts=2592.0, h_pts=1728.0))
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), canvas=(24.0, 36.0), allow_rotated=True)
)
assert rc == 0
def test_swapped_dims_accepted_when_page_rotated(tmp_path, monkeypatch) -> None:
"""Page rot 90 legitimizes the swap even without --allow-rotated."""
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo(w_pts=2592.0, h_pts=1728.0, rot=90))
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 0
def test_wrong_page_count_fails(tmp_path, monkeypatch) -> None:
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo(pages=2))
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 1
def test_oversize_file_fails(tmp_path, monkeypatch) -> None:
"""Dimensions correct but file over --max-size-mb → FAIL."""
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo())
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), canvas=(24.0, 36.0), max_size_mb=0.0)
)
assert rc == 1
def test_unparseable_page_size_fails(tmp_path, monkeypatch) -> None:
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(
monkeypatch,
"Pages: 1\nPage size: letter\nPage rot: 0\n",
)
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 1
def test_pdfinfo_missing_returns_2(tmp_path, monkeypatch) -> None:
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, exc=FileNotFoundError("pdfinfo"))
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 2
def test_failure_output_is_ascii(tmp_path, monkeypatch, capsys) -> None:
"""Round-8: runtime stdout/stderr on a FAIL must be ASCII-clean
(no +/-, x, deg, -> mojibake when pasted into CI logs / issues)."""
pdf = _real_pdf(tmp_path)
_patch_pdfinfo(monkeypatch, _pdfinfo(w_pts=2592.0, h_pts=1728.0))
rc = verify_final.cmd_verify_final(_args(pdf=str(pdf), canvas=(24.0, 36.0)))
assert rc == 1
out = capsys.readouterr()
(out.out + out.err).encode("ascii") # raises UnicodeEncodeError if not
@pytest.mark.skipif(
shutil.which("pdfinfo") is None,
reason="poppler/pdfinfo not installed",
)
def test_hello_world_pdf_real_pdfinfo() -> None:
"""Round-10: exercise the REAL pdfinfo round-trip on the shipped
example PDF (no monkeypatch) — this is the integration coverage the
README/docstring refer to. Skipped when poppler is absent."""
from pathlib import Path
root = Path(__file__).resolve().parent.parent
pdf = root / "examples" / "hello_world" / "poster_preview.pdf"
html = root / "examples" / "hello_world" / "poster.html"
if not pdf.exists():
pytest.skip(
"example PDF is a gitignored build artifact -- run the "
"hello_world render step to generate it"
)
assert html.exists(), f"example HTML missing at {html}"
rc = verify_final.cmd_verify_final(
_args(pdf=str(pdf), from_html=str(html))
)
assert rc == 0

Xet Storage Details

Size:
8.65 kB
·
Xet hash:
b84fe7f88e126725b416e01712bb79d86a9f6d2fc04725d60c27ef7bdcb94b20

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.