unsloth/tests
Daniel Han 9d47eb2e95
studio/tests: AbortSignal-bound in-page fetches and wall-clock watchdog for Playwright probes (#5391)
* studio/tests: AbortSignal-bound in-page fetches + wall-clock watchdog

Run 25696797934 / job 75446949358 on PR #5387 cancelled the
"Chat UI Tests" macos-14 job at 30 min: studio.log went idle after
the chat surface mounted, no further requests reached the server,
and Playwright silently sat on a `page.evaluate(async () => fetch(
/api/inference/load))` for 27+ minutes before the runner-level
timeout fired. The two other Chat UI Tests jobs on the same SHA
passed in 5-17 min, so this was a transient renderer wedge under
--single-process Chromium, not a regression from the security
bumps in that PR.

Root cause: Playwright's `page.evaluate(...)` has no `timeout=`
argument. If the JS body awaits a fetch whose promise never
settles (the renderer's network thread stalls behind the busy main
thread on the free macos-14 runner), the entire Python script
hangs until something external kills it.

Add two helpers in `_playwright_robust.py`:

  - `evaluate_fetch(page, url, *, method, headers, body, timeout_ms)`
    wraps `fetch()` in an `AbortController` so the JS resolves
    either with a real response or with `{status: 0, error:
    "AbortError..."}` after the budget elapses. Callers fail loud
    on a non-None `error` and the wedge surfaces as a one-line
    diagnostic instead of a 30-min cancel.

  - `install_wall_clock_watchdog(deadline_s)` starts a daemon
    Timer that hard-exits the process at the deadline. Belt-and-
    suspenders for any wedge inside the browser that the per-
    action timeouts cannot bound. Default 720s (12 min); healthy
    runs measure 5-9 min on macos-14 so the headroom is small
    without amplifying a wedge to the 30-min runner cap.

Wire both into `playwright_chat_ui.py` and `playwright_extra_ui.py`:

  - Replace every `page.evaluate(async () => fetch(...))` site
    with `evaluate_fetch(...)`: refresh-token exchange, defaults
    fetch, inference load, health probe, post-rotation refresh.
    Five sites in chat_ui, two in extra_ui.
  - Arm the watchdog at the top of `with sync_playwright()` and
    cancel it on clean exit.

Knobs (all default-safe, override only for slow runners):
  STUDIO_UI_WALL_TIMEOUT_S   (default 720s)
  STUDIO_UI_FETCH_TIMEOUT_MS (default 30000ms)
  STUDIO_UI_LOAD_TIMEOUT_MS  (default 180000ms)

Verified locally with `python -c "ast.parse(...)"` on all three
files and a unit smoke that confirms `evaluate_fetch`'s JS argument
shape and that `install_wall_clock_watchdog` returns a daemonised
Timer that responds to `.cancel()`.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-05-11 20:37:24 -07:00
..
notebooks CI: scope GITHUB_TOKEN permissions, add MLX CI, unblock ~60 skipped tests (#5312) 2026-05-11 03:19:13 -07:00
python fix: unblock 4 tests deselected/skipped in #5312 (real bugs) (#5359) 2026-05-11 02:39:17 -07:00
qlora Revert "[pre-commit.ci] auto fixes from pre-commit.com hooks" 2025-12-01 07:24:58 -08:00
saving chore: fix typo cleanup across tests and backend strings (#5152) 2026-04-24 12:51:27 +01:00
sh fix(tests/sh): accept pinned tokenizers line after #5359 (#5361) 2026-05-11 02:58:20 -07:00
studio studio/tests: AbortSignal-bound in-page fetches and wall-clock watchdog for Playwright probes (#5391) 2026-05-11 20:37:24 -07:00
utils feat: Add cactus QAT scheme support (#4679) 2026-04-15 07:40:03 -07:00
version_compat CI: scope GITHUB_TOKEN permissions, add MLX CI, unblock ~60 skipped tests (#5312) 2026-05-11 03:19:13 -07:00
vllm_compat CI: scope GITHUB_TOKEN permissions, add MLX CI, unblock ~60 skipped tests (#5312) 2026-05-11 03:19:13 -07:00
__init__.py Qwen 3, Bug Fixes (#2445) 2025-04-30 22:38:39 -07:00
_zoo_aggressive_cuda_spoof.py CI: scope GITHUB_TOKEN permissions, add MLX CI, unblock ~60 skipped tests (#5312) 2026-05-11 03:19:13 -07:00
conftest.py Add Studio PR-time CI: pin enforcement, frontend, backend, wheel smoke (#5298) 2026-05-06 04:41:57 -07:00
run_all.sh fix: add tokenizers to no-torch deps and TORCH_CONSTRAINT for arm64 macOS py313+ (#4748) 2026-04-01 06:12:17 -07:00
test_cli_export_unpacking.py studio: stream export worker output into the export dialog (#4897) 2026-04-14 08:55:43 -07:00
test_gemma4_chat_template.py update gema4 chat templates (#5116) 2026-04-22 09:04:08 -07:00
test_get_model_name.py feat: Add support for OLMo-3 model (#4678) 2026-04-15 07:39:11 -07:00
test_loader_glob_skip.py Add unit tests for HfFileSystem glob skip guard (#4854) 2026-04-06 08:54:36 -07:00
test_model_registry.py Revert "[FIX] Vllm guided decoding params (#3662)" 2025-12-01 05:43:45 -08:00
test_peft_weight_converter_compat.py Patch checkpoint reload init functions to strip unsupported args (#5167) 2026-04-29 02:50:49 -07:00
test_raw_text.py Add Studio PR-time CI: pin enforcement, frontend, backend, wheel smoke (#5298) 2026-05-06 04:41:57 -07:00
test_resolve_model_class.py fix: guard resolve_model_class fallback against unresolvable transformers AutoModel entries (#5155) 2026-04-24 05:59:17 -07:00
test_studio_install_workspace_guard.py install: support STUDIO_HOME / UNSLOTH_STUDIO_HOME for custom install paths (#5190) 2026-05-05 23:17:40 -07:00
test_studio_root_resilience.py install: support STUDIO_HOME / UNSLOTH_STUDIO_HOME for custom install paths (#5190) 2026-05-05 23:17:40 -07:00