test(cursor): stabilize test_no_repost_when_unchanged on idle signal (#2477)
The test synchronized on the wrong signal. `_run_loop_until(...)` exited as soon as the usage POST landed (`_usage_posts`), but the assertions read the idle POST (`_idle_posts`). Between the usage POST and the idle POST the loop does `await asyncio.to_thread(_write_usage_state, ...)`, a real event-loop yield. Under xdist load the driver poll could slip into that window, so `_run_loop_until` returned and its `finally: task.cancel()` killed the forwarder before the idle POST was emitted → `_idle_posts` empty → assert 0 == 1. Gate on `_idle_posts` instead. The idle POST is the last side effect of processing turn 1, so once it lands both the usage POST and the state write have already completed and both assertions become race-free. The `asyncio.sleep(0.1)` upper-bound check is unchanged. Co-authored-by: omnigent <noreply@omnigent.ai>
This commit is contained in:
@@ -330,7 +330,10 @@ class TestForwardLoop:
|
||||
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
usage.record_usage_payload(tmp_path, _TURN1)
|
||||
client = await _run_loop_until(monkeypatch, tmp_path, _usage_posts)
|
||||
# Gate on the idle POST: it is the LAST side effect of processing turn 1
|
||||
# (usage POST, then the state write, then idle), so once it lands both
|
||||
# assertions below read fully-settled state instead of racing the write.
|
||||
client = await _run_loop_until(monkeypatch, tmp_path, _idle_posts)
|
||||
# Let several more polls run; with no new turns there must be no 2nd
|
||||
# usage POST and no further idle edge.
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
Reference in New Issue
Block a user