Files
ModelForge-Public/backend/tests/test_deployed_schema_convergence.py
T

256 lines
11 KiB
Python

"""Preserve deployed migration meaning and prove additive convergence on isolated databases."""
from __future__ import annotations
import hashlib
import importlib
import importlib.util
from datetime import UTC, datetime
from pathlib import Path
from uuid import uuid4
import pytest
from alembic.config import Config
from alembic.migration import MigrationContext
from alembic.operations import Operations
from alembic.script import ScriptDirectory
from sqlalchemy import Column, Integer, MetaData, Table, create_engine, inspect, select, text
from sqlalchemy.exc import DBAPIError
from sqlalchemy.orm import Session
from modelforge_api.persistence.models import AuditEvent, ModelRevision, ProjectBinding
from modelforge_api.services.recovery_fingerprint import _actual_table
from tests.test_managed_identities_postgres import IdentityDatabase, identity_database
from tests.test_selected_comparison_postgres import _valid_selection
from tests.test_serving_generation_recovery import legacy_generation_fixture
__all__ = ["identity_database"]
ROOT = Path(__file__).resolve().parents[1]
VERSIONS = ROOT / "alembic" / "versions"
FROZEN = {
"20260909_0029_external_creative_coordination.py": "ac41923b2bd7a8729abeaae5c872afa3186d4b188fe002015d77c9bc23b9c5db",
"20260909_0030_model_update_inbox.py": "265379bd5e1c2cee78a9c4a4e6004ec802a6dbbc57e5f30c422e8eb91fea99cf",
"20260909_0031_external_creative_governance.py": "397d4b288bb7564eb50da5950e1478db237f2a91d801de3d3786112b638f2c55",
"20260909_0032_audio_creative_workloads.py": "ede826fa5ada798e5730ef99b0a8380d1831d3ed11a1baccda9ed5bc0e60d362",
}
HISTORY_TABLES = (
"model_update_watches",
"model_update_notices",
"external_creative_allocations",
"external_creative_resources",
"external_creative_action_attestations",
"external_creative_profile_observations",
)
def _migration():
specification = importlib.util.spec_from_file_location(
"convergence", VERSIONS / "20260909_0033_deployed_hub_convergence.py"
)
assert specification is not None and specification.loader is not None
module = importlib.util.module_from_spec(specification)
specification.loader.exec_module(module)
return module
def test_deployed_migration_content_remains_frozen_and_graph_is_linear() -> None:
for name, digest in FROZEN.items():
# Normalize checkout line endings only; the deployed repository blobs are LF.
assert (
hashlib.sha256((VERSIONS / name).read_bytes().replace(b"\r\n", b"\n")).hexdigest()
== digest
)
config = Config()
config.set_main_option("script_location", str(ROOT / "alembic"))
graph = ScriptDirectory.from_config(config)
assert graph.get_heads() == ["20260924_0039"]
assert Path(graph.get_revision("20260909_0029").path).name in FROZEN
assert Path(graph.get_revision("20260909_0030").path).name in FROZEN
assert graph.get_revision("20260909_0033").down_revision == "20260909_0032"
assert graph.get_revision("20260923_0036").down_revision == "20260911_0035"
assert graph.get_revision("20260923_0037").down_revision == "20260923_0036"
assert graph.get_revision("20260924_0038").down_revision == "20260923_0037"
assert graph.get_revision("20260924_0039").down_revision == "20260924_0038"
assert not (VERSIONS / "20260909_0029_model_update_inbox.py").exists()
assert not (VERSIONS / "20260909_0030_selected_model_comparisons.py").exists()
@pytest.mark.parametrize("populated", HISTORY_TABLES)
def test_new_downgrade_refuses_populated_deployed_history(populated: str) -> None:
engine = create_engine("sqlite://")
with engine.begin() as connection:
for name in HISTORY_TABLES:
Table(name, MetaData(), Column("id", Integer)).create(connection)
connection.execute(text("ALTER TABLE model_update_watches ADD COLUMN upstream_ref TEXT"))
module = _migration()
module.op = Operations(MigrationContext.configure(connection))
module.upgrade()
table = Table(populated, MetaData(), autoload_with=connection)
connection.execute(table.insert().values(id=1))
with pytest.raises(RuntimeError, match="history exists"):
module.downgrade()
assert inspect(connection).has_table("selected_model_comparisons")
assert {
column["name"] for column in inspect(connection).get_columns("model_update_watches")
} >= {"enabled", "version"}
engine.dispose()
def test_populated_0032_upgrade_preserves_creative_watch_audit_history_and_restricts_runtime(
identity_database: IdentityDatabase,
) -> None:
database = identity_database
alembic = importlib.import_module("alembic.command")
alembic.upgrade(database.migration(), "20260909_0032")
with legacy_generation_fixture(database.owner), Session(database.runtime) as session:
request, client_id = _valid_selection(session)
connection = session.connection()
tables = {name: _actual_table(connection, name) for name in HISTORY_TABLES}
project_id = connection.scalar(
select(ProjectBinding.project_id).where(ProjectBinding.id == request.project_binding_id),
)
revision = connection.execute(
select(ModelRevision.id, ModelRevision.model_id, ModelRevision.resolved_commit_sha).order_by(ModelRevision.id).limit(1)
).one()
watch_id, allocation_id, resource_id = uuid4(), uuid4(), uuid4()
connection.execute(
tables["model_update_watches"]
.insert()
.values(
id=watch_id,
model_id=revision.model_id,
baseline_revision_id=revision.id,
baseline_commit_sha=revision.resolved_commit_sha,
upstream_ref="main",
)
)
connection.execute(
tables["model_update_notices"]
.insert()
.values(
id=uuid4(),
watch_id=watch_id,
model_id=revision.model_id,
baseline_commit_sha=revision.resolved_commit_sha,
candidate_revision_id=revision.id,
candidate_commit_sha=revision.resolved_commit_sha,
status="dismissed",
)
)
connection.execute(
tables["external_creative_allocations"]
.insert()
.values(
id=allocation_id,
service_client_id=client_id,
project_id=project_id,
request_id="preserved",
idempotency_key="preserved",
request_sha256="a" * 64,
workload="audio",
resource_ref="fixture.audio@1",
provider_resource_id="fixture",
required_vram_bytes=1024,
priority="background",
ttl_seconds=600,
state="released",
decision_code="OFFLINE_FIXTURE",
decision_evidence={"preserve": True},
required_actions=[],
)
)
connection.execute(
tables["external_creative_resources"]
.insert()
.values(
id=resource_id,
project_id=project_id,
resource_ref="fixture.audio@1",
workload="audio",
provider_resource_id="fixture",
approved=False,
configured_vram_bytes=1024,
)
)
connection.execute(
tables["external_creative_action_attestations"]
.insert()
.values(
id=uuid4(),
allocation_id=allocation_id,
action="release_idle_comfy",
before_vram_bytes=1024,
after_vram_bytes=0,
observed_at=datetime.now(UTC),
validated=True,
)
)
connection.execute(
tables["external_creative_profile_observations"]
.insert()
.values(
id=uuid4(),
allocation_id=allocation_id,
resource_ref="fixture.audio@1",
provider_resource_id="fixture",
workload="audio",
observed_peak_vram_bytes=512,
reserved_vram_bytes=1024,
duration_ms=1,
outcome="succeeded",
)
)
session.commit()
before = {
name: session.execute(select(table).order_by(table.c.id)).mappings().all()
for name, table in tables.items()
}
audit_before = session.execute(
select(AuditEvent.id, AuditEvent.canonical_payload, AuditEvent.event_hash).order_by(AuditEvent.sequence)
).all()
assert "enabled" not in {
column["name"]
for column in inspect(session.connection()).get_columns("model_update_watches")
}
alembic.upgrade(database.migration(), "20260909_0033")
with database.runtime.connect() as connection:
for name, table in tables.items():
assert (
connection.execute(select(table).order_by(table.c.id)).mappings().all()
== before[name]
)
assert (
connection.execute(
select(AuditEvent.id, AuditEvent.canonical_payload, AuditEvent.event_hash).order_by(AuditEvent.sequence)
).all()
== audit_before
)
assert connection.execute(
text("SELECT enabled, version FROM model_update_watches WHERE id=:id"), {"id": watch_id}
).one() == (True, 1)
assert connection.scalar(text("SELECT count(*) FROM selected_model_comparisons")) == 0
for table_name in (
"model_update_watches",
"model_update_notices",
"selected_model_comparisons",
):
for privilege in ("SELECT", "INSERT", "UPDATE"):
assert connection.scalar(
text("SELECT has_table_privilege(current_user, :table, :privilege)"),
{"table": table_name, "privilege": privilege},
)
for privilege in ("DELETE", "TRUNCATE"):
assert not connection.scalar(
text("SELECT has_table_privilege(current_user, :table, :privilege)"),
{"table": table_name, "privilege": privilege},
)
with pytest.raises(DBAPIError):
connection.execute(
text("DELETE FROM model_update_watches WHERE id=:id"), {"id": watch_id}
)
connection.rollback()
with pytest.raises(RuntimeError, match="history exists"):
alembic.downgrade(database.migration(), "20260909_0032")
with database.runtime.connect() as connection:
assert connection.scalar(text("SELECT version_num FROM alembic_version")) == "20260909_0033"