Snapshot the window set before the GUI test dispatch loop by whosawhatsis · Pull Request #7046 · openscad/openscad · GitHub
Skip to content

Snapshot the window set before the GUI test dispatch loop - #7046

Open
whosawhatsis wants to merge 1 commit into
openscad:masterfrom
whosawhatsis:feature/gui-test-window-snapshot
Open

whosawhatsis wants to merge 1 commit into
openscad:masterfrom
whosawhatsis:feature/gui-test-window-snapshot

Conversation

@whosawhatsis

Copy link
Copy Markdown
Contributor

openscad_gui.cc's GUI-test dispatch loop iterates app.windowManager.getWindows() directly:

for (auto w : app.windowManager.getWindows()) {
  failureCount += runAllTest(w);
}

WindowManager::getWindows() returns a const QSet<MainWindow *>& — a reference to the live set, not a copy — so if any test opens a new window while this loop is running (as a real "File > New Window" test would, and as the new regression test below does), the QSet can mutate mid-iteration. That's undefined behavior for a range-for over a live container: growing a QSet can trigger a rehash that invalidates every existing iterator, including the one this loop is using.

Fix: take an explicit snapshot before iterating.

const QSet<MainWindow *> windows = app.windowManager.getWindows();
for (auto w : windows) {
  failureCount += runAllTest(w);
}

Added TestMainWindow::checkOpeningWindowDuringTestRunDoesNotCrash(), which opens a second window mid-run (new MainWindow(QStringList()) — on_fileActionNewWindow_triggered() is a private slot, not reachable from the test) and asserts the window count grew by exactly one, then closes the extra window so later tests see the expected single-window state.

This is part of the preparatory refactoring series for re-implementing #6977 (declined on size) as a reviewable stack of smaller PRs.

Testing

  • Test-first attempted: with the loop unfixed, running --run-all-gui-tests repeatedly (3 runs) did not crash — with the window count only going from 1 to 2, this build's QSet bucket table doesn't happen to rehash, so there's no deterministic crash to assert on at this scale. The bug is genuine regardless (iterating a container while mutating it is UB per the standard, independent of whether a particular run's hash-table size happens not to trigger a rehash) — the new test guards the actual invariant (opening a window mid-run does not change the window count in a surprising way) and the snapshot fix removes the UB outright.
  • With the fix applied: ./OpenSCAD --run-all-gui-tests — all suites pass including the new test, 0 failures.
  • ctest -j8 on macOS: 3 known SVG arc tessellation failures only (same as master).
  • ./scripts/beautify.sh --check clean with clang-format 18.1.8.

User documentation (for the openscad.org wiki)

No user-visible change — internal test-infrastructure fix only.

🤖 Generated with Claude Code

openscad_gui.cc's GUI-test dispatch loop iterated
app.windowManager.getWindows() directly -- a reference to the live
QSet, not a copy. A test opening a new window mid-run (as a real
"File > New Window" test would) mutates that QSet while the loop is
iterating it, which is undefined behavior: growing a QSet can trigger
a rehash that invalidates the loop's iterator.

Snapshot the window set into a local QSet before iterating. Added
TestMainWindow::checkOpeningWindowDuringTestRunDoesNotCrash(), which
opens a second window mid-run and asserts the window count grew by
exactly one, then closes the extra window.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant