"""Boot recovery must not rewrite historical rows whose claims are already clear."""
import ast
from contextlib import contextmanager
from pathlib import Path
import sqlite3


def test_recover_clears_only_outstanding_claims():
    source = Path(__file__).resolve().parents[1] / 'app/event_artifact_store.py'
    tree = ast.parse(source.read_text())
    cls = next(n for n in tree.body if isinstance(n, ast.ClassDef) and n.name == 'ArtifactStore')
    method = next(n for n in cls.body if isinstance(n, ast.FunctionDef) and n.name == 'recover')
    namespace = {}
    exec(compile(ast.Module(body=[method], type_ignores=[]), str(source), 'exec'), namespace)
    statements = []

    class Store:
        @contextmanager
        def transaction(self):
            yield self

        def execute(self, sql):
            statements.append(sql)

        def scan_storage(self):
            self.scanned = True

        def expire(self):
            self.expired = True

    store = Store()
    namespace['recover'](store)
    sql = next(s for s in statements if s.startswith('UPDATE contextra_event_artifacts SET claim_token='))
    assert 'WHERE claim_token IS NOT NULL' in sql
    with sqlite3.connect(':memory:') as db:
        db.execute('CREATE TABLE contextra_event_artifacts (claim_token TEXT, reservation INTEGER)')
        db.executemany('INSERT INTO contextra_event_artifacts VALUES (?, ?)', [(None, 0), ('claim-a', 20), ('', 5)])
        assert db.execute(sql).rowcount == 2
        assert db.execute('SELECT claim_token, reservation FROM contextra_event_artifacts').fetchall() == [(None, 0), (None, 20), (None, 5)]
        assert db.execute(sql).rowcount == 0
    assert store.scanned and store.expired
    assert len(statements) == 8
    assert statements[0].endswith('FOR UPDATE')
