fix(test): kill the a11y suite's pending-timer flake at its root

Finally caught with a creation stack trace: when the last gRPC
stream closes, Http2ClientConnection arms the channel's 5-minute
idleTimeout timer — even on a shut-down connection — so the
test's 1-minute drain never covered it and the framework's
pending-timer invariant tripped whenever the arm landed inside
the test window (frequent while a real hub listens on 50051).

The suite now closes the channel in real-async space at the end
of the body (new @visibleForTesting HubService.debugResetChannel;
shutdown is deliberately not awaited — it wedges on a mid-connect
socket, but cancels its timers synchronously) and pumps past the
idle timeout so the timer fires inside the test. 6 consecutive
full-suite runs + 3 isolated runs green; before, roughly 1 in 3
full runs failed.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-18 18:02:03 +02:00
parent 383490027b
commit c18bb7f357
2 changed files with 32 additions and 0 deletions

View file

@ -88,6 +88,19 @@ void main() {
// !timersPending after the test body.
await tester.pumpWidget(const SizedBox.shrink());
await tester.pump(const Duration(minutes: 1));
// The suite's long-standing pending-timer flake, finally
// caught with a creation stack: when the last gRPC stream
// closes, Http2ClientConnection._handleActiveStateChanged
// arms the channel's 5-minute idleTimeout timer — even on a
// shut-down connection so a 1-minute drain never covered
// it. Close the channel in real-async space (lets in-flight
// socket callbacks land), then pump PAST the idle timeout so
// the timer fires inside the test body.
await tester.runAsync(() async {
HubService.instance.debugResetChannel();
await Future<void>.delayed(const Duration(milliseconds: 100));
});
await tester.pump(const Duration(minutes: 6));
expect(
violations,
isEmpty,