Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/server-sanitize.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
source .venv/bin/activate
cd tools/server/tests
export ${{ matrix.extra_args }}
./tests.sh
PYTEST_WORKERS=1 ./tests.sh

- name: Slow tests
id: server_integration_tests_slow
Expand All @@ -112,4 +112,4 @@ jobs:
source .venv/bin/activate
cd tools/server/tests
export ${{ matrix.extra_args }}
SLOW_TESTS=1 ./tests.sh
PYTEST_WORKERS=1 SLOW_TESTS=1 ./tests.sh
20 changes: 18 additions & 2 deletions tools/server/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import os
import pytest
from filelock import FileLock
from utils import *


@pytest.fixture(scope="session", autouse=True)
def configure_worker_port(request):
worker_id = getattr(request.config, "workerinput", {}).get("workerid", "master")
if worker_id != "master":
worker_num = int(worker_id[2:])
base = 8080 + worker_num * 10
os.environ["BASE_PORT"] = str(base)
os.environ["PORT"] = str(base)


# ref: https://stackoverflow.com/questions/22627659/run-code-before-and-after-each-test-in-py-test
@pytest.fixture(autouse=True)
def stop_server_after_each_test():
Expand All @@ -16,6 +28,10 @@ def stop_server_after_each_test():


@pytest.fixture(scope="session", autouse=True)
def load_server_presets():
def load_server_presets(configure_worker_port, tmp_path_factory):
# this will be run once per test session, before any tests
ServerPreset.load_all()

# serialize model downloads across parallel workers.
root_tmp_dir = tmp_path_factory.getbasetemp().parent
with FileLock(str(root_tmp_dir / "load_all.lock")):
ServerPreset.load_all()
2 changes: 2 additions & 0 deletions tools/server/tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
aiohttp~=3.9.3
pytest~=8.3.3
pytest-xdist~=3.6
filelock~=3.16
numpy~=1.26.4
openai~=2.14.0
prometheus-client~=0.20.0
Expand Down
9 changes: 6 additions & 3 deletions tools/server/tests/tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ cd $SCRIPT_DIR

set -eu

WORKERS="${PYTEST_WORKERS:-auto}"

if [ $# -lt 1 ]
then
if [[ "${SLOW_TESTS:-0}" == 1 ]]; then
pytest --durations=30 -v -x
# --dist=loadfile means that all tests in the same file will be sent to the same worker.
pytest --durations=30 -v -x -n "${WORKERS}" --dist=loadfile
else
pytest --durations=30 -v -x -m "not slow"
pytest --durations=30 -v -x -n "${WORKERS}" --dist=loadfile -m "not slow"
fi
else
pytest --durations=30 "$@"
pytest --durations=30 -n "${WORKERS}" --dist=loadfile "$@"
fi
6 changes: 3 additions & 3 deletions tools/server/tests/unit/test_compat_anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def create_server():
global server
server = ServerPreset.tinyllama2()
server.model_alias = "tinyllama-2-anthropic"
server.server_port = 8082
server.server_port = server_base_port() + 2
Comment thread
danbev marked this conversation as resolved.
Resolved
server.n_slots = 1
server.n_ctx = 8192
server.n_batch = 2048
Expand All @@ -34,7 +34,7 @@ def vision_server():
server = ServerPreset.tinygemma3()
server.offline = False # Allow downloading the model
server.model_alias = "tinygemma3-anthropic"
server.server_port = 8083 # Different port to avoid conflicts
server.server_port = server_base_port() + 3 # Different port to avoid conflicts
server.n_slots = 1
return server

Expand Down Expand Up @@ -1015,7 +1015,7 @@ def test_anthropic_thinking_with_reasoning_model(stream):
server.jinja = True
server.n_ctx = 8192
server.n_predict = 1024
server.server_port = 8084
server.server_port = server_base_port() + 4
server.start(timeout_seconds=600) # large model needs time to download

if stream:
Expand Down
10 changes: 5 additions & 5 deletions tools/server/tests/unit/test_mcp_servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def _start_server_with_mcp(mcp_json: str, **kwargs) -> ServerProcess:
srv = ServerPreset.router()
srv.server_tools = "all"
srv.no_ui = True
srv.server_port = 8085 # avoid conflict with load_all() which uses 8080
srv.server_port = server_base_port() + 5 # avoid conflict with primary port
srv.mcp_servers_json = mcp_json
for k, v in kwargs.items():
setattr(srv, k, v)
Expand Down Expand Up @@ -183,7 +183,7 @@ def test_mcp_tools_not_listed_when_not_configured():
server = ServerPreset.router()
server.server_tools = "all"
server.no_ui = True
server.server_port = 8085
server.server_port = server_base_port() + 5
server.start()

try:
Expand Down Expand Up @@ -250,7 +250,7 @@ def test_mcp_tools_via_json_config_file():
server = ServerPreset.router()
server.server_tools = "all"
server.no_ui = True
server.server_port = 8085
server.server_port = server_base_port() + 5
server.mcp_servers_config = config_path
server.start()

Expand Down Expand Up @@ -468,7 +468,7 @@ def test_mcp_config_file_errors():
server = ServerPreset.router()
server.server_tools = "all"
server.no_ui = True
server.server_port = 8085
server.server_port = server_base_port() + 5
server.mcp_servers_json = "not valid json"
try:
server.start()
Expand All @@ -480,7 +480,7 @@ def test_mcp_config_file_errors():
server = ServerPreset.router()
server.server_tools = "all"
server.no_ui = True
server.server_port = 8085
server.server_port = server_base_port() + 5
server.mcp_servers_config = "/nonexistent/path.json"
try:
server.start()
Expand Down
2 changes: 1 addition & 1 deletion tools/server/tests/unit/test_tool_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def create_server():
global server
server = ServerPreset.tinyllama2()
server.model_alias = "tinyllama-2-tool-call"
server.server_port = 8081
server.server_port = server_base_port() + 1
server.n_slots = 1
server.n_ctx = 8192
server.n_batch = 2048
Expand Down
6 changes: 6 additions & 0 deletions tools/server/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ def start(self, timeout_seconds: int = DEFAULT_HTTP_TIMEOUT) -> None:
server_args.append("--backend_sampling")
if self.gcp_compat:
env["AIP_MODE"] = "PREDICTION"
env["AIP_HTTP_PORT"] = str(self.server_port)

args = [str(arg) for arg in [server_path, *server_args]]
print(f"tests: starting server with: {' '.join(args)}")
Expand Down Expand Up @@ -518,6 +519,11 @@ def make_any_request(
server_instances: Set[ServerProcess] = set()


def server_base_port() -> int:
"""Return the base port for this worker. Offset secondary servers from this value."""
return int(os.environ.get("BASE_PORT", "8080"))


class ServerPreset:
@staticmethod
def load_all() -> None:
Expand Down
Loading