Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b6Kg9RWSTJzyz6KP9X
81 lines
4.5 KiB
Bash
Executable File
81 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regenerates everything under output/. Needs JDK 25, Maven, curl, poppler (pdftoppm, pdftotext, pdffonts),
|
|
# python3 with Pillow built with libraqm. Network is needed once for Maven and for 00-versions-and-licences.txt.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
mkdir -p output/pdf output/png
|
|
JAR=target/pdf-invoice-1.0.0.jar
|
|
HOST="$(java -version 2>&1 | grep -v JAVA_TOOL | head -1) | $(nproc) vCPU | $(awk '/MemTotal/ {printf "%d MB RAM", $2/1024}' /proc/meminfo)"
|
|
|
|
scripts/licences.sh > output/00-versions-and-licences.txt || echo "licence check skipped (offline?)"
|
|
|
|
mvn -q -B test # writes output/01, 04, 05
|
|
mvn -q -B -DskipTests package
|
|
|
|
serve() { # serve <port> : start the packaged jar, wait until it answers
|
|
setsid nohup java -jar "$JAR" --server.port="$1" > "target/app-$1.log" 2>&1 < /dev/null &
|
|
echo $! > "target/app-$1.pid"
|
|
for _ in $(seq 1 60); do curl -s -o /dev/null "localhost:$1/invoices/openpdf.pdf" && return 0; sleep 1; done
|
|
echo "app did not start" >&2; return 1
|
|
}
|
|
stop() { kill "$(cat "target/app-$1.pid")" 2>/dev/null || true; }
|
|
|
|
P=$((20000 + RANDOM % 10000))
|
|
serve "$P"
|
|
ENGINES="openpdf itext flyingsaucer openpdf-jdk openpdf-jdk-actualtext flyingsaucer-shaped"
|
|
|
|
for e in $ENGINES; do
|
|
curl -s -o "output/pdf/$e.pdf" "localhost:$P/invoices/$e.pdf"
|
|
curl -s -o "output/pdf/probe-$e.pdf" "localhost:$P/invoices/$e.pdf?probe=true"
|
|
done
|
|
|
|
{
|
|
echo "# HTTP: status and headers per engine (curl -D -), then streaming vs buffered, then a failure after rendering"
|
|
echo "# $HOST"
|
|
for e in $ENGINES; do
|
|
echo "--- GET /invoices/$e.pdf"
|
|
curl -s -D - -o /dev/null "localhost:$P/invoices/$e.pdf" | tr -d '\r' | grep -i -E '^HTTP|^content-type|^content-disposition|^content-length|^transfer-encoding'
|
|
done
|
|
echo "--- GET /invoices/openpdf.pdf?mode=buffered"
|
|
curl -s -D - -o /dev/null "localhost:$P/invoices/openpdf.pdf?mode=buffered" | tr -d '\r' | grep -i -E '^HTTP|^content-length|^transfer-encoding'
|
|
echo "--- GET /invoices/openpdf.pdf?disposition=inline"
|
|
curl -s -D - -o /dev/null "localhost:$P/invoices/openpdf.pdf?disposition=inline" | tr -d '\r' | grep -i -E '^HTTP|^content-disposition'
|
|
echo "--- GET /invoices/nope.pdf"
|
|
curl -s -D - -o /dev/null "localhost:$P/invoices/nope.pdf" | tr -d '\r' | grep -i -E '^HTTP'
|
|
echo "--- GET /invoices/openpdf.pdf?failAtEnd=true (streamed: headers are already gone when the failure happens)"
|
|
curl -s -D - -o target/fail-stream.pdf -w "curl exit=%{exitcode} bytes_received=%{size_download}\n" "localhost:$P/invoices/openpdf.pdf?failAtEnd=true" 2>&1 | tr -d '\r' | grep -i -E '^HTTP|^content-length|^transfer-encoding|curl exit' || true
|
|
echo "--- GET /invoices/openpdf.pdf?failAtEnd=true&mode=buffered (rendered into memory first)"
|
|
curl -s -D - -o target/fail-buffered.bin -w "curl exit=%{exitcode} bytes_received=%{size_download}\n" "localhost:$P/invoices/openpdf.pdf?failAtEnd=true&mode=buffered" 2>&1 | tr -d '\r' | grep -i -E '^HTTP|^content-length|curl exit' || true
|
|
} > output/02-endpoints.txt
|
|
|
|
{
|
|
echo "# pdffonts per engine (poppler): name, type, embedded, subset"
|
|
for e in $ENGINES; do echo "--- $e ($(stat -c %s "output/pdf/$e.pdf") bytes)"; pdffonts "output/pdf/$e.pdf"; done
|
|
echo; echo "# Producer/Creator lines the libraries write into the PDF (pdfinfo)"
|
|
for e in openpdf itext flyingsaucer; do echo "--- $e"; pdfinfo "output/pdf/$e.pdf" | grep -E '^(Title|Creator|Producer)'; done
|
|
} > output/03-pdffonts-and-producer.txt
|
|
|
|
stop "$P"
|
|
|
|
# the FOP variant needs Apache FOP (121 jars with Batik) on the classpath: Maven profile fop
|
|
mvn -q -B -Pfop -DskipTests package
|
|
P2=$((20000 + RANDOM % 10000))
|
|
serve "$P2"
|
|
curl -s -o output/pdf/openpdf-fop.pdf "localhost:$P2/invoices/openpdf-fop.pdf"
|
|
curl -s -o output/pdf/probe-openpdf-fop.pdf "localhost:$P2/invoices/openpdf-fop.pdf?probe=true"
|
|
stop "$P2"
|
|
mvn -q -B -DskipTests package # back to the default jar
|
|
|
|
for e in openpdf itext flyingsaucer openpdf-jdk-actualtext flyingsaucer-shaped openpdf-fop; do
|
|
pdftoppm -r 110 -png -singlefile -H 800 "output/pdf/$e.pdf" "output/png/invoice-$e"
|
|
done
|
|
python3 scripts/compare.py output/pdf output/png src/main/resources/fonts/NotoSansDevanagari-Regular.ttf
|
|
|
|
{
|
|
echo "# in-process timing, $HOST"
|
|
echo "# indicative: shared sandbox, one JVM, one run per line"
|
|
java -jar "$JAR" --spring.profiles.active=bench --spring.main.web-application-type=none \
|
|
--bench.n="${BENCH_N:-500}" --bench.engines=openpdf,itext,flyingsaucer,openpdf-jdk-actualtext,flyingsaucer-shaped 2>/dev/null | grep -E '^#|^[a-z]'
|
|
} > output/06-bench.txt
|
|
echo done
|