File size: 2,868 Bytes
c34ff1f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | from types import SimpleNamespace
from typing import TYPE_CHECKING, cast
from unittest.mock import Mock
import pytest
from tests.e2e import utils
if TYPE_CHECKING:
import subprocess
class _FakeResponse:
def __init__(self, status: int):
self.status = status
def __enter__(self):
return self
def __exit__(self, *_args):
return None
def test_wait_for_server_requires_stable_health(monkeypatch):
clock = [0.0]
statuses = iter([503, 200, 200, 200, 200])
def advance(seconds):
clock[0] += seconds
monkeypatch.setattr(utils.time, "monotonic", lambda: clock[0])
monkeypatch.setattr(utils.time, "sleep", advance)
monkeypatch.setattr(
utils.urllib.request,
"urlopen",
lambda *_args, **_kwargs: _FakeResponse(next(statuses)),
)
utils.wait_for_server(
8000,
timeout=20,
poll_interval=1,
readiness_stability=3,
)
assert clock[0] == 4
def test_wait_for_server_checks_process_during_stability(monkeypatch):
clock = [0.0]
polls = iter([None, None, 1])
process = cast(
"subprocess.Popen",
SimpleNamespace(returncode=1, poll=lambda: next(polls)),
)
def advance(seconds):
clock[0] += seconds
monkeypatch.setattr(utils.time, "monotonic", lambda: clock[0])
monkeypatch.setattr(utils.time, "sleep", advance)
monkeypatch.setattr(
utils.urllib.request,
"urlopen",
lambda *_args, **_kwargs: _FakeResponse(200),
)
with pytest.raises(RuntimeError, match="exited with code 1"):
utils.wait_for_server(
8000,
timeout=20,
poll_interval=1,
readiness_stability=3,
process=process,
)
def test_launch_vllm_server_uses_an_isolated_process_group(monkeypatch, tmp_path):
process = Mock(pid=1234, returncode=None)
process.poll.return_value = None
popen = Mock(return_value=process)
monkeypatch.setattr(utils.subprocess, "Popen", popen)
monkeypatch.setattr(utils, "wait_for_server", Mock())
result = utils.launch_vllm_server(
"model",
8000,
str(tmp_path / "hidden_states"),
)
assert result is process
assert popen.call_args.kwargs["start_new_session"] is True
def test_stop_vllm_server_cleans_up_the_process_group(monkeypatch):
process = Mock(pid=1234, returncode=-15)
process.poll.return_value = None
process.wait.return_value = None
killpg = Mock(side_effect=ProcessLookupError)
monkeypatch.setattr(utils.os, "killpg", killpg)
utils.stop_vllm_server(process)
process.terminate.assert_called_once_with()
process.wait.assert_called_once_with(timeout=30)
assert killpg.call_args_list[0].args == (1234, utils.signal.SIGTERM)
assert killpg.call_args_list[1].args == (1234, 0)
|