Files
s5p/tests/test_config.py
user 714e8efb3d feat: cap concurrent connections with semaphore
Add max_connections config (default 256) with -m/--max-connections CLI
flag. Server wraps on_client in asyncio.Semaphore to prevent fd
exhaustion under load. Value reloads on SIGHUP; active connections
drain normally. Also adds pool_size/pool_max_idle config fields and
first_hop_pool wiring in server.py (used by next commits), and fixes
asyncio.TimeoutError -> TimeoutError lint warnings.
2026-02-15 17:55:50 +01:00

93 lines
2.9 KiB
Python

"""Tests for configuration loading and proxy URL parsing."""
import pytest
from s5p.config import ChainHop, Config, load_config, parse_proxy_url
class TestParseProxyUrl:
"""Test proxy URL parsing."""
def test_socks5_basic(self):
hop = parse_proxy_url("socks5://127.0.0.1:9050")
assert hop.proto == "socks5"
assert hop.host == "127.0.0.1"
assert hop.port == 9050
assert hop.username is None
assert hop.password is None
def test_socks5_with_auth(self):
hop = parse_proxy_url("socks5://user:pass@proxy.example.com:1080")
assert hop.proto == "socks5"
assert hop.host == "proxy.example.com"
assert hop.port == 1080
assert hop.username == "user"
assert hop.password == "pass"
def test_socks4(self):
hop = parse_proxy_url("socks4://10.0.0.1:1080")
assert hop.proto == "socks4"
assert hop.host == "10.0.0.1"
assert hop.port == 1080
def test_http_connect(self):
hop = parse_proxy_url("http://proxy:8080")
assert hop.proto == "http"
assert hop.host == "proxy"
assert hop.port == 8080
def test_default_port_socks5(self):
hop = parse_proxy_url("socks5://host")
assert hop.port == 1080
def test_default_port_http(self):
hop = parse_proxy_url("http://host")
assert hop.port == 8080
def test_unsupported_protocol(self):
with pytest.raises(ValueError, match="unsupported protocol"):
parse_proxy_url("ftp://host:21")
def test_missing_host(self):
with pytest.raises(ValueError, match="missing host"):
parse_proxy_url("socks5://")
class TestChainHop:
"""Test ChainHop string representation."""
def test_str_without_auth(self):
hop = ChainHop(proto="socks5", host="localhost", port=9050)
assert str(hop) == "socks5://localhost:9050"
def test_str_with_auth(self):
hop = ChainHop(proto="http", host="proxy", port=8080, username="u", password="p")
assert str(hop) == "http://u@proxy:8080"
class TestConfig:
"""Test Config defaults."""
def test_defaults(self):
c = Config()
assert c.listen_host == "127.0.0.1"
assert c.listen_port == 1080
assert c.chain == []
assert c.timeout == 10.0
assert c.max_connections == 256
assert c.pool_size == 0
assert c.pool_max_idle == 30.0
def test_max_connections_from_yaml(self, tmp_path):
cfg_file = tmp_path / "test.yaml"
cfg_file.write_text("max_connections: 512\n")
c = load_config(cfg_file)
assert c.max_connections == 512
def test_pool_size_from_yaml(self, tmp_path):
cfg_file = tmp_path / "test.yaml"
cfg_file.write_text("pool_size: 16\npool_max_idle: 45.0\n")
c = load_config(cfg_file)
assert c.pool_size == 16
assert c.pool_max_idle == 45.0