openenv-customer-support / tests /test_services.py
Anuj2209's picture
updated EICC v2 environment, APIs, and training pipeline
ca51294
Raw
History Blame Contribute Delete
4.65 kB
"""Tests for deterministic service mesh behavior."""
from __future__ import annotations
import pytest
from env.services import (
Alert,
BLAST_RADIUS,
SERVICE_OBSERVABILITY,
ServiceMesh,
)
# =====================================================================
# Core mesh behavior
# =====================================================================
def test_inject_failure_cascades_to_dependents() -> None:
"""Root outage should degrade transitive dependents."""
mesh = ServiceMesh(seed=7)
mesh.inject_failure("database", "oom")
summary = mesh.get_health_summary()
assert summary["database"] == "down"
assert summary["payments"] == "degraded"
assert summary["analytics"] == "degraded"
assert summary["notifications"] == "degraded"
assert summary["auth"] == "healthy"
def test_apply_fix_root_cause_heals_chain() -> None:
"""Correct root-cause fix should heal root and dependents."""
mesh = ServiceMesh(seed=11)
mesh.inject_failure("auth", "config_corruption")
result = mesh.apply_fix("auth", "config_change")
assert result.success is True
assert "auth" in result.healed_services
assert mesh.get_health_summary()["auth"] == "healthy"
assert mesh.get_health_summary()["payments"] == "healthy"
def test_apply_fix_symptom_is_temporary() -> None:
"""Fixing a symptom should not resolve root-cause state."""
mesh = ServiceMesh(seed=3)
mesh.inject_failure("database", "oom")
result = mesh.apply_fix("payments", "restart_service")
assert result.success is False
assert mesh.services["database"].is_root_cause is True
# =====================================================================
# Advanced features
# =====================================================================
def test_topology_hidden_on_hard_and_nightmare() -> None:
"""Dependency graph must be hidden on hard/nightmare modes."""
mesh = ServiceMesh(seed=1)
assert mesh.get_dependencies("easy")
assert mesh.get_dependencies("medium")
assert mesh.get_dependencies("hard") == {}
assert mesh.get_dependencies("nightmare") == {}
def test_observability_affects_probe_detail() -> None:
"""Low-observability services return minimal probe findings."""
mesh = ServiceMesh(seed=8)
high = mesh.probe_service("auth", "logs")
low = mesh.probe_service("analytics", "logs")
assert SERVICE_OBSERVABILITY["auth"] == "high"
assert SERVICE_OBSERVABILITY["analytics"] == "low"
assert len(high.findings) > len(low.findings)
def test_flickering_pattern_is_deterministic() -> None:
"""Flickering service should follow deterministic repeating pattern."""
mesh = ServiceMesh(seed=9)
mesh.set_flickering("payments", "connection_flap")
observed = []
for step in range(4):
mesh.tick_service_health(step + 1)
observed.append(mesh.services["payments"].health)
assert observed == ["degraded", "healthy", "degraded", "healthy"]
def test_time_based_degradation_can_reach_down() -> None:
"""Degraded services worsen every 5 steps and eventually fail hard."""
mesh = ServiceMesh(seed=2)
mesh.inject_failure("database", "oom")
mesh.services["payments"].error_rate = 0.89
mesh.tick_service_health(5)
assert mesh.services["payments"].health == "down"
def test_apply_wrong_fix_triggers_blast_radius() -> None:
"""Wrong fix should apply configured penalty and extra damage."""
mesh = ServiceMesh(seed=10)
mesh.inject_failure("auth", "rate_limiting")
result = mesh.apply_wrong_fix("database", "schema_migration")
assert result.penalty == pytest.approx(float(BLAST_RADIUS["schema_migration"]["penalty"]))
assert result.cascade is True
assert "database" in result.damaged_services
def test_generate_alerts_is_deterministic() -> None:
"""Alert stream should be reproducible for same seed and step."""
mesh_a = ServiceMesh(seed=5)
mesh_b = ServiceMesh(seed=5)
mesh_a.inject_failure("database", "oom")
mesh_b.inject_failure("database", "oom")
alerts_a = mesh_a.generate_alerts(step=6)
alerts_b = mesh_b.generate_alerts(step=6)
assert [a.model_dump() for a in alerts_a] == [b.model_dump() for b in alerts_b]
assert all(isinstance(alert, Alert) for alert in alerts_a)
def test_generate_red_herrings_is_deterministic() -> None:
"""Per-incident red herring generation should be deterministic."""
mesh = ServiceMesh(seed=4)
first = mesh.generate_red_herrings("HARD-012")
second = mesh.generate_red_herrings("HARD-012")
assert [h.model_dump() for h in first] == [h.model_dump() for h in second]