"""RED test for S1: /api/sessions pagination + sort""" import urllib.request, json, sys BASE = "http://127.0.0.1:5000" passed = 0 failed = 0 def test(label, path, check_fn): global passed, failed try: with urllib.request.urlopen(f"{BASE}{path}", timeout=15) as r: body = r.read() d = json.loads(body) ok, msg = check_fn(d) if ok: passed += 1 print(f" PASS {label}: {msg}") else: failed += 1 print(f" FAIL {label}: {msg}") except Exception as e: failed += 1 print(f" FAIL {label}: {e}") # TC1: page=1&per_page=10 def check_tc1(d): ok = d.get("ok") data = d.get("data", []) total = d.get("total") page = d.get("page") per_page = d.get("per_page") if not ok: return False, f"ok=False" if not isinstance(data, list): return False, f"data not list" if total is None: return False, f"total missing" if page != 1: return False, f"page={page} expected 1" if per_page != 10: return False, f"per_page={per_page} expected 10" if len(data) > 10: return False, f"data len={len(data)} exceeds 10" return True, f"total={total} page={page} per_page={per_page} len={len(data)}" # TC2: page 1 vs page 2 — no overlap def check_tc2_a(d): global page1_ids data = d.get("data", []) page1_ids = [s.get("talker") for s in data] return True, f"page1 ids={len(page1_ids)}" def check_tc2_b(d): data = d.get("data", []) page2_ids = [s.get("talker") for s in data] overlap = set(page1_ids) & set(page2_ids) if len(overlap) > 0: return False, f"overlap: {overlap}" return True, f"page2 unique={len(page2_ids)} no overlap" # TC3: sort=time_asc def check_tc3(d): data = d.get("data", []) if len(data) < 2: return True, f"only {len(data)} items, skip" times = [s.get("createTime", 0) for s in data] for i in range(len(times) - 1): if times[i] > times[i+1]: return False, f"not ascending at index {i}: {times[i]} > {times[i+1]}" return True, f"ascending: first={times[0]} last={times[-1]}" # TC4: backward compat — no params def check_tc4(d): ok = d.get("ok") data = d.get("data", []) total = d.get("total") if not ok: return False, f"ok=False" if total is None: return False, f"total missing" if not isinstance(data, list): return False, f"data not list" return True, f"total={total} len={len(data)}" # TC5: per_page=0 boundary def check_tc5(d): ok = d.get("ok") per_page = d.get("per_page") data = d.get("data", []) # Should default to 10, not crash if not ok: return False, f"ok=False (crash?)" if len(data) > 10: return False, f"per_page=0 returned {len(data)} items (expected ≤10)" return True, f"per_page=0 → got per_page={per_page} len={len(data)}" print("=== S1 RED: /api/sessions pagination + sort ===\n") page1_ids = [] test("TC1: page=1&per_page=10", "/api/sessions?page=1&per_page=10", check_tc1) if failed == 0: test("TC2a: page=1&per_page=10", "/api/sessions?page=1&per_page=10", check_tc2_a) test("TC2b: page=2&per_page=10", "/api/sessions?page=2&per_page=10", check_tc2_b) else: print(" SKIP TC2: TC1 failed") test("TC3: sort=time_asc", "/api/sessions?page=1&per_page=20&sort=time_asc", check_tc3) test("TC4: no params (backward compat)", "/api/sessions", check_tc4) test("TC5: per_page=0 boundary", "/api/sessions?page=1&per_page=0", check_tc5) print(f"\n{passed}/{passed+failed} 通过") sys.exit(0 if failed == 0 else 1)