"""Verify durable Campaign child-Run identity migration semantics.""" import importlib import sqlalchemy as sa from alembic.migration import MigrationContext from alembic.operations import Operations def _legacy_eval_runs(connection) -> None: connection.execute(sa.text("CREATE TABLE campaigns (id VARCHAR PRIMARY KEY)")) connection.execute( sa.text( "CREATE TABLE eval_runs (" "id VARCHAR PRIMARY KEY, campaign_id VARCHAR NULL, " "status VARCHAR NOT NULL)" ) ) connection.execute(sa.text("INSERT INTO eval_runs (id, campaign_id, status) VALUES ('old', NULL, 'completed')")) def test_campaign_run_identity_migration_is_nullable_unique_and_reversible(tmp_path): engine = sa.create_engine(f"sqlite:///{tmp_path / 'campaign-run-identity.db'}") migration = importlib.import_module( "migrations.versions.c2f4a6b8d0e1_add_campaign_run_identity" ) with engine.begin() as connection: _legacy_eval_runs(connection) operations = Operations(MigrationContext.configure(connection)) migration.op = operations migration.upgrade() inspector = sa.inspect(connection) columns = {column["name"]: column for column in inspector.get_columns("eval_runs")} assert columns["campaign_plan_index"]["nullable"] is True assert columns["campaign_occurrence_index"]["nullable"] is True assert connection.execute(sa.text("SELECT campaign_plan_index, campaign_occurrence_index FROM eval_runs WHERE id='old'")) .one() == (None, None) indexes = inspector.get_indexes("eval_runs") assert any( index["name"] == "uq_eval_runs_campaign_occurrence" and bool(index["unique"]) and index["column_names"] == ["campaign_id", "campaign_plan_index", "campaign_occurrence_index"] for index in indexes ) connection.execute( sa.text( "INSERT INTO eval_runs (id, campaign_id, campaign_plan_index, campaign_occurrence_index, status) " "VALUES ('child-1', 'campaign-1', 0, 0, 'pending')" ) ) try: connection.execute( sa.text( "INSERT INTO eval_runs (id, campaign_id, campaign_plan_index, campaign_occurrence_index, status) " "VALUES ('child-duplicate', 'campaign-1', 0, 0, 'pending')" ) ) except sa.exc.IntegrityError: pass else: # pragma: no cover - assertion guard raise AssertionError("Campaign child identity must be unique") migration.downgrade() assert "campaign_plan_index" not in {column["name"] for column in sa.inspect(connection).get_columns("eval_runs")} assert "campaign_occurrence_index" not in {column["name"] for column in sa.inspect(connection).get_columns("eval_runs")} def test_fresh_schema_exposes_same_identity_columns_and_unique_index(tmp_path): """SQLModel's fresh-database path matches the Alembic contract.""" from agenteval.storage.db import EvalRunDB # noqa: F401 - register table from sqlmodel import SQLModel, create_engine engine = create_engine(f"sqlite:///{tmp_path / 'fresh.db'}") SQLModel.metadata.create_all(engine) inspector = sa.inspect(engine) columns = {column["name"] for column in inspector.get_columns("eval_runs")} assert {"campaign_plan_index", "campaign_occurrence_index"} <= columns assert any( index["name"] == "uq_eval_runs_campaign_occurrence" and bool(index["unique"]) and index["column_names"] == ["campaign_id", "campaign_plan_index", "campaign_occurrence_index"] for index in inspector.get_indexes("eval_runs") )