Files
wehub-resource-sync 8f10353f0c
CI / lint (push) Has been cancelled
CI / js-syntax (push) Successful in 10m24s
CI / deps-audit (push) Has been cancelled
CI / test (push) Failing after 24m55s
CI / sast-bandit (push) Failing after 11m13s
CI / trivy (push) Failing after 9m32s
Docker Publish / build-and-push (push) Failing after 34m3s
chore: import upstream snapshot with attribution
2026-07-13 12:32:09 +08:00

117 lines
4.2 KiB
Python

from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from app.core import settings as settings_mod
from app.main import _is_host_request, _is_loopback, app
MOBILE_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) Mobile/15E148"
@pytest.mark.parametrize(
"host,expected",
[
("127.0.0.1", True),
("::1", True),
("localhost", True),
("::ffff:127.0.0.1", True),
("127.0.1.1", True),
("192.168.1.14", False),
("10.0.0.5", False),
("", False),
(None, False),
],
)
def test_is_loopback(host, expected):
assert _is_loopback(host) is expected
def test_host_request_recognizes_own_lan_ip(monkeypatch):
# The host reaching itself via its LAN address must count as local, so
# turning network access off never cuts the host off from its own server.
monkeypatch.setattr("app.main._local_ips", lambda: frozenset({"192.168.1.14"}))
assert _is_host_request("192.168.1.14") is True # the host's own IP
assert _is_host_request("127.0.0.1") is True # loopback
assert _is_host_request("192.168.1.99") is False # a different device
def test_default_is_off_in_desktop_mode(monkeypatch):
# Desktop keeps network off; the user opts in via the UI toggle.
monkeypatch.delenv("STEMDECK_ALLOW_NETWORK", raising=False)
monkeypatch.setenv("STEMDECK_DESKTOP", "1")
assert settings_mod._default_allow_network() is False
def test_default_is_on_in_server_mode(monkeypatch):
# Server/Docker deployments open the gate by default.
monkeypatch.delenv("STEMDECK_ALLOW_NETWORK", raising=False)
monkeypatch.delenv("STEMDECK_DESKTOP", raising=False)
assert settings_mod._default_allow_network() is True
def test_env_var_pre_enables(monkeypatch):
monkeypatch.setenv("STEMDECK_ALLOW_NETWORK", "1")
assert settings_mod._default_allow_network() is True
def test_runtime_settings_round_trip_and_clamp():
with TestClient(app) as c:
r = c.post("/api/settings", json={"max_duration_sec": 600, "video_max_height": 1080})
assert r.status_code == 200
body = r.json()
assert body["max_duration_sec"] == 600
assert body["video_max_height"] == 1080
# GET reflects the new values.
assert c.get("/api/settings").json()["max_duration_sec"] == 600
# Out-of-range values are clamped, not rejected.
assert settings_mod.set_max_duration_sec(5) == 60 # floor
assert settings_mod.set_max_duration_sec(99999) == 1200 # ceiling = 20 min
assert settings_mod.set_video_max_height(99999) == 2160 # ceil
def test_port_default_and_clamp():
assert settings_mod.get_port() == 8000 # default
with TestClient(app) as c:
assert c.post("/api/settings", json={"port": 9000}).json()["port"] == 9000
assert settings_mod.set_port(80) == 1024 # floor (privileged ports rejected)
assert settings_mod.set_port(70000) == 65535 # ceil
def test_settings_reject_non_integer():
with TestClient(app) as c:
assert c.post("/api/settings", json={"max_duration_sec": "abc"}).status_code == 422
def test_gate_blocks_non_loopback_when_off():
settings_mod.set_allow_network(False)
# TestClient's client host ("testclient") is treated as non-loopback.
with TestClient(app) as c:
r = c.get("/", headers={"user-agent": MOBILE_UA})
assert r.status_code == 403
def test_gate_allows_everyone_when_on():
settings_mod.set_allow_network(True)
with TestClient(app) as c:
assert c.get("/api/health").status_code == 200
def test_loopback_always_allowed_even_when_off(monkeypatch):
settings_mod.set_allow_network(False)
monkeypatch.setattr("app.main._is_loopback", lambda _host: True)
with TestClient(app) as c:
assert c.get("/api/health").status_code == 200
def test_post_toggles_off_then_blocks():
settings_mod.set_allow_network(True) # so the non-loopback client can reach POST
with TestClient(app) as c:
r = c.post("/api/settings", json={"allow_network": False})
assert r.status_code == 200
assert r.json()["allow_network"] is False
# Now off → a non-loopback client is blocked from everything.
with TestClient(app) as c:
assert c.get("/api/settings").status_code == 403