Neo flagged this on #926: tests.test_dashboard_routes.TheReadOnlyRoutesAnswer.test_each_one_returns_the_payload_its_builder_produces (/api/stats) failed once, on ubuntu-latest / Python 3.12 for the #934 merge (run 36031884313, attempt 1). It passed on a rerun, and the other 8 jobs were green.
Cause: a clock race, not leaked state. The test calls GET /api/stats and then calls build_stats_payload() again, and asserts the two are equal. The payload includes transfer.uptime_seconds (and uptime_text), which is stats_mgr.get_uptime_seconds() = int(time.time() - start_time). If a whole-second boundary falls between the two calls, the uptimes differ by 1 and the dicts differ. The window is the few milliseconds between the calls, so on a slow runner it fails about once in a few hundred runs.
Reproduced deterministically by making get_uptime_seconds() tick between calls: the test fails with the same {'library': ...} != {'top': ...} message as the CI run.
Fix (test-only): hold the uptime still while this test compares the route with its builder, and add a check that a ticking clock can no longer fail it. The daemon's code is correct: a live uptime is supposed to change.
Neo flagged this on #926:
tests.test_dashboard_routes.TheReadOnlyRoutesAnswer.test_each_one_returns_the_payload_its_builder_produces(/api/stats) failed once, on ubuntu-latest / Python 3.12 for the #934 merge (run 36031884313, attempt 1). It passed on a rerun, and the other 8 jobs were green.Cause: a clock race, not leaked state. The test calls
GET /api/statsand then callsbuild_stats_payload()again, and asserts the two are equal. The payload includestransfer.uptime_seconds(anduptime_text), which isstats_mgr.get_uptime_seconds()=int(time.time() - start_time). If a whole-second boundary falls between the two calls, the uptimes differ by 1 and the dicts differ. The window is the few milliseconds between the calls, so on a slow runner it fails about once in a few hundred runs.Reproduced deterministically by making
get_uptime_seconds()tick between calls: the test fails with the same{'library': ...} != {'top': ...}message as the CI run.Fix (test-only): hold the uptime still while this test compares the route with its builder, and add a check that a ticking clock can no longer fail it. The daemon's code is correct: a live uptime is supposed to change.