quest-openenv / test_env.py
chikleNeha's picture
all files are created
8dc575c
Raw History Blame Contribute Delete
10.1 kB
"""
test_env.py β€” Local smoke tests for MetaQuestOSEnv.
Tests the environment directly (no HTTP server needed).
Run this before deploying to catch any issues early.
Usage:
python test_env.py
"""
from __future__ import annotations
import sys
import traceback
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
PASS = "βœ“"
FAIL = "βœ—"
results = []
def check(name: str, fn):
try:
fn()
print(f" {PASS} {name}")
results.append((name, True))
except Exception as e:
print(f" {FAIL} {name}")
print(f" β†’ {e}")
traceback.print_exc()
results.append((name, False))
# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------
def test_imports():
import models, database, tasks, environment
from models import TaskID, SensorStatus, KernelStatus
assert hasattr(models, "SystemObservation")
assert hasattr(models, "ActionRequest")
assert hasattr(models, "ResetRequest")
def test_db_init():
import database as db
db.init_db()
db.set_state("test_key", {"hello": "world"})
val = db.get_state("test_key")
assert val == {"hello": "world"}, f"Got {val}"
db.set_state_bulk({"a": 1, "b": 2})
assert db.get_state("a") == 1
assert db.get_state("b") == 2
def test_task1_reset_and_step():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
r = env.reset(TaskID.THERMAL_MITIGATION, seed=42)
assert r.task_id == TaskID.THERMAL_MITIGATION
assert len(r.available_actions) > 0
assert r.observation.thermals.gpu_temp_c >= 80.0, "GPU should start hot"
assert r.observation.kernel.status.value == "Active"
assert r.max_steps == 10
def test_task1_reward_range():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.THERMAL_MITIGATION, seed=42)
actions = [
"EXEC_THERMAL_THROTTLE --enable",
"EXEC_DISPLAY_REFRESH --rate=72",
"EXEC_GPU_POWER_LIMIT --level=low",
]
for action in actions:
result = env.step(action)
assert 0.0 <= result.reward <= 1.0, f"Reward {result.reward} out of range"
def test_task1_solvable():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.THERMAL_MITIGATION, seed=42)
policy = [
"EXEC_THERMAL_THROTTLE --enable",
"EXEC_DISPLAY_REFRESH --rate=72",
"EXEC_GPU_POWER_LIMIT --level=low",
"EXEC_KILL_BACKGROUND_PROCS",
"EXEC_FAN_OVERRIDE --speed=max",
]
final = None
for action in policy:
final = env.step(action)
if final.done:
break
assert final is not None
assert final.observation.thermals.gpu_temp_c < 70.0, (
f"GPU still too hot: {final.observation.thermals.gpu_temp_c}"
)
assert final.reward == 1.0
def test_task2_reset_and_step():
from environment import MetaQuestOSEnv
from models import TaskID, SensorStatus
env = MetaQuestOSEnv()
r = env.reset(TaskID.SENSOR_RECOVERY, seed=42)
assert r.observation.sensors.lidar_status == SensorStatus.DRIFTING
assert r.observation.sensors.tracking_stability < 0.5, "Should start unstable"
assert r.max_steps == 12
def test_task2_solvable():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.SENSOR_RECOVERY, seed=42)
policy = [
"EXEC_SENSOR_RESET --target=lidar",
"EXEC_VIO_RESET --priority=imu",
"EXEC_SENSOR_RECALIBRATE --target=lidar",
"EXEC_ANCHOR_RECOMPUTE",
]
final = None
for action in policy:
final = env.step(action)
if final.done:
break
assert final is not None
assert final.observation.sensors.tracking_stability > 0.9, (
f"Stability still low: {final.observation.sensors.tracking_stability}"
)
assert final.reward == 1.0
def test_task3_reset_and_step():
from environment import MetaQuestOSEnv
from models import TaskID, KernelStatus
env = MetaQuestOSEnv()
r = env.reset(TaskID.KERNEL_PANIC_RECOVERY, seed=42)
assert r.observation.kernel.status == KernelStatus.PANIC
assert r.observation.spatial_anchors.session_data_intact == False
assert r.max_steps == 15
def test_task3_solvable():
from environment import MetaQuestOSEnv
from models import TaskID, KernelStatus
env = MetaQuestOSEnv()
env.reset(TaskID.KERNEL_PANIC_RECOVERY, seed=42)
policy = [
"EXEC_SAFE_MODE_INIT --stage=1",
"EXEC_SAFE_MODE_INIT --stage=2",
"EXEC_SAFE_MODE_INIT --stage=3",
"EXEC_MEMORY_LOCK_CLEAR --target=world_anchor",
"EXEC_ANCHOR_CACHE_FLUSH",
"EXEC_SESSION_RESTORE --source=backup",
"EXEC_KERNEL_RESTART --mode=safe",
]
final = None
for action in policy:
final = env.step(action)
if final.done:
break
assert final is not None
assert final.observation.kernel.status == KernelStatus.ACTIVE
assert final.observation.spatial_anchors.session_data_intact == True
assert final.reward == 1.0
def test_task3_partial_rewards():
"""Verify partial reward signals exist between 0 and 1."""
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.KERNEL_PANIC_RECOVERY, seed=42)
# Only do stage 1 β€” should get partial reward
r = env.step("EXEC_SAFE_MODE_INIT --stage=1")
assert 0.0 < r.reward < 1.0, f"Expected partial reward, got {r.reward}"
assert not r.done
def test_invalid_action():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.THERMAL_MITIGATION, seed=42)
r = env.step("TOTALLY_INVALID_COMMAND")
assert r.reward == 0.0
assert not r.observation.last_action_success
def test_max_steps_terminates():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.THERMAL_MITIGATION, seed=42)
for _ in range(10): # max_steps for task 1
result = env.step("NOOP")
assert result.done, "Episode should end at max_steps"
def test_state_endpoint():
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
env.reset(TaskID.SENSOR_RECOVERY, seed=42)
env.step("EXEC_SENSOR_RESET --target=lidar")
state = env.state()
assert state.step == 1
assert state.task_id == TaskID.SENSOR_RECOVERY
assert not state.done
def test_pydantic_serialization():
from environment import MetaQuestOSEnv
from models import TaskID
import json
env = MetaQuestOSEnv()
r = env.reset(TaskID.THERMAL_MITIGATION, seed=42)
# Must be JSON-serializable (required for HTTP API)
serialized = r.model_dump_json()
parsed = json.loads(serialized)
assert "observation" in parsed
assert "thermals" in parsed["observation"]
assert "gpu_temp_c" in parsed["observation"]["thermals"]
def test_psutil_integration():
"""Verify real system metrics are being injected."""
from environment import MetaQuestOSEnv
from models import TaskID
env = MetaQuestOSEnv()
r = env.reset(TaskID.THERMAL_MITIGATION, seed=99)
# RAM and CPU should be real values, not zeros
assert r.observation.resources.ram_used_mb > 0, "RAM should be > 0"
assert r.observation.resources.cpu_usage_pct >= 0, "CPU should be >= 0"
assert r.observation.resources.ram_used_mb < 8192, "RAM should be < 8GB total"
def test_list_tasks():
from environment import MetaQuestOSEnv
env = MetaQuestOSEnv()
tasks = env.list_tasks()
assert len(tasks) == 3
task_ids = {t.task_id.value for t in tasks}
assert "thermal_mitigation" in task_ids
assert "sensor_recovery" in task_ids
assert "kernel_panic_recovery" in task_ids
for t in tasks:
assert 0.0 <= t.success_threshold <= 1.0
# ---------------------------------------------------------------------------
# Runner
# ---------------------------------------------------------------------------
def main():
print(f"\n{'='*60}")
print(" MetaQuestOSEnv β€” Local Smoke Tests")
print(f"{'='*60}\n")
check("Imports work", test_imports)
check("Database init and read/write", test_db_init)
check("Task 1: reset initializes correctly", test_task1_reset_and_step)
check("Task 1: rewards in [0.0, 1.0]", test_task1_reward_range)
check("Task 1: solvable (reward=1.0 achievable)", test_task1_solvable)
check("Task 2: reset initializes correctly", test_task2_reset_and_step)
check("Task 2: solvable (reward=1.0 achievable)", test_task2_solvable)
check("Task 3: reset initializes correctly", test_task3_reset_and_step)
check("Task 3: solvable (reward=1.0 achievable)", test_task3_solvable)
check("Task 3: partial rewards exist", test_task3_partial_rewards)
check("Invalid action handled gracefully", test_invalid_action)
check("Max steps terminates episode", test_max_steps_terminates)
check("State endpoint works", test_state_endpoint)
check("Pydantic serialization to JSON", test_pydantic_serialization)
check("psutil real metrics injected", test_psutil_integration)
check("List tasks returns all 3", test_list_tasks)
print(f"\n{'='*60}")
passed = sum(1 for _, ok in results if ok)
total = len(results)
print(f" Results: {passed}/{total} tests passed")
failed = [(n, ok) for n, ok in results if not ok]
if failed:
print(f"\n Failed tests:")
for name, _ in failed:
print(f" βœ— {name}")
print(f"{'='*60}\n")
sys.exit(1)
else:
print(f" βœ“ All tests passed β€” ready to submit!")
print(f"{'='*60}\n")
sys.exit(0)
if __name__ == "__main__":
main()