|
| 1 | +"""v1.108.83 — watch-all CPU under WSL (issue #356). |
| 2 | +
|
| 3 | +watchfiles auto-enables polling under WSL; its default 300ms poll re-stats every |
| 4 | +watched tree several times a second, pegging the CPU on a many-repo host. We |
| 5 | +raise the poll floor (tunable) and emit a one-time WSL hint. These tests pin the |
| 6 | +poll-delay resolution + WSL detection helpers (the awatch wiring itself needs the |
| 7 | +optional `watchfiles` extra, so it's exercised by the live watcher suite). |
| 8 | +""" |
| 9 | +from __future__ import annotations |
| 10 | + |
| 11 | +import builtins |
| 12 | + |
| 13 | +import pytest |
| 14 | + |
| 15 | +from jcodemunch_mcp import watcher |
| 16 | + |
| 17 | + |
| 18 | +# --- poll delay resolution --------------------------------------------------- |
| 19 | + |
| 20 | +def _clear_delay_env(monkeypatch): |
| 21 | + monkeypatch.delenv("JCODEMUNCH_WATCH_POLL_DELAY_MS", raising=False) |
| 22 | + monkeypatch.delenv("WATCHFILES_POLL_DELAY_MS", raising=False) |
| 23 | + |
| 24 | + |
| 25 | +def test_default_poll_delay_is_raised_floor(monkeypatch): |
| 26 | + _clear_delay_env(monkeypatch) |
| 27 | + assert watcher._watch_poll_delay_ms() == watcher.DEFAULT_WATCH_POLL_DELAY_MS == 1000 |
| 28 | + |
| 29 | + |
| 30 | +def test_jcm_env_overrides_poll_delay(monkeypatch): |
| 31 | + _clear_delay_env(monkeypatch) |
| 32 | + monkeypatch.setenv("JCODEMUNCH_WATCH_POLL_DELAY_MS", "2500") |
| 33 | + assert watcher._watch_poll_delay_ms() == 2500 |
| 34 | + |
| 35 | + |
| 36 | +@pytest.mark.parametrize("bad", ["0", "-5", "junk", ""]) |
| 37 | +def test_non_positive_or_garbage_falls_back_to_default(monkeypatch, bad): |
| 38 | + _clear_delay_env(monkeypatch) |
| 39 | + monkeypatch.setenv("JCODEMUNCH_WATCH_POLL_DELAY_MS", bad) |
| 40 | + assert watcher._watch_poll_delay_ms() == watcher.DEFAULT_WATCH_POLL_DELAY_MS |
| 41 | + |
| 42 | + |
| 43 | +def test_watchfiles_env_is_fallback(monkeypatch): |
| 44 | + _clear_delay_env(monkeypatch) |
| 45 | + monkeypatch.setenv("WATCHFILES_POLL_DELAY_MS", "1800") |
| 46 | + assert watcher._watch_poll_delay_ms() == 1800 |
| 47 | + |
| 48 | + |
| 49 | +def test_jcm_env_takes_precedence_over_watchfiles_env(monkeypatch): |
| 50 | + _clear_delay_env(monkeypatch) |
| 51 | + monkeypatch.setenv("WATCHFILES_POLL_DELAY_MS", "1800") |
| 52 | + monkeypatch.setenv("JCODEMUNCH_WATCH_POLL_DELAY_MS", "4000") |
| 53 | + assert watcher._watch_poll_delay_ms() == 4000 |
| 54 | + |
| 55 | + |
| 56 | +# --- WSL detection ----------------------------------------------------------- |
| 57 | + |
| 58 | +def test_is_wsl_false_on_non_linux(monkeypatch): |
| 59 | + monkeypatch.setattr(watcher.sys, "platform", "win32") |
| 60 | + assert watcher._is_wsl() is False |
| 61 | + |
| 62 | + |
| 63 | +def test_is_wsl_true_when_proc_version_names_microsoft(monkeypatch): |
| 64 | + monkeypatch.setattr(watcher.sys, "platform", "linux") |
| 65 | + real_open = builtins.open |
| 66 | + |
| 67 | + def fake_open(path, *a, **k): |
| 68 | + if str(path) == "/proc/version": |
| 69 | + from io import StringIO |
| 70 | + return StringIO("Linux version 5.15.0-microsoft-standard-WSL2 ...") |
| 71 | + return real_open(path, *a, **k) |
| 72 | + |
| 73 | + monkeypatch.setattr(builtins, "open", fake_open) |
| 74 | + assert watcher._is_wsl() is True |
| 75 | + |
| 76 | + |
| 77 | +def test_is_wsl_false_on_bare_metal_linux(monkeypatch): |
| 78 | + monkeypatch.setattr(watcher.sys, "platform", "linux") |
| 79 | + real_open = builtins.open |
| 80 | + |
| 81 | + def fake_open(path, *a, **k): |
| 82 | + if str(path) == "/proc/version": |
| 83 | + from io import StringIO |
| 84 | + return StringIO("Linux version 6.8.0-generic (gcc ...) ") |
| 85 | + return real_open(path, *a, **k) |
| 86 | + |
| 87 | + monkeypatch.setattr(builtins, "open", fake_open) |
| 88 | + assert watcher._is_wsl() is False |
0 commit comments