mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-09 23:36:02 +00:00
test: add 105 new unit tests for untested core functionality
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).
This commit is contained in:
167
tests/unit_tests/utils/test_proxy.py
Normal file
167
tests/unit_tests/utils/test_proxy.py
Normal file
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user