pdforacle

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2026 License: MPL-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package pdforacle judges PDF output with programs that share no code with the PDF library under test: qpdf's JSON dump and checker for structure, Poppler's pdftotext for page text, and pdfinfo and pdftoppm for geometry. It deliberately does not import pdfcpu or the engine.

A Document is the structure of one file; Verify compares it with an Expectation written from the inputs (source page markers, link graphs, geometry) and returns the checks that failed. A test that should detect corruption is a negative control: it feeds Verify a wrong Expectation and requires the matching check to fail.

Index

Constants

View Source
const (
	CheckStructure         = "qpdf-check"
	CheckPageCount         = "page-count"
	CheckPageText          = "page-text-order"
	CheckDistinctPages     = "distinct-page-dicts"
	CheckAnnotMembership   = "annot-membership-per-page"
	CheckAnnotParent       = "annot-P-is-own-page"
	CheckLinkDangling      = "link-dest-not-dangling"
	CheckLinkInTree        = "link-dest-in-output-page-tree"
	CheckLinkOccurrence    = "link-dest-same-occurrence"
	CheckLinkPage          = "link-dest-right-source-page"
	CheckNamedDests        = "named-dests-reach-output-pages"
	CheckFormRoots         = "form-widgets-reach-AcroForm-Fields"
	CheckFormParents       = "form-parent-refs-resolve"
	CheckFormWidgets       = "form-fields-have-page-widgets"
	CheckFormWidgetsShared = "form-widget-objects-not-shared"
	CheckGeometry          = "geometry-effective-attrs"
	CheckVersion           = "output-version>=max-input"
	CheckOutlines          = "outline-dests-reach-output-pages"
	CheckOrphanPages       = "no-orphan-page-objects"
)

Names of the checks Verify runs; Finding.Check holds one of them.

View Source
const RequireToolsEnv = "PDFCONCAT_REQUIRE_QA_TOOLS"

RequireToolsEnv names the environment variable that turns missing QA tools from a skip into a failure. CI sets it to "1"; a developer without the tools only loses these checks locally.

Variables

This section is empty.

Functions

func Failed

func Failed(findings []Finding) []string

Failed returns the names of the checks that failed.

func HasMuPDF added in v0.2.0

func HasMuPDF() bool

HasMuPDF reports whether the additional independent renderer is installed.

func QPDFJSON added in v0.2.0

func QPDFJSON(tools Tools, path string) ([]byte, error)

QPDFJSON returns the independent parser's complete object/page dump without interpreting it. Tests can inspect serialized geometry and action graphs beyond the standard expectation checks.

Types

type Document

type Document struct {

	// Path is the file.
	Path string
	// Version is the header version reported by qpdf, for example "1.7".
	Version string
	// contains filtered or unexported fields
}

Document is the parsed structure of one PDF file.

func Load

func Load(tools Tools, path string) (*Document, error)

Load dumps path with qpdf and extracts its text with pdftotext.

func (*Document) AppearanceDifference

func (d *Document) AppearanceDifference(page int, source *Document, sourcePage int, tolerance uint8) (float64, error)

AppearanceDifference compares independent full-page rasterizations. The result is the fraction of pixels with a channel differing by more than tolerance; positions and image marks matter.

func (*Document) Attachments

func (d *Document) Attachments() int

Attachments is the number of embedded files qpdf finds.

func (*Document) CatalogKeys

func (d *Document) CatalogKeys() []string

CatalogKeys returns the names of the catalog entries, such as "/Pages".

func (*Document) CatalogVersion

func (d *Document) CatalogVersion() string

CatalogVersion is the catalog /Version entry without its slash, or "".

func (*Document) ColorCounts added in v0.2.0

func (d *Document) ColorCounts(number int, colors [][3]uint8) ([]int, error)

ColorCounts counts exact RGB landmarks across one independent whole-page rendering. It detects formerly hidden marks anywhere on a sheet without repeatedly rendering for each sampled pixel.

func (*Document) EffectiveVersion

func (d *Document) EffectiveVersion() int

EffectiveVersion is the larger of the header version and the catalog /Version, as major*10+minor.

func (*Document) FirstLine

func (d *Document) FirstLine(number int) string

FirstLine returns the first non-blank text line of page number (1-based), or "" when the page has none.

func (*Document) InfoKeys

func (d *Document) InfoKeys() []string

InfoKeys returns the keys of the trailer's /Info dictionary, such as "/Producer".

