test: the lab prints from a signed-in lesson, and judges black and white on the job
A lesson site for the lab (session cookie, one-time addresses, a second origin, a request log) and real right-clicks on its words and on a JPEG, a PNG, a transparent PNG, a one-time picture, another site's, a blob:, a WebP, a canvas, a linked picture, a broken one, and Cancel. Each is judged on the job CUPS kept — where and how large, no other ink — and on the site log: nothing was fetched again. The clipboard is the teacher's afterwards. Black and white: a colourful lesson turned back and forth five times on page 2, a worksheet, a picture at 50% top left, a page full of pictures, back to Color, and Cancel. Every grey preview is grey pixel for pixel and the job is byte-for-byte the file shown, through pxlmono. The three 0.2.6.2 black-and-white scenarios now wait for the grey file before Print, as a teacher has to. 343 checks, none failing. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
594fbd810e
commit
cb12e59dea
+173
-27
@@ -27,6 +27,9 @@ lab 'mkdir -p /opt/wonderink-check'
|
||||
docker cp "$ROOT/tools/lab/wonderink-print-rig.py" "$NAME:$RIG" >/dev/null
|
||||
MEASURE=/opt/wonderink-check/wonderink-picture-measure.py
|
||||
docker cp "$ROOT/tools/lab/wonderink-picture-measure.py" "$NAME:$MEASURE" >/dev/null
|
||||
SITE=/opt/wonderink-check/wonderink-lesson-site.py
|
||||
SITE_LOG=/opt/wonderink-check/site.log
|
||||
docker cp "$ROOT/tools/lab/wonderink-lesson-site.py" "$NAME:$SITE" >/dev/null
|
||||
lab "chmod -R a+rX /opt/wonderink-check && test -r $RIG" || {
|
||||
echo "could not put the rig in the lab" >&2
|
||||
exit 1
|
||||
@@ -70,9 +73,10 @@ mkdir -p /opt/wonderink-check/www
|
||||
cupsctl PreserveJobFiles=Yes
|
||||
' || { echo "could not prepare the lab's CUPS" >&2; exit 1; }
|
||||
|
||||
lab "test -f /opt/wonderink-check/www/ark-clear.png || \
|
||||
QT_QPA_PLATFORM=offscreen python3 $MEASURE make /opt/wonderink-check/www; \
|
||||
chmod -R a+r /opt/wonderink-check/www; test -f /opt/wonderink-check/www/ark-clear.png" || {
|
||||
lab "test -f /opt/wonderink-check/www/ark-wide.webp || \
|
||||
QT_QPA_PLATFORM=offscreen QTWEBENGINE_CHROMIUM_FLAGS='--no-sandbox --disable-gpu' \
|
||||
python3 $MEASURE make /opt/wonderink-check/www; \
|
||||
chmod -R a+r /opt/wonderink-check/www; test -f /opt/wonderink-check/www/ark-wide.webp" || {
|
||||
echo "could not make the test pictures" >&2
|
||||
exit 1
|
||||
}
|
||||
@@ -82,6 +86,15 @@ lab "test -f /opt/wonderink-check/www/ark-clear.png || \
|
||||
lab 'pgrep -f "[h]ttp.server 8089" >/dev/null' || \
|
||||
docker exec -d -w /opt/wonderink-check/www "$NAME" python3 -m http.server 8089
|
||||
|
||||
# The signed-in lesson with pictures in it, restarted each run so that its
|
||||
# one-time addresses start unused.
|
||||
lab "pkill -f '[w]onderink-lesson-site.py' ; : > $SITE_LOG; chmod a+rw $SITE_LOG"
|
||||
docker exec -d "$NAME" python3 "$SITE" /opt/wonderink-check/www 8094 8095 "$SITE_LOG"
|
||||
lab 'for _ in $(seq 20); do curl -s -o /dev/null http://127.0.0.1:8094/login && exit 0; sleep 0.3; done; exit 1' || {
|
||||
echo "the lesson site did not start" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
passed=0
|
||||
failed=0
|
||||
|
||||
@@ -112,6 +125,48 @@ count() { wc -w <<< "$jobs"; }
|
||||
# The file CUPS was handed for a job, kept by PreserveJobFiles.
|
||||
spool_file() { local id="${1%% *}"; printf '/var/spool/cups/d%05d-001' "${id##*-}"; }
|
||||
said() { grep -q -- "$1" <<< "$out"; }
|
||||
# Every line of the rig's output that starts with WORD.
|
||||
lines() { grep -o -- "$1.*" <<< "$out"; }
|
||||
# Is every page of a PDF in the lab grey? {"pages", "spreads", "gray"}
|
||||
colour_of() { lab "python3 $MEASURE colour $1"; }
|
||||
is_gray() { python3 -c 'import json,sys; sys.exit(0 if json.loads(sys.argv[1])["gray"] else 1)' "$1"; }
|
||||
# What the lesson site was asked for after the right-click.
|
||||
fetched_since() {
|
||||
local since
|
||||
since=$(grep -o 'since=[0-9.]*' <<< "$out" | head -1 | cut -d= -f2)
|
||||
lab "python3 -c 'import json,sys; print(sum(1 for l in open(\"$SITE_LOG\") if json.loads(l)[\"t\"] > float(sys.argv[1])))' ${since:-0}"
|
||||
}
|
||||
teacher_text_kept() { said "CLIPBOARD \"TEACHER'S TEXT, John 3:16\""; }
|
||||
# picture layout, measured on the page CUPS kept: judges its own lines.
|
||||
judge_layout() { # FILE_DIMS SIZE POSITION PAPER FILL COLOUR
|
||||
local dims=$1 size=$2 position=$3 paper=$4 fill=$5 color=$6 spool result
|
||||
spool=$(spool_file "$jobs")
|
||||
judge "CUPS was given exactly the page the preview showed" \
|
||||
"[[ -n '$spool' ]] && lab 'cmp -s /tmp/rig-out/preview.pdf $spool'"
|
||||
result=$(lab "python3 $MEASURE measure $spool $dims $size $position $paper $fill")
|
||||
field() { python3 -c "import json,sys; print(json.loads(sys.argv[1])[sys.argv[2]])" "$result" "$1"; }
|
||||
judge "the paper is turned the way asked ($paper): $(field page)" \
|
||||
'[[ "$(field page_landscape)" == "$(field wanted_landscape)" ]]'
|
||||
judge "the picture is where and as large as asked, within 3 points (off by $(field off_by_points))" \
|
||||
'[[ "$(field off_by_points)" != None ]] && (( $(field off_by_points) <= 3 ))'
|
||||
judge "no ink anywhere else on the page — no bars ($(field ink_outside_picture) pixels)" \
|
||||
'[[ "$(field ink_outside_picture)" == 0 ]]'
|
||||
if [[ "$fill" == fill ]]; then
|
||||
# The mark is in the picture's left fifth, which filling a
|
||||
# portrait page with a wide picture cuts off. That is what the
|
||||
# control says it does; the fit scenarios prove it happens only
|
||||
# when asked.
|
||||
judge "Fill cut the edges off, as it says it will" '(( $(field pink_pixels) == 0 ))'
|
||||
elif [[ "$color" == gray ]]; then
|
||||
judge "the corner mark is on the paper, in grey — nothing cut off" '[[ "$(field mark_inked)" == True ]]'
|
||||
judge "and the page is grey, as the preview showed (colour spread $(field colour_spread))" \
|
||||
'(( $(field colour_spread) == 0 ))'
|
||||
judge "and it went in black and white, by the driver's own option" \
|
||||
'[[ "$(job_options $jobs)" == *ColorModel=Grayscale* && "$(job_device $jobs)" == *pxlmono* ]]'
|
||||
else
|
||||
judge "the pink corner mark is on the paper — nothing cut off" '(( $(field pink_pixels) > 0 ))'
|
||||
fi
|
||||
}
|
||||
exited_cleanly() { said 'exit=0' && ! said 'Traceback' && ! said 'Segmentation' && ! said 'Aborted'; }
|
||||
|
||||
# Where a picture goes, measured on the page CUPS was given:
|
||||
@@ -125,12 +180,36 @@ PICTURES=(
|
||||
picture:ark-wide.png:100:centre:portrait:fill
|
||||
picture:ark-wide.jpg:75:right:auto:fit:gray
|
||||
picture:ark-clear.png:50:top:auto:fit
|
||||
picture:ark-wide.png:50:top-left:auto:fit:gray
|
||||
)
|
||||
|
||||
# Black and white shown as it prints, and Color again (0.2.6.3).
|
||||
COLOURS=(bw-web bw-pdf bw-colour-again bw-cancel)
|
||||
|
||||
# Right-click in a signed-in lesson (0.2.6.3):
|
||||
# rclick-image:ELEMENT:SIZE:POSITION[:gray], the elements in
|
||||
# wonderink-lesson-site.py.
|
||||
RIGHT_CLICKS=(
|
||||
rclick-page
|
||||
rclick-page-gray
|
||||
rclick-image:private-jpg:50:top-left
|
||||
rclick-image:private-png:100:centre
|
||||
rclick-image:clear:50:top-left
|
||||
rclick-image:once:100:centre
|
||||
rclick-image:cross:75:right
|
||||
rclick-image:blob:100:centre
|
||||
rclick-image:webp:100:centre
|
||||
rclick-image:canvas:100:centre
|
||||
rclick-image:linked:33:bottom-right
|
||||
rclick-image:private-jpg:50:top-left:gray
|
||||
rclick-broken
|
||||
rclick-cancel
|
||||
)
|
||||
|
||||
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
|
||||
dark-page "${PICTURES[@]}")
|
||||
dark-page "${PICTURES[@]}" "${COLOURS[@]}" "${RIGHT_CLICKS[@]}")
|
||||
|
||||
# The inline scenario needs a PDF to serve; the worksheet scenario writes one.
|
||||
lab 'test -f /opt/wonderink-check/www/ark.pdf' || { run pdf >/dev/null; lab 'cp "/home/teacher/Downloads/Wonder Ink/Colour the Ark.pdf" /opt/wonderink-check/www/ark.pdf; chmod a+r /opt/wonderink-check/www/ark.pdf'; }
|
||||
@@ -204,31 +283,98 @@ for scenario in "${scenarios[@]}"; do
|
||||
IFS=: read -r _ file size position paper fill color <<< "$scenario"
|
||||
judge "the picture controls appeared, and none for a page" "said 'PICTURE picture_box=True'"
|
||||
judge "the print interface says Color" "said \"labels='Color','Color'\""
|
||||
judge "one job reached CUPS" '[[ $(count) -eq 1 ]]'
|
||||
spool=$(spool_file "$jobs")
|
||||
judge "CUPS was given exactly the page the preview showed" \
|
||||
"[[ -n '$spool' ]] && lab 'cmp -s /tmp/rig-out/preview.pdf $spool'"
|
||||
dims=$(lab "python3 -c 'from PyQt6.QtGui import QImage; i=QImage(\"/opt/wonderink-check/www/$file\"); print(f\"{i.width()}x{i.height()}\")'" 2>/dev/null)
|
||||
result=$(lab "python3 $MEASURE measure $spool $dims $size $position $paper $fill")
|
||||
field() { python3 -c "import json,sys; print(json.loads(sys.argv[1])[sys.argv[2]])" "$result" "$1"; }
|
||||
judge "the paper is turned the way asked ($paper): $(field page)" \
|
||||
'[[ "$(field page_landscape)" == "$(field wanted_landscape)" ]]'
|
||||
judge "the picture is where and as large as asked, within 3 points (off by $(field off_by_points))" \
|
||||
'[[ "$(field off_by_points)" != None ]] && (( $(field off_by_points) <= 3 ))'
|
||||
judge "no ink anywhere else on the page — no bars ($(field ink_outside_picture) pixels)" \
|
||||
'[[ "$(field ink_outside_picture)" == 0 ]]'
|
||||
if [[ "$fill" == fill ]]; then
|
||||
# The mark is in the picture's left fifth, which filling a
|
||||
# portrait page with a wide picture cuts off. That is what the
|
||||
# control says it does; the fit scenarios prove it happens only
|
||||
# when asked.
|
||||
judge "Fill cut the edges off, as it says it will" '(( $(field pink_pixels) == 0 ))'
|
||||
else
|
||||
judge "the pink corner mark is on the paper — nothing cut off" '(( $(field pink_pixels) > 0 ))'
|
||||
fi
|
||||
if [[ "$color" == gray ]]; then
|
||||
judge "and it went in black and white" '[[ "$(job_device $jobs)" == *pxlmono* ]]'
|
||||
judge "the preview shows it in black and white" "said 'shown_gray=True'"
|
||||
fi
|
||||
judge "one job reached CUPS" '[[ $(count) -eq 1 ]]'
|
||||
dims=$(lab "python3 -c 'from PyQt6.QtGui import QImage; i=QImage(\"/opt/wonderink-check/www/$file\"); print(f\"{i.width()}x{i.height()}\")'" 2>/dev/null)
|
||||
judge_layout "$dims" "$size" "$position" "$paper" "$fill" "$color" ;;
|
||||
bw-*)
|
||||
judge "the preview starts in colour" "said 'COLOUR FIRST shown_gray=False'"
|
||||
if [[ "$scenario" != bw-colour-again ]]; then
|
||||
judge "Black and white shows a grey page, every time it is chosen" \
|
||||
'! lines "want=gray" | grep -qv "shown_gray=True" && lines "want=gray" | grep -q .'
|
||||
fi
|
||||
if lines "want=colour" | grep -q .; then
|
||||
judge "Color shows the colour page again, every time" '! lines "want=colour" | grep -qv "shown_gray=False"'
|
||||
fi
|
||||
case "$scenario" in
|
||||
bw-web)
|
||||
judge "turned over and over, it stays on page 2 of 3" '! lines TOGGLE | grep -qv "page=2/3"'
|
||||
judge "black and white is made once, and the same file shown each time" \
|
||||
'[[ $(lines "want=gray" | grep -o "pdf=[^ ]*" | sort -u | wc -l) -eq 1 ]]'
|
||||
judge "and shown again at once (after the first: $(lines 'want=gray' | tail -n +2 | grep -o 'took=[0-9.]*' | tr '\n' ' '))" \
|
||||
'! lines "want=gray" | tail -n +2 | grep -o "took=[0-9.]*" | cut -d= -f2 | grep -qv "^0\.[0-4]"'
|
||||
judge "one job" '[[ $(count) -eq 1 ]]'
|
||||
judge "page 2 only, two copies" \
|
||||
'[[ "$(job_options $jobs)" == *page-ranges=2* && "$(job_options $jobs)" == *"argv[4]=\"2\""* ]]'
|
||||
judge "in black and white, by the driver's own option" \
|
||||
'[[ "$(job_options $jobs)" == *ColorModel=Grayscale* && "$(job_device $jobs)" == *pxlmono* ]]' ;;
|
||||
bw-pdf)
|
||||
judge "one job" '[[ $(count) -eq 1 ]]'
|
||||
judge "in black and white, by the driver's own option" \
|
||||
'[[ "$(job_options $jobs)" == *ColorModel=Grayscale* && "$(job_device $jobs)" == *pxlmono* ]]' ;;
|
||||
bw-colour-again)
|
||||
judge "one job" '[[ $(count) -eq 1 ]]'
|
||||
judge "in colour, with no grey option" \
|
||||
'[[ "$(job_options $jobs)" != *ColorModel=Grayscale* && "$(job_device $jobs)" == *pxlcolor* ]]' ;;
|
||||
bw-cancel)
|
||||
judge "Cancel sends nothing" '[[ $(count) -eq 0 ]]'
|
||||
judge "and nothing was left behind" "said 'scratch_left=\[\]'" ;;
|
||||
esac
|
||||
if [[ $(count) -eq 1 ]]; then
|
||||
spool=$(spool_file "$jobs")
|
||||
judge "CUPS was given exactly the file the preview showed" "lab 'cmp -s /tmp/rig-out/preview.pdf $spool'"
|
||||
answer=$(colour_of "$spool")
|
||||
if [[ "$scenario" == bw-colour-again ]]; then
|
||||
judge "and it is in colour ($answer)" '! is_gray "$answer"'
|
||||
else
|
||||
judge "and every page of it is grey ($answer)" 'is_gray "$answer"'
|
||||
fi
|
||||
fi ;;
|
||||
rclick-page)
|
||||
judge "right-click on the words offers Print page, and not Print image" \
|
||||
"said \"MENU .*'Print page…'\" && ! said \"'Print image…'\""
|
||||
judge "which prints the lesson page, not a picture" "said 'PREVIEW picture=False'"
|
||||
judge "one job" '[[ $(count) -eq 1 ]]'
|
||||
judge "CUPS was given exactly the page the preview showed" \
|
||||
"lab 'cmp -s /tmp/rig-out/preview.pdf $(spool_file "$jobs")'"
|
||||
judge "the teacher's clipboard is untouched" teacher_text_kept ;;
|
||||
rclick-page-gray)
|
||||
judge "a lesson page full of pictures turns grey in the preview ($(lines 'GRAY PAGE' | grep -o 'took=[0-9.]*'))" \
|
||||
"said 'GRAY PAGE .*shown_gray=True'"
|
||||
judge "one job" '[[ $(count) -eq 1 ]]'
|
||||
spool=$(spool_file "$jobs")
|
||||
judge "CUPS was given exactly the file the preview showed" "lab 'cmp -s /tmp/rig-out/preview.pdf $spool'"
|
||||
answer=$(colour_of "$spool")
|
||||
judge "and every page of it is grey ($answer)" 'is_gray "$answer"'
|
||||
judge "in black and white, by the driver's own option" \
|
||||
'[[ "$(job_options $jobs)" == *ColorModel=Grayscale* && "$(job_device $jobs)" == *pxlmono* ]]' ;;
|
||||
rclick-image:*)
|
||||
IFS=: read -r _ element size position color <<< "$scenario"
|
||||
judge "right-click on the picture offers Print image and Print page" \
|
||||
"said \"MENU .*'Print image…', 'Print page…'\""
|
||||
judge "Print image opens the picture layout" "said 'PICTURE picture_box=True'"
|
||||
judge "named for the lesson it came from" "said \"title='Picture from Picture lesson'\""
|
||||
judge "nothing was fetched again to get it ($(fetched_since) requests)" '[[ $(fetched_since) -eq 0 ]]'
|
||||
judge "the teacher's clipboard is theirs again" teacher_text_kept
|
||||
if [[ "$color" == gray ]]; then
|
||||
judge "the preview shows it in black and white" "said 'shown_gray=True'"
|
||||
fi
|
||||
judge "one job reached CUPS" '[[ $(count) -eq 1 ]]'
|
||||
dims=$(grep -o 'image=[0-9]*x[0-9]*' <<< "$out" | head -1 | cut -d= -f2)
|
||||
judge_layout "$dims" "$size" "$position" auto fit "$color" ;;
|
||||
rclick-broken)
|
||||
judge "a picture that never loaded is still offered as a picture" "said \"MENU .*'Print image…'\""
|
||||
judge "and the teacher is told it could not be taken, with Print off" \
|
||||
"said \"BROKEN status='This picture could not be taken from the page\" && said 'print_enabled=False pages=0 picture=False'"
|
||||
judge "the whole page is not printed instead" '[[ $(count) -eq 0 ]]'
|
||||
judge "the teacher's clipboard is untouched" teacher_text_kept ;;
|
||||
rclick-cancel)
|
||||
judge "the picture preview came up" "said 'PREVIEW picture=True'"
|
||||
judge "Cancel sends nothing" '[[ $(count) -eq 0 ]]'
|
||||
judge "the teacher's clipboard is theirs again" teacher_text_kept
|
||||
judge "and nothing was left behind" "said 'scratch_left=\[\]'" ;;
|
||||
esac
|
||||
|
||||
[[ "$failed" -eq 0 ]] || { echo "$out" | tail -15 | sed 's/^/ /'; }
|
||||
|
||||
Reference in New Issue
Block a user