python-e2e-battery-due-cycle
The E2E-001 harness must be launched as a module-level FastAPI app bound to <ip-address>:8777, gated by a health-200 check before the battery, and torn down with a port-free verification after. The examples/echo.py anti-pattern fails because it builds app only under __main__ (invisible to the uvicorn worker process) and binds zombie-occupied :8000.
1. Canonical runner — module-level app (the core fix) — /tmp/e2e/echo_runner.py:
import sys
sys.path.insert(0, "/tmp/e2e")
from h3sdk import EchoHarness, build_app
app = build_app(EchoHarness()) # MODULE level: uvicorn imports this, so it must exist at import time
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="<ip-address>", port=8777, log_level="warning") # convenience only
2. App assembly — create_router(EchoHarness()) + add_middleware, with a real CORS bug fixed (allow_methods defaults to ["GET"] and rejects POST preflight with 400 — caught by the battery at this tick):
from fastapi import FastAPI, APIRouter
from fastapi.middleware.cors import CORSMiddleware
def build_app(harness=None, *, with_middleware=True) -> FastAPI:
app = FastAPI(title="EchoHarness runner", version="1.0.0")
app.include_router(create_router(EchoHarness())) # canonical composition point
if with_middleware:
app.add_middleware(CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"], # NOT the default ["GET"]
allow_headers=["*"])
app.add_middleware(TimingMiddleware) # last-added runs outermost
return app
def create_router(harness) -> APIRouter:
router = APIRouter(prefix="/v1", tags=["echo"])
@router.get("/health")
def health(): return harness.health()
@router.post("/echo")
def echo(payload, request): return harness.echo(payload, request)
return router
3. Full cycle driver — launch via venv python in background → health-200 gate → battery → kill → port-free verify:
proc = subprocess.Popen([PY, "-m", "uvicorn", "echo_runner:app",
"--host", "<ip-address>", "--port", "8777", "--log-level", "warning"],
cwd=ROOT, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True)
assert port_free("<ip-address>", 8777), "preflight: port already bound (zombie)" # BEFORE launch
wait_health() # poll /v1/health until 200 (timeout 15s) — verify BEFORE battery
rc = subprocess.run([PY, "run_battery.py"]).returncode # 44-test battery from shim .venv
proc.terminate(); proc.wait(5) or proc.kill() # kill harness
assert port_free("<ip-address>", 8777) # verify AFTER — no zombie for next window
Two battery-side fixes were also required to get a trustworthy 44/44 PASS line: latency persistence must live in conftest.py (pytest doesn't register pytest_sessionfinish hooks from test modules reliably), and the summary line must be parsed by regex (r"(\d+) passed"), not out.count("passed") (which returns 1 for "44 passed").
Verified end-to-end on <ip-address>:8777 with the shim `.venv` (`fastapi 0.141.1`, `uvicorn`, `httpx`, `pytest`): ``` [preflight] <ip-address>:8777 free [harness] listening, health 200 44/44 PASS in 0.49s (p50 1.26ms, p95 1.91ms) BATTERY PASS [cleanup] harness stopped, port free → exit 0 ``` - **Repeatability (3 consecutive cycles, all exit 0):** `44/44 PASS in 0.49s (p50 1.26ms, p95 1.91ms)` · `0.35s (p50 0.84ms, p95 1.56ms)` · `0.40s (p50 0.68ms, p95 1.36ms)` — p50/p95 in the same sub-2ms band as the reference tick; no zombie left behind (`ss -ltn` shows 8777 free after each). - **Negative control 1 — `__main__`-only app:** `uvicorn echo_broken:app` → `ERROR: Error loading ASGI app. Attribute "app" not found in module "echo_broken"` — proves the module-level-app requirement. - **Negative control 2 — zombie port:** with a socket bound on 8777, preflight `port_free()` returns `False` and the cycle aborts before launch (no double-bind crash, no battery against a stale server). - **Negative control 3 — server down:** battery against a dead port → 44× `httpx.ConnectError`, exit non-zero (battery never false-passes). - **Edge cases covered by the 44 tests:** 32 echo round-trips (empty, 1B→128KiB, unicode/emoji/RTL/control chars, quoting, 404/405 paths, `null`/`true`-like strings), 4 nested-meta fidelity, health+uptime, middleware timing header, CORS preflight (exposed the `allow_methods` bug), 404/405, server-nonce uniqueness, missing-optional-field tolerance.
{"model": "deepseek-v4-flash", "problem_class": "python-e2e-battery-due-cycle", "result": "passed", "tests": 44}