Files
ServiceMap-Public/backend/tests/test_config_io.py
T

134 lines
3.5 KiB
Python

import sqlite3
from pathlib import Path
import pytest
from app.config_io import export_document, import_document, parse_document, serialize_document
from app.models import ServiceCreate, ServiceKind
from app.store import Store
CONFIG = """
version: 1
services:
- name: Database
kind: tcp
host: db.local
port: 5432
depends_on: []
- name: API
kind: http
url: https://api.local
depends_on: [Database]
"""
def test_yaml_import_export_round_trip(tmp_path: Path) -> None:
store = Store(str(tmp_path / "servicemap.db"))
result = import_document(store, parse_document(CONFIG, "yaml"), "replace")
assert result.created == 2
services = store.list_services()
assert len(services) == 2
api = store.get_service_by_name("API")
database = store.get_service_by_name("Database")
assert api is not None and database is not None
assert api.depends_on == [database.id]
exported = export_document(store)
yaml_text = serialize_document(exported, "yaml")
reparsed = parse_document(yaml_text, "yaml")
assert [service.name for service in reparsed.services] == [service.name for service in exported.services]
def test_merge_can_reference_existing_service_not_in_document(tmp_path: Path) -> None:
store = Store(str(tmp_path / "servicemap.db"))
database = store.create_service(
ServiceCreate(name="Database", kind=ServiceKind.TCP, host="db.local", port=5432)
)
document = parse_document(
"""
version: 1
services:
- name: API
kind: http
url: https://api.local
depends_on: [Database]
""",
"yaml",
)
result = import_document(store, document, "merge")
assert result.created == 1
assert result.updated == 0
api = store.get_service_by_name("API")
assert api is not None
assert api.depends_on == [database.id]
def test_import_rejects_missing_dependency_and_cycles(tmp_path: Path) -> None:
store = Store(str(tmp_path / "servicemap.db"))
missing = parse_document(
"""
version: 1
services:
- name: API
kind: http
url: https://api.local
depends_on: [Database]
""",
"yaml",
)
with pytest.raises(ValueError, match="unknown dependencies"):
import_document(store, missing, "replace")
cyclic = """
version: 1
services:
- name: A
kind: http
url: https://a.local
depends_on: [B]
- name: B
kind: http
url: https://b.local
depends_on: [A]
"""
with pytest.raises(ValueError, match="cycle"):
parse_document(cyclic, "yaml")
with pytest.raises(ValueError, match="less than or equal to 1"):
parse_document("version: 2\nservices: []", "yaml")
def test_replace_import_rolls_back_on_mid_transaction_failure(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
store = Store(str(tmp_path / "servicemap.db"))
original = store.create_service(
ServiceCreate(name="Original", kind=ServiceKind.HTTP, url="https://original.local")
)
document = parse_document(
"""
version: 1
services:
- name: First
kind: http
url: https://first.local
depends_on: []
- name: Second
kind: http
url: https://second.local
depends_on: []
""",
"yaml",
)
monkeypatch.setattr("app.store.uuid4", lambda: "duplicate-id")
with pytest.raises(sqlite3.IntegrityError):
import_document(store, document, "replace")
remaining = store.list_services()
assert [(service.id, service.name) for service in remaining] == [(original.id, "Original")]