Files
stack/tests/aco/test_snapshot.py
kert e07c8e76e9 add P8 quality: 99% coverage, health checks, snapshots, CI pipeline
- 76 new tests covering CLI commands, API routes, auth, runner,
  load modules — coverage 99% (169 remaining lines are infrastructure)
- Enhanced /health endpoint with DuckDB, bib, pipeline service checks
- Added `stack health` CLI command with graceful degradation
- SnapshotManager for DuckDB data versioning and rollback
- .woodpecker.yml CI pipeline: lint, test (99% gate), marimo check
- Error handling audit: no bare except clauses, all exceptions logged
Closes #31, #32, #33, #34, #35.
2026-03-12 18:28:55 -04:00

77 lines
2.4 KiB
Python

"""Tests for aco.lake.snapshot — data versioning."""
from __future__ import annotations
import duckdb
from aco.lake.snapshot import SnapshotManager
class TestSnapshotManager:
def test_create_and_list(self, tmp_path) -> None:
db_path = tmp_path / "test.duckdb"
con = duckdb.connect(str(db_path))
con.execute("CREATE TABLE t1 (a INT)")
con.execute("INSERT INTO t1 VALUES (1), (2), (3)")
con.close()
mgr = SnapshotManager(str(db_path))
snap_id = mgr.create(label="test snapshot")
assert snap_id
snaps = mgr.list_snapshots()
assert len(snaps) == 1
assert snaps[0]["label"] == "test snapshot"
assert snaps[0]["snapshot_id"] == snap_id
def test_rollback(self, tmp_path) -> None:
db_path = tmp_path / "test.duckdb"
# Create initial state
con = duckdb.connect(str(db_path))
con.execute("CREATE TABLE t1 (a INT)")
con.execute("INSERT INTO t1 VALUES (1), (2), (3)")
con.close()
mgr = SnapshotManager(str(db_path))
snap_id = mgr.create(label="before change")
# Modify the database
con = duckdb.connect(str(db_path))
con.execute("INSERT INTO t1 VALUES (4), (5)")
count_after = con.execute("SELECT COUNT(*) FROM t1").fetchone()[0]
con.close()
assert count_after == 5
# Rollback
assert mgr.rollback(snap_id) is True
# Verify rollback
con = duckdb.connect(str(db_path), read_only=True)
count_rolled = con.execute("SELECT COUNT(*) FROM t1").fetchone()[0]
con.close()
assert count_rolled == 3
def test_rollback_missing(self, tmp_path) -> None:
db_path = tmp_path / "test.duckdb"
duckdb.connect(str(db_path)).close()
mgr = SnapshotManager(str(db_path))
assert mgr.rollback("nonexistent") is False
def test_empty_list(self, tmp_path) -> None:
db_path = tmp_path / "test.duckdb"
duckdb.connect(str(db_path)).close()
mgr = SnapshotManager(str(db_path))
snaps = mgr.list_snapshots()
assert snaps == []
def test_git_sha(self, tmp_path) -> None:
db_path = tmp_path / "test.duckdb"
mgr = SnapshotManager(str(db_path))
sha = mgr._git_sha()
# Should return a short SHA or "unknown"
assert isinstance(sha, str)
assert len(sha) > 0