Commit e97010147 for llama.cpp
commit e9701014703d251593b23ce1703db8a7299dad0f
Author: Pascal <admin@serveurperso.com>
Date: Thu Nov 12 23:13:37 2026 +0100
server: skip LAN address tests when the host cannot reach it [no ci] (#32166)
The same-origin tests over the LAN address block forever on the Metal
runners: the request to the host's own LAN address never returns and
has no timeout, so the job runs until the 6h limit.
get_lan_ip() now probes /health on that address with a short timeout
and returns None when the host cannot reach it, which skips the test.
The test requests themselves use the default request timeout so a
hang fails the test instead of stalling the job.
diff --git a/tools/server/tests/unit/test_router.py b/tools/server/tests/unit/test_router.py
index e4e62086b..b5c6fcdae 100644
--- a/tools/server/tests/unit/test_router.py
+++ b/tools/server/tests/unit/test_router.py
@@ -934,24 +934,24 @@ def test_router_download_drops_stale_partials():
def test_router_restricted_cors_same_origin_reaches_child():
# same-origin request via LAN address must not be refused by the child
global server
- lan_ip = get_lan_ip()
- if lan_ip is None:
- pytest.skip("no non-loopback interface") # ty: ignore[too-many-positional-arguments]
server.cors_origins = "localhost"
server.server_host = "0.0.0.0"
server.start()
+ lan_ip = get_lan_ip(server)
+ if lan_ip is None:
+ pytest.skip("no LAN address reachable from this host") # ty: ignore[too-many-positional-arguments]
body = {
"model": "ggml-org-dev/tinygemma3-GGUF:Q8_0",
"max_tokens": 4,
"messages": [{"role": "user", "content": "hello"}],
}
- res = requests.post(server.make_url("/chat/completions", host=lan_ip), json=body, headers={
+ res = server.make_request("POST", "/chat/completions", data=body, host=lan_ip, headers={
"Origin": f"http://{lan_ip}:{server.server_port}",
"Sec-Fetch-Site": "same-origin",
})
- assert res.status_code == 200, res.text
+ assert res.status_code == 200, res.body
- res = requests.post(server.make_url("/chat/completions", host="127.0.0.1"), json=body, headers={"Origin": "http://evil.com"})
+ res = server.make_request("POST", "/chat/completions", data=body, host="127.0.0.1", headers={"Origin": "http://evil.com"})
assert res.status_code == 403
diff --git a/tools/server/tests/unit/test_security.py b/tools/server/tests/unit/test_security.py
index ceec582ac..ef4e48fa8 100644
--- a/tools/server/tests/unit/test_security.py
+++ b/tools/server/tests/unit/test_security.py
@@ -170,16 +170,16 @@ def test_cors_origins_localhost_blocks_simple_requests(headers: dict, expected_s
def test_cors_origins_localhost_allows_same_origin():
global server
- lan_ip = get_lan_ip()
- if lan_ip is None:
- pytest.skip("no non-loopback interface") # ty: ignore[too-many-positional-arguments]
server.api_key = None
server.cors_origins = "localhost"
server.server_host = "0.0.0.0"
server.start()
+ lan_ip = get_lan_ip(server)
+ if lan_ip is None:
+ pytest.skip("no LAN address reachable from this host") # ty: ignore[too-many-positional-arguments]
# UI opened via LAN address: Origin matches Host
url = server.make_url("/tokenize", host=lan_ip)
- res = requests.post(url, data='{"content": "hello"}', headers={
+ res = requests.post(url, data='{"content": "hello"}', timeout=DEFAULT_REQUEST_TIMEOUT, headers={
"Content-Type": "text/plain",
"Origin": f"http://{lan_ip}:{server.server_port}",
})
diff --git a/tools/server/tests/utils.py b/tools/server/tests/utils.py
index 71470c2b6..56c88b354 100644
--- a/tools/server/tests/utils.py
+++ b/tools/server/tests/utils.py
@@ -34,6 +34,9 @@ DEFAULT_HTTP_TIMEOUT = 600
# per-request timeout, a hung server fails the test instead of stalling the CI for hours
DEFAULT_REQUEST_TIMEOUT = 600
+# timeout of the reachability probe of the LAN address
+LAN_PROBE_TIMEOUT = 5
+
class ServerResponse:
headers: dict
@@ -805,7 +808,7 @@ def download_file(url: str, output_file_path: str | None = None) -> str:
return output_file
-def get_lan_ip() -> str | None:
+def get_lan_ip(server: ServerProcess) -> str | None:
# address of the interface that routes outside, no packet is sent
import socket
try:
@@ -814,7 +817,14 @@ def get_lan_ip() -> str | None:
ip = s.getsockname()[0]
except OSError:
return None
- return None if ip.startswith("127.") else ip
+ if ip.startswith("127."):
+ return None
+ # a host can fail to reach its own LAN address (firewall, VPN, system proxy)
+ try:
+ requests.get(server.make_url("/health", host=ip), timeout=LAN_PROBE_TIMEOUT)
+ except requests.exceptions.RequestException:
+ return None
+ return ip
def is_slow_test_allowed():