X11 tests under Xvfb, a test of the X11 window, and coverage #1

Merged
bcox merged 4 commits from bcox/ci-xvfb-coverage into main 2026-11-04 00:24:24 +00:00 AGit
Owner

What

  • The X11 tests run in CI. Each lane starts Xvfb (-noreset) and passes it as DISPLAY. Before this, x11_clipboard_test skipped everywhere.
  • New x11_window_test. It acts as the window's host: it gives the window a parent, sends it pointer, wheel, key, expose and leave events, resizes the parent and reads the window's pixels back. A View that records its calls shows what arrived.
  • No more silent skips. With DISPLAY set but unreachable, the X11 tests now fail. Without DISPLAY they still skip.
  • Coverage. bazel coverage is configured in .bazelrc. tools/coverage.sh writes coverage/, and on a pull request a coverage job after the lanes posts the coverage of the changed lines here.

Results

Line coverage goes from 65.3% to 89.3%. x11_window.cc goes from 0% to 85.6% and x11_clipboard.cc from 0% to 73.9%.

Testing

  • Every lane (default -Werror, opt, asan, ubsan, tsan) and the coverage step ran in an amd64 debian:12 container with tools/ci_test.sh, exactly as ci.yml runs it. All passed, and no X11 test skipped.
  • A throwaway change to two source lines confirmed that the changed-lines report finds them.
  • plugin-template's tests pass against this branch.

🤖 Generated with Claude Code

## What - **The X11 tests run in CI.** Each lane starts Xvfb (`-noreset`) and passes it as `DISPLAY`. Before this, `x11_clipboard_test` skipped everywhere. - **New `x11_window_test`.** It acts as the window's host: it gives the window a parent, sends it pointer, wheel, key, expose and leave events, resizes the parent and reads the window's pixels back. A View that records its calls shows what arrived. - **No more silent skips.** With `DISPLAY` set but unreachable, the X11 tests now fail. Without `DISPLAY` they still skip. - **Coverage.** `bazel coverage` is configured in `.bazelrc`. `tools/coverage.sh` writes `coverage/`, and on a pull request a `coverage` job after the lanes posts the coverage of the changed lines here. ## Results Line coverage goes from 65.3% to 89.3%. `x11_window.cc` goes from 0% to 85.6% and `x11_clipboard.cc` from 0% to 73.9%. ## Testing - Every lane (default `-Werror`, opt, asan, ubsan, tsan) and the coverage step ran in an amd64 `debian:12` container with `tools/ci_test.sh`, exactly as `ci.yml` runs it. All passed, and no X11 test skipped. - A throwaway change to two source lines confirmed that the changed-lines report finds them. - plugin-template's tests pass against this branch. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
X11 tests under Xvfb, a test of the X11 window, and coverage
Some checks failed
ci / default (pull_request) Failing after 5m21s
ci / opt (pull_request) Failing after 5m13s
ci / asan (pull_request) Failing after 5m14s
ci / ubsan (pull_request) Failing after 5m46s
ci / tsan (pull_request) Failing after 5m24s
ci / coverage (pull_request) Failing after 5m58s
339ab165f4
CI's lanes run the X11 tests against Xvfb (-noreset: the server otherwise
starts over whenever its last client leaves, refusing the next test's
connection). x11_window_test drives the window as its host would: a parent
window, input sent to it, the parent resized, its pixels read back. With
DISPLAY set and unreachable the X11 tests now fail instead of skipping.

bazel coverage is configured in .bazelrc, and tools/coverage.sh writes
coverage/: the merged report, a summary, genhtml's pages and diff-cover's
report of the lines changed since a base. A coverage job follows the lanes
on a pull request and posts that report on it. Line coverage goes from 65%
to 89%; x11_window.cc from none to 86%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI on a runner labeled x86-64-v3
Some checks failed
ci / default (pull_request) Successful in 2m10s
ci / opt (pull_request) Successful in 2m20s
ci / asan (pull_request) Has been cancelled
ci / ubsan (pull_request) Has been cancelled
ci / tsan (pull_request) Has been cancelled
ci / coverage (pull_request) Has been cancelled
0a3f3f1b78
The tests run the plugins, which refuse a processor without AVX2 and FMA, and
the runner labeled docker is an Ivy Bridge, so every lane failed there before
running a test. Every job now asks for x86-64-v3, as gridrunner is labeled; all
on one runner, they share its cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The clipboard test waits for the server, not for time
Some checks failed
ci / default (pull_request) Successful in 2m14s
ci / opt (pull_request) Successful in 2m14s
ci / asan (pull_request) Successful in 2m16s
ci / ubsan (pull_request) Successful in 2m21s
ci / tsan (pull_request) Failing after 2m23s
ci / coverage (pull_request) Successful in 4m23s
91417091cd
Copy and Paste flush their requests, but two connections' requests reach the
server in either order: when the asker's came first it found no owner, never
asked again, and the opt lane failed (run 5). Each side now makes a round trip
after it takes the selection, and the one it was taken from another before it
asks, in place of the sleeps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

No lines with coverage information in this diff.

Whole suite: 89.3% 1924/2154 total. Every file: the coverage-html artifact of this run.

# Diff Coverage ## Diff: origin/main...HEAD, staged and unstaged changes No lines with coverage information in this diff. Whole suite: 89.3% 1924/2154 total. Every file: the coverage-html artifact of [this run](https://forge.djehuti.com/bcox/plugin-kit/actions/runs/7).
TSan's container without Podman's seccomp filter
Some checks failed
ci / default (pull_request) Successful in 2m8s
ci / opt (pull_request) Successful in 2m10s
ci / asan (pull_request) Successful in 2m10s
ci / ubsan (pull_request) Successful in 2m12s
ci / tsan (pull_request) Failing after 2m10s
ci / coverage (pull_request) Has been cancelled
64185e8b34
On gridrunner every TSan test died at once: its kernel gives addresses more
random bits than TSan can work with, and TSan restarts itself with ASLR off
when so, by a personality call Podman's default seccomp filter refuses. The
TSan job's container runs without the filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bcox force-pushed bcox/ci-xvfb-coverage from 64185e8b34
Some checks failed
ci / default (pull_request) Successful in 2m8s
ci / opt (pull_request) Successful in 2m10s
ci / asan (pull_request) Successful in 2m10s
ci / ubsan (pull_request) Successful in 2m12s
ci / tsan (pull_request) Failing after 2m10s
ci / coverage (pull_request) Has been cancelled
to 708180317e
All checks were successful
ci / default (pull_request) Successful in 2m8s
ci / opt (pull_request) Successful in 2m13s
ci / asan (pull_request) Successful in 2m12s
ci / ubsan (pull_request) Successful in 2m12s
ci / tsan (pull_request) Successful in 2m12s
ci / coverage (pull_request) Successful in 2m21s
2026-11-04 00:07:58 +00:00
Compare

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

No lines with coverage information in this diff.

Whole suite: 89.3% 1924/2154 total. Every file: the coverage-html artifact of this run.

# Diff Coverage ## Diff: origin/main...HEAD, staged and unstaged changes No lines with coverage information in this diff. Whole suite: 89.3% 1924/2154 total. Every file: the coverage-html artifact of [this run](https://forge.djehuti.com/bcox/plugin-kit/actions/runs/13).
bcox merged commit 78f7b27f5d into main 2026-11-04 00:24:24 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/plugin-kit!1
No description provided.