mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 12:05:54 +00:00
Add comprehensive tests for B-class issues (core functionality untested): Pipeline: - test_pool.py: QueryPool ID generation, caching, async context (12 tests) - test_ratelimit.py: Fixed timing-sensitive test tolerance - test_pipelinemgr.py: Use real Pydantic StageProcessResult instead of Mock Utils: - test_version.py: Version comparison functions (20 tests) - test_logcache.py: Log page management and retrieval (18 tests) - test_httpclient.py: HTTP session pool management (10 tests) - test_proxy.py: Proxy configuration from env and config (10 tests) - test_image.py: URL parsing and base64 extraction (12 tests) - test_pkgmgr.py: Pip command generation (8 tests) Discover: - test_engine.py: I18nString, Metadata, Component manifest (15 tests) Test count: 1193 → 1298 (+105 tests) Note: Some B-class issues cannot be tested due to circular import bugs filed as GitHub issues #2175 (pipeline) and #2176 (persistence).
168 lines
5.8 KiB
Python
168 lines
5.8 KiB
Python
"""
|
|
Unit tests for ProxyManager.
|
|
|
|
Tests proxy configuration from environment and config.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
import os
|
|
from unittest.mock import Mock, patch
|
|
|
|
from langbot.pkg.utils.proxy import ProxyManager
|
|
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
|
|
class TestProxyManager:
|
|
"""Tests for ProxyManager class."""
|
|
|
|
def _create_mock_app(self, proxy_config: dict = None):
|
|
"""Create mock app with proxy config."""
|
|
mock_app = Mock()
|
|
mock_app.instance_config = Mock()
|
|
mock_app.instance_config.data = {'proxy': proxy_config or {}}
|
|
return mock_app
|
|
|
|
def test_init_creates_empty_proxies(self):
|
|
"""ProxyManager initializes with empty forward_proxies."""
|
|
mock_app = self._create_mock_app()
|
|
pm = ProxyManager(mock_app)
|
|
|
|
assert pm.forward_proxies == {}
|
|
|
|
async def test_initialize_reads_env_variables(self):
|
|
"""initialize reads HTTP_PROXY from environment."""
|
|
mock_app = self._create_mock_app()
|
|
|
|
with patch.dict(os.environ, {'HTTP_PROXY': 'http://env-proxy:8080', 'HTTPS_PROXY': 'https://env-proxy:8443'}):
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert pm.forward_proxies['http://'] == 'http://env-proxy:8080'
|
|
assert pm.forward_proxies['https://'] == 'https://env-proxy:8443'
|
|
|
|
async def test_initialize_reads_lower_case_env(self):
|
|
"""initialize reads lower case http_proxy from environment."""
|
|
mock_app = self._create_mock_app()
|
|
|
|
with patch.dict(os.environ, {'http_proxy': 'http://lower-proxy:8080'}, clear=True):
|
|
# Clear HTTP_PROXY to test fallback
|
|
if 'HTTP_PROXY' in os.environ:
|
|
del os.environ['HTTP_PROXY']
|
|
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert pm.forward_proxies['http://'] == 'http://lower-proxy:8080'
|
|
|
|
async def test_initialize_config_overrides_env(self):
|
|
"""Config proxy overrides environment variables."""
|
|
mock_app = self._create_mock_app(proxy_config={
|
|
'http': 'http://config-proxy:8080',
|
|
'https': 'https://config-proxy:8443',
|
|
})
|
|
|
|
with patch.dict(os.environ, {'HTTP_PROXY': 'http://env-proxy:8080'}):
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert pm.forward_proxies['http://'] == 'http://config-proxy:8080'
|
|
assert pm.forward_proxies['https://'] == 'https://config-proxy:8443'
|
|
|
|
async def test_initialize_sets_env_variables(self):
|
|
"""initialize sets proxy to environment variables."""
|
|
mock_app = self._create_mock_app(proxy_config={
|
|
'http': 'http://test-proxy:8080',
|
|
'https': 'https://test-proxy:8443',
|
|
})
|
|
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert os.environ.get('HTTP_PROXY') == 'http://test-proxy:8080'
|
|
assert os.environ.get('HTTPS_PROXY') == 'https://test-proxy:8443'
|
|
|
|
async def test_initialize_handles_empty_config(self):
|
|
"""initialize handles empty proxy config."""
|
|
mock_app = self._create_mock_app(proxy_config={})
|
|
|
|
with patch.dict(os.environ, clear=True):
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert pm.forward_proxies['http://'] is None
|
|
assert pm.forward_proxies['https://'] is None
|
|
|
|
async def test_initialize_handles_no_env_no_config(self):
|
|
"""initialize handles no env and no config."""
|
|
mock_app = self._create_mock_app(proxy_config={})
|
|
|
|
# Clear proxy env vars
|
|
env_backup = {}
|
|
for key in ['HTTP_PROXY', 'http_proxy', 'HTTPS_PROXY', 'https_proxy']:
|
|
env_backup[key] = os.environ.get(key)
|
|
if key in os.environ:
|
|
del os.environ[key]
|
|
|
|
try:
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert pm.forward_proxies['http://'] is None
|
|
assert pm.forward_proxies['https://'] is None
|
|
finally:
|
|
# Restore env
|
|
for key, value in env_backup.items():
|
|
if value is not None:
|
|
os.environ[key] = value
|
|
|
|
def test_get_forward_proxies_returns_copy(self):
|
|
"""get_forward_proxies returns a copy of the dict."""
|
|
mock_app = self._create_mock_app()
|
|
pm = ProxyManager(mock_app)
|
|
pm.forward_proxies = {'http://': 'http://test:8080'}
|
|
|
|
result = pm.get_forward_proxies()
|
|
|
|
assert result == pm.forward_proxies
|
|
assert result is not pm.forward_proxies # Different object
|
|
|
|
def test_get_forward_proxies_modification_safe(self):
|
|
"""Modifying returned dict doesn't affect internal state."""
|
|
mock_app = self._create_mock_app()
|
|
pm = ProxyManager(mock_app)
|
|
pm.forward_proxies = {'http://': 'http://test:8080'}
|
|
|
|
result = pm.get_forward_proxies()
|
|
result['http://'] = 'http://modified:9999'
|
|
|
|
assert pm.forward_proxies['http://'] == 'http://test:8080'
|
|
|
|
async def test_initialize_http_only_config(self):
|
|
"""initialize handles http-only config."""
|
|
mock_app = self._create_mock_app(proxy_config={
|
|
'http': 'http://http-only:8080',
|
|
})
|
|
|
|
# Clear any existing proxy env vars
|
|
env_backup = {}
|
|
for key in ['HTTP_PROXY', 'http_proxy', 'HTTPS_PROXY', 'https_proxy']:
|
|
env_backup[key] = os.environ.get(key)
|
|
if key in os.environ:
|
|
del os.environ[key]
|
|
|
|
try:
|
|
pm = ProxyManager(mock_app)
|
|
await pm.initialize()
|
|
|
|
assert pm.forward_proxies['http://'] == 'http://http-only:8080'
|
|
assert pm.forward_proxies['https://'] is None
|
|
finally:
|
|
# Restore env
|
|
for key, value in env_backup.items():
|
|
if value is not None:
|
|
os.environ[key] = value
|