fix(hwfit): tolerate non-numeric gpu_count in /api/hwfit/models (#3639)

* fix(hwfit): tolerate non-numeric gpu_count in /api/hwfit/models

The route did `n = int(gpu_count)` with no guard, so a non-numeric query param
like `?gpu_count=abc` raised ValueError and returned HTTP 500. Parse it
defensively (mirroring the gpu_group guard a few lines above): a malformed value
is ignored, exactly like omitting the param, and valid values still apply.

Adds tests/test_hwfit_gpu_count_nonnumeric.py: a non-numeric gpu_count returns a
ranking instead of raising, and a numeric value is still accepted.

* test(hwfit): cover non-numeric manual_gpu_count too

Follow-up to the gpu_count guard: add a regression test for the sibling
manual_gpu_count query param (the hardware simulator in _apply_manual_hardware),
which dev already guards by defaulting to 1 on a non-numeric value. This pins
that behaviour so the endpoint's count parsing is fully covered and cannot
regress to a 500.
This commit is contained in:
Mazen Tamer Salah
2026-06-11 02:01:58 +03:00
committed by GitHub
parent d1a5a7d680
commit 9c00da6d1c
2 changed files with 46 additions and 2 deletions
+8 -2
View File
@@ -177,8 +177,14 @@ def setup_hwfit_routes():
system["gpu_name"] = g["name"]
system["active_group"] = {**g, "use_count": n}
if gpu_count != "":
n = int(gpu_count)
# Parse the optional count defensively (matches the gpu_group guard
# above): a non-numeric query param previously raised ValueError ->
# HTTP 500. A malformed value is ignored, same as omitting it.
try:
n = int(gpu_count) if gpu_count != "" else None
except ValueError:
n = None
if n is not None:
if n == 0:
# RAM-only mode: rank against system memory, offload allowed.
system["has_gpu"] = False
+38
View File
@@ -0,0 +1,38 @@
"""GET /api/hwfit/models must not 500 on a non-numeric gpu_count.
The handler did `n = int(gpu_count)` with no guard, so `?gpu_count=abc` (or any
non-integer) raised ValueError -> HTTP 500. A malformed count is now ignored,
matching how the neighbouring gpu_group param is already parsed.
"""
from routes.hwfit_routes import setup_hwfit_routes
def _get_models():
router = setup_hwfit_routes()
for route in router.routes:
if getattr(route, "path", "").endswith("/models") and "GET" in getattr(route, "methods", set()):
return route.endpoint
raise AssertionError("hwfit /models route not found")
def test_non_numeric_gpu_count_does_not_raise():
handler = _get_models()
# Previously raised ValueError (HTTP 500); now degrades to a normal ranking.
result = handler(gpu_count="abc")
assert isinstance(result, dict)
def test_numeric_gpu_count_still_accepted():
handler = _get_models()
result = handler(gpu_count="0")
assert isinstance(result, dict)
def test_non_numeric_manual_gpu_count_does_not_raise():
# manual_gpu_count is the other count param on this endpoint (the hardware
# simulator in _apply_manual_hardware). A non-numeric value must also degrade
# (default to 1) rather than 500, so the endpoint's count parsing is fully
# covered.
handler = _get_models()
result = handler(manual_mode="gpu", manual_gpu_count="abc")
assert isinstance(result, dict)