From ff523f7e6e154f190f3737e37cc199ad131a7cc7 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 7 Jun 2026 16:56:05 -0400 Subject: [PATCH] fix(test_api_generate_blocked_while_stale): sleep in monkeypatches to keep switch in-flight The test had a pre-existing race: it monkeypatched _rebuild_rag_index and _flush_to_project to no-ops, which made _do_project_switch complete synchronously inside the io_pool worker. By the time the test's _api_generate call ran is_project_stale() was already False (the worker had cleared _project_switch_in_progress), so the 409 contract was never exercised. Fix: replace the no-op lambdas with `lambda: time.sleep(0.5)`. This keeps the worker busy for 500ms, which is more than enough window for the test to call _api_generate and observe the stale flag. _wait_for_switch then drains the rest of the work. Also: removed the @pytest.mark.skip marker; the underlying issue is now fixed in the test. Verified: 9/9 in tests/test_project_switch_persona_preset.py pass (previously 8 passed + 1 skipped). --- tests/test_project_switch_persona_preset.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/test_project_switch_persona_preset.py b/tests/test_project_switch_persona_preset.py index 24c7150f..d7233c66 100644 --- a/tests/test_project_switch_persona_preset.py +++ b/tests/test_project_switch_persona_preset.py @@ -269,7 +269,6 @@ def test_switch_project_non_blocking(tmp_path, monkeypatch): assert ctrl.active_project_path == str(project_b_path) -@pytest.mark.skip(reason="Pre-existing test bug: monkeypatches _rebuild_rag_index and _flush_to_project to no-ops, which makes _do_project_switch complete synchronously before _api_generate is called. By the time _api_generate checks is_project_stale(), the io_pool worker has already cleared the flag -> so is_project_stale() returns False and the function continues, hitting the next failure (e.g. KeyError on 'output_dir'). The 409 contract only holds while the io_pool worker is still running. Tracked as pre-existing.") def test_api_generate_blocked_while_stale(tmp_path, monkeypatch): """_api_generate returns 409 when the project switch is in progress.""" project_a_path, project_b_path = _setup_two_projects(tmp_path) @@ -285,6 +284,14 @@ def test_api_generate_blocked_while_stale(tmp_path, monkeypatch): ctrl.persona_manager = PersonaManager(Path(project_a_path).parent) ctrl._refresh_from_project() + # Add a sleep to the no-op patches so the io_pool worker is busy + # long enough for the subsequent _api_generate call to observe + # _project_switch_in_progress=True. Without the sleep, the worker + # completes synchronously and is_project_stale() returns False by + # the time _api_generate runs. + monkeypatch.setattr(ctrl, "_rebuild_rag_index", lambda: time.sleep(0.5)) + monkeypatch.setattr(ctrl, "_flush_to_project", lambda: time.sleep(0.5)) + ctrl._switch_project(str(project_b_path)) assert ctrl.is_project_stale() from fastapi import HTTPException