Files
jarca-ledger-mcp/tests/test_schema_14_to_15_actual.py
T

78 lines
3.9 KiB
Python

from __future__ import annotations
import hashlib
import sqlite3
from pathlib import Path
import pytest
from jarca_ledger_mcp.infrastructure.sqlite import migrations
from jarca_ledger_mcp.infrastructure.sqlite.migrations import init_db
FIXTURE = Path(__file__).parent / "fixtures" / "schema_v14.sql"
def _v14_db(path: Path) -> None:
with sqlite3.connect(path) as db:
db.executescript(FIXTURE.read_text())
db.execute("INSERT INTO accounts VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ("a1", "Main", "bank", "Bank", "KRW", 1, "memo", "1234", "User", 100000, "2026-01-31", "", "ok", "cash", "2026-01-01", "2026-01-31"))
db.execute("INSERT INTO transactions (id,transaction_date,type,amount,account_id,created_at,updated_at) VALUES (?,?,?,?,?,?,?)", ("t1", "2026-01-15", "expense", -1200, "a1", "2026-01-15", "2026-01-15"))
db.execute("INSERT INTO asset_snapshots (id,basis_date,source_type,source_id,name,amount,closed_at,created_at) VALUES (?,?,?,?,?,?,?,?)", ("s1", "2026-01-31", "account", "a1", "Main", 100000, "2026-01-31T10:00:00", "2026-01-31T10:00:00"))
db.execute("INSERT INTO asset_snapshot_runs (id,basis_date,close_status,created_at) VALUES (?,?,?,?)", ("run1", "2026-01-31", "closed", "2026-01-31T10:00:00"))
db.execute("INSERT OR REPLACE INTO schema_meta VALUES ('schema_version','14')")
db.commit()
def _rows(path: Path, table: str):
with sqlite3.connect(path) as db:
return db.execute(f"SELECT * FROM {table} ORDER BY 1").fetchall()
def test_actual_v14_fixture_is_tag_ddl_and_migrates_preserving_rows(tmp_path):
path = tmp_path / "ledger.sqlite3"
_v14_db(path)
before_accounts, before_tx = _rows(path, "accounts"), _rows(path, "transactions")
init_db(str(path))
with sqlite3.connect(path) as db:
assert db.execute("SELECT value FROM schema_meta WHERE key='schema_version'").fetchone()[0] == "15"
assert db.execute("SELECT amount, closed_at FROM account_snapshot WHERE id='s1'").fetchone() == (100000, "2026-01-31T10:00:00")
assert db.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='asset_snapshot_runs'").fetchone() is None
assert db.execute("PRAGMA foreign_key_check").fetchall() == []
assert db.execute("PRAGMA integrity_check").fetchone()[0] == "ok"
assert _rows(path, "accounts") == before_accounts
assert _rows(path, "transactions") == before_tx
def test_actual_v14_migration_is_idempotent_and_snapshot_unchanged(tmp_path):
path = tmp_path / "ledger.sqlite3"
_v14_db(path)
init_db(str(path))
first = _rows(path, "account_snapshot")
init_db(str(path))
assert _rows(path, "account_snapshot") == first
def test_migration_failure_rolls_back_legacy_renames_and_metadata(tmp_path, monkeypatch):
path = tmp_path / "ledger.sqlite3"
_v14_db(path)
original = migrations.migrate_db
def fail(conn):
raise RuntimeError("injected")
monkeypatch.setattr(migrations, "migrate_db", fail)
with pytest.raises(RuntimeError, match="injected"):
init_db(str(path))
with sqlite3.connect(path) as db:
assert db.execute("SELECT value FROM schema_meta WHERE key='schema_version'").fetchone()[0] == "14"
assert db.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='asset_snapshots'").fetchone()
assert not db.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='account_snapshot'").fetchone()
monkeypatch.setattr(migrations, "migrate_db", original)
def test_new_init_has_same_contract(tmp_path):
path = tmp_path / "new.sqlite3"
init_db(str(path))
with sqlite3.connect(path) as db:
assert db.execute("SELECT value FROM schema_meta WHERE key='schema_version'").fetchone()[0] == "15"
cols = {r[1] for r in db.execute("PRAGMA table_info(account_snapshot)")}
assert {"monthly_settlement_id", "verification_status", "evidence_kind"} <= cols