-
Notifications
You must be signed in to change notification settings - Fork 1.3k
ui-smoke phase 3: screenshots, writable config mirrors, homing settle #4136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
grandixximo
wants to merge
28
commits into
LinuxCNC:master
Choose a base branch
from
grandixximo:ui-tests-phase3
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
36c9bb2
test: ui-smoke phase 3, screenshot the GUI on failure and confirm on …
grandixximo 6f29198
test: run gmoccapy ui-smoke against a writable config mirror
grandixximo 58cd4f8
ui-smoke: settle after homing before requesting AUTO
grandixximo 477441d
test: ui-smoke compare confirm shot to a committed reference image
grandixximo 2f200c5
ci: install gdb up front so the ui-smoke crash dump path does not apt…
grandixximo 418f509
tests/runtests: export NOSUDO via RUNTESTS_NOSUDO so children can hon…
grandixximo 6e3ce4c
test: ui-smoke touchy-fit, fail if the window exceeds the screen
grandixximo d5f84a8
test: bump ui-smoke compare fuzz to 40 % so the metric tracks real drift
grandixximo 9465f6f
test: refresh touchy ui-smoke for the new minimum-height patch
grandixximo 14dd4dd
test: regenerate axis/gmoccapy/qtdragon references from CI output
grandixximo 191f13f
ci: move gdb to control build-deps so package-arch tests get it too
grandixximo e79a3e4
ui-smoke: only use a readable core from this run for the native backt…
grandixximo ce9f034
tests: dual red and absolute-difference ui-smoke diffs at 0% fuzz
grandixximo 57be056
test: adopt CI confirm shots as ui-smoke references
grandixximo a0656c2
tests: stabilize qtdragon ui-smoke preview and gcode scroll
grandixximo c6c1b9f
tests: arm the ui-smoke core dump via sudo so CI gets a native backtrace
grandixximo 1c9e6d2
tests: settle the ui-smoke confirm shot until the UI stops changing
grandixximo 7641388
test: update axis ui-smoke reference to the settled Max Velocity
grandixximo 6d70dfc
tests: make crash dumps opt-in via runtests -d
grandixximo 003c8cc
tests: reject runtests -d with -u instead of silently no-op
grandixximo a0fe9dc
Merge branch 'master' into ui-tests-phase3
grandixximo 394a92f
tests: drop unused ROOT var in make-references.sh (shellcheck SC2034)
grandixximo 5c7a7d2
Merge branch 'master' into ui-tests-phase3
grandixximo 1ad4e00
test: update axis ui-smoke reference back to the 300 Max Velocity
grandixximo dd90878
Merge remote-tracking branch 'upstream/master' into ui-tests-phase3
grandixximo ed61cd9
tests: let the GUI see the opened program before AUTO_RUN
grandixximo d861d36
tests: collect ui-smoke cores without sudo, via coredumpctl or CI-arm…
grandixximo 4cb04a5
tests: retry ui-smoke homing after a late GUI startup ESTOP
grandixximo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| #!/bin/bash | ||
| # Known-good image comparison for the UI smoke confirm shots. Complements | ||
| # screenshot.sh: that grabs confirm.png on a clean run; this compares it to | ||
| # a committed reference.png and writes two visual diffs. Like screenshot.sh | ||
| # it carries no state and is a logged no-op whenever it cannot run, so it can | ||
| # never turn a pass into a fail. | ||
| # | ||
| # Two diff images, both at 0% fuzz so nothing is hidden: | ||
| # diff.png red highlight over a faded copy of the reference (where it | ||
| # changed, ImageMagick "compare" style) | ||
| # diff-abs.png absolute per-channel difference |b - a|, black where equal | ||
| # and bright where it changed (unbiased, magnitude preserved) | ||
| # | ||
| # Policy: we never fail a test on the image difference. freetype/font | ||
| # versions differ across distros, so some drift is expected; the diffs are | ||
| # here to record what changed, not to gate. The function always returns 0. | ||
| # | ||
| # Local "make a known-good image" workflow: run a test with | ||
| # UI_SMOKE_UPDATE_REFERENCE=1 (see make-references.sh) and the freshly | ||
| # captured shot is saved as the committed reference instead of compared. | ||
|
|
||
| # Set IM_COMPARE and IM_CONVERT to the IM7 or IM6 entry points; return 1 | ||
| # if ImageMagick is absent. | ||
| _im_tools() { | ||
| if command -v magick >/dev/null 2>&1; then | ||
| IM_COMPARE="magick compare"; IM_CONVERT="magick" | ||
| elif command -v compare >/dev/null 2>&1; then | ||
| IM_COMPARE="compare"; IM_CONVERT="convert" | ||
| else | ||
| return 1 | ||
| fi | ||
| } | ||
|
|
||
| # compare_to_reference <shot> <reference> <diff> <diff_abs> | ||
| # Compare the captured shot to the committed reference, writing a red-highlight | ||
| # diff and an absolute-difference diff. Always returns 0. | ||
| compare_to_reference() { | ||
| shot="$1" | ||
| reference="$2" | ||
| diff="$3" | ||
| diff_abs="$4" | ||
|
|
||
| if [ ! -s "$shot" ]; then | ||
| echo "compare: no shot at $shot, skipping" | ||
| return 0 | ||
| fi | ||
|
|
||
| # Update mode: adopt this shot as the new known-good reference. | ||
| if [ "${UI_SMOKE_UPDATE_REFERENCE:-}" = "1" ]; then | ||
| if cp -f "$shot" "$reference"; then | ||
| echo "compare: saved reference $reference (UI_SMOKE_UPDATE_REFERENCE=1)" | ||
| else | ||
| echo "compare: failed to save reference $reference" | ||
| fi | ||
| return 0 | ||
| fi | ||
|
|
||
| if [ ! -s "$reference" ]; then | ||
| echo "compare: no reference at $reference yet, skipping (run with UI_SMOKE_UPDATE_REFERENCE=1 to create one)" | ||
| return 0 | ||
| fi | ||
|
|
||
| _im_tools || { | ||
| echo "compare: no ImageMagick available, skipping" | ||
| return 0 | ||
| } | ||
|
|
||
| # Red-highlight diff at 0% fuzz: -metric AE counts every differing pixel | ||
| # (interpretable), and the same call writes diff.png. compare exits 0 | ||
| # (identical), 1 (differ) or 2 (error, e.g. the shots are different | ||
| # sizes). We log the outcome and always succeed. | ||
| metric=$($IM_COMPARE -metric AE -fuzz 0% "$reference" "$shot" "$diff" 2>&1) | ||
| rc=$? | ||
| case "$rc" in | ||
| 0) echo "compare: $shot matches $reference (AE=$metric)" ;; | ||
| 1) echo "compare: $shot differs from $reference (AE=$metric differing pixels); diff at $diff" ;; | ||
| *) echo "compare: could not compare $shot to $reference (rc=$rc): $metric" ;; | ||
| esac | ||
|
|
||
| # Absolute-difference diff |b - a|: black where equal, bright where it | ||
| # changed. Unbiased (direction does not matter) and keeps magnitude. | ||
| if $IM_CONVERT "$reference" "$shot" -compose difference -composite "$diff_abs" 2>/dev/null; then | ||
| echo "compare: absolute-difference diff at $diff_abs" | ||
| else | ||
| echo "compare: could not write absolute-difference diff $diff_abs" | ||
| fi | ||
| return 0 | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,45 +1,68 @@ | ||
| #!/bin/bash | ||
| # Native crash capture for the UI smoke launchers. A GUI segfault is the | ||
| # failure these tests most need to explain, and it lands in C/C++ (Qt, | ||
| # dbus, GL) where PYTHONFAULTHANDLER stops at the event-loop frame. Arm a | ||
| # core dump before launch; after the run, if the GUI left a core, print a | ||
| # native backtrace into the log so CI shows the faulting frame directly. | ||
| # Source with LIB_DIR set; runs only on the failure path, so green runs | ||
| # pay nothing. | ||
| # Native crash capture for the UI smoke launchers. A GUI segfault lands in | ||
| # C/C++ (Qt, dbus, GL); PYTHONFAULTHANDLER (set in launch-env.sh) prints a | ||
| # Python traceback to linuxcnc.err naming the frame that called in, which is | ||
| # the reliable, environment-independent crash signal and is surfaced in every | ||
| # failure log. This helper adds a best-effort native backtrace on top when | ||
| # runtests is given -d (ENABLE_CRASHDUMPS=1): raise the core size limit | ||
| # before launch, and after the run, if a readable core from this run is | ||
| # found, gdb-print its backtrace. Cores are collected from wherever the | ||
| # system puts them: systemd-coredump via coredumpctl, or a plain-file | ||
| # kernel.core_pattern (the CI workflow points it at CORE_DIR with a job-level | ||
| # sudo sysctl on the disposable runner; local runs often just get ./core). | ||
| # No sudo and no global system changes here. Source with LIB_DIR set; the | ||
| # report runs only on the failure path, so green runs pay nothing. | ||
|
|
||
| crashdump_arm() { | ||
| CORE_DIR="$(mktemp -d -t ui-smoke-cores.XXXXXX)" | ||
| # Off unless runtests was given -d. The Python faulthandler traceback | ||
| # does not depend on this and is always present. | ||
| [ "${ENABLE_CRASHDUMPS:-0}" = "1" ] || return 0 | ||
| # CORE_DIR is where the CI workflow's core_pattern writes; it also | ||
| # receives a core extracted via coredumpctl. | ||
| CORE_DIR="${UI_SMOKE_CORE_DIR:-/tmp/linuxcnc-ui-smoke-cores}" | ||
| mkdir -p "$CORE_DIR" 2>/dev/null || true | ||
| export CORE_DIR | ||
| ulimit -c unlimited 2>/dev/null || true | ||
| # core_pattern is global; only set it if already root. Never sudo: | ||
| # the suite must run unattended. Non-root falls back to a cwd "core". | ||
| if [ "$(id -u)" = 0 ]; then | ||
| sysctl -w "kernel.core_pattern=$CORE_DIR/core.%e.%p" >/dev/null 2>&1 || true | ||
| fi | ||
| crashdump_arm_time=$(date +%s) | ||
| } | ||
|
|
||
| crashdump_report() { | ||
| [ "${ENABLE_CRASHDUMPS:-0}" = "1" ] || return 0 | ||
| [ -n "${CORE_DIR:-}" ] || return 0 | ||
| local core | ||
| # shellcheck disable=SC2012 # mktemp dir, no odd filenames | ||
| core=$(ls -t "$CORE_DIR"/core* ./core* /tmp/core* 2>/dev/null | head -1) | ||
| if [ -n "$core" ]; then | ||
| echo "=== crash: native backtrace ($core) ===" | ||
| # gdb reads the core; pull it in if missing, only when root. | ||
| if ! command -v gdb >/dev/null 2>&1 && [ "$(id -u)" = 0 ]; then | ||
| apt-get install -y -q gdb >/dev/null 2>&1 || true | ||
| fi | ||
| if command -v gdb >/dev/null 2>&1; then | ||
| # "bt" first: gdb auto-selects the faulting thread on a SIGSEGV | ||
| # core. "thread apply all bt" after gives the rest. | ||
| gdb -batch -nx \ | ||
| -ex "bt" \ | ||
| -ex "echo \n=== all threads ===\n" \ | ||
| -ex "thread apply all bt" \ | ||
| "$(command -v python3)" "$core" 2>&1 | head -400 | ||
| else | ||
| echo "(gdb unavailable; core left at $core)" | ||
| local c core="" | ||
| # Only trust a core we know is from this run and can actually read: one | ||
| # in CORE_DIR, a relative "core" in the cwd that postdates arming, or | ||
| # one systemd-coredump logged since arming (coredumpctl needs no root | ||
| # for our own processes). A broad /tmp glob would pick up a stale or | ||
| # foreign core, and gdb would just print "Permission denied". | ||
| for c in "$CORE_DIR"/core*; do | ||
| [ -e "$c" ] && [ -r "$c" ] && { core="$c"; break; } | ||
| done | ||
| if [ -z "$core" ]; then | ||
| for c in ./core*; do | ||
| [ -e "$c" ] && [ -r "$c" ] && [ "$c" -nt "$CORE_DIR" ] && { core="$c"; break; } | ||
| done | ||
| fi | ||
| if [ -z "$core" ] && command -v coredumpctl >/dev/null 2>&1; then | ||
| if coredumpctl list --no-legend --since "@$crashdump_arm_time" python3 2>/dev/null | grep -q .; then | ||
| coredumpctl dump python3 --output="$CORE_DIR/core.coredumpctl" >/dev/null 2>&1 || true | ||
| [ -s "$CORE_DIR/core.coredumpctl" ] && core="$CORE_DIR/core.coredumpctl" | ||
| fi | ||
| fi | ||
| if [ -n "$core" ] && command -v gdb >/dev/null 2>&1; then | ||
| echo "=== crash: native backtrace ($core) ===" | ||
| # "bt" first: gdb auto-selects the faulting thread on a SIGSEGV | ||
| # core. "thread apply all bt" after gives the rest. | ||
| gdb -batch -nx \ | ||
| -ex "bt" \ | ||
| -ex "echo \n=== all threads ===\n" \ | ||
| -ex "thread apply all bt" \ | ||
| "$(command -v python3)" "$core" 2>&1 | head -400 | ||
| else | ||
| # No readable core. The Python faulthandler traceback in | ||
| # linuxcnc.err already names the crash site; the native backtrace | ||
| # is only a best-effort extra. | ||
| echo "=== crash: no readable core dump; see the Python traceback in linuxcnc.err above ===" | ||
| fi | ||
| rm -rf "$CORE_DIR" | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.