func (*Document) MuPDFRaster added in v0.2.0

func (d *Document) MuPDFRaster(number int) (image.Image, error)

MuPDFRaster uses MuPDF's fixed PNG/72dpi interface; it does not affect runtime PDF assembly.

func (*Document) ObjectCount

func (d *Document) ObjectCount() int

ObjectCount is the number of objects qpdf reports in the file.

func (*Document) PageCount

func (d *Document) PageCount() int

PageCount is the number of pages in qpdf's page list.

func (*Document) PageObjects

func (d *Document) PageObjects() []string

PageObjects returns the object reference of each page in order.

func (*Document) PixelColor

func (d *Document) PixelColor(number, x, y int) ([3]uint8, error)

PixelColor returns the 8-bit red, green and blue of the pixel at (x, y), counted from the top-left corner, in the 72 dpi rendering of page number (1-based).

func (*Document) Raster added in v0.2.0

func (d *Document) Raster(number int) (image.Image, error)

Raster returns one independent Poppler rendering for batch pixel comparisons.

func (*Document) RawTexts

func (d *Document) RawTexts() ([]string, error)

RawTexts extracts without Poppler's physical-layout spacing heuristic. This preserves explicit spaces in very small text, which -layout may infer away despite the PDF's correct text mapping.

func (*Document) RenderedSize

func (d *Document) RenderedSize(number int) (int, int, error)

RenderedSize returns the pixel width and height of page number (1-based) rendered at 72 dpi with the CropBox and rotation applied. Poppler rounds sizes up and does not apply UserUnit; multiply by UserUnit for the physical size.

func (*Document) UserUnit

func (d *Document) UserUnit(number int) float64

UserUnit returns the /UserUnit of page number (1-based), or 1 when the page has none.

func (*Document) Verify

func (d *Document) Verify(exp Expectation) []Finding

Verify runs every check against exp and returns the failures; no findings means the output matches.

type Expectation

type Expectation struct {
	// Sources holds the facts of each named source.
	Sources map[string]SourceFact
	// Pages lists the output pages in order.
	Pages []ExpectedPage
}

Expectation is everything Verify checks the output against.

type ExpectedPage

type ExpectedPage struct {
	// Geometry, when set, is the expected geometry (used for generated pages).
	Geometry *Geometry
	// Text is the first text line the page must show.
	Text string
	// Source names the source in Expectation.Sources, or "" for a generated page.
	Source string
	// Occurrence numbers the occurrence of the source, from 1, so links must stay within it.
	Occurrence int
	// SourcePage is the 1-based source page.
	SourcePage int
}

ExpectedPage is one output page.

type Finding

type Finding struct {
	// Check is one of the Check constants.
	Check string
	// Detail says what was wrong.
	Detail string
}

Finding is one failed check.

type Geometry

type Geometry struct {
	// MediaBox is the effective MediaBox.
	MediaBox []float64
	// CropBox is the effective CropBox; nil requires that none is in effect.
	CropBox []float64
	// Rotate is the effective rotation in [0, 360).
	Rotate int
	// UserUnit is the page's UserUnit; 0 means the default 1.
	UserUnit float64
}

Geometry is the page attributes an output page must have in effect.

type SourceFact

type SourceFact struct {
	// Links maps a source page to the source pages its link annotations and actions must reach.
	Links map[int][]int
	// Geometry maps a source page to its expected attributes; absent pages are not checked.
	Geometry map[int]Geometry
	// Pages is the page count.
	Pages int
	// Version is the effective version as major*10+minor.
	Version int
}

SourceFact is what the test knows about a source document independently of the engine.

type Tools

type Tools struct {
	QPDF, PDFToText, PDFInfo, PDFToPPM string
}

Tools are the independent QA programs: qpdf for structure, Poppler for text and geometry.

func FindTools

func FindTools() (Tools, error)

FindTools locates the QA tools and reports the first one that is missing.

func RequireTools

func RequireTools(tb testing.TB) Tools

RequireTools locates the QA tools. When one is missing it fails the test if RequireToolsEnv is "1" and otherwise skips it.

func (Tools) Check

func (t Tools) Check(path string) error

Check runs qpdf's structural check on path. It fails when qpdf does, and when it succeeds but reports a warning, which for a generated fixture or an assembled output is also a defect.

func (Tools) Encrypt

func (t Tools) Encrypt(path, userPassword string) error

Encrypt rewrites the PDF at path in place with qpdf, using AES-256 with the given user password.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL