mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-20 07:14:13 +02:00
Register the quit-during-modal test with CTest, and fix two bugs in it
The test added with the #904 fix was run by hand. Register it so it runs with the rest of the suite, and fix two defects found while extending it to the element editor -- both of which made it report success it had not earned. nm -C "$BINARY" | grep -q <sym> under `set -o pipefail`: grep exits at the first match, nm dies of SIGPIPE, and the pipeline reports failure. The symbol check therefore skipped the test on every build that could actually run it. Read nm's output into a variable once and match with `case`. The input file was copied to a hardcoded "$SANDBOX/project.qet". QElectroTech picks the editor from the extension, so passing a .elmt gave a failed project load in the diagram editor rather than an element editor -- the run still found a dialog, still called quitQET(), and still reported a result, just for the wrong window. Preserve the basename. With that fixed, the element-editor path is exercised on its own: a read-only .elmt opens a message box, and on a build without the fix the run aborts with "double free or corruption" under ~QETElementEditor(), where before it named ~QETDiagramEditor(). The guard QETElementEditor calls from its closeEvent() covers a real crash, not a theoretical one. Registered on Linux only, and it reports 77 -- CTest's SKIP_RETURN_CODE -- when it cannot run at all: no gdb, a gdb built without Python, or a stripped binary whose QETApp symbols it cannot call. A release build that this test cannot drive is not a failing build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,5 +29,7 @@ message(". Add sub directory googletest")
|
||||
add_subdirectory(googletest)
|
||||
message(". Add sub directory googlemock")
|
||||
add_subdirectory(googlemock)
|
||||
message(". Add sub directory modal-quit-regression")
|
||||
add_subdirectory(modal-quit-regression)
|
||||
message(". Add sub directory qttest")
|
||||
add_subdirectory(qttest)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Copyright 2006 The QElectroTech Team
|
||||
# This file is part of QElectroTech.
|
||||
#
|
||||
# QElectroTech is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# QElectroTech is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Issue #904 -- see run.sh for what this guards and how.
|
||||
#
|
||||
# Driven by gdb, so it is registered on Linux only. It reports 77 (SKIP)
|
||||
# rather than failing when it cannot run at all: no gdb, a gdb without
|
||||
# Python, or a stripped binary whose symbols it cannot call.
|
||||
if(UNIX AND NOT APPLE)
|
||||
message(". Add test modal_quit_regression")
|
||||
add_test(
|
||||
NAME modal_quit_regression
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/run.sh --binary $<TARGET_FILE:qelectrotech>)
|
||||
set_tests_properties(modal_quit_regression PROPERTIES
|
||||
SKIP_RETURN_CODE 77
|
||||
TIMEOUT 180)
|
||||
endif()
|
||||
@@ -18,7 +18,17 @@ tests/modal-quit-regression/run.sh --binary build/qelectrotech
|
||||
Needs `gdb` with Python. It runs on the offscreen platform, so no X server or
|
||||
window manager is required. Takes about ten seconds.
|
||||
|
||||
Exit codes: `0` survived, `1` crashed, `2` the scenario did not happen.
|
||||
It is also registered with CTest on Linux (`ctest -R modal_quit_regression`).
|
||||
|
||||
Exit codes: `0` survived, `1` crashed, `2` the scenario did not happen,
|
||||
`77` it could not run here.
|
||||
|
||||
That last one matters for a release build. The scenario is driven by calling
|
||||
`QETApp::instance()` and `QETApp::quitQET()` through gdb, so those symbols have
|
||||
to survive into the binary: against a **stripped** build there is nothing to
|
||||
call, and the same applies without gdb or with a gdb built without Python. All
|
||||
three report 77, which is CTest's `SKIP_RETURN_CODE`, so a build this test
|
||||
cannot drive is skipped rather than failed.
|
||||
|
||||
## How it works, and why this way
|
||||
|
||||
@@ -38,5 +48,24 @@ the dialog's loop is running. The test does the same thing through gdb:
|
||||
It matches no window titles and no window ids. Titles are translated, and
|
||||
`tests/ipc-regression` once shipped a pass that could not fail because of that.
|
||||
|
||||
Checked both ways before being committed: it fails on a build without the fix
|
||||
(signal 6, `free(): invalid size`) and passes with it.
|
||||
## Covering the element editor too
|
||||
|
||||
`--project` decides which editor is under test, because QElectroTech picks the
|
||||
editor from the file extension. Pass a `.qet` and the run exercises
|
||||
`QETDiagramEditor`; pass a **read-only `.elmt`** and it exercises
|
||||
`QETElementEditor`, which shows a "file is read-only" message box on open and so
|
||||
reaches the same nested loop by a different route:
|
||||
|
||||
```bash
|
||||
chmod -w some.elmt
|
||||
tests/modal-quit-regression/run.sh --binary build/qelectrotech --project some.elmt
|
||||
```
|
||||
|
||||
That distinction is why the file name is preserved when it is copied into the
|
||||
sandbox. Renaming a `.elmt` to `project.qet` would make the run silently test
|
||||
the diagram editor again, and still report PASS.
|
||||
|
||||
Checked both ways, in both editors, before being committed: without the fix the
|
||||
diagram-editor run aborts with signal 6 under `~QETDiagramEditor()` and the
|
||||
element-editor run with `double free or corruption` under
|
||||
`~QETElementEditor()`; with the fix both survive.
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
# Quit-during-modal regression gate -- issue #904.
|
||||
#
|
||||
# tests/modal-quit-regression/run.sh --binary build/qelectrotech
|
||||
# tests/modal-quit-regression/run.sh --binary build/qelectrotech \
|
||||
# --project read-only.elmt
|
||||
#
|
||||
# --project also picks the editor under test: QElectroTech chooses it from the
|
||||
# extension, so a .qet exercises QETDiagramEditor and a read-only .elmt
|
||||
# exercises QETElementEditor (which opens a message box of its own).
|
||||
#
|
||||
# WHAT IT GUARDS
|
||||
#
|
||||
@@ -39,9 +45,13 @@
|
||||
# needed -- only gdb with Python.
|
||||
#
|
||||
# RESULT
|
||||
# exit 0 PASS quitQET() ran inside the modal loop and the process survived
|
||||
# exit 1 FAIL the process died of a signal after quitQET()
|
||||
# exit 2 ERROR the scenario never happened (no dialog, gdb problem, ...)
|
||||
# exit 0 PASS quitQET() ran inside the modal loop and the process survived
|
||||
# exit 1 FAIL the process died of a signal after quitQET()
|
||||
# exit 2 ERROR the scenario never happened (no dialog, gdb problem, ...)
|
||||
# exit 77 SKIP cannot run here: no gdb, a gdb without Python, or a
|
||||
# stripped binary. 77 is CTest's SKIP_RETURN_CODE, so a
|
||||
# build this test cannot drive is reported as skipped
|
||||
# rather than failed.
|
||||
#
|
||||
set -uo pipefail
|
||||
|
||||
@@ -68,9 +78,30 @@ if [ -z "$PROJECT" ]; then
|
||||
fi
|
||||
[ -f "$PROJECT" ] || { echo "no project found; pass --project" >&2; exit 2; }
|
||||
|
||||
command -v gdb >/dev/null || { echo "missing required tool: gdb" >&2; exit 2; }
|
||||
skip() { echo "SKIP: $1"; exit 77; }
|
||||
|
||||
command -v gdb >/dev/null || skip "gdb is not installed"
|
||||
gdb -batch -ex 'python import gdb' >/dev/null 2>&1 \
|
||||
|| { echo "gdb has no Python support" >&2; exit 2; }
|
||||
|| skip "this gdb has no Python support"
|
||||
|
||||
# The scenario is driven by calling QETApp::instance() and QETApp::quitQET()
|
||||
# through gdb, so their symbols have to survive into the binary. A stripped
|
||||
# release build cannot be driven at all -- that is a property of the build,
|
||||
# not a failure of the code under test, so report it as skipped.
|
||||
#
|
||||
# Read nm's output once into a variable rather than piping it into grep -q:
|
||||
# grep -q exits at the first match, nm dies of SIGPIPE, and under `set -o
|
||||
# pipefail` the pipeline reports failure even though the symbol was found --
|
||||
# which would skip this test on every build that can actually run it.
|
||||
if command -v nm >/dev/null; then
|
||||
SYMBOLS="$(nm -C "$BINARY" 2>/dev/null || true)"
|
||||
for sym in "QETApp::instance()" "QETApp::quitQET()"; do
|
||||
case "$SYMBOLS" in
|
||||
*"$sym"*) ;;
|
||||
*) skip "binary has no symbol for $sym (stripped build?)" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
SANDBOX="$(mktemp -d /tmp/qet-modal-quit.XXXXXX)"
|
||||
cleanup() { [ "${KEEP_LOGS:-0}" = "1" ] || rm -rf "$SANDBOX"; }
|
||||
@@ -82,7 +113,12 @@ trap cleanup EXIT
|
||||
TEST_BINARY="$SANDBOX/qelectrotech-modalquit"
|
||||
cp "$BINARY" "$TEST_BINARY" || { echo "could not copy binary" >&2; exit 2; }
|
||||
|
||||
cp "$PROJECT" "$SANDBOX/project.qet" || { echo "could not copy project" >&2; exit 2; }
|
||||
# Keep the original file name. QElectroTech decides what to open from the
|
||||
# extension, so copying a .elmt to "project.qet" would quietly turn an
|
||||
# element-editor run into a failed project load -- and the scenario would
|
||||
# still "work", against the wrong window.
|
||||
SANDBOX_PROJECT="$SANDBOX/$(basename "$PROJECT")"
|
||||
cp "$PROJECT" "$SANDBOX_PROJECT" || { echo "could not copy input file" >&2; exit 2; }
|
||||
|
||||
export HOME="$SANDBOX/home"
|
||||
export XDG_CONFIG_HOME="$HOME/.config"
|
||||
@@ -119,7 +155,7 @@ bt 20
|
||||
kill
|
||||
EOF
|
||||
|
||||
gdb -batch -x "$SANDBOX/scenario.gdb" --args "$TEST_BINARY" "$SANDBOX/project.qet" \
|
||||
gdb -batch -x "$SANDBOX/scenario.gdb" --args "$TEST_BINARY" "$SANDBOX_PROJECT" \
|
||||
> "$SANDBOX/gdb.log" 2>&1 &
|
||||
GDB_PID=$!
|
||||
( sleep 120; kill -9 "$GDB_PID" 2>/dev/null ) &
|
||||
|
||||
Reference in New Issue
Block a user