#!/usr/bin/env python3 """Phase 3b S2 end-to-end smoke: login -> submit factor analysis (ma5, multi-symbol) -> poll -> verify ic-summary non-empty. """ import json import sys import time import urllib.request BASE = "http://192.168.2.154:8000" def _req(method, path, token=None, body=None): headers = {"Content-Type": "application/json"} if token: headers["Authorization"] = f"Bearer {token}" data = json.dumps(body).encode() if body is not None else None req = urllib.request.Request(BASE + path, data=data, headers=headers, method=method) with urllib.request.urlopen(req, timeout=60) as resp: return json.loads(resp.read()) def main() -> int: tok = _req("POST", "/api/v1/auth/login", body={"username": "admin", "password": "admin"})["token"] print("[1] login OK") fl = _req("GET", "/api/v1/factor/list", token=tok) print(f"[2] factors: {[f['name'] for f in fl['factors']]}") sub = _req("POST", "/api/v1/factor/analyze", token=tok, body={ "symbols": ["600000", "000001", "300750"], "factor_names": ["ma5"], "start": "2024-01-01", "end": "2024-06-30", }) tid = sub["task_id"] print(f"[3] submitted: {tid}") status = "pending" for i in range(60): s = _req("GET", f"/api/v1/task/{tid}", token=tok) status = s["status"] print(f" [{i:02d}] status={status} stage={s.get('stage', '')}") if status in ("done", "failed"): break time.sleep(3) if status != "done": print(f"[!] factor analysis did not complete: {status}") return 1 ic = _req("GET", f"/api/v1/task/{tid}/ic-summary", token=tok)["ic_summary"] print(f"[4] ic_summary keys: {list(ic.keys())}") assert "ma5" in ic, "ma5 missing from ic_summary" ma5 = ic["ma5"] print(f" ma5 status: {ma5.get('status')}") print(f" ma5 ic: {json.dumps(ma5.get('ic', {}), ensure_ascii=False)[:300]}") assert ma5.get("ic"), "ma5 ic empty" print("[5] SMOKE PASSED") return 0 if __name__ == "__main__": try: sys.exit(main()) except AssertionError as e: print(f"[SMOKE FAILED] {e}") sys.exit(2) except Exception as e: print(f"[SMOKE ERROR] {type(e).__name__}: {e}") sys.exit(3)