mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-25 11:24:12 +02:00
599228fe6e
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>
72 lines
3.2 KiB
Markdown
72 lines
3.2 KiB
Markdown
# Quit-during-modal regression test
|
|
|
|
Guards the abort reported in #904.
|
|
|
|
`QETDiagramEditor::openAndAddProject()` shows `BackupDialog` as a stack object
|
|
parented to the editor and `exec()`s it, and `QET::QetMessageBox` does the same
|
|
for every message box. `exec()` runs a nested event loop. Closing the editor
|
|
during that loop turns `WA_DeleteOnClose` into a `deleteLater()` that the nested
|
|
loop processes, so `~QWidget()` deletes the stack-allocated dialog and the
|
|
process aborts. `QETMainWindow::refuseCloseWhileModal()` refuses such a close.
|
|
|
|
## Running it
|
|
|
|
```bash
|
|
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.
|
|
|
|
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
|
|
|
|
On Linux there is nothing to click: the menu bar belongs to the window the
|
|
dialog blocks, and Qt ignores window-manager close requests for a blocked
|
|
window. The reported route is macOS, where File > Quit lives in the application
|
|
menu and stays usable during a modal — and what it does is call `close()` while
|
|
the dialog's loop is running. The test does the same thing through gdb:
|
|
|
|
1. break on `QDialog::exec()`;
|
|
2. let the dialog's loop run, then interrupt it, so the main thread is inside
|
|
the nested loop — the only place the bug exists, because a `deleteLater()`
|
|
posted *before* `exec()` started is not processed by that loop;
|
|
3. call `QETApp::quitQET()`, which closes every editor;
|
|
4. let it run: an unfixed build aborts within a second.
|
|
|
|
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.
|
|
|
|
## 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.
|