Files
Waybar/test/smoke
AlexandClaude Opus 4.8 a7b3a2c0db ci(smoke): fix state tier hang from bare wait on a lingering daemon
The state tier started actually running mpd in 74f0d33, which exposed a
deadlock in teardown: state.sh launches `mpd --no-daemon &` and never kills
it during the tier, and its cleanup() called smoke::stop *before* killing mpd.
smoke::stop ended in a bare `wait`, which reaps *every* background job of the
shell -- including the still-running mpd -- so it blocked until GitHub's 6h
job timeout. continue-on-error doesn't help: it catches failures, not hangs.

- lib.sh: smoke::stop now waits only on the PIDs it owns (waybar, compositor),
  so an unrelated daemon left running by a tier can't deadlock teardown.
- state.sh: cleanup() tears down mpd/pulseaudio before smoke::stop.
- smoke.yml: add timeout-minutes: 20 so a future hang fails fast instead of
  burning the default 6h runner budget.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 23:00:33 +02:00
..

Smoke / render / interaction tests

The smoke workflow builds Waybar with AddressSanitizer and runs the real binary inside a headless compositor (software-rendered, no GPU) to exercise it end to end. All helpers share lib.sh.

What it checks

Tier Check Script
0 Launches, stays alive, and logs no ASan / Gtk-CRITICAL / crash — for every launch below lib.sh assert_clean
Coverage tripwire — every Factory module must be classified (source-only, runs before the build) coverage.sh
1 Renders — deterministic config screenshotted with grim, bar strip not blank run.sh
1 Per-module matrix — each headless-safe module rendered standalone and inside a group, each torn down via SIGINT modules.sh
2 Golden — screenshot vs reference.png (fuzz 8%, 800px) workflow
2 Interaction — inject pointer clicks via sway; assert on-click side effect + format-alt toggle interact.sh
2 Accessibility — assert module labels via the AT-SPI tree (robust to fonts) a11y.sh / a11y.py
3 Layout matrix — top / bottom / left (vertical) + HiDPI (scale 2) positions.sh
3 Second compositor — same launch under labwc workflow (COMPOSITOR=labwc)
4 Lifecycle / teardown — clean SIGINT exit, runtime output hotplug, toggle + reload churn, fast-interval teardown (the C++ destructor path a kill never runs, #5182) lifecycle.sh
4 Custom-backend fuzz — empty / non-zero-exit / invalid-JSON / huge / non-UTF8 / empty-format exec output fuzz.sh
5 State transitions (best-effort) — real mpd driven through an empty queue (#5183) + stop/clear, pulseaudio + slider on a null sink state.sh
6 Fake hardware (best-effort)backlight, backlight/slider (#5179) and battery via umockdev hardware.sh
Leak check (report-only) — clean-exit run under LSan leakcheck.sh

AddressSanitizer (plus -D_GLIBCXX_ASSERTIONS) runs under all of the above, so any memory bug in the real render/teardown path aborts the run. Tiers 56 and the leak check are best-effort (continue-on-error): they depend on daemon setup / mock devices that vary by runner. The interaction step is likewise best-effort — a headless seat exposes no pointer capability, so injected clicks may be dropped (hardening it needs a virtual pointer, uinput/wlr-virtual-pointer).

Because the teardown path (~Bar → window unmap → toggleSuspend) is where the exit-time crashes live, tests assert on a clean SIGINT exit via smoke::assert_clean_exit rather than killing with SIGTERM, and re-check the log for sanitizer reports emitted during destruction.

Updating the reference image

reference.png must be generated by the CI environment (local rendering differs from Ubuntu's). Two ways:

  • One click: Actions → smokeRun workflow with bless = true. The job regenerates the screenshot and commits it to your branch.
  • Manual: download the waybar-smoke artifact from a run and commit its bar.png as test/smoke/reference.png.

Do this whenever an intended visual change trips the golden comparison.

Run locally

On a machine with sway, grim, imagemagick, jq and Waybar built:

export WAYBAR_BIN=$PWD/build/waybar
./test/smoke/coverage.sh                     # no compositor needed
./test/smoke/run.sh       test/smoke/config.jsonc test/smoke/style.css /tmp/bar.png
./test/smoke/modules.sh   /tmp/module-shots
./test/smoke/lifecycle.sh
./test/smoke/fuzz.sh
./test/smoke/interact.sh  /tmp/interaction-shots
./test/smoke/positions.sh /tmp/layout-shots
dbus-run-session -- ./test/smoke/a11y.sh
# best-effort (need extra daemons / tools):
./test/smoke/state.sh                        # needs mpd + mpc, pulseaudio
./test/smoke/hardware.sh                     # needs umockdev
./test/smoke/leakcheck.sh