Build reusable bot framework
Some checks failed
CI / test (push) Has been cancelled
CI / compose-smoke (push) Has been cancelled

This commit is contained in:
Chelsea Lee
2026-07-19 21:53:24 -05:00
parent 7ecc1107b2
commit fbdf33e894
66 changed files with 8428 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
"""Unit tests for migration discovery and history decisions."""
from contextlib import contextmanager
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
from core import migrations
@pytest.fixture
def migrationRoot():
with TemporaryDirectory(prefix=".migration-test-", dir=Path.cwd()) as directory:
yield Path(directory)
def _writeMigration(root, relativePath, content="SELECT 1;"):
path = root / relativePath
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
return path
class FakeCursor:
def __init__(self, applied=None, historyTable=True):
self.applied = list(applied or [])
self.historyTable = historyTable
self.executed = []
self._one = None
self._all = []
def __enter__(self):
return self
def __exit__(self, *_args):
return False
def execute(self, query, params=None):
normalized = " ".join(query.split())
self.executed.append((normalized, params))
if "SELECT to_regclass" in normalized:
self._one = {
"table_name": "schema_migrations" if self.historyTable else None
}
elif normalized.startswith("SELECT namespace, version, checksum"):
self._all = self.applied
def fetchone(self):
return self._one
def fetchall(self):
return self._all
class FakeConnection:
def __init__(self, cursor):
self.activeCursor = cursor
def cursor(self, **_kwargs):
return self.activeCursor
def _connectionFor(cursor):
@contextmanager
def fakeConnection():
yield FakeConnection(cursor)
return fakeConnection
def test_discovery_orders_core_before_feature_namespaces(migrationRoot):
_writeMigration(migrationRoot, "config/migrations/0002_second.sql", "SELECT 2;")
_writeMigration(migrationRoot, "config/migrations/0001_first.sql", "SELECT 1;")
_writeMigration(migrationRoot, "modules/zeta/migrations/0001_zeta.sql")
_writeMigration(migrationRoot, "modules/alpha/migrations/0002_alpha.sql")
found = migrations.discover_migrations(migrationRoot)
assert [(item.namespace, item.version) for item in found] == [
("core", 1),
("core", 2),
("alpha", 2),
("zeta", 1),
]
assert len(found[0].checksum) == 64
assert found[0].path == Path(
migrationRoot, "config/migrations/0001_first.sql"
)
def test_discovery_rejects_bad_names_and_duplicate_versions(migrationRoot):
_writeMigration(migrationRoot, "config/migrations/not-numbered.sql")
with pytest.raises(migrations.MigrationError, match="Invalid migration filename"):
migrations.discover_migrations(migrationRoot)
Path(migrationRoot, "config/migrations/not-numbered.sql").unlink()
_writeMigration(migrationRoot, "config/migrations/0001_first.sql")
_writeMigration(migrationRoot, "config/migrations/0001_duplicate.sql")
with pytest.raises(migrations.MigrationError, match="Duplicate migration"):
migrations.discover_migrations(migrationRoot)
def test_upgrade_applies_pending_and_skips_matching_history(
migrationRoot, monkeypatch
):
_writeMigration(migrationRoot, "config/migrations/0001_first.sql", "SELECT 42;")
migration = migrations.discover_migrations(migrationRoot)[0]
cursor = FakeCursor()
monkeypatch.setattr(migrations.postgres, "get_connection", _connectionFor(cursor))
assert migrations.upgrade(migrationRoot) == [migration]
queries = [query for query, _params in cursor.executed]
assert any("pg_advisory_xact_lock" in query for query in queries)
assert "SELECT 42;" in queries
assert any(query.startswith("INSERT INTO schema_migrations") for query in queries)
cursor = FakeCursor(
applied=[
{
"namespace": "core",
"version": 1,
"checksum": migration.checksum,
"applied_at": None,
}
]
)
monkeypatch.setattr(migrations.postgres, "get_connection", _connectionFor(cursor))
assert migrations.upgrade(migrationRoot) == []
assert "SELECT 42;" not in [query for query, _params in cursor.executed]
def test_upgrade_rejects_changed_applied_migration(migrationRoot, monkeypatch):
_writeMigration(migrationRoot, "config/migrations/0001_first.sql", "SELECT 1;")
cursor = FakeCursor(
applied=[
{
"namespace": "core",
"version": 1,
"checksum": "0" * 64,
"applied_at": None,
}
]
)
monkeypatch.setattr(migrations.postgres, "get_connection", _connectionFor(cursor))
with pytest.raises(migrations.MigrationError, match="checksum changed"):
migrations.upgrade(migrationRoot)
def test_status_handles_new_database_and_missing_source(migrationRoot, monkeypatch):
_writeMigration(migrationRoot, "config/migrations/0001_first.sql", "SELECT 1;")
cursor = FakeCursor(historyTable=False)
monkeypatch.setattr(migrations.postgres, "get_connection", _connectionFor(cursor))
assert migrations.migration_status(migrationRoot)[0]["state"] == "pending"
cursor = FakeCursor(
applied=[
{
"namespace": "removed_feature",
"version": 3,
"checksum": "a" * 64,
"applied_at": "earlier",
}
]
)
monkeypatch.setattr(migrations.postgres, "get_connection", _connectionFor(cursor))
status = migrations.migration_status(migrationRoot)
assert [item["state"] for item in status] == ["pending", "missing"]
assert status[1]["namespace"] == "removed_feature"