Files
Classroom_Desktop/tools/lab/wonderink-print-check
T
ekklesiaandClaude Opus 5.5 1cb9fd35d2 feat: Wonder Ink looks like the classroom, and its preview shows the page
The tab strip is drawn from the classroom's own palette, the one the
panel, Parent Call and Presentations read: larger titles, an accent
under the active tab, worksheets marked with a document icon. Its one
corner widget is the lesson's size and Print — not a new-tab button. With
one tab the strip stays hidden, as before; a change of size shows a
moment's badge instead, and the right-click menu and keys still work.
The window is named "Lesson — Wonder Ink" and carries its own icon.

The print preview showed "Page 1 could not be shown" in the real
session while printing correctly: poppler 25.03 does not write to stdout
when asked for "-" — it writes a file called "-.png" into the current
directory, which for Wonder Ink is the teacher's home. Pages are now
rendered into a directory of their own, and the lab print check fails
any preview that does not draw its page.

The teacher's manual has lesson size and printing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-23 19:13:04 -05:00

160 lines
7.4 KiB
Bash
Executable File

#!/bin/bash
# Does Wonder Ink print — and does a job really reach CUPS?
#
# The lab's CUPS gets an "Elmer" built from Elmer's own PPD and options,
# writing to a file instead of socket://10.10.0.155:9100, so every job
# goes through the same filters the real printer's jobs do and none can
# reach a printer. A second queue refuses jobs, to show a teacher is told.
#
# Each scenario runs the INSTALLED classroom-wonderink under a real
# QtWebEngine (offscreen), presses the preview's buttons, and is then
# judged by CUPS's own record of what it was given.
#
# tools/lab/wonderink-print-check [SCENARIO...]
set -uo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
NAME="${LAB_NAME:-classroom-v2-lab}"
COMMAND="${WONDERINK:-/usr/local/bin/classroom-wonderink}"
lab() { docker exec -i "$NAME" bash -c "$1"; }
docker cp "$ROOT/tools/lab/wonderink-print-rig.py" "$NAME:/tmp/wonderink-print-rig.py" >/dev/null
lab 'chmod a+r /tmp/wonderink-print-rig.py'
# The church's printer network is fenced off inside the lab. Checked, not
# assumed: a lab job must never be able to reach the real Elmer.
lab 'ip route replace blackhole 10.10.0.0/16 2>/dev/null
! timeout 3 bash -c "exec 3<>/dev/tcp/10.10.0.155/9100" 2>/dev/null' || {
echo "REFUSING TO CONTINUE: the real Elmer is reachable from the lab" >&2
exit 1
}
lab '
set -e
export DEBIAN_FRONTEND=noninteractive
command -v lpadmin >/dev/null && command -v pdftoppm >/dev/null || \
apt-get install -y -qq cups cups-client poppler-utils >/dev/null 2>&1
dpkg -s foomatic-db-compressed-ppds >/dev/null 2>&1 || \
apt-get install -y -qq foomatic-db-compressed-ppds cups-filters ghostscript >/dev/null 2>&1
grep -q "^FileDevice Yes" /etc/cups/cups-files.conf || echo "FileDevice Yes" >> /etc/cups/cups-files.conf
pkill -x cupsd || true; sleep 1; /usr/sbin/cupsd; sleep 1
cupsctl --debug-logging
: > /var/log/cups/error_log
mkdir -p /var/lab-print && chown lp /var/lab-print
driver="foomatic-db-compressed-ppds:0/ppd/foomatic-ppd/Generic-PCL_6_PCL_XL_Printer-pxlcolor.ppd"
for q in $(lpstat -e 2>/dev/null); do lpadmin -x "$q"; done
lpadmin -p Elmer -E -v file:///var/lab-print/elmer.pxl -m "$driver" \
-D "LAB STAND-IN for Elmer: its PPD, a file for a printer" \
-o PrintoutMode=Normal -o ColorModel=Color 2>/dev/null
lpadmin -d Elmer
lpadmin -p Refusing -E -v file:///dev/null -m "$driver" -D "LAB: refuses jobs" 2>/dev/null
cupsreject Refusing
id teacher >/dev/null 2>&1 || useradd -m teacher
install -d -o teacher -m 700 /tmp/teacher-rt
# An inline PDF, served the way a site shows one rather than sends it.
mkdir -p /tmp/www
pgrep -f "http.server 8088" >/dev/null || (cd /tmp/www && setsid python3 -m http.server 8088 >/dev/null 2>&1 &)
' || { echo "could not prepare the lab's CUPS" >&2; exit 1; }
passed=0
failed=0
judge() {
if eval "$2"; then
printf ' \033[32mPASS\033[0m %s\n' "$1"
passed=$((passed + 1))
else
printf ' \033[31mFAIL\033[0m %s\n' "$1"
failed=$((failed + 1))
fi
}
# Runs one scenario; leaves its output in $out and the jobs it caused in $jobs.
run() {
local before
before=$(lab 'lpstat -W all -o 2>/dev/null | wc -l')
out=$(lab "su teacher -c 'cd /tmp; XDG_RUNTIME_DIR=/tmp/teacher-rt QT_QPA_PLATFORM=offscreen \
QTWEBENGINE_CHROMIUM_FLAGS=\"--no-sandbox --disable-gpu\" \
timeout 120 python3 /tmp/wonderink-print-rig.py $COMMAND $1 2>&1'; echo \"exit=\$?\"")
sleep 3
jobs=$(lab "lpstat -W all -o | tail -n +$((before + 1)) | awk '{print \$1}' | tr '\n' ' '")
job_options() { lab "grep -E '\\[Job ${1#*-}\\] argv\\[(4|5)\\]' /var/log/cups/error_log"; }
job_device() { lab "grep -E '\\[Job ${1#*-}\\]' /var/log/cups/error_log | grep -oE 'sDEVICE=[a-z]+' | sort -u"; }
}
count() { wc -w <<< "$jobs"; }
said() { grep -q -- "$1" <<< "$out"; }
exited_cleanly() { said 'exit=0' && ! said 'Traceback' && ! said 'Segmentation' && ! said 'Aborted'; }
scenarios=("$@")
[[ ${#scenarios[@]} -gt 0 ]] || scenarios=(web pdf pdf-options pdf-viewer-button inline
options bad-range broken cancel page-closes-itself close-window page-prints-again repeat)
# The inline scenario needs a PDF to serve; the worksheet scenario writes one.
lab 'test -f /tmp/www/ark.pdf' || { run pdf >/dev/null; lab 'cp "/home/teacher/Downloads/Wonder Ink/Colour the Ark.pdf" /tmp/www/ark.pdf; chmod a+r /tmp/www/ark.pdf'; }
for scenario in "${scenarios[@]}"; do
echo "$scenario"
run "$scenario"
judge "Wonder Ink did not crash, and exited by itself" exited_cleanly
# The preview has to SHOW the page, not merely count it. A preview
# that printed the right thing while showing a blank was what the
# first version of this check let through.
if said 'PREVIEW '; then
judge "the preview drew the page it will print" "! grep 'PREVIEW ' <<< \"\$out\" | grep -q 'shown=False'"
fi
case "$scenario" in
web)
judge "the preview showed the lesson, 3 Letter pages, Elmer chosen" \
"said \"pages=3 printers=\\['Elmer', 'Refusing'\\] paper=Letter\""
judge "one job reached CUPS" '[[ $(count) -eq 1 ]]'
judge "Elmer's filters printed it in colour" '[[ "$(job_device $jobs)" == *pxlcolor* ]]'
judge "and nothing was left behind" "said 'scratch_left=\\[\\]'" ;;
pdf|pdf-viewer-button)
judge "the preview showed the worksheet's own 2 pages" "said 'pages=2'"
judge "one job reached CUPS" '[[ $(count) -eq 1 ]]' ;;
pdf-options)
judge "one job" '[[ $(count) -eq 1 ]]'
judge "page 2 only, three copies" \
'[[ "$(job_options $jobs)" == *"argv[4]=\"3\""* && "$(job_options $jobs)" == *page-ranges=2* ]]'
judge "in black and white, by the driver's own option" \
'[[ "$(job_options $jobs)" == *ColorModel=Grayscale* && "$(job_device $jobs)" == *pxlmono* ]]' ;;
inline)
judge "the inline PDF was recognised" "said \"mime='application/pdf'\""
judge "and opened as a worksheet tab" "said 'current_is_pdf=True'"
judge "one job reached CUPS" '[[ $(count) -eq 1 ]]' ;;
options)
judge "pages 2-3, two copies, black and white" \
'[[ "$(job_options $jobs)" == *page-ranges=2-3* && "$(job_options $jobs)" == *"argv[4]=\"2\""* && "$(job_device $jobs)" == *pxlmono* ]]' ;;
bad-range)
judge "a page that does not exist is explained, not printed" "said 'This document has 3 pages'"
judge "and once corrected, one job" '[[ $(count) -eq 1 ]]' ;;
broken)
judge "a refusing printer is reported in CUPS's words" "said 'Refusing did not take the job'"
judge "and no job is claimed" '[[ $(count) -eq 0 ]] && ! said "NOTIFY Sent"' ;;
cancel)
judge "Cancel sends nothing" '[[ $(count) -eq 0 ]]' ;;
page-closes-itself)
judge "the preview says the page closed, and cannot print" \
"said \"status='The page was closed.' print_enabled=False\""
judge "and sends nothing" '[[ $(count) -eq 0 ]]' ;;
close-window)
judge "closing Wonder Ink with the preview open sends nothing" '[[ $(count) -eq 0 ]]' ;;
page-prints-again)
judge "a second print request does not open a second preview" "said 'still one preview=True'"
judge "one job" '[[ $(count) -eq 1 ]]' ;;
repeat)
judge "five prints in a row, five jobs" '[[ $(count) -eq 5 ]]' ;;
esac
[[ "$failed" -eq 0 ]] || { echo "$out" | tail -15 | sed 's/^/ /'; }
done
echo
echo "$passed passed, $failed failed"
[[ "$failed" -eq 0 ]]