70 lines
3.4 KiB
Python
70 lines
3.4 KiB
Python
# #region Test.ScenarioExecution.LiveBindingMigration [C:3] [TYPE Module] [SEMANTICS test,scenario,execution,live-binding,migration]
|
|
# @BRIEF Verify the live-binding migration is additive and leaves historical runs nullable.
|
|
# @RELATION BINDS_TO -> [Alembic.ScenarioLiveExecutionBinding]
|
|
# @RELATION VERIFIES -> [Alembic.ScenarioLiveExecutionBinding.Upgrade]
|
|
# @RELATION VERIFIES -> [Alembic.ScenarioLiveExecutionBinding.Downgrade]
|
|
# @TEST_CONTRACT: scenario_runs legacy schema -> nullable binding reference and identity snapshot columns
|
|
# @TEST_FIXTURE: legacy_scenario_runs_044 -> INLINE_JSON nullable additive column contract
|
|
# @TEST_EDGE: no_binding -> nullable columns; downgrade -> both columns/index removed; legacy_authority_inference -> forbidden
|
|
# @TEST_INVARIANT Alembic.ScenarioLiveExecutionBinding: Existing runs remain valid with no binding and therefore fail closed as unavailable live I/O. -> VERIFIED_BY: additive_upgrade, additive_downgrade
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
from unittest.mock import Mock
|
|
|
|
|
|
# #region Test.ScenarioExecution.LiveBindingMigration.Load [C:1] [TYPE Function]
|
|
def _migration_module():
|
|
path = Path(__file__).resolve().parents[1] / "alembic" / "versions" / "c1d2e3f4a5b6_add_scenario_live_execution_binding.py"
|
|
spec = importlib.util.spec_from_file_location("scenario_live_binding_migration", path)
|
|
assert spec and spec.loader
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
# #endregion Test.ScenarioExecution.LiveBindingMigration.Load
|
|
|
|
|
|
# #region Test.ScenarioExecution.LiveBindingMigration.Upgrade [C:2] [TYPE Function]
|
|
# @BRIEF Upgrade adds only nullable identity columns and an index; it never backfills authority.
|
|
def test_upgrade_adds_nullable_binding_identity_columns(monkeypatch):
|
|
migration = _migration_module()
|
|
add_column = Mock()
|
|
create_index = Mock()
|
|
monkeypatch.setattr(migration.op, "add_column", add_column)
|
|
monkeypatch.setattr(migration.op, "create_index", create_index)
|
|
|
|
migration.upgrade()
|
|
|
|
assert [(call.args[1].name, call.args[1].nullable) for call in add_column.call_args_list] == [
|
|
("live_execution_binding_ref", True),
|
|
("live_execution_binding_snapshot", True),
|
|
]
|
|
create_index.assert_called_once_with(
|
|
"ix_scenario_runs_live_execution_binding_ref",
|
|
"scenario_runs",
|
|
["live_execution_binding_ref"],
|
|
)
|
|
# #endregion Test.ScenarioExecution.LiveBindingMigration.Upgrade
|
|
|
|
|
|
# #region Test.ScenarioExecution.LiveBindingMigration.Downgrade [C:2] [TYPE Function]
|
|
# @BRIEF Downgrade removes only the additive identity fields in reverse dependency order.
|
|
def test_downgrade_removes_only_binding_identity_columns(monkeypatch):
|
|
migration = _migration_module()
|
|
drop_index = Mock()
|
|
drop_column = Mock()
|
|
monkeypatch.setattr(migration.op, "drop_index", drop_index)
|
|
monkeypatch.setattr(migration.op, "drop_column", drop_column)
|
|
|
|
migration.downgrade()
|
|
|
|
drop_index.assert_called_once_with("ix_scenario_runs_live_execution_binding_ref", table_name="scenario_runs")
|
|
assert [call.args for call in drop_column.call_args_list] == [
|
|
("scenario_runs", "live_execution_binding_snapshot"),
|
|
("scenario_runs", "live_execution_binding_ref"),
|
|
]
|
|
# #endregion Test.ScenarioExecution.LiveBindingMigration.Downgrade
|
|
|
|
# #endregion Test.ScenarioExecution.LiveBindingMigration
|