Files
turnstone/tests/test_pdf.py
T
Patrick Buckley 8e05c10b78 fix(attachments): address PR review feedback (Copilot + code-quality)
- TextDecoder in the text-preview stream now flushes on completion/cancel, so a multibyte UTF-8 char split across a chunk boundary isn't dropped (Copilot).

- send() clears self._wire_part_cache in a finally so the per-send memo (which can hold large rasterized PDF page-images) is released at send end instead of retained on an idle session until the next send (Copilot + fix-review).

- Make the implicit byte-string concatenation in _minimal_pdf explicit (+) in test_pdf.py and test_thumbnails.py so it can't read as a missing comma (CodeQL / github-code-quality).
2026-06-16 00:48:14 -07:00

51 lines
1.8 KiB
Python

"""Tests for core.pdf text extraction (the no-native-PDF wire fallback)."""
from __future__ import annotations
from turnstone.core.pdf import extract_pdf_text, rasterize_pdf
def _minimal_pdf(text: str = "Hello PDF") -> bytes:
"""A valid one-page PDF with a single text line (xref offsets computed)."""
stream = b"BT /F1 24 Tf 20 60 Td (" + text.encode("latin-1") + b") Tj ET"
objs = [
b"<</Type/Catalog/Pages 2 0 R>>",
b"<</Type/Pages/Kids[3 0 R]/Count 1>>",
b"<</Type/Page/Parent 2 0 R/MediaBox[0 0 300 144]"
+ b"/Contents 4 0 R/Resources<</Font<</F1 5 0 R>>>>>>",
b"<</Length %d>>\nstream\n%s\nendstream" % (len(stream), stream),
b"<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>",
]
pdf = b"%PDF-1.4\n"
offsets = []
for i, obj in enumerate(objs, 1):
offsets.append(len(pdf))
pdf += b"%d 0 obj\n%s\nendobj\n" % (i, obj)
xref = len(pdf)
pdf += b"xref\n0 %d\n0000000000 65535 f \n" % (len(objs) + 1)
for off in offsets:
pdf += b"%010d 00000 n \n" % off
pdf += b"trailer\n<</Size %d/Root 1 0 R>>\nstartxref\n%d\n%%%%EOF" % (len(objs) + 1, xref)
return pdf
class TestExtractPdfText:
def test_extracts_text(self) -> None:
assert "Hello PDF" in extract_pdf_text(_minimal_pdf("Hello PDF"))
def test_garbage_returns_empty_no_raise(self) -> None:
assert extract_pdf_text(b"not a pdf at all") == ""
def test_empty_returns_empty(self) -> None:
assert extract_pdf_text(b"") == ""
class TestRasterizePdf:
def test_renders_pages_to_png(self) -> None:
pages = rasterize_pdf(_minimal_pdf("Hello PDF"))
assert len(pages) == 1
assert pages[0][:8] == b"\x89PNG\r\n\x1a\n"
def test_garbage_returns_empty_no_raise(self) -> None:
assert rasterize_pdf(b"not a pdf at all") == []