Skip to content

Fix flaky offline-integration test that decided NetworkMonitor state by fixed sleeps - #830

Merged
Yaraslaut merged 1 commit into
masterfrom
fix/821-offline-test-fixed-sleeps
Sep 26, 2026
Merged

Yaraslaut merged 1 commit into
masterfrom
fix/821-offline-test-fixed-sleeps

Conversation

@Yaraslaut

Copy link
Copy Markdown
Member

tests/test_offline_integration.cpp decided two NetworkMonitor state transitions with fixed sleep_for(80ms)/sleep_for(150ms) margins before asserting, instead of waiting for the actual state. Under scheduling load the monitor's probe thread can run later than the fixed margin, so the assertion races OS scheduling latency rather than checking the behaviour under test — this is exactly what happened on CI in PR #806 (linked in the issue).

Both sites are replaced with morph::testing::waitUntil(pred, budget), the polling idiom already used identically for the same NetworkMonitor operations in tests/test_network_monitor.cpp. The test now fails only when the monitor genuinely does not reach the expected state, not when its thread is merely late.

Test-only change; include/morph/offline/network_monitor.hpp is untouched.

Fixes #821

@codecov

codecov Bot commented Sep 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…rgin

tests/test_offline_integration.cpp decided two NetworkMonitor outcomes by
sleeping a fixed wall-clock margin (80ms, then 150ms) before asserting on
state that a probe thread sets asynchronously. Under load, the probe thread
can be scheduled later than that margin, so the assertion races OS
scheduling latency instead of the behaviour under test — reproduced on CI
(PR #806) and, deterministically here, by widening probeInterval past the
fixed margins on unmodified code.

Replace both sites with morph::testing::waitUntil, the polling idiom
already used for the same NetworkMonitor operations in
tests/test_network_monitor.cpp. The test now fails only when the monitor
genuinely does not reach the expected state, not when its thread is late.

Removing the fixed 150ms sleep exposed a second, previously-masked race:
the test called handler.execute() as soon as replayed.size()==3 became
true, but bridge.switchBackend() runs immediately *after* the replay in
the same onOnline callback, on the probe thread. The old fixed sleep
almost always gave switchBackend() enough incidental slack to finish too;
waitUntil can return the instant the replay condition is met, without that
slack, letting the main thread call execute() while the switch is still in
flight (observed as CI#830's Windows failure). Fixed by waiting on an
explicit backendSwitched flag set after switchBackend() returns, instead
of relying on replay completion as a stand-in for it.

Also: two scoped_lock declarations flagged by clang-tidy-diff
(misc-const-correctness) marked const.

Fixes #821

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fEUahMFF32wQLiWjbsfkc
Signed-off-by: Yaraslau Tamashevich <yaraslau.tamashevich@gmail.com>
@Yaraslaut
Yaraslaut force-pushed the fix/821-offline-test-fixed-sleeps branch from 6cb0da9 to 3819b7c Compare September 26, 2026 09:09
@Yaraslaut
Yaraslaut merged commit f505120 into master Sep 26, 2026
37 checks passed
@Yaraslaut
Yaraslaut deleted the fix/821-offline-test-fixed-sleeps branch September 26, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tests: offline integration test decides NetworkMonitor state by fixed sleeps (flaky under load)

1 participant