119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
import unittest
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from govoplan_connectors.backend.db.models import (
|
|
ConnectorSanctionsAcquisitionRun,
|
|
ConnectorSanctionsSnapshot,
|
|
ConnectorTabularSource,
|
|
)
|
|
from govoplan_connectors.backend.manifest import manifest
|
|
from govoplan_connectors.backend.provider_state import (
|
|
SANCTIONS_PROVIDER_ID,
|
|
TABULAR_PROVIDER_ID,
|
|
sanctions_provider_states,
|
|
tabular_provider_states,
|
|
)
|
|
from govoplan_core.core.provider_governance import ExternalProviderStateContext
|
|
from govoplan_core.db.base import Base
|
|
|
|
|
|
class ConnectorsProviderStateTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.engine = create_engine("sqlite+pysqlite:///:memory:", future=True)
|
|
Base.metadata.create_all(
|
|
self.engine,
|
|
tables=(
|
|
ConnectorTabularSource.__table__,
|
|
ConnectorSanctionsAcquisitionRun.__table__,
|
|
ConnectorSanctionsSnapshot.__table__,
|
|
),
|
|
)
|
|
self.session = sessionmaker(bind=self.engine, expire_on_commit=False)()
|
|
|
|
def tearDown(self) -> None:
|
|
self.session.close()
|
|
self.engine.dispose()
|
|
|
|
def test_immutable_tabular_snapshot_reports_ready_state(self) -> None:
|
|
self.session.add(
|
|
ConnectorTabularSource(
|
|
id="tabular-1",
|
|
tenant_id="tenant-1",
|
|
source_name="monthly",
|
|
name="Monthly input",
|
|
status="active",
|
|
schema_version=1,
|
|
schema_=[{"name": "id", "type": "string"}],
|
|
rows=[{"id": "1"}],
|
|
fingerprint="a" * 64,
|
|
row_count=1,
|
|
byte_count=10,
|
|
)
|
|
)
|
|
self.session.commit()
|
|
|
|
state = tabular_provider_states(
|
|
ExternalProviderStateContext(session=self.session, tenant_id="tenant-1")
|
|
)[0]
|
|
|
|
self.assertEqual("healthy", state.health)
|
|
self.assertEqual("ready", state.recovery)
|
|
self.assertEqual("not_applicable", state.freshness)
|
|
|
|
def test_sanctions_state_hashes_binding_and_manifest_registers_state(self) -> None:
|
|
now = datetime.now(UTC)
|
|
run = ConnectorSanctionsAcquisitionRun(
|
|
id="run-1",
|
|
tenant_id="tenant-1",
|
|
provider_id="eu",
|
|
source_id="secret-source-name",
|
|
status="succeeded",
|
|
attempt_count=1,
|
|
started_at=now,
|
|
finished_at=now,
|
|
)
|
|
snapshot = ConnectorSanctionsSnapshot(
|
|
id="snapshot-1",
|
|
tenant_id="tenant-1",
|
|
provider_id="eu",
|
|
publisher="European Union",
|
|
jurisdiction="EU",
|
|
list_type="sanctions",
|
|
source_id="secret-source-name",
|
|
source_version="2026-08-01",
|
|
acquired_at=now,
|
|
source_url="https://source.example.test/list.xml",
|
|
content_type="application/xml",
|
|
byte_count=8,
|
|
sha256="b" * 64,
|
|
parser_version="1",
|
|
connector_run_id=run.id,
|
|
raw_content=b"<list/>",
|
|
)
|
|
run.snapshot_id = snapshot.id
|
|
self.session.add_all((run, snapshot))
|
|
self.session.commit()
|
|
|
|
state = sanctions_provider_states(
|
|
ExternalProviderStateContext(session=self.session, tenant_id="tenant-1")
|
|
)[0]
|
|
|
|
self.assertEqual("healthy", state.health)
|
|
self.assertEqual("ready", state.recovery)
|
|
rendered = str(state.to_dict())
|
|
self.assertNotIn("secret-source-name", rendered)
|
|
self.assertNotIn("source.example.test", rendered)
|
|
self.assertEqual(
|
|
{TABULAR_PROVIDER_ID, SANCTIONS_PROVIDER_ID},
|
|
{item.provider_id for item in manifest.external_provider_state_providers},
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|