| from __future__ import annotations |
|
|
| import os |
| import sys |
| import tempfile |
| from pathlib import Path |
|
|
| from fastapi.testclient import TestClient |
|
|
| _repo_root = Path(__file__).resolve().parents[2] |
| if str(_repo_root) not in sys.path: |
| sys.path.insert(0, str(_repo_root)) |
|
|
| from Spider_XHS.service.app import create_app |
| from Spider_XHS.service.errors import ERROR_CODE_SUCCESS |
|
|
|
|
| def _assert(cond: bool, msg: str) -> None: |
| if not cond: |
| raise AssertionError(msg) |
|
|
|
|
| def _assert_wrapper(body: dict) -> None: |
| _assert(isinstance(body.get("code"), int), f"missing code: {body}") |
| _assert(isinstance(body.get("msg"), str), f"missing msg: {body}") |
| _assert("data" in body, f"missing data: {body}") |
| _assert(body.get("code") == ERROR_CODE_SUCCESS, f"unexpected code={body.get('code')}") |
|
|
|
|
| def _get(client: TestClient, path: str) -> dict: |
| resp = client.get(path) |
| _assert(resp.status_code == 200, f"expected 200, got={resp.status_code}, path={path}, body={resp.text}") |
| body = resp.json() |
| _assert(isinstance(body, dict), f"response not dict: {body}") |
| _assert_wrapper(body) |
| data = body.get("data") |
| _assert(isinstance(data, dict), f"data not dict: {data}") |
| return data |
|
|
|
|
| def verify_resources_api_v1() -> None: |
| old_env = dict(os.environ) |
| try: |
| os.environ["ENABLE_LEGACY_ROUTES"] = "0" |
| with tempfile.TemporaryDirectory() as td: |
| os.environ["STORAGE_ROOT"] = td |
| app = create_app() |
| with TestClient(app) as client: |
| accounts = _get(client, "/api/v1/resources/accounts") |
| _assert(isinstance(accounts.get("now"), str) and accounts.get("now"), "accounts.now missing") |
| _assert(isinstance(accounts.get("seed"), int), "accounts.seed missing") |
| acc_list = accounts.get("accounts") |
| _assert(isinstance(acc_list, list) and len(acc_list) >= 1, "accounts.accounts missing") |
| acc0 = acc_list[0] |
| _assert(isinstance(acc0, dict), "accounts.accounts[0] not dict") |
| for k in ( |
| "id", |
| "tags", |
| "risk_score", |
| "enabled", |
| "available", |
| "cooldown_remaining_s", |
| "cooldown_until", |
| "last_error_kind", |
| "last_error_at", |
| ): |
| _assert(k in acc0, f"account missing {k}") |
|
|
| sessions = _get(client, "/api/v1/resources/sessions") |
| _assert(isinstance(sessions.get("now"), str) and sessions.get("now"), "sessions.now missing") |
| sess_list = sessions.get("sessions") |
| _assert(isinstance(sess_list, list) and len(sess_list) >= 1, "sessions.sessions missing") |
| sess0 = sess_list[0] |
| _assert(isinstance(sess0, dict), "sessions.sessions[0] not dict") |
| for k in ( |
| "id", |
| "account_id", |
| "has_cookie", |
| "has_storage_state", |
| "cookie_ok", |
| "storage_state_ok", |
| "cookie_reason", |
| "storage_state_reason", |
| "checked_at", |
| ): |
| _assert(k in sess0, f"session missing {k}") |
|
|
| proxies = _get(client, "/api/v1/resources/proxies") |
| for k in ( |
| "available_count", |
| "avg_score", |
| "ejected_total", |
| "failures_total_by_reason", |
| "recent_failures_by_reason", |
| "last_fail_reasons_by_reason", |
| ): |
| _assert(k in proxies, f"proxies missing {k}") |
| _assert(isinstance(proxies.get("available_count"), int), "proxies.available_count not int") |
| _assert(isinstance(proxies.get("avg_score"), (int, float)), "proxies.avg_score not number") |
| _assert(isinstance(proxies.get("ejected_total"), int), "proxies.ejected_total not int") |
| _assert(isinstance(proxies.get("failures_total_by_reason"), dict), "proxies.failures_total_by_reason not dict") |
| _assert(isinstance(proxies.get("recent_failures_by_reason"), dict), "proxies.recent_failures_by_reason not dict") |
| _assert( |
| isinstance(proxies.get("last_fail_reasons_by_reason"), dict), |
| "proxies.last_fail_reasons_by_reason not dict", |
| ) |
| finally: |
| os.environ.clear() |
| os.environ.update(old_env) |
|
|
|
|
| def main() -> None: |
| verify_resources_api_v1() |
| print("ok") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|
|
|