Files
DECNET/tests/ttp/store/conftest.py
anti f2b3393669 chore: relicense to AGPL-3.0-or-later and add SPDX headers
Replaces LICENSE (GPLv3 -> AGPLv3) and prepends
`SPDX-License-Identifier: AGPL-3.0-or-later` to every source file
across decnet/, decnet_web/, tests/, scripts/, and tools/.

Rationale: closes the GPLv3 ASP loophole so any party operating a
modified DECNET as a network service must offer their modified
source. Personal copyright (Samuel Paschuan) + inbound=outbound
contributions make a future unilateral relicense infeasible.

- LICENSE: full AGPL-3.0 text (gnu.org/licenses/agpl-3.0.txt)
- COPYRIGHT: project copyright notice
- tools/add_spdx_headers.py: idempotent header injector
  (shebang- and PEP 263-aware)

Touches 1565 source files (.py, .ts, .tsx, .js, .jsx, .css, .sh).
No behavior change; comments only.
2026-05-22 21:04:16 -04:00

110 lines
4.0 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""Parametrized ``rule_store`` fixture for E.2.14b.
The conformance contract from ``development/TTP_TAGGING.md`` §E.2.14b:
both backends — :class:`FilesystemRuleStore` and
:class:`DatabaseRuleStore` — must satisfy the same observable
behavior. Tests that consume :func:`rule_store` are run twice, once
per backend.
Filesystem is skipped on non-Linux (it raises ``RuntimeError`` from
``__init__`` on macOS / Windows because the inotify dep is
Linux-only).
"""
from __future__ import annotations
import sys
from pathlib import Path
from typing import AsyncIterator
import pytest
import pytest_asyncio
from decnet.ttp.store.base import RuleStore
from decnet.ttp.store.impl.database import DatabaseRuleStore
from decnet.ttp.store.impl.filesystem import FilesystemRuleStore
from decnet.web.db.models import TTPRule
async def _seed_rule_filesystem(
store: FilesystemRuleStore, rule_id: str, yaml_text: str,
) -> None:
rules_dir: Path = store._rules_dir
rules_dir.mkdir(parents=True, exist_ok=True)
(rules_dir / f"{rule_id}.yaml").write_text(yaml_text, encoding="utf-8")
async def _seed_rule_database(
store: DatabaseRuleStore, rule_id: str, yaml_text: str,
) -> None:
# Direct ``ttp_rule`` insert — bypass the master sync helper to
# keep tests deterministic. Mirrors what a swarm master would have
# written into the table.
repo = await store._ensure_repo()
async with repo._session() as session: # type: ignore[attr-defined]
from datetime import datetime, timezone # noqa: PLC0415
session.add(TTPRule(
rule_id=rule_id,
rule_version=1,
source_path=f"./rules/ttp/{rule_id}.yaml",
yaml_content=yaml_text,
updated_at=datetime.now(timezone.utc),
updated_by="test",
))
await session.commit()
async def seed_rule(store: RuleStore, rule_id: str, yaml_text: str) -> None:
"""Backend-aware test helper: write a rule into the store.
Filesystem store: drop a YAML file under ``_rules_dir``.
Database store: insert a ``ttp_rule`` row directly.
"""
if isinstance(store, FilesystemRuleStore):
await _seed_rule_filesystem(store, rule_id, yaml_text)
elif isinstance(store, DatabaseRuleStore):
await _seed_rule_database(store, rule_id, yaml_text)
else: # pragma: no cover
raise TypeError(f"unknown rule store backend: {type(store).__name__}")
@pytest_asyncio.fixture(
params=["filesystem", "database"],
ids=["filesystem", "database"],
)
async def rule_store(
request: pytest.FixtureRequest, tmp_path: Path,
) -> AsyncIterator[RuleStore]:
"""Yield a fresh :class:`RuleStore` instance per parametrization.
The filesystem backend is constructed against a ``tmp_path``
rules dir so tests never touch the real ``./rules/``. The
database backend gets a per-test SQLite repo (initialized with
``metadata.create_all``) so each test sees an empty
``ttp_rule`` / ``ttp_rule_state`` pair.
"""
backend = request.param
if backend == "filesystem":
if sys.platform != "linux":
pytest.skip("FilesystemRuleStore requires Linux (inotify)")
yield FilesystemRuleStore(rules_dir=tmp_path)
else:
from decnet.web.db.sqlite.repository import SQLiteRepository # noqa: PLC0415
repo = SQLiteRepository(db_path=str(tmp_path / "ttp_store.db"))
await repo.initialize()
store = DatabaseRuleStore(repo=repo)
# Mirror FS store's ``_rules_dir`` attr so cross-backend tests
# that need to drop sample YAML on disk have somewhere to put
# it; the DB-backend tests that need rule definitions either
# write to ``ttp_rule`` directly or call ``upsert_rule``.
store._rules_dir = tmp_path # type: ignore[attr-defined]
try:
yield store
finally:
try:
await repo.engine.dispose()
except Exception: # noqa: BLE001 — teardown best-effort
pass