Files
govoplan-workflow-engine/tests/test_migrations.py
T

169 lines
6.3 KiB
Python

from __future__ import annotations
import tempfile
import unittest
from pathlib import Path
import shutil
from alembic.runtime.migration import MigrationContext
from sqlalchemy import create_engine, inspect
from govoplan_core.db.migrations import migrate_database
from dataclasses import replace
from govoplan_workflow_engine.backend.manifest import get_manifest
class WorkflowMigrationTests(unittest.TestCase):
def test_migration_creates_definition_tables_and_head(self) -> None:
with tempfile.TemporaryDirectory(
prefix="govoplan-workflow-engine-migration-"
) as directory:
url = f"sqlite:///{Path(directory) / 'workflow.db'}"
migrate_database(
database_url=url,
enabled_modules=("workflow_engine",),
manifest_factories=(get_manifest,),
)
engine = create_engine(url)
try:
with engine.connect() as connection:
self.assertIn(
"0b4e7c9a2d6f",
set(MigrationContext.configure(connection).get_current_heads()),
)
self.assertEqual(
{
"workflow_definition_revisions",
"workflow_definitions",
"workflow_instance_events",
"workflow_instance_steps",
"workflow_instances",
},
{
name
for name in inspect(connection).get_table_names()
if name.startswith("workflow_")
},
)
revision_columns = {
item["name"]
for item in inspect(connection).get_columns(
"workflow_definition_revisions"
)
}
self.assertTrue(
{
"bpmn_xml",
"bpmn_hash",
"bpmn_adapter_id",
"bpmn_adapter_version",
"bpmn_runtime_kind",
"bpmn_executable",
"execution_mode",
"view_id",
"view_revision_id",
}.issubset(revision_columns)
)
instance_columns = {
item["name"]
for item in inspect(connection).get_columns(
"workflow_instances"
)
}
self.assertIn("start_origin", instance_columns)
definition_columns = {
item["name"]
for item in inspect(connection).get_columns(
"workflow_definitions"
)
}
self.assertIn(
"standard_origin_module_id",
definition_columns,
)
finally:
engine.dispose()
def test_existing_workflow_migration_head_transfers_without_replay(self) -> None:
with tempfile.TemporaryDirectory(
prefix="govoplan-workflow-engine-upgrade-"
) as directory:
url = f"sqlite:///{Path(directory) / 'workflow.db'}"
engine_manifest = get_manifest()
assert engine_manifest.migration_spec is not None
legacy_revisions = Path(directory) / "legacy-revisions"
legacy_revisions.mkdir()
current_revisions = Path(
engine_manifest.migration_spec.script_location or ""
)
for path in current_revisions.glob("*.py"):
if path.name.startswith("0b4e7c9a2d6f_"):
continue
shutil.copy2(path, legacy_revisions / path.name)
legacy_manifest = replace(
engine_manifest,
id="workflow",
name="Workflow",
permission_namespace=None,
migration_spec=replace(
engine_manifest.migration_spec,
module_id="workflow",
script_location=str(legacy_revisions),
),
)
migrate_database(
database_url=url,
enabled_modules=("workflow",),
manifest_factories=(lambda: legacy_manifest,),
)
engine = create_engine(url)
try:
first_tables = set(inspect(engine).get_table_names())
with engine.connect() as connection:
self.assertIn(
"f1b7d3e5a9c2",
set(
MigrationContext.configure(
connection
).get_current_heads()
),
)
self.assertNotIn(
"standard_origin_module_id",
{
item["name"]
for item in inspect(engine).get_columns(
"workflow_definitions"
)
},
)
finally:
engine.dispose()
result = migrate_database(
database_url=url,
enabled_modules=("workflow_engine",),
manifest_factories=(get_manifest,),
)
self.assertIn("0b4e7c9a2d6f", result.current_revision or "")
engine = create_engine(url)
try:
self.assertEqual(first_tables, set(inspect(engine).get_table_names()))
self.assertIn(
"standard_origin_module_id",
{
item["name"]
for item in inspect(engine).get_columns(
"workflow_definitions"
)
},
)
finally:
engine.dispose()
if __name__ == "__main__":
unittest.main()