Co-authored-by: Quentin Torroba <quentin.torroba@mistral.ai> Co-authored-by: Clément Siriex <clement.sirieix@mistral.ai> Co-authored-by: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai> Co-authored-by: Michel Thomazo <michel.thomazo@mistral.ai> Co-authored-by: Clément Drouin <clement.drouin@mistral.ai>
304 lines
10 KiB
Python
304 lines
10 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from vibe.core.paths.global_paths import GLOBAL_ENV_FILE
|
|
from vibe.core.proxy_setup import (
|
|
SUPPORTED_PROXY_VARS,
|
|
ProxySetupError,
|
|
get_current_proxy_settings,
|
|
parse_proxy_command,
|
|
set_proxy_var,
|
|
unset_proxy_var,
|
|
)
|
|
|
|
|
|
def _write_env_file(content: str) -> None:
|
|
GLOBAL_ENV_FILE.path.parent.mkdir(parents=True, exist_ok=True)
|
|
GLOBAL_ENV_FILE.path.write_text(content, encoding="utf-8")
|
|
|
|
|
|
class TestProxySetupError:
|
|
def test_inherits_from_exception(self) -> None:
|
|
assert issubclass(ProxySetupError, Exception)
|
|
|
|
def test_preserves_message(self) -> None:
|
|
error = ProxySetupError("test message")
|
|
assert str(error) == "test message"
|
|
|
|
|
|
class TestSupportedProxyVars:
|
|
def test_contains_all_expected_keys(self) -> None:
|
|
expected_keys = {
|
|
"HTTP_PROXY",
|
|
"HTTPS_PROXY",
|
|
"ALL_PROXY",
|
|
"NO_PROXY",
|
|
"SSL_CERT_FILE",
|
|
"SSL_CERT_DIR",
|
|
}
|
|
assert set(SUPPORTED_PROXY_VARS.keys()) == expected_keys
|
|
|
|
def test_all_keys_are_uppercase(self) -> None:
|
|
for key in SUPPORTED_PROXY_VARS:
|
|
assert key == key.upper()
|
|
|
|
def test_all_values_are_non_empty_strings(self) -> None:
|
|
for value in SUPPORTED_PROXY_VARS.values():
|
|
assert isinstance(value, str)
|
|
assert len(value) > 0
|
|
|
|
|
|
class TestGetCurrentProxySettings:
|
|
def test_returns_all_none_when_env_file_does_not_exist(self) -> None:
|
|
result = get_current_proxy_settings()
|
|
|
|
assert all(value is None for value in result.values())
|
|
|
|
def test_returns_dict_with_all_supported_keys(self) -> None:
|
|
result = get_current_proxy_settings()
|
|
|
|
assert set(result.keys()) == set(SUPPORTED_PROXY_VARS.keys())
|
|
|
|
def test_returns_values_from_env_file(self) -> None:
|
|
_write_env_file(
|
|
"HTTP_PROXY=http://proxy:8080\nHTTPS_PROXY=https://proxy:8443\n"
|
|
)
|
|
|
|
result = get_current_proxy_settings()
|
|
|
|
assert result["HTTP_PROXY"] == "http://proxy:8080"
|
|
assert result["HTTPS_PROXY"] == "https://proxy:8443"
|
|
|
|
def test_returns_none_for_unset_keys(self) -> None:
|
|
_write_env_file("HTTP_PROXY=http://proxy:8080\n")
|
|
|
|
result = get_current_proxy_settings()
|
|
|
|
assert result["HTTP_PROXY"] == "http://proxy:8080"
|
|
assert result["HTTPS_PROXY"] is None
|
|
assert result["ALL_PROXY"] is None
|
|
|
|
def test_ignores_non_proxy_vars_in_env_file(self) -> None:
|
|
_write_env_file("HTTP_PROXY=http://proxy:8080\nOTHER_VAR=ignored\n")
|
|
|
|
result = get_current_proxy_settings()
|
|
|
|
assert "OTHER_VAR" not in result
|
|
assert result["HTTP_PROXY"] == "http://proxy:8080"
|
|
|
|
def test_handles_values_with_special_characters(self) -> None:
|
|
_write_env_file("HTTP_PROXY=http://user:p@ss@proxy:8080\n")
|
|
|
|
result = get_current_proxy_settings()
|
|
|
|
assert result["HTTP_PROXY"] == "http://user:p@ss@proxy:8080"
|
|
|
|
def test_returns_all_none_when_env_file_read_fails(
|
|
self, monkeypatch: pytest.MonkeyPatch
|
|
) -> None:
|
|
_write_env_file("HTTP_PROXY=http://proxy:8080\n")
|
|
|
|
def raise_error(*args, **kwargs):
|
|
raise OSError("Permission denied")
|
|
|
|
monkeypatch.setattr("vibe.core.proxy_setup.dotenv_values", raise_error)
|
|
|
|
result = get_current_proxy_settings()
|
|
|
|
assert all(value is None for value in result.values())
|
|
|
|
|
|
class TestSetProxyVar:
|
|
def test_sets_valid_proxy_var(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://proxy:8080")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] == "http://proxy:8080"
|
|
|
|
@pytest.mark.parametrize("key", SUPPORTED_PROXY_VARS.keys())
|
|
def test_sets_all_supported_vars(self, key: str) -> None:
|
|
set_proxy_var(key, "test-value")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result[key] == "test-value"
|
|
|
|
def test_uppercases_key_before_validation(self) -> None:
|
|
set_proxy_var("http_proxy", "http://proxy:8080")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] == "http://proxy:8080"
|
|
|
|
def test_raises_error_for_unknown_key(self) -> None:
|
|
with pytest.raises(ProxySetupError) as exc_info:
|
|
set_proxy_var("UNKNOWN_KEY", "value")
|
|
|
|
assert "Unknown key 'UNKNOWN_KEY'" in str(exc_info.value)
|
|
|
|
def test_error_message_contains_supported_keys(self) -> None:
|
|
with pytest.raises(ProxySetupError) as exc_info:
|
|
set_proxy_var("UNKNOWN_KEY", "value")
|
|
|
|
error_msg = str(exc_info.value)
|
|
assert "HTTP_PROXY" in error_msg
|
|
assert "HTTPS_PROXY" in error_msg
|
|
|
|
def test_creates_env_file_if_missing(self) -> None:
|
|
assert not GLOBAL_ENV_FILE.path.exists()
|
|
|
|
set_proxy_var("HTTP_PROXY", "http://proxy:8080")
|
|
|
|
assert GLOBAL_ENV_FILE.path.exists()
|
|
|
|
def test_overwrites_existing_value(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://old:8080")
|
|
set_proxy_var("HTTP_PROXY", "http://new:8080")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] == "http://new:8080"
|
|
|
|
def test_preserves_other_values(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://proxy:8080")
|
|
set_proxy_var("HTTPS_PROXY", "https://proxy:8443")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] == "http://proxy:8080"
|
|
assert result["HTTPS_PROXY"] == "https://proxy:8443"
|
|
|
|
def test_handles_value_with_spaces(self) -> None:
|
|
set_proxy_var("NO_PROXY", "localhost, 127.0.0.1, .local")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["NO_PROXY"] == "localhost, 127.0.0.1, .local"
|
|
|
|
def test_handles_url_with_credentials(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://user:password@proxy:8080")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] == "http://user:password@proxy:8080"
|
|
|
|
|
|
class TestUnsetProxyVar:
|
|
def test_removes_existing_var(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://proxy:8080")
|
|
unset_proxy_var("HTTP_PROXY")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] is None
|
|
|
|
def test_uppercases_key_before_validation(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://proxy:8080")
|
|
unset_proxy_var("http_proxy")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] is None
|
|
|
|
def test_raises_error_for_unknown_key(self) -> None:
|
|
with pytest.raises(ProxySetupError) as exc_info:
|
|
unset_proxy_var("UNKNOWN_KEY")
|
|
|
|
assert "Unknown key 'UNKNOWN_KEY'" in str(exc_info.value)
|
|
|
|
def test_error_message_contains_supported_keys(self) -> None:
|
|
with pytest.raises(ProxySetupError) as exc_info:
|
|
unset_proxy_var("UNKNOWN_KEY")
|
|
|
|
error_msg = str(exc_info.value)
|
|
assert "HTTP_PROXY" in error_msg
|
|
|
|
def test_no_op_when_env_file_does_not_exist(self) -> None:
|
|
assert not GLOBAL_ENV_FILE.path.exists()
|
|
|
|
unset_proxy_var("HTTP_PROXY")
|
|
|
|
assert not GLOBAL_ENV_FILE.path.exists()
|
|
|
|
def test_no_op_when_key_not_in_file(self) -> None:
|
|
set_proxy_var("HTTPS_PROXY", "https://proxy:8443")
|
|
unset_proxy_var("HTTP_PROXY")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] is None
|
|
assert result["HTTPS_PROXY"] == "https://proxy:8443"
|
|
|
|
def test_preserves_other_values(self) -> None:
|
|
set_proxy_var("HTTP_PROXY", "http://proxy:8080")
|
|
set_proxy_var("HTTPS_PROXY", "https://proxy:8443")
|
|
unset_proxy_var("HTTP_PROXY")
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result["HTTP_PROXY"] is None
|
|
assert result["HTTPS_PROXY"] == "https://proxy:8443"
|
|
|
|
@pytest.mark.parametrize("key", SUPPORTED_PROXY_VARS.keys())
|
|
def test_all_supported_vars_can_be_unset(self, key: str) -> None:
|
|
set_proxy_var(key, "test-value")
|
|
unset_proxy_var(key)
|
|
|
|
result = get_current_proxy_settings()
|
|
assert result[key] is None
|
|
|
|
|
|
class TestParseProxyCommand:
|
|
def test_parses_key_only(self) -> None:
|
|
key, value = parse_proxy_command("HTTP_PROXY")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
assert value is None
|
|
|
|
def test_parses_key_and_value(self) -> None:
|
|
key, value = parse_proxy_command("HTTP_PROXY http://proxy:8080")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
assert value == "http://proxy:8080"
|
|
|
|
def test_uppercases_key(self) -> None:
|
|
key, value = parse_proxy_command("http_proxy")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
|
|
def test_preserves_value_case(self) -> None:
|
|
key, value = parse_proxy_command("HTTP_PROXY http://Proxy:8080")
|
|
|
|
assert value == "http://Proxy:8080"
|
|
|
|
def test_strips_leading_whitespace(self) -> None:
|
|
key, value = parse_proxy_command(" HTTP_PROXY")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
|
|
def test_strips_trailing_whitespace(self) -> None:
|
|
key, value = parse_proxy_command("HTTP_PROXY ")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
assert value is None
|
|
|
|
def test_splits_on_first_space_only(self) -> None:
|
|
key, value = parse_proxy_command("NO_PROXY localhost, 127.0.0.1, .local")
|
|
|
|
assert key == "NO_PROXY"
|
|
assert value == "localhost, 127.0.0.1, .local"
|
|
|
|
def test_raises_error_for_empty_string(self) -> None:
|
|
with pytest.raises(ProxySetupError) as exc_info:
|
|
parse_proxy_command("")
|
|
|
|
assert "No key provided" in str(exc_info.value)
|
|
|
|
def test_raises_error_for_whitespace_only(self) -> None:
|
|
with pytest.raises(ProxySetupError) as exc_info:
|
|
parse_proxy_command(" ")
|
|
|
|
assert "No key provided" in str(exc_info.value)
|
|
|
|
def test_handles_tab_as_separator(self) -> None:
|
|
key, value = parse_proxy_command("HTTP_PROXY\thttp://proxy:8080")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
assert value == "http://proxy:8080"
|
|
|
|
def test_handles_multiple_spaces_as_separator(self) -> None:
|
|
key, value = parse_proxy_command("HTTP_PROXY http://proxy:8080")
|
|
|
|
assert key == "HTTP_PROXY"
|
|
assert value == "http://proxy:8080"
|