"""G5 -- chaos flags toggle at runtime, without a restart.""" import pytest from harness.config import POSTGRES_DSN from harness.pg import statement_count pytestmark = pytest.mark.contract ALL_FLAGS = { "slow_sanctions", "sanctions_errors", "n_plus_one", "pool_starvation", "row_lock_contention", "blocking_event_loop", "retry_storm", "no_batching", "unbounded_cache", "slow_consumer", "cold_cache", "poison_data", "chatty_health", } async def test_chaos_lists_all_thirteen_flags(chaos): """G5: GET /api/admin/chaos lists all thirteen flags by name.""" state = await chaos.get() assert set(state["flags"]) == ALL_FLAGS, state["flags"] async def test_toggling_one_flag_changes_only_that_flag(chaos): """G5: toggling a single flag changes only that flag.""" before = (await chaos.get())["flags"] await chaos.set_flag("slow_sanctions", True) after = (await chaos.get())["flags"] assert after["slow_sanctions"] is True for flag in ALL_FLAGS - {"slow_sanctions"}: assert after[flag] == before[flag], f"{flag} changed unexpectedly" async def test_profile_clean_sets_all_false(chaos): """G5: the `clean` profile sets every flag to false.""" state = await chaos.set_profile("clean") assert all(v is False for v in state["flags"].values()), state["flags"] async def test_profile_nightmare_sets_all_true(chaos): """G5: the `nightmare` profile sets every flag to true.""" state = await chaos.set_profile("nightmare") assert all(v is True for v in state["flags"].values()), state["flags"] async def test_profile_light_sets_exactly_two_flags(chaos): """G5: the `light` profile sets exactly slow_sanctions and cold_cache.""" state = await chaos.set_profile("light") enabled = {flag for flag, v in state["flags"].items() if v} assert enabled == {"slow_sanctions", "cold_cache"}, enabled async def test_flag_change_is_live_no_restart(api, chaos, manifest): """G5: enabling n_plus_one via the API changes the query count for the very next insights request -- with no container restart -- proving live reconfiguration rather than timing noise.""" account_id = manifest["clean_account_id"] await chaos.set_profile("clean") with statement_count(POSTGRES_DSN) as baseline: resp = await api.get(f"/api/accounts/{account_id}/insights") assert resp.status_code == 200 await chaos.set_flag("n_plus_one", True) with statement_count(POSTGRES_DSN) as degraded: resp = await api.get(f"/api/accounts/{account_id}/insights") assert resp.status_code == 200 assert degraded.calls > baseline.calls, ( f"expected more SQL statements after enabling n_plus_one live " f"(baseline={baseline.calls}, degraded={degraded.calls})" ) async def test_unknown_flag_returns_400(chaos): """G5: setting an unknown flag name returns 400.""" resp = await chaos.set_flag("not_a_real_flag", True) assert resp.status_code == 400