coenv / tests /test_simulation_service.py
SandyTheAdventurer's picture
Upload folder using huggingface_hub
05a686e verified
import pytest
from server.simulation_service import (
CoenvEnvironment,
calculate_reward,
check_task_complete,
get_objective_for_task,
)
from models import CoenvAction
class StubPod:
def __init__(self, deployment: str, status: str, restarts: int = 0):
self.deployment = deployment
self.status = status
self.restarts = restarts
class StubHPA:
def __init__(self, name: str, min_replicas: int, max_replicas: int, cpu_target_percent: int):
self.name = name
self.min_replicas = min_replicas
self.max_replicas = max_replicas
self.cpu_target_percent = cpu_target_percent
class StubWorld:
def __init__(self, pods, hpas=None):
self._pods = pods
self._hpas = hpas or []
def get_pods(self):
return self._pods
def get_hpas(self):
return self._hpas
def test_get_objective_for_task_known_and_unknown():
known = get_objective_for_task("pod_recovery")
unknown = get_objective_for_task("unknown-task")
assert "crash-looping" in known
assert unknown == "Maintain cluster health"
def test_calculate_reward_pod_recovery():
world = StubWorld(
[
StubPod("frontend", "Running"),
StubPod("frontend", "Running"),
StubPod("frontend", "CrashLoopBackOff"),
]
)
reward = calculate_reward(world, "pod_recovery")
assert reward == pytest.approx(2 / 3)
def test_calculate_reward_autoscaling_rewards_stability_and_hpa_policy():
healthy_world = StubWorld(
[
StubPod("backend", "Running", restarts=0),
StubPod("backend", "Running", restarts=0),
],
hpas=[StubHPA("backend-hpa", min_replicas=2, max_replicas=6, cpu_target_percent=70)],
)
unstable_world = StubWorld(
[
StubPod("backend", "Running", restarts=10),
StubPod("backend", "Running", restarts=9),
],
hpas=[StubHPA("backend-hpa", min_replicas=2, max_replicas=6, cpu_target_percent=70)],
)
no_hpa_world = StubWorld(
[
StubPod("backend", "Running", restarts=0),
StubPod("backend", "Running", restarts=0),
],
hpas=[],
)
healthy_reward = calculate_reward(healthy_world, "autoscaling")
unstable_reward = calculate_reward(unstable_world, "autoscaling")
no_hpa_reward = calculate_reward(no_hpa_world, "autoscaling")
assert healthy_reward == pytest.approx(1.0)
assert unstable_reward < healthy_reward
assert no_hpa_reward < healthy_reward
def test_check_task_complete_incident_true_and_false():
healthy_world = StubWorld(
[
StubPod("auth-service", "Running"),
StubPod("api-gateway", "Running"),
StubPod("frontend", "Running"),
]
)
unhealthy_world = StubWorld(
[
StubPod("auth-service", "Running"),
StubPod("api-gateway", "CrashLoopBackOff"),
StubPod("frontend", "Running"),
]
)
assert check_task_complete(healthy_world, "incident") is True
assert check_task_complete(unhealthy_world, "incident") is False
def test_environment_reset_sets_task_and_returns_observation():
env = CoenvEnvironment()
obs = env.reset(task="autoscaling")
assert env.current_task == "autoscaling"
assert obs.objective == env.current_objective
assert obs.done is False
assert obs.reward == 0.0
assert "task" in obs.metadata
def test_environment_step_scale_and_describe_paths():
env = CoenvEnvironment()
env.reset(task="pod_recovery")
scale_obs = env.step(
CoenvAction(action_type="scale", deployment="frontend", replicas=4)
)
assert "scaled" in scale_obs.metadata
assert scale_obs.step >= 1
describe_obs = env.step(
CoenvAction(action_type="describe", resource_type="deployment", name="frontend")
)
assert "described" in describe_obs.metadata
assert "describe_detail" in describe_obs.metadata
wait_obs = env.step(CoenvAction(action_type="wait"))
assert wait_obs.metadata.get("waited") is True
def test_environment_step_exception_is_captured_in_metadata(monkeypatch):
env = CoenvEnvironment()
env.reset(task="pod_recovery")
def _boom(*args, **kwargs):
raise RuntimeError("forced failure")
monkeypatch.setattr(env.world, "scale", _boom)
action = CoenvAction(action_type="scale", deployment="frontend", replicas=2)
obs = env.step(action)
assert "error" in obs.metadata
assert "forced failure" in obs.metadata["error"]