chore: import upstream snapshot with attribution
Test Migrations / Migrations (SQLite) (push) Has been cancelled
Build Dev Image / build-dev-image (push) Has been cancelled
Check i18n Keys / Check i18n Key Consistency (push) Has been cancelled
Lint / Ruff Lint & Format (push) Has been cancelled
Lint / Frontend Lint (push) Has been cancelled
Test Migrations / Migrations (PostgreSQL) (push) Has been cancelled
Test Migrations / Migrations (SQLite) (push) Has been cancelled
Build Dev Image / build-dev-image (push) Has been cancelled
Check i18n Keys / Check i18n Key Consistency (push) Has been cancelled
Lint / Ruff Lint & Format (push) Has been cancelled
Lint / Frontend Lint (push) Has been cancelled
Test Migrations / Migrations (PostgreSQL) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
"""
|
||||
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