76 lines
2.6 KiB
Python
76 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import unittest
|
|
from uuid import uuid4
|
|
|
|
from alembic import command
|
|
from alembic.config import Config
|
|
from sqlalchemy import select, update
|
|
from sqlalchemy.exc import DBAPIError
|
|
|
|
from services.control_api.persistence.db import (
|
|
create_engine_from_url,
|
|
session_factory,
|
|
)
|
|
from services.control_api.persistence.models import AuditEventRow, WorkspaceRow
|
|
from services.control_api.persistence.seed import seed_database
|
|
|
|
|
|
@unittest.skipUnless(
|
|
os.getenv("WP030_DATABASE_URL"),
|
|
"set WP030_DATABASE_URL to run the disposable PostgreSQL acceptance test",
|
|
)
|
|
class PostgresAcceptanceTests(unittest.TestCase):
|
|
def test_migrate_seed_and_audit_append_only(self) -> None:
|
|
url = os.environ["WP030_DATABASE_URL"]
|
|
config = Config("infrastructure/database/alembic.ini")
|
|
config.set_main_option("sqlalchemy.url", url)
|
|
command.upgrade(config, "head")
|
|
engine = create_engine_from_url(url)
|
|
factory = session_factory(engine)
|
|
workspace_id = uuid4()
|
|
try:
|
|
with factory() as session:
|
|
result = seed_database(session)
|
|
self.assertIsNotNone(result.workspace_id)
|
|
workspace = WorkspaceRow(
|
|
id=workspace_id,
|
|
slug=f"pg-{workspace_id.hex[:12]}",
|
|
name="PostgreSQL acceptance workspace",
|
|
status="active",
|
|
)
|
|
session.add(workspace)
|
|
session.flush()
|
|
event = AuditEventRow(
|
|
workspace_id=workspace_id,
|
|
project_id=None,
|
|
trace_id="wp-030-test",
|
|
event_type="acceptance.test",
|
|
outcome="allowed",
|
|
sanitized_arguments={"safe": True},
|
|
)
|
|
session.add(event)
|
|
session.commit()
|
|
event_id = event.id
|
|
|
|
with factory() as session:
|
|
with self.assertRaises(DBAPIError):
|
|
session.execute(
|
|
update(AuditEventRow)
|
|
.where(AuditEventRow.id == event_id)
|
|
.values(outcome="tampered")
|
|
)
|
|
session.rollback()
|
|
|
|
with factory() as session:
|
|
stored = session.scalar(select(AuditEventRow).where(AuditEventRow.id == event_id))
|
|
self.assertIsNotNone(stored)
|
|
self.assertEqual(stored.outcome, "allowed")
|
|
finally:
|
|
engine.dispose()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|