fix: allow guarded production Flow v2 shadow rebuild
This commit is contained in:
104
tests/test_blif_flow_v2_production_shadow_rebuild.py
Normal file
104
tests/test_blif_flow_v2_production_shadow_rebuild.py
Normal file
@@ -0,0 +1,104 @@
|
||||
from inspect import getsource
|
||||
|
||||
import pytest
|
||||
|
||||
import app.blif_flow_v2_projection_service as projection
|
||||
import scripts.rebuild_blif_flow_v2_projection as cli
|
||||
import scripts.simulate_blif_flow_v2 as simulator
|
||||
|
||||
|
||||
def test_help_performs_no_rebuild(monkeypatch, capsys):
|
||||
monkeypatch.setattr(cli, "validate_execution", lambda **kwargs: pytest.fail("help reached execution"))
|
||||
with pytest.raises(SystemExit) as exc:
|
||||
cli.main(["--help"])
|
||||
assert exc.value.code == 0
|
||||
assert "--production-shadow" in capsys.readouterr().out
|
||||
|
||||
|
||||
def test_default_execution_does_not_authorize_production():
|
||||
with pytest.raises(RuntimeError, match="explicit --production-shadow"):
|
||||
cli.validate_execution(production_shadow=False, mode="shadow", database="clientflow")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ["", "off", "compare", "authoritative"])
|
||||
def test_production_shadow_requires_exact_shadow_mode(mode):
|
||||
with pytest.raises(RuntimeError, match="requires BLIF_FLOW_V2_MODE=shadow"):
|
||||
cli.validate_execution(production_shadow=True, mode=mode, database="clientflow")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("database", ["clientflow_codex_test", "clientflow_codex_shadow", "other"])
|
||||
def test_production_shadow_requires_exact_production_database(database):
|
||||
with pytest.raises(RuntimeError, match="requires database 'clientflow'"):
|
||||
cli.validate_execution(production_shadow=True, mode="shadow", database=database)
|
||||
|
||||
|
||||
def test_production_shadow_explicit_proof_is_accepted():
|
||||
cli.validate_execution(production_shadow=True, mode="shadow", database="clientflow")
|
||||
|
||||
|
||||
def test_global_write_allowlist_remains_test_only():
|
||||
assert projection.WRITE_DATABASE_ALLOWLIST == frozenset({"clientflow_codex_test"})
|
||||
assert "clientflow" not in projection.WRITE_DATABASE_ALLOWLIST
|
||||
|
||||
|
||||
def test_factual_read_transaction_remains_read_only():
|
||||
source = getsource(simulator._load)
|
||||
assert 'conn.execute(text("BEGIN READ ONLY"))' in source
|
||||
assert 'conn.execute(text("ROLLBACK"))' in source
|
||||
|
||||
|
||||
def test_projection_writer_only_mutates_two_additive_tables():
|
||||
source = getsource(projection.rebuild_blif_flow_v2_projection).upper()
|
||||
assert projection.PROJECTION_WRITE_TABLES == {
|
||||
"opportunity_flow_state_v2", "opportunity_flow_transitions"}
|
||||
assert "INSERT INTO OPPORTUNITY_FLOW_TRANSITIONS" in source
|
||||
assert "INSERT INTO OPPORTUNITY_FLOW_STATE_V2" in source
|
||||
for forbidden in ("OPPORTUNITIES", "TASKS", "MESSAGES", "COMMUNICATIONS",
|
||||
"COMMERCIAL_DOCUMENTS", "CUSTOMERS", "PAYMENTS", "OPERATION_LINKS"):
|
||||
assert f"INSERT INTO {forbidden}" not in source
|
||||
assert f"UPDATE {forbidden}" not in source
|
||||
assert f"DELETE FROM {forbidden}" not in source
|
||||
|
||||
|
||||
def test_production_derivation_has_no_fixed_328_requirement(monkeypatch):
|
||||
captured = {}
|
||||
|
||||
def fake_collect(**kwargs):
|
||||
captured.update(kwargs)
|
||||
return {"opportunities": [{"opportunity_id": "one"}]}
|
||||
|
||||
monkeypatch.setattr(simulator, "collect", fake_collect)
|
||||
rows = projection._derive_all(
|
||||
expected_database="clientflow", expected_user="runtime-role",
|
||||
expected_opportunity_count=None, require_opportunities=True,
|
||||
)
|
||||
assert rows == [{"opportunity_id": "one"}]
|
||||
assert captured["expected_opportunity_count"] is None
|
||||
assert captured["require_opportunities"] is True
|
||||
|
||||
|
||||
def test_snapshot_expected_count_validation_is_still_available(monkeypatch):
|
||||
monkeypatch.setattr(simulator, "_load", lambda **kwargs: {"opportunities": [object()]})
|
||||
with pytest.raises(RuntimeError, match="expected 328 opportunities, found 1"):
|
||||
simulator.collect(expected_opportunity_count=328)
|
||||
|
||||
|
||||
def test_empty_production_universe_is_rejected(monkeypatch):
|
||||
monkeypatch.setattr(simulator, "collect", lambda **kwargs: {"opportunities": []})
|
||||
assert projection._derive_all(
|
||||
expected_database="clientflow", expected_user=None,
|
||||
expected_opportunity_count=None, require_opportunities=True,
|
||||
) == []
|
||||
with pytest.raises(RuntimeError, match="at least one opportunity"):
|
||||
projection.rebuild_blif_flow_v2_projection(
|
||||
mode="shadow", derived_rows=[], require_opportunities=True,
|
||||
)
|
||||
|
||||
|
||||
def test_existing_test_defaults_remain_guarded(monkeypatch):
|
||||
captured = {}
|
||||
monkeypatch.setattr(simulator, "collect", lambda **kwargs: captured.update(kwargs) or {"opportunities": []})
|
||||
projection._derive_all()
|
||||
assert captured["expected_database"] == "clientflow_codex_test"
|
||||
assert captured["expected_user"] == "clientflow_codex_test"
|
||||
assert captured["expected_opportunity_count"] == 328
|
||||
Reference in New Issue
Block a user