forked from luopingyi/xc_agent_platform_demo
71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
"""SIGTERM should stop the server subprocess promptly (<< 30s platform window)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import unittest
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
class TestSigterm(unittest.TestCase):
|
|
def test_sigterm_exits_quickly(self) -> None:
|
|
port = "19090"
|
|
env = os.environ.copy()
|
|
env["STRATEGY_ID"] = "sigterm-test"
|
|
env["ALLOW_LIVE_SUBMIT"] = "0"
|
|
env["PORT"] = port
|
|
env["HOST"] = "127.0.0.1"
|
|
|
|
proc = subprocess.Popen(
|
|
[sys.executable, "-m", "src.server"],
|
|
cwd=str(ROOT),
|
|
env=env,
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
try:
|
|
# wait until health is up
|
|
url = f"http://127.0.0.1:{port}/health"
|
|
deadline = time.time() + 5
|
|
while time.time() < deadline:
|
|
try:
|
|
with urllib.request.urlopen(url, timeout=0.5) as resp:
|
|
data = json.loads(resp.read().decode("utf-8"))
|
|
if resp.status == 200 and data.get("status") == "ok":
|
|
break
|
|
except Exception:
|
|
time.sleep(0.1)
|
|
else:
|
|
if proc.poll() is not None:
|
|
self.fail(f"server exited before health check: {proc.stderr.read().decode(errors='replace')}")
|
|
self.fail("server did not become healthy in time")
|
|
|
|
t0 = time.time()
|
|
proc.send_signal(signal.SIGTERM)
|
|
try:
|
|
proc.wait(timeout=5)
|
|
except subprocess.TimeoutExpired:
|
|
proc.kill()
|
|
self.fail("server did not exit within 5s after SIGTERM (platform allows ≤30s)")
|
|
elapsed = time.time() - t0
|
|
self.assertLess(elapsed, 5.0, f"exit took {elapsed:.2f}s")
|
|
self.assertEqual(proc.returncode, 0, "SIGTERM must exit cleanly, not kill the process")
|
|
finally:
|
|
if proc.poll() is None:
|
|
proc.kill()
|
|
proc.wait(timeout=2)
|
|
if proc.stderr:
|
|
proc.stderr.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|