Tests for a PDF

17 points by lvmbdv 20 days ago on lobsters | 4 comments

In Prince we need to do this a lot. The basic process is that the test suite compares generated output to expected output. The generated output is produced with a few flags to make the PDF easier to compare: --pdf-id= --no-producer --no-compress. Then the output is compared using a special (GNU) diff invocation:

diff_pdf () ( # subshell
    exp=$1
    out=$2

    # If both files are empty or non-existent, do nothing.
    if [ ! -s "$exp" ] && [ ! -s "$out" ]; then
        return 0
    fi

    $DIFF -u -a \
      --show-function-line='^[0-9][0-9]* 0 obj'	\
      -I '^/FontName' \
      -I '^/BaseFont' \
      -I '^/MediaBox' \
      -I '^/BleedBox' \
      -I '^/TrimBox' \
      -I '^<pdf:Producer' \
      -I '^<xmp:CreateDate' \
      -I '^<xmp:MetadataDate' \
      -I '^<xmp:ModifyDate' \
      -I '^<xmpMM:DocumentID' \
      -I '^\(<<\)*/ModDate' \
      -I '^\(<<\)*/CreationDate' \
      -I '^\(<<\)*/Producer' \
      -I '^[0-9]* 00000 n $' \
      -I '^[1-9][0-9]*$' \
      -I '^/ID \[<' \
      -I '^\(<<\)\?/XRefStm [1-9][0-9]*$' \
      -I '^/Prev [1-9][0-9]*$' \
      "$exp" "$out"
)

If the output fails that comparison further files are generated as needed:

  • A diff file for the pdf
  • The output of pdftotxt is compared and a diff of that output is generated if different
  • The PDF is rasterized (to TIFF) with pdftoppm, and expected versus actual images are kept for each page that differs.

This all works pretty well.

[OP] lvmbdv | 19 days ago

Thanks for sharing, Prince looks useful!

I always enjoy some unusual tests.

jesseb34r | 20 days ago

Fun to read about some programatic working with pdfs. I've been meaning to investigate this for my personal accounting software I'm writing that parses bank statements. So far I've been working with just OFX files, but I want to tackle pdfs at some point because some institutions don't have an OFX export option and the CSV options often don't have as much info as the monthly pdf e-statements do.