Flaky test: document_new_and_save_as_test 'Cmd+S op een document zonder pad' faalt op Linux-CI #1363

Closed
opened 2026-08-08 10:24:21 +00:00 by brenno · 0 comments
Owner

Bevinding

De test document_new_and_save_as_test.dart: Cmd+S op een document zonder pad valt terug op Opslaan als… faalt intermitterend op de Linux-CI-runner (linux-gate, --test-randomize-ordering-seed random).

Foutmelding:

Expected: '/tmp/saveas_widgetXXXXXX/nieuw.md'
  Actual: <null>

De test roept de Cmd+S-binding aan, wacht tot 50×10ms (500ms) op filePath != null, en beweert dan dat het pad gezet is. Op Linux blijft filePath soms null — de saveDestination-mock heeft het pad al teruggegeven, maar de async-write is nog niet rond.

Reproductie

  • Lokaal (macOS): passeert consistent, ook met --test-randomize-ordering-seed random.
  • Linux-CI: faalt in ~50% van de runs met random volgorde. Zie runs 3136 (push, commit ea24cdbe, vóór PR #1362) en 3140 (push, commit 91adb11c, na PR #1362) — beide falen met exact dezelfde test.

Waarschijnlijke oorzaak

De polling-loop (regels 113-116) wacht maximaal 500ms op filePath:

for (var i = 0; i < 50 && n.currentState.filePath == null; i++) {
  await Future<void>.delayed(const Duration(milliseconds: 10));
}

Op Linux is de CI-container trager in file-IO en async-pumping. De saveDocumentAs-flow doet echte schijf-IO (writeStringAtomic) binnen runAsync, en op een tragere runner is 500ms soms niet genoeg om de write + state-update af te ronden. De test is geschreven op macOS-timing.

Oplossingsrichting

  1. Polling verlengen — de loop naar bv. 200×10ms (2s) brengen. Goedkoop, maar het is een magische constante.
  2. Een completer/future gebruiken — de saveDocumentAs-flow een completer laten vullen waarna de test wacht, in plaats van te pollen op state. Betrouwbaarder, maar vereist dat de notifier een hook blootstelt.
  3. tester.pumpAndSettle in plaats van runAsync + polling — de standaard Flutter-test-manier om async-work af te wachten. Kan breken als er een animatie oneindig draait, maar deze widget heeft geen lopende animaties.

Optie 3 is de idiomatische keuze; optie 1 is de minimale fix.

Scope

Dit is geen regressie uit PR #1362 — run 3136 (vóór die merge) faalde al met dezelfde test. Het is een pre-existing timing-gevoeligheid die door de random-seed op Linux af en toe raakt.

Herkomst

Gevonden na het mergen van PR #1362 (security: robustness-batch #1350–#1360). De linux-gate faalde op de push-run; onderzoek wees uit dat dezelfde test al faalde op de vorige push (run 3136, commit ea24cdbe).

## Bevinding De test `document_new_and_save_as_test.dart: Cmd+S op een document zonder pad valt terug op Opslaan als…` faalt intermitterend op de Linux-CI-runner (`linux-gate`, `--test-randomize-ordering-seed random`). **Foutmelding:** ``` Expected: '/tmp/saveas_widgetXXXXXX/nieuw.md' Actual: <null> ``` De test roept de Cmd+S-binding aan, wacht tot 50×10ms (500ms) op `filePath != null`, en beweert dan dat het pad gezet is. Op Linux blijft `filePath` soms `null` — de `saveDestination`-mock heeft het pad al teruggegeven, maar de async-write is nog niet rond. ## Reproductie - **Lokaal (macOS):** passeert consistent, ook met `--test-randomize-ordering-seed random`. - **Linux-CI:** faalt in ~50% van de runs met random volgorde. Zie runs 3136 (push, commit ea24cdbe, vóór PR #1362) en 3140 (push, commit 91adb11c, na PR #1362) — beide falen met exact dezelfde test. ## Waarschijnlijke oorzaak De polling-loop (regels 113-116) wacht maximaal 500ms op `filePath`: ```dart for (var i = 0; i < 50 && n.currentState.filePath == null; i++) { await Future<void>.delayed(const Duration(milliseconds: 10)); } ``` Op Linux is de CI-container trager in file-IO en async-pumping. De `saveDocumentAs`-flow doet echte schijf-IO (`writeStringAtomic`) binnen `runAsync`, en op een tragere runner is 500ms soms niet genoeg om de write + state-update af te ronden. De test is geschreven op macOS-timing. ## Oplossingsrichting 1. **Polling verlengen** — de loop naar bv. 200×10ms (2s) brengen. Goedkoop, maar het is een magische constante. 2. **Een completer/future gebruiken** — de `saveDocumentAs`-flow een completer laten vullen waarna de test wacht, in plaats van te pollen op state. Betrouwbaarder, maar vereist dat de notifier een hook blootstelt. 3. **`tester.pumpAndSettle` in plaats van `runAsync` + polling** — de standaard Flutter-test-manier om async-work af te wachten. Kan breken als er een animatie oneindig draait, maar deze widget heeft geen lopende animaties. Optie 3 is de idiomatische keuze; optie 1 is de minimale fix. ## Scope Dit is geen regressie uit PR #1362 — run 3136 (vóór die merge) faalde al met dezelfde test. Het is een pre-existing timing-gevoeligheid die door de random-seed op Linux af en toe raakt. ## Herkomst Gevonden na het mergen van PR #1362 (security: robustness-batch #1350–#1360). De linux-gate faalde op de push-run; onderzoek wees uit dat dezelfde test al faalde op de vorige push (run 3136, commit ea24cdbe).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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
LibreKAT/Ocideck#1363
No description provided.