whassan's picture
Deploy Sensorflow Studio (part 4)
4b5fa98 verified
Raw History Blame Contribute Delete
6.38 kB
"""API lifecycle over an isolated router: bank -> run -> query ->
attribution -> consequence -> HITL -> flywheel -> gate."""
from __future__ import annotations
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sensorflow.rotr.api import router
SPEC_QUERY = ("failed to yield to pedestrian at uncontrolled intersection "
"during low visibility")
@pytest.fixture()
def client():
app = FastAPI()
app.include_router(router)
return TestClient(app)
@pytest.fixture()
def run(client):
r = client.post("/api/rotr/runs",
json={"n_scenarios": 28, "seed": 7,
"model_version": "stack-v1"})
assert r.status_code == 200, r.text
return r.json()
class TestLifecycle:
def test_health_and_rules(self, client):
assert client.get("/api/rotr/health").json()["status"] == "ok"
rules = client.get("/api/rotr/rules").json()
assert len(rules["rules"]) == 6
assert "ILLUSTRATIVE" in rules["config_note"]
def test_bank_endpoints(self, client):
r = client.post("/api/rotr/banks",
json={"n_scenarios": 14, "seed": 3,
"model_version": "stack-v1"})
assert r.status_code == 200
bank = r.json()
assert client.get(f"/api/rotr/banks/{bank['bank_id']}").status_code == 200
sid = bank["scenarios"][0]["scenario_id"]
sc = client.get(f"/api/rotr/banks/{bank['bank_id']}/scenarios/{sid}").json()
assert sc["ego"] and sc["actual_context"]
assert client.post("/api/rotr/banks",
json={"model_version": "nope"}).status_code == 422
def test_run_and_metrics(self, client, run):
assert run["metrics"]["rotr_recall"] == 1.0
assert run["metrics"]["false_accusation_rate"] == 0.0
assert run["gate"]["outcome"] == "NO_GO"
got = client.get(f"/api/rotr/runs/{run['run_id']}").json()
assert got["run_id"] == run["run_id"]
assert client.get("/api/rotr/runs").json()
def test_violation_listing_and_taxonomy_filters(self, client, run):
rid = run["run_id"]
allv = client.get(f"/api/rotr/runs/{rid}/violations").json()
assert allv["n_results"] > 0
vru = client.get(f"/api/rotr/runs/{rid}/violations",
params={"vulnerability": "VRU"}).json()
assert 0 < vru["n_results"] < allv["n_results"]
assert all(x["taxonomy"]["vulnerability"] == "VRU"
for x in vru["results"])
def test_spec_structured_query(self, client, run):
r = client.post("/api/rotr/query",
json={"run_id": run["run_id"], "text": SPEC_QUERY})
assert r.status_code == 200
out = r.json()
assert out["query"]["actor"] == "pedestrian"
assert out["query"]["visibility"] == "low"
assert out["n_results"] >= 1
for item in out["results"]:
assert item["taxonomy"]["legality"] == "YIELD"
assert item["environment"]["visibility"] == "low"
assert item["cluster_id"]
assert item["provenance"]["model_version"] == "stack-v1"
def test_attribution_matrix_and_consequence(self, client, run):
rid = run["run_id"]
matrix = client.get(f"/api/rotr/runs/{rid}/attribution").json()
assert matrix["rows"]
row = matrix["rows"][0]
assert set(row["layers"]) == {
"perception", "prediction", "planning", "localization", "map",
"control", "policy_rule", "data_label"}
vid = row["violation_id"]
detail = client.get(f"/api/rotr/runs/{rid}/violations/{vid}").json()
assert detail["attribution"]["primary_layer"]
cf = client.get(
f"/api/rotr/runs/{rid}/violations/{vid}/consequence").json()
assert cf["planner_evaluation"]["observed_trajectory"]
assert cf["planner_evaluation"]["corrected_trajectory"]
assert "scenario_geometry" in cf
def test_clusters_and_gate(self, client, run):
rid = run["run_id"]
clusters = client.get(f"/api/rotr/runs/{rid}/clusters").json()
assert clusters and clusters[0]["count"] >= 1
gate = client.get(f"/api/rotr/runs/{rid}/gate").json()
assert gate["outcome"] in ("GO", "NO_GO")
policy = client.get("/api/rotr/stopship/policy").json()
assert policy["policy_version"]
class TestHITLAndFlywheel:
def test_validate_then_guard_then_override(self, client, run):
rid = run["run_id"]
queue = client.get(f"/api/rotr/runs/{rid}/hitl").json()
assert queue and queue[0]["status"] == "PENDING"
review = queue[0]
r = client.post("/api/rotr/hitl/action",
json={"run_id": rid, "review_id": review["review_id"],
"action": "VALIDATE", "actor": "reviewer",
"notes": "confirmed"})
assert r.status_code == 200
cand = r.json()["candidate"]
assert cand["dataset_role"] == "REGRESSION"
suite = client.get("/api/rotr/flywheel/suite").json()
assert any(m["candidate_id"] == cand["candidate_id"]
for m in suite["members"])
promote = client.post("/api/rotr/flywheel/promote",
json={"candidate_id": cand["candidate_id"],
"actor": "sneaky"})
assert promote.status_code == 409 # contamination guard
override = client.post("/api/rotr/flywheel/override",
json={"candidate_id": cand["candidate_id"],
"actor": "safety-lead",
"reason": "governed exception"})
assert override.status_code == 200
promote2 = client.post("/api/rotr/flywheel/promote",
json={"candidate_id": cand["candidate_id"],
"actor": "lead"})
assert promote2.status_code == 200
assert promote2.json()["guard_state"] == "OVERRIDDEN"
class TestDocs:
def test_architecture_doc_served(self, client):
r = client.get("/api/rotr/docs/architecture")
assert r.status_code == 200
assert "Right-of-the-Road" in r.json()["markdown"]