Skip to content

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

Description

@christianparpart

tests/test_offline_integration.cpp, "Integration: offline queue replayed and backend switched on network recovery", decides two outcomes of NetworkMonitor's probe thread by fixed sleeps rather than by waiting for them.

  • Line 104–105: sleep_for(80ms), then REQUIRE_FALSE(monitor.isOnline()), with probeInterval = 30ms and failureThreshold = 1. The assertion holds only if the probe thread was scheduled and ran its first probe within 80 ms.
  • Line 111–117: sleep_for(150ms), then REQUIRE(replayed.size() == 3) and REQUIRE(queue.drain().empty()). These hold only if the recovery probe, onOnline, SyncWorker::run() and switchBackend all finished within 150 ms.

On a loaded runner (ctest -j), neither bound is guaranteed.

Observed: Linux / all optional features (clang) on PR #806, head e984ebe1, failed at line 105 with REQUIRE_FALSE( monitor.isOnline() ) expanded to !true:
https://github.com/LASTRADA-Software/morph/actions/runs/36127304451/job/108046632860

The same leg passed on the previous head, and the gcc leg passed on this one. #806 does not touch include/morph/offline or this test, and NetworkMonitor runs its own std::thread/condition_variable.

Fix: the pattern #446 and #396 applied elsewhere. Wait for the state with morph::testing::waitUntil instead of sleeping for a fixed time:

  • REQUIRE(morph::testing::waitUntil([&] { return !monitor.isOnline(); }));
  • after networkOnline.store(true), REQUIRE(morph::testing::waitUntil([&] { std::scoped_lock lock{replayMtx}; return replayed.size() == 3; })), then the drain and execute checks as now.

The test then fails only when the monitor really does not go offline or recover, not when its thread is late.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: offlineSubsystem: offlinebugSomething isn't workingtriage: validWell-framed; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions