Skip to content

test(gallery): wait for other goroutines' work before restyling a demo in place - #273

Draft
houko wants to merge 1 commit into
nsgo-dev:mainfrom
houko:fix/gallery-appearance-flake
Draft

houko wants to merge 1 commit into
nsgo-dev:mainfrom
houko:fix/gallery-appearance-flake

Conversation

@houko

@houko houko commented Nov 15, 2026

Copy link
Copy Markdown
Collaborator

Fixes #255

What changed

TestAppearanceRestylesInPlace reads a demo, switches it to dark and compares it with a fresh dark build. Four demos do part of their work on goroutines of their own, which FastForward and Settle do not wait for, so that work could land between the reads or before one build's read and after the other's:

  • Editor: the simulated language server answers after a real sleep (lspAsk), replacing "No problems" with the problems list; this is the failure the issue reports. The editor's own highlighter also lexes on a goroutine (base/editor/editor.go), which showed up under load as a differing span on the sample's first line.
  • TextView: the failure the issue reports is not the highlighter but the formulas. Each formula.View whose renderer's font has not loaded yet loads it through core.NewResource and draws nothing (an em-square placeholder canvas with no ops) until then. The light build is the process's first, so a formula could still be blank after the switch while the fresh dark build, with the font loaded, drew it. The document's Go block is also lexed on a goroutine the first time (base/textview/highlight).
  • DiffView: the diff lexes each build's files on a goroutine (base/diff/view.go), so either build could be read before its colors arrived. It failed once in the 50-run loop after the first two fixes.

The test's settle now waits in real time, as TestEditor and TestTextViewFormulas already do, for that work to be done in both builds: the Editor's problems and colored code, every canvas in the TextView's document drawing and its Go block colored, and the DiffView's code colored. A small lexed helper checks that a lexer split the matched lines into spans. The demos stay as they are: their servers and lexers run off the engine's goroutine on purpose.

Verification

go test -count=50 -run 'TestAppearanceRestylesInPlace$' ./examples/gallery:

  • before: 11 of 50 runs failed, all in Editor ("No problems" built again, or 845 views against 809)
  • after: 0 of 50 failed

-count=50 reuses one process, so the font and the highlighter's cache are cold only in its first run. The first-build failures were reproduced by running the compiled test binary once per process, 8 at a time:

  • -run 'TestAppearanceRestylesInPlace$/^TextView$', 60 processes: 18 failed before (the blank formula canvas), 0 after
  • -run 'TestAppearanceRestylesInPlace$/^Editor$', 60 processes: 28 failed before, 0 after
  • -run 'TestAppearanceRestylesInPlace$/^DiffView$', 60 processes: 4 failed with the first two fixes, before the DiffView wait
  • Editor, DiffView and TextView together, 80 processes: 61 failed before, 0 after

go tool nsgo check passes. go tool nsgo test ./examples/gallery: 93 passed, 11 skipped, and TestTerminal failed (the shell's title never arrived within 10 s); it fails the same way on this machine with main's test binary, and this change does not touch it.

Screenshots: none

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

examples/gallery: TestAppearanceRestylesInPlace is flaky because the Editor demo's language server answers after a real sleep

1 participant