Files
wehub-resource-sync e4dcfc49aa
Tests / Lint and Format (push) Waiting to run
Tests / Web Node Tests (push) Waiting to run
Tests / Import Check (Python 3.11) (push) Waiting to run
Tests / Import Check (Python 3.12) (push) Waiting to run
Tests / Import Check (Python 3.13) (push) Waiting to run
Tests / Import Check (Python 3.14) (push) Waiting to run
Tests / Python Tests (Python 3.11) (push) Blocked by required conditions
Tests / Python Tests (Python 3.12) (push) Blocked by required conditions
Tests / Python Tests (Python 3.13) (push) Blocked by required conditions
Tests / Python Tests (Python 3.14) (push) Blocked by required conditions
Tests / Test Summary (push) Blocked by required conditions
chore: import upstream snapshot with attribution
2026-07-13 13:00:43 +08:00

188 lines
6.0 KiB
Python

from __future__ import annotations
import builtins
from pathlib import Path
import pytest
from deeptutor.runtime import launcher
class _FakeTty:
def isatty(self) -> bool:
return True
def test_packaged_web_cache_replaces_next_public_placeholders(tmp_path: Path) -> None:
packaged = tmp_path / "pkg"
(packaged / ".next" / "static").mkdir(parents=True)
(packaged / "server.js").write_text(
"const api='__NEXT_PUBLIC_API_BASE_PLACEHOLDER__';",
encoding="utf-8",
)
(packaged / ".next" / "static" / "app.js").write_text(
"auth='__NEXT_PUBLIC_AUTH_ENABLED_PLACEHOLDER__'",
encoding="utf-8",
)
runtime = launcher._copy_packaged_web_if_needed(
packaged,
home=tmp_path / "home",
api_base="http://localhost:8001",
auth_enabled=True,
)
assert (runtime / "server.js").read_text(encoding="utf-8") == (
"const api='http://localhost:8001';"
)
assert "auth='true'" in (runtime / ".next" / "static" / "app.js").read_text(encoding="utf-8")
def test_packaged_web_cache_refreshes_when_public_settings_change(tmp_path: Path) -> None:
packaged = tmp_path / "pkg"
(packaged / ".next").mkdir(parents=True)
(packaged / "server.js").write_text(
"const api='__NEXT_PUBLIC_API_BASE_PLACEHOLDER__';",
encoding="utf-8",
)
home = tmp_path / "home"
first = launcher._copy_packaged_web_if_needed(
packaged,
home=home,
api_base="http://localhost:8001",
auth_enabled=False,
)
second = launcher._copy_packaged_web_if_needed(
packaged,
home=home,
api_base="https://api.example",
auth_enabled=False,
)
assert first == second
assert "https://api.example" in (second / "server.js").read_text(encoding="utf-8")
def test_detect_existing_source_frontend_from_next_dev_lock(tmp_path: Path, monkeypatch) -> None:
source = tmp_path / "web"
lock = source / ".next" / "dev" / "lock"
lock.parent.mkdir(parents=True)
lock.write_text(
'{"pid":12345,"port":3999,"appUrl":"http://localhost:3999"}',
encoding="utf-8",
)
monkeypatch.setattr(launcher, "_is_pid_alive", lambda pid: pid == 12345)
monkeypatch.setattr(launcher, "_port_accepts_connection", lambda port: False)
existing = launcher._detect_existing_source_frontend(
launcher.FrontendRuntime("source", [], source)
)
assert existing is not None
assert existing.url == "http://localhost:3999"
assert existing.port == 3999
assert existing.pid == 12345
assert existing.lock_path == lock
def test_detect_existing_source_frontend_ignores_stale_lock(tmp_path: Path, monkeypatch) -> None:
source = tmp_path / "web"
lock = source / ".next" / "dev" / "lock"
lock.parent.mkdir(parents=True)
lock.write_text(
'{"pid":12345,"port":3999,"appUrl":"http://localhost:3999"}',
encoding="utf-8",
)
monkeypatch.setattr(launcher, "_is_pid_alive", lambda pid: False)
monkeypatch.setattr(launcher, "_port_accepts_connection", lambda port: False)
existing = launcher._detect_existing_source_frontend(
launcher.FrontendRuntime("source", [], source)
)
assert existing is None
def test_resolve_port_conflicts_passthrough_when_free(tmp_path: Path, monkeypatch) -> None:
monkeypatch.setattr(launcher, "_port_accepts_connection", lambda port: False)
result = launcher._resolve_port_conflicts(
backend_port=8000,
frontend_port=3784,
check_frontend=True,
settings_dir=tmp_path,
)
assert result == (8000, 3784)
def test_resolve_port_conflicts_non_tty_exits_with_message(tmp_path: Path, monkeypatch) -> None:
monkeypatch.setattr(launcher, "_port_accepts_connection", lambda port: port == 8000)
monkeypatch.setattr(launcher, "_port_listeners", lambda port: [(123, "python uvicorn")])
monkeypatch.setattr(launcher.sys, "stdin", None)
with pytest.raises(SystemExit) as excinfo:
launcher._resolve_port_conflicts(
backend_port=8000,
frontend_port=3784,
check_frontend=True,
settings_dir=tmp_path,
)
assert "8000" in str(excinfo.value)
def test_resolve_port_conflicts_kill_option_frees_port(tmp_path: Path, monkeypatch) -> None:
occupied = {8000}
killed: list[int] = []
def fake_kill(pid, pgid, sig):
killed.append(pid)
occupied.discard(8000)
monkeypatch.setattr(launcher, "_port_accepts_connection", lambda port: port in occupied)
monkeypatch.setattr(launcher, "_port_listeners", lambda port: [(123, "python uvicorn")])
monkeypatch.setattr(launcher, "_send_tree_signal", fake_kill)
monkeypatch.setattr(launcher.sys, "stdin", _FakeTty())
monkeypatch.setattr(builtins, "input", lambda prompt="": "2")
result = launcher._resolve_port_conflicts(
backend_port=8000,
frontend_port=3784,
check_frontend=True,
settings_dir=tmp_path,
)
assert result == (8000, 3784)
assert killed == [123]
def test_resolve_port_conflicts_change_option_prompts_and_persists(
tmp_path: Path, monkeypatch
) -> None:
saved: dict[str, int] = {}
def fake_persist(settings_dir, backend_port, frontend_port):
saved["backend"] = backend_port
saved["frontend"] = frontend_port
return settings_dir / "system.json"
answers = iter(["1", "8002", "3785"])
monkeypatch.setattr(launcher, "_port_accepts_connection", lambda port: port == 8000)
monkeypatch.setattr(launcher, "_port_listeners", lambda port: [(123, "python uvicorn")])
monkeypatch.setattr(launcher, "_persist_ports", fake_persist)
monkeypatch.setattr(launcher.sys, "stdin", _FakeTty())
monkeypatch.setattr(builtins, "input", lambda prompt="": next(answers))
result = launcher._resolve_port_conflicts(
backend_port=8000,
frontend_port=3784,
check_frontend=True,
settings_dir=tmp_path,
)
assert result == (8002, 3785)
assert saved == {"backend": 8002, "frontend": 3785}