chore: bump VERSION to v2.0.0beta, reimport TlsDB, remove stale test files
This commit is contained in:
@@ -11,8 +11,8 @@
|
||||
:ipd.orgn,目标IP组织名称,字符串,97.61%
|
||||
:ips.city,源IP所在城市,字符串,99.26%
|
||||
:ipd.city,目标IP所在城市,字符串,98.74%
|
||||
:ips.anon,源IP匿名状态,"anon, hosting"或无,12.66%
|
||||
:ipd.anon,目标IP匿名状态,"anon, hosting"或无,15.54%
|
||||
:ips.anon,源IP匿名状态,"anon, hosting"或"anon, vpn"或"anon, server"或无,12.66%
|
||||
:ipd.anon,目标IP匿名状态,"anon, hosting"或"anon, vpn"或"anon, server"或无,15.54%
|
||||
:ips.doma,源IP域名,字符串,28.91%
|
||||
:ipd.doma,目标IP域名,字符串,13.48%
|
||||
:prs,源端口,整数,100%
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 14 and column 43.
|
@@ -1,7 +1,7 @@
|
||||
"""E2E batch upload test: upload 10 CSV files (2 batches of 5), cluster, verify."""
|
||||
import subprocess, time, os, sys, glob, json
|
||||
|
||||
PROJ = r"C:\Users\25044\Desktop\Proj\天璇"
|
||||
PROJ = r"E:\hjq\天璇"
|
||||
PORT = 8765
|
||||
BASE = f"http://127.0.0.1:{PORT}"
|
||||
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
"""E2E test v1.1.4: upload 10 CSVs → cluster → verify globe.
|
||||
|
||||
Full pipeline WITHOUT manual server start/stop.
|
||||
Port 8766 avoids conflicts with 8000.
|
||||
Uses stdlib urllib (no pip install needed).
|
||||
"""
|
||||
import subprocess
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
import json
|
||||
import uuid
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
PORT = 8766
|
||||
BASE = f"http://127.0.0.1:{PORT}"
|
||||
PROJ = r"C:\Users\25044\Desktop\Proj\天璇"
|
||||
|
||||
|
||||
def http_get(path, timeout=30):
|
||||
"""GET and return (status_code, body_bytes)."""
|
||||
try:
|
||||
r = urllib.request.urlopen(f"{BASE}{path}", timeout=timeout)
|
||||
body = r.read()
|
||||
code = r.status
|
||||
r.close()
|
||||
return code, body
|
||||
except urllib.error.HTTPError as e:
|
||||
return e.code, e.read()
|
||||
|
||||
|
||||
def http_post_json(path, data_dict, timeout=30):
|
||||
"""POST JSON and return (status_code, parsed_json)."""
|
||||
body = json.dumps(data_dict).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
f"{BASE}{path}", data=body, headers={"Content-Type": "application/json"}
|
||||
)
|
||||
try:
|
||||
r = urllib.request.urlopen(req, timeout=timeout)
|
||||
return r.status, json.loads(r.read())
|
||||
except urllib.error.HTTPError as e:
|
||||
return e.code, json.loads(e.read())
|
||||
|
||||
|
||||
def http_post_files(path, file_paths, timeout=120):
|
||||
"""POST multipart/form-data upload. Returns (status_code, parsed_json)."""
|
||||
boundary = uuid.uuid4().hex
|
||||
lines = []
|
||||
for fp in file_paths:
|
||||
fname = os.path.basename(fp)
|
||||
with open(fp, "rb") as f:
|
||||
filedata = f.read()
|
||||
lines.append(f"--{boundary}".encode())
|
||||
lines.append(
|
||||
f'Content-Disposition: form-data; name="files"; filename="{fname}"'.encode()
|
||||
)
|
||||
lines.append(b"Content-Type: text/csv")
|
||||
lines.append(b"")
|
||||
lines.append(filedata)
|
||||
lines.append(f"--{boundary}--".encode())
|
||||
body = b"\r\n".join(lines)
|
||||
|
||||
req = urllib.request.Request(
|
||||
f"{BASE}{path}",
|
||||
data=body,
|
||||
headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
|
||||
)
|
||||
try:
|
||||
r = urllib.request.urlopen(req, timeout=timeout)
|
||||
return r.status, json.loads(r.read())
|
||||
except urllib.error.HTTPError as e:
|
||||
return e.code, json.loads(e.read())
|
||||
|
||||
|
||||
# ── 1. Start server ──
|
||||
print("[1/6] Starting Django server...")
|
||||
import tempfile as _tmp
|
||||
_stderr_log = os.path.join(PROJ, "tests", "_server_stderr.log")
|
||||
_stderr_fh = open(_stderr_log, "w")
|
||||
server = subprocess.Popen(
|
||||
[
|
||||
os.path.join(PROJ, "runtime", "python", "python.exe"),
|
||||
"manage.py",
|
||||
"runserver",
|
||||
f"127.0.0.1:{PORT}",
|
||||
"--noreload",
|
||||
],
|
||||
cwd=PROJ,
|
||||
stdout=_stderr_fh,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
time.sleep(8)
|
||||
|
||||
# Verify server is up
|
||||
for attempt in range(10):
|
||||
try:
|
||||
urllib.request.urlopen(f"{BASE}/", timeout=3)
|
||||
print(" Server is up.")
|
||||
break
|
||||
except Exception:
|
||||
if attempt == 9:
|
||||
print(" FAIL: Server did not start within 30 seconds")
|
||||
server.terminate()
|
||||
server.wait()
|
||||
sys.exit(1)
|
||||
time.sleep(2)
|
||||
|
||||
# ── 2. Upload 10 test_*.csv files ──
|
||||
csv_files = sorted(glob.glob(os.path.join(PROJ, "data", "multi_upload", "test_*.csv")))
|
||||
print(f"[2/6] Found {len(csv_files)} CSV files. Uploading first 10...")
|
||||
batch = csv_files[:10]
|
||||
code, data = http_post_files("/upload/csv/", batch, timeout=120)
|
||||
|
||||
if code != 200:
|
||||
print(f" FAIL: Upload returned HTTP {code}: {data}")
|
||||
server.terminate()
|
||||
server.wait()
|
||||
sys.exit(1)
|
||||
|
||||
run_id = data["run_id"]
|
||||
print(f" Uploaded 10 files → run_id={run_id}, status={data['status']}")
|
||||
|
||||
# ── 3. Poll until upload processing completes (status='ready') ──
|
||||
print("[3/6] Waiting for background processing...")
|
||||
s = {}
|
||||
for i in range(180):
|
||||
code, body = http_get(f"/runs/{run_id}/status/", timeout=10)
|
||||
s = json.loads(body) if code == 200 else {}
|
||||
if s.get("status") in ("ready", "failed"):
|
||||
break
|
||||
if i % 10 == 0:
|
||||
print(f" Poll #{i}: {s.get('status')} ({s.get('progress_pct', 0)}%)")
|
||||
time.sleep(2)
|
||||
print(f" Status: {s.get('status')}, progress={s.get('progress_pct')}%")
|
||||
|
||||
if s.get("status") == "failed":
|
||||
print(f" FAIL: {s.get('error_message', '')[:500]}")
|
||||
server.terminate()
|
||||
server.wait()
|
||||
sys.exit(1)
|
||||
|
||||
if s.get("status") != "ready":
|
||||
print(f" FAIL: Timed out waiting for 'ready', got '{s.get('status')}'")
|
||||
server.terminate()
|
||||
server.wait()
|
||||
sys.exit(1)
|
||||
|
||||
# ── 4. Run clustering ──
|
||||
print("[4/6] Starting clustering (HDBSCAN, min_cluster_size=5)...")
|
||||
code, resp = http_post_json(
|
||||
"/analyze/run/",
|
||||
{"run_id": run_id, "algorithm": "hdbscan", "min_cluster_size": 5, "cluster_mode": "raw"},
|
||||
timeout=30,
|
||||
)
|
||||
print(f" Response HTTP {code}: {resp.get('status')}")
|
||||
|
||||
if code != 200:
|
||||
print(f" FAIL: Clustering start failed: {resp}")
|
||||
server.terminate()
|
||||
server.wait()
|
||||
sys.exit(1)
|
||||
|
||||
# ── 5. Poll until clustering completes ──
|
||||
print("[5/6] Waiting for clustering...")
|
||||
for i in range(120):
|
||||
code, body = http_get(f"/runs/{run_id}/status/", timeout=10)
|
||||
s = json.loads(body) if code == 200 else {}
|
||||
if s.get("status") in ("completed", "failed"):
|
||||
break
|
||||
if i % 5 == 0:
|
||||
print(
|
||||
f" Poll #{i}: {s.get('status')} ({s.get('progress_pct', 0)}%)"
|
||||
f" - {s.get('progress_msg', '')}"
|
||||
)
|
||||
time.sleep(3)
|
||||
print(
|
||||
f" Final: status={s.get('status')}, entity_count={s.get('entity_count')},"
|
||||
f" cluster_count={s.get('cluster_count')}"
|
||||
)
|
||||
|
||||
# ── 6. Verify globe page ──
|
||||
print("[6/6] Verifying globe page...")
|
||||
code, body = http_get(f"/globe/?runs={run_id}", timeout=30)
|
||||
globe_text = body.decode("utf-8", errors="replace")
|
||||
has_arcs = "arcCount" in globe_text
|
||||
print(f" Globe HTTP {code}, arcCount present: {has_arcs}")
|
||||
|
||||
# ── Cleanup ──
|
||||
server.terminate()
|
||||
server.wait()
|
||||
_stderr_fh.close()
|
||||
|
||||
# Print last 30 lines of server output on failure
|
||||
_need_server_log = False
|
||||
|
||||
# ── Report ──
|
||||
errors = []
|
||||
|
||||
if s.get("status") != "completed":
|
||||
errors.append(f"Expected status='completed', got '{s.get('status')}'")
|
||||
errors.append(f"error: {s.get('error_message', '')[:500]}")
|
||||
|
||||
if s.get("cluster_count", 0) == 0:
|
||||
errors.append("No clusters found (cluster_count=0)")
|
||||
|
||||
if not has_arcs:
|
||||
errors.append("Globe page missing 'arcCount' element")
|
||||
|
||||
if errors:
|
||||
print(f"\nFAIL ({len(errors)} errors):")
|
||||
for e in errors:
|
||||
print(f" - {e}")
|
||||
# Show server stderr tail
|
||||
if os.path.exists(_stderr_log):
|
||||
with open(_stderr_log, "r", encoding="utf-8", errors="replace") as f:
|
||||
lines = f.readlines()
|
||||
tail = lines[-30:] if len(lines) > 30 else lines
|
||||
print(f"\n--- Server stderr (last {len(tail)} lines) ---")
|
||||
for line in tail:
|
||||
print(f" {line.rstrip()}")
|
||||
sys.exit(1)
|
||||
|
||||
print("\n*** E2E v1.1.4 PASSED ***")
|
||||
print(
|
||||
f" run_id={run_id}, clusters={s.get('cluster_count')},"
|
||||
f" entities={s.get('entity_count')}, globe_arcs={'yes' if has_arcs else 'no'}"
|
||||
)
|
||||
@@ -1,237 +0,0 @@
|
||||
"""E2E test v1.1.6: generate 50 CSVs → upload 10 → cluster → verify globe.
|
||||
|
||||
Self-contained: generates data, starts server, uploads, clusters, verifies globe, reports.
|
||||
Port 18766. Uses requests for HTTP (installed automatically if missing).
|
||||
"""
|
||||
import subprocess
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
PORT = 18766
|
||||
BASE = f"http://127.0.0.1:{PORT}"
|
||||
PROJ = r"C:\Users\25044\Desktop\Proj\天璇"
|
||||
PYTHON = os.path.join(PROJ, "runtime", "python", "python.exe")
|
||||
|
||||
# ── Ensure requests is installed ──
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("[0] Installing requests...")
|
||||
subprocess.run([PYTHON, "-m", "pip", "install", "requests", "-q"], cwd=PROJ, check=True, timeout=120)
|
||||
import requests
|
||||
|
||||
|
||||
def http_get(path, timeout=30):
|
||||
"""GET and return (status_code, parsed_json or body_bytes)."""
|
||||
try:
|
||||
r = requests.get(f"{BASE}{path}", timeout=timeout)
|
||||
try:
|
||||
return r.status_code, r.json()
|
||||
except Exception:
|
||||
return r.status_code, r.text
|
||||
except Exception as e:
|
||||
return 0, str(e)
|
||||
|
||||
|
||||
def http_post_json(path, data_dict, timeout=30):
|
||||
"""POST JSON and return (status_code, parsed_json)."""
|
||||
try:
|
||||
r = requests.post(f"{BASE}{path}", json=data_dict, timeout=timeout)
|
||||
try:
|
||||
return r.status_code, r.json()
|
||||
except Exception:
|
||||
return r.status_code, r.text
|
||||
except Exception as e:
|
||||
return 0, str(e)
|
||||
|
||||
|
||||
def http_post_files(path, file_paths, timeout=120):
|
||||
"""POST multipart/form-data upload. Returns (status_code, parsed_json)."""
|
||||
files = [("files", (os.path.basename(fp), open(fp, "rb"), "text/csv")) for fp in file_paths]
|
||||
try:
|
||||
r = requests.post(f"{BASE}{path}", files=files, timeout=timeout)
|
||||
return r.status_code, r.json()
|
||||
except Exception as e:
|
||||
return 0, str(e)
|
||||
|
||||
|
||||
def poll_status(run_id, target_status, max_wait_sec, description):
|
||||
"""Poll /runs/<run_id>/status/ until target_status or timeout. Returns status dict."""
|
||||
s = {}
|
||||
for i in range(max_wait_sec // 2):
|
||||
code, body = http_get(f"/runs/{run_id}/status/", timeout=10)
|
||||
s = body if isinstance(body, dict) else {}
|
||||
if s.get("status") in (target_status, "failed"):
|
||||
break
|
||||
if i % 10 == 0:
|
||||
print(f" [{description}] Poll #{i}: {s.get('status')} ({s.get('progress_pct', 0)}%)")
|
||||
time.sleep(2)
|
||||
print(f" [{description}] Final: status={s.get('status')}, progress={s.get('progress_pct', 0)}%")
|
||||
return s
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# MAIN
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
errors = []
|
||||
|
||||
# ── 1. Generate 50 test CSV files ──
|
||||
print("[1/6] Generating 50 test CSV files (100 rows each)...")
|
||||
gen_result = subprocess.run(
|
||||
[PYTHON, "scripts/gen_multi.py", "--files", "50", "--rows", "100"],
|
||||
cwd=PROJ, capture_output=True, text=True, timeout=180,
|
||||
)
|
||||
if gen_result.returncode != 0:
|
||||
print(f" FAIL: gen_multi.py failed.\nSTDERR:\n{gen_result.stderr}")
|
||||
sys.exit(1)
|
||||
print(gen_result.stdout.strip())
|
||||
|
||||
csv_files = sorted(glob.glob(os.path.join(PROJ, "data", "multi_upload", "test_*.csv")))
|
||||
print(f" Generated {len(csv_files)} CSV files.")
|
||||
|
||||
# ── 2. Start Django server ──
|
||||
print(f"[2/6] Starting Django server on port {PORT}...")
|
||||
stderr_log = os.path.join(PROJ, "tests", "_e2e_server_v116.log")
|
||||
stderr_fh = open(stderr_log, "w")
|
||||
server = subprocess.Popen(
|
||||
[PYTHON, "manage.py", "runserver", f"127.0.0.1:{PORT}", "--noreload"],
|
||||
cwd=PROJ, stdout=stderr_fh, stderr=subprocess.STDOUT,
|
||||
)
|
||||
time.sleep(6)
|
||||
|
||||
# Verify server is up
|
||||
server_up = False
|
||||
for attempt in range(15):
|
||||
try:
|
||||
urllib.request.urlopen(f"{BASE}/", timeout=3)
|
||||
server_up = True
|
||||
print(" Server is up.")
|
||||
break
|
||||
except Exception:
|
||||
if attempt == 14:
|
||||
errors.append("Server did not start within 45 seconds")
|
||||
time.sleep(2)
|
||||
|
||||
if not server_up:
|
||||
server.terminate(); server.wait(); stderr_fh.close()
|
||||
print("\nFAIL")
|
||||
for e in errors: print(f" - {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# ── 3. Upload first 10 CSV files ──
|
||||
print("[3/6] Uploading first 10 CSV files...")
|
||||
batch = csv_files[:10]
|
||||
code, data = http_post_files("/upload/csv/", batch, timeout=180)
|
||||
|
||||
if code != 200:
|
||||
errors.append(f"Upload returned HTTP {code}: {str(data)[:300]}")
|
||||
server.terminate(); server.wait(); stderr_fh.close()
|
||||
print("\nFAIL")
|
||||
for e in errors: print(f" - {e}")
|
||||
sys.exit(1)
|
||||
|
||||
run_id = data["run_id"]
|
||||
print(f" Uploaded {len(batch)} files → run_id={run_id}, status={data['status']}")
|
||||
|
||||
# ── 4. Poll until background processing completes (status='ready') ──
|
||||
print("[4/6] Waiting for background upload processing (max 300s)...")
|
||||
s = poll_status(run_id, "ready", 300, "Upload processing")
|
||||
|
||||
if s.get("status") == "failed":
|
||||
errors.append(f"Upload processing failed: {s.get('error_message', '')[:500]}")
|
||||
|
||||
if s.get("status") not in ("ready",):
|
||||
errors.append(f"Expected status='ready', got '{s.get('status')}'")
|
||||
|
||||
if errors:
|
||||
server.terminate(); server.wait(); stderr_fh.close()
|
||||
print("\nFAIL")
|
||||
for e in errors: print(f" - {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# ── 5. Run clustering and poll ──
|
||||
print("[5/6] Starting clustering (HDBSCAN, min_cluster_size=5)...")
|
||||
code, resp = http_post_json(
|
||||
"/analyze/run/",
|
||||
{"run_id": run_id, "algorithm": "hdbscan", "min_cluster_size": 5, "cluster_mode": "raw"},
|
||||
timeout=30,
|
||||
)
|
||||
print(f" Response HTTP {code}: {resp if isinstance(resp, dict) else str(resp)[:200]}")
|
||||
|
||||
if code != 200:
|
||||
errors.append(f"Clustering start failed: {resp}")
|
||||
server.terminate(); server.wait(); stderr_fh.close()
|
||||
print("\nFAIL")
|
||||
for e in errors: print(f" - {e}")
|
||||
sys.exit(1)
|
||||
|
||||
s_cluster = poll_status(run_id, "completed", 600, "Clustering")
|
||||
|
||||
if s_cluster.get("status") == "failed":
|
||||
errors.append(f"Clustering failed: {s_cluster.get('error_message', '')[:500]}")
|
||||
|
||||
if s_cluster.get("status") != "completed":
|
||||
errors.append(f"Expected status='completed', got '{s_cluster.get('status')}'")
|
||||
|
||||
# ── 6. Verify globe page ──
|
||||
print("[6/6] Verifying globe page...")
|
||||
code, globe_body = http_get(f"/globe/?runs={run_id}", timeout=30)
|
||||
globe_text = globe_body if isinstance(globe_body, str) else json.dumps(globe_body)
|
||||
has_arcs = "arcCount" in globe_text if isinstance(globe_text, str) else False
|
||||
print(f" Globe HTTP {code}, arcCount present: {has_arcs}")
|
||||
|
||||
# ── Cleanup ──
|
||||
server.terminate()
|
||||
server.wait()
|
||||
stderr_fh.close()
|
||||
|
||||
# ── Collect metrics ──
|
||||
total_flows = s_cluster.get("total_flows", "?")
|
||||
entity_count = s_cluster.get("entity_count", 0)
|
||||
cluster_count = s_cluster.get("cluster_count", 0)
|
||||
status = s_cluster.get("status", "unknown")
|
||||
|
||||
# ── Validate required metrics ──
|
||||
if not has_arcs:
|
||||
errors.append("Globe page missing 'arcCount' element")
|
||||
if entity_count == 0:
|
||||
errors.append("entity_count=0 (no entities detected)")
|
||||
if cluster_count == 0:
|
||||
errors.append("cluster_count=0 (no clusters found)")
|
||||
|
||||
# ── Show server log tail on failure ──
|
||||
if errors and os.path.exists(stderr_log):
|
||||
with open(stderr_log, "r", encoding="utf-8", errors="replace") as f:
|
||||
lines = f.readlines()
|
||||
tail = lines[-40:] if len(lines) > 40 else lines
|
||||
print(f"\n--- Server log tail ({len(tail)} lines) ---")
|
||||
for line in tail:
|
||||
print(f" {line.rstrip()}")
|
||||
|
||||
# ── Report ──
|
||||
print()
|
||||
print("=" * 60)
|
||||
print(" E2E v1.1.6 RESULTS")
|
||||
print("=" * 60)
|
||||
print(f" run_id : {run_id}")
|
||||
print(f" status : {status}")
|
||||
print(f" total_flows : {total_flows}")
|
||||
print(f" entity_count : {entity_count}")
|
||||
print(f" cluster_count : {cluster_count}")
|
||||
print(f" globe_arcs : {'PASS' if has_arcs else 'FAIL'}")
|
||||
|
||||
if errors:
|
||||
print(f"\n FAIL ({len(errors)} errors):")
|
||||
for e in errors:
|
||||
print(f" - {e}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"\n *** E2E v1.1.6 PASSED ***")
|
||||
print(f" run_id={run_id}, clusters={cluster_count}, entities={entity_count}, globe_arcs=yes")
|
||||
sys.exit(0)
|
||||
@@ -1,70 +0,0 @@
|
||||
import subprocess, time, os, sys, glob, json
|
||||
|
||||
PORT = 17766
|
||||
PROJ = r"C:\Users\25044\Desktop\Proj\天璇"
|
||||
os.chdir(PROJ)
|
||||
|
||||
# 1. Start server
|
||||
print("Starting server...")
|
||||
server = subprocess.Popen(
|
||||
[r"runtime\python\python.exe", "manage.py", "runserver", f"127.0.0.1:{PORT}", "--noreload"],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
||||
)
|
||||
time.sleep(6)
|
||||
|
||||
import requests
|
||||
|
||||
# 2. Upload 50 files
|
||||
print("Uploading 50 files...")
|
||||
csvs = sorted(glob.glob("data/multi_upload/[0-9]*.csv"))[:50]
|
||||
files = [("files", (os.path.basename(f), open(f, "rb"), "text/csv")) for f in csvs]
|
||||
r = requests.post(f"http://127.0.0.1:{PORT}/upload/csv/", files=files, timeout=300)
|
||||
data = r.json()
|
||||
run_id = data["run_id"]
|
||||
print(f"run_id={run_id}")
|
||||
|
||||
# 3. Poll until ready
|
||||
for _ in range(180):
|
||||
r = requests.get(f"http://127.0.0.1:{PORT}/runs/{run_id}/status/", timeout=10)
|
||||
s = r.json()
|
||||
st = s["status"]
|
||||
if st in ("ready", "failed"):
|
||||
break
|
||||
time.sleep(2)
|
||||
print(f"Upload status={st}, flows={s.get('total_flows')}, error={s.get('error_message','')[:300]}")
|
||||
|
||||
if st == "failed":
|
||||
print(f"FAILED: {s.get('error_message','')}")
|
||||
server.terminate(); sys.exit(1)
|
||||
|
||||
# 4. Run clustering
|
||||
print("Running clustering...")
|
||||
r = requests.post(f"http://127.0.0.1:{PORT}/analyze/run/",
|
||||
json={"run_id": run_id, "algorithm": "hdbscan", "min_cluster_size": 5, "cluster_mode": "raw"},
|
||||
timeout=30)
|
||||
print(f"Cluster started: {r.json()}")
|
||||
|
||||
# 5. Poll until completed
|
||||
for _ in range(120):
|
||||
r = requests.get(f"http://127.0.0.1:{PORT}/runs/{run_id}/status/", timeout=10)
|
||||
s = r.json()
|
||||
st = s["status"]
|
||||
if st in ("completed", "failed"):
|
||||
break
|
||||
time.sleep(5)
|
||||
print(f"Cluster status={st}, entity_count={s.get('entity_count')}, cluster_count={s.get('cluster_count')}")
|
||||
|
||||
# 6. Verify globe
|
||||
r = requests.get(f"http://127.0.0.1:{PORT}/globe/?runs={run_id}", timeout=10)
|
||||
has_arcs = "arcCount" in r.text
|
||||
print(f"Globe arcCount present: {has_arcs}")
|
||||
|
||||
# 7. Result
|
||||
server.terminate()
|
||||
server.wait()
|
||||
if st == "completed" and s.get("cluster_count", 0) > 0:
|
||||
print(f"E2E PASSED: {s['entity_count']} entities, {s['cluster_count']} clusters")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(f"E2E FAILED")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user