platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
80
tests/vpn_login_flow.py
Executable file
80
tests/vpn_login_flow.py
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VPN login session smoke: start -> state polling -> optional action -> stop."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from urllib import request
|
||||
|
||||
API_BASE = os.environ.get("API_URL", "http://127.0.0.1:8080")
|
||||
TIMEOUT = int(os.environ.get("VPN_FLOW_TIMEOUT_SEC", "20"))
|
||||
|
||||
|
||||
def call(method, path, data=None, timeout=10):
|
||||
url = f"{API_BASE}{path}"
|
||||
payload = json.dumps(data).encode("utf-8") if data is not None else None
|
||||
req = request.Request(url, data=payload, method=method)
|
||||
if payload is not None:
|
||||
req.add_header("Content-Type", "application/json")
|
||||
try:
|
||||
with request.urlopen(req, timeout=timeout) as resp:
|
||||
body = resp.read()
|
||||
except Exception as err:
|
||||
print(f"[vpn] request {path} failed: {err}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
try:
|
||||
return json.loads(body)
|
||||
except json.JSONDecodeError:
|
||||
print(f"[vpn] non-json response for {path}: {body[:200]!r}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
print(f"[vpn] API_BASE={API_BASE}")
|
||||
start = call("POST", "/api/v1/vpn/login/session/start")
|
||||
if "ok" not in start or "phase" not in start or "level" not in start:
|
||||
print(f"[vpn] invalid start payload: {start}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
print(f"[vpn] start phase={start.get('phase')} ok={start.get('ok')}")
|
||||
|
||||
cursor = 0
|
||||
saw_state = False
|
||||
tried_action = False
|
||||
deadline = time.time() + TIMEOUT
|
||||
|
||||
while time.time() < deadline:
|
||||
state = call("GET", f"/api/v1/vpn/login/session/state?since={cursor}")
|
||||
saw_state = True
|
||||
if "cursor" in state:
|
||||
cursor = int(state["cursor"])
|
||||
phase = state.get("phase")
|
||||
alive = bool(state.get("alive"))
|
||||
can_check = bool(state.get("can_check"))
|
||||
print(f"[vpn] state phase={phase} alive={alive} cursor={cursor}")
|
||||
|
||||
if can_check and alive and not tried_action:
|
||||
action = call("POST", "/api/v1/vpn/login/session/action", {"action": "check"})
|
||||
if not action.get("ok", False):
|
||||
print(f"[vpn] action check failed: {action}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
tried_action = True
|
||||
print("[vpn] action=check sent")
|
||||
|
||||
if phase in ("success", "already_logged", "failed", "cancelled"):
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
if not saw_state:
|
||||
print("[vpn] no state response received", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
stop = call("POST", "/api/v1/vpn/login/session/stop")
|
||||
if not stop.get("ok", False):
|
||||
print(f"[vpn] stop failed: {stop}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
print("[vpn] flow smoke passed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user