Files
podman-mvp/control/tests/test_action_contract_freeze.py
T

166 lines
4.7 KiB
Python

import importlib
import importlib.util
from pathlib import Path
from fastapi.testclient import TestClient
def load_app_module():
try:
return importlib.import_module("app")
except ModuleNotFoundError:
app_path = Path("/app/app.py")
spec = importlib.util.spec_from_file_location("app", app_path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
# ============================================================
# /containers/{action}/{name}
# ============================================================
def test_container_action_invalid_action_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/containers/invalid/dummy")
# Freeze whatever baseline currently is
body = r.json()
# Must be JSON and deterministic structure
assert isinstance(body, (dict, list))
# If dict variant
if isinstance(body, dict):
assert set(body.keys()) == {"error"}
assert body["error"] == "Invalid action"
def test_container_action_failure_shape_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/containers/start/nonexistent_container_12345")
body = r.json()
# Freeze exact variant structure
if isinstance(body, dict) and body.get("method") == "podman":
assert "name" in body
assert "cmd" in body
assert "status_code" in body
else:
# Any other baseline variant must still be JSON
assert isinstance(body, (dict, list))
# ============================================================
# /actions/{action}/{name}
# ============================================================
def test_legacy_actions_invalid_action_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/actions/invalid/dummy")
body = r.json()
assert isinstance(body, dict)
assert set(body.keys()) == {"status"}
assert body["status"] == "unknown"
# ============================================================
# /pods/actions/{action}/{podname}
# ============================================================
def test_pods_action_invalid_action_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/pods/actions/invalid/dummy")
body = r.json()
# Baseline may return tuple-style 400 or JSON
assert isinstance(body, (dict, list))
if isinstance(body, dict) and "error" in body:
assert body["error"] == "Invalid action"
def test_pods_action_variant_shape_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/pods/actions/start/nonexistent_pod_12345")
body = r.json()
# Freeze possible baseline variants
if isinstance(body, dict):
if body.get("method") == "systemd_then_podman":
assert set(body.keys()) == {"method", "note", "systemd", "podman"}
assert body["note"] == "systemd failed; falling back to podman"
elif body.get("method") == "podman":
assert set(body.keys()) == {"method", "result"}
else:
assert isinstance(body, list)
# ============================================================
# /{action}/{unit}
# ============================================================
def test_systemctl_wrapper_invalid_action_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/invalid/dummy.service")
body = r.json()
assert set(body.keys()) == {"detail"}
assert body["detail"] == "Invalid action"
def test_systemctl_wrapper_status_shape_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/status/nonexistent.service")
body = r.json()
# allowlist may cause 403
if r.status_code == 403:
assert set(body.keys()) == {"detail"}
else:
assert set(body.keys()) == {"cmd", "exit", "output"}
# ============================================================
# /api/<action>/<unit>
# ============================================================
def test_legacy_api_invalid_action_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/api/invalid/dummy.service")
body = r.json()
# Baseline: HTTPException 400 with {"detail": "..."}
assert r.status_code == 400
assert set(body.keys()) == {"detail"}
def test_legacy_api_status_shape_contract():
app_mod = load_app_module()
client = TestClient(app_mod.app)
r = client.post("/api/status/nonexistent.service")
body = r.json()
if r.status_code == 403:
assert set(body.keys()) == {"detail"}
else:
assert set(body.keys()) == {"cmd", "exit", "output"}