This commit is contained in:
1 parent
b22e82a8c2
commit
509af2a410
5 files changed
+238
-35
No files matched your search
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
# Job-level check that PRINTER_OPTIONS queue defaults reach the emitted job.
|
||||
#
|
||||
# The authority for this test is the PostScript that cupsd sends to the
|
||||
# printer, not a settings file and NOT `lpoptions -p <queue> -l`: that command
|
||||
# renders PPD Boolean options incorrectly (it shows `TonerSaveMode ... *False`
|
||||
# even when the queue default is `True`), which is exactly the misreading this
|
||||
# test guards against.
|
||||
#
|
||||
# Why `cupsfilter` and not "read cupsd's spool file after `lp`": with no
|
||||
# reachable printer the job sticks at "The printer may not exist or is
|
||||
# unavailable", the filters never run, and the spool file still holds the
|
||||
# unfiltered input PDF. `cupsfilter -p /etc/cups/ppd/<queue>.ppd` produces the
|
||||
# same `%%BeginFeature`/effect-line structure without needing a printer.
|
||||
#
|
||||
# Verified against cups-daemon 2.4.2-3+deb12u9 (Debian bookworm, the base of
|
||||
# Containerfile).
|
||||
set -euo pipefail
|
||||
|
||||
IMAGE="${IMAGE:-printserver:latest}"
|
||||
QUEUE="${QUEUE:-HL4150CDN}"
|
||||
CONTAINER="${CONTAINER:-printserver-queue-defaults-test}"
|
||||
SAMPLE="${SAMPLE:-/usr/share/cups/data/default-testpage.pdf}"
|
||||
PPD="/etc/cups/ppd/${QUEUE}.ppd"
|
||||
|
||||
# The documented PRINTER_OPTIONS example from the spec / README.
|
||||
PRINTER_OPTIONS_VALUE="BRColorMode=Vivid TonerSaveMode=False"
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
cleanup() {
|
||||
podman rm -f "${CONTAINER}" >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
check() {
|
||||
# check <label> <postscript-file> <expected-line>
|
||||
local label="$1" file="$2" expected="$3"
|
||||
if podman exec "${CONTAINER}" grep -aqF -- "${expected}" "${file}"; then
|
||||
echo "PASS: ${label}: found '${expected}'"
|
||||
pass=$((pass + 1))
|
||||
else
|
||||
echo "FAIL: ${label}: expected '${expected}' in ${file}"
|
||||
echo " actual option features:"
|
||||
podman exec "${CONTAINER}" sh -c \
|
||||
"grep -ao '%%BeginFeature: \\*[A-Za-z0-9]*' '${file}' | sort -u | sed 's/^/ /'" \
|
||||
|| true
|
||||
fail=$((fail + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "== building ${IMAGE} =="
|
||||
podman build -t "${IMAGE}" .
|
||||
|
||||
echo "== starting container with PRINTER_OPTIONS=\"${PRINTER_OPTIONS_VALUE}\" =="
|
||||
podman rm -f "${CONTAINER}" >/dev/null 2>&1 || true
|
||||
podman run -d --name "${CONTAINER}" \
|
||||
-e PRINTER_IP=192.0.2.1 \
|
||||
-e "PRINTER_OPTIONS=${PRINTER_OPTIONS_VALUE}" \
|
||||
"${IMAGE}" >/dev/null
|
||||
|
||||
ready=0
|
||||
for _ in $(seq 1 90); do
|
||||
if podman logs "${CONTAINER}" 2>&1 | grep -q 'ready: CUPS on 631/tcp'; then
|
||||
ready=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if [ "${ready}" -ne 1 ]; then
|
||||
echo "FAIL: container did not reach 'ready: CUPS on 631/tcp'"
|
||||
podman logs "${CONTAINER}" 2>&1 | tail -20
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# `podman logs` can lag behind the container by a few seconds, and the ready
|
||||
# line is printed after the option lines, so poll the log for each assignment
|
||||
# instead of inspecting it once.
|
||||
for opt in ${PRINTER_OPTIONS_VALUE}; do
|
||||
applied=0
|
||||
for _ in $(seq 1 30); do
|
||||
if podman logs "${CONTAINER}" 2>&1 | grep -qF "queue default ${opt} applied"; then
|
||||
applied=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if [ "${applied}" -ne 1 ]; then
|
||||
echo "FAIL: entrypoint did not report '${opt}' as applied"
|
||||
podman logs "${CONTAINER}" 2>&1 | grep -i 'entrypoint\|warning' | tail -10
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "PASS: entrypoint applied every PRINTER_OPTIONS assignment"
|
||||
|
||||
echo "== queue state cross-check (config views, not the acceptance signal) =="
|
||||
# TonerSaveMode is deliberately not asserted here: see the header comment.
|
||||
podman exec "${CONTAINER}" lpoptions -p "${QUEUE}" -l | grep BRColorMode
|
||||
podman exec "${CONTAINER}" grep -E '^\*Default(BRColorMode|TonerSaveMode)' "${PPD}"
|
||||
|
||||
echo "== filtering: queue defaults =="
|
||||
podman exec "${CONTAINER}" sh -c \
|
||||
"cupsfilter -p '${PPD}' -m application/vnd.cups-postscript '${SAMPLE}' > /tmp/qd.ps 2>/dev/null"
|
||||
|
||||
check "queue default BRColorMode=Vivid" /tmp/qd.ps "%%BeginFeature: *BRColorMode Vivid"
|
||||
check "queue default BRColorMode=Vivid (effect)" /tmp/qd.ps "<</UseCIEColor true>>setpagedevice"
|
||||
check "queue default TonerSaveMode=False" /tmp/qd.ps "%%BeginFeature: *TonerSaveMode False"
|
||||
|
||||
# A per-job option must win over the queue default: this is the regression guard
|
||||
# that the options channel is live rather than pinned to a vendor value.
|
||||
echo "== filtering: per-job override =="
|
||||
podman exec "${CONTAINER}" sh -c \
|
||||
"cupsfilter -p '${PPD}' -m application/vnd.cups-postscript -o BRColorMode=None '${SAMPLE}' > /tmp/override.ps 2>/dev/null"
|
||||
|
||||
check "per-job BRColorMode=None wins" /tmp/override.ps "%%BeginFeature: *BRColorMode None"
|
||||
|
||||
if podman exec "${CONTAINER}" grep -aqF -- "%%BeginFeature: *BRColorMode Vivid" /tmp/override.ps; then
|
||||
echo "FAIL: per-job override: queue default Vivid leaked into the explicit None job"
|
||||
fail=$((fail + 1))
|
||||
else
|
||||
echo "PASS: per-job override: queue default Vivid did not leak into the explicit None job"
|
||||
pass=$((pass + 1))
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "== result: ${pass} passed, ${fail} failed =="
|
||||
[ "${fail}" -eq 0 ] || exit 1
|
||||
Reference in new issue
Block a user