import tempfile import threading from pathlib import Path from approval_engine.errors import Conflict from approval_engine.store import Engine from tests.conftest import approve def test_second_supersession_loses(engine): obj = approve(engine) first = engine.supersede(obj.id) assert engine.get(obj.id).status == "superseded" assert first["successor_id"] try: engine.supersede(obj.id) raise AssertionError("second supersession must conflict") except Conflict: pass claim = engine.claim(obj.id) assert claim["valid_now"] is False assert claim["reason_code"] == "superseded" def test_concurrent_supersessions_one_winner(): with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / "a.sqlite" setup = Engine(path) obj = approve(setup) setup.close() winners: list[str] = [] errors: list[str] = [] barrier = threading.Barrier(2) def race(): eng = Engine(path) barrier.wait() try: result = eng.supersede(obj.id) winners.append(result["successor_id"]) except Conflict as exc: errors.append(str(exc)) finally: eng.close() threads = [threading.Thread(target=race) for _ in range(2)] for t in threads: t.start() for t in threads: t.join() assert len(winners) == 1 assert len(errors) == 1 check = Engine(path) assert check.get(obj.id).status == "superseded" check.close() def test_internal_consume_cas_once(engine): obj = approve(engine) engine._cas_consume(obj.id) try: engine._cas_consume(obj.id) raise AssertionError("double consume must conflict") except Conflict: pass claim = engine.claim(obj.id) assert claim["consumed"] is True assert claim["valid_now"] is False assert claim["reason_code"] == "consumed"