free-claude-code/tests/test_config.py
Cursor Agent 1cface7f8c Fix all ty check errors without using type: ignore
- messaging/telegram.py: Remove unused type: ignore, fix retry_after typing
  with isinstance(timedelta), use local app variable for None narrowing
- messaging/tree_data.py: Replace _queue._queue access with drain-and-restore
  approach for get_queue_snapshot (avoids private API)
- tests/test_api.py: Use APIError instead of RuntimeError for status_code test
- tests/test_config.py: Use cast(Any, ...) for invalid validation tests
- tests/test_dependencies.py: Add isinstance check for NvidiaNimProvider
- tests/test_handler_markdown_and_status_edges.py: Use patch.object for
  tree_queue method mocks
- tests/test_response_models.py: Add isinstance narrowing for content blocks,
  use Literal list for stop_reason parametrization
- tests/test_restart_reply_restore.py: Use patch.object for enqueue mock
- tests/test_server_module.py: Use patch.object for uvicorn.run and
  get_settings
- tests/test_telegram_edge_cases.py: Use patch.object for method mocks
- tests/test_tree_concurrency.py: Add None assertions for get_node/get_tree

Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
2026-02-15 02:28:33 +00:00

220 lines
7.3 KiB
Python

"""Tests for config/settings.py and config/nim.py"""
import pytest
from pydantic import ValidationError
from config.nim import NimSettings
class TestSettings:
"""Test Settings configuration."""
def test_settings_loads(self):
"""Ensure Settings can be instantiated."""
from config.settings import Settings
settings = Settings()
assert settings is not None
def test_default_values(self):
"""Test default values are set and have correct types."""
from config.settings import Settings
settings = Settings()
assert isinstance(settings.nvidia_nim_rate_limit, int)
assert isinstance(settings.nvidia_nim_rate_window, int)
assert isinstance(settings.nim.temperature, float)
assert isinstance(settings.fast_prefix_detection, bool)
assert isinstance(settings.max_cli_sessions, int)
def test_get_settings_cached(self):
"""Test get_settings returns cached instance."""
from config.settings import get_settings
s1 = get_settings()
s2 = get_settings()
assert s1 is s2 # Same object (cached)
def test_empty_string_to_none_for_optional_int(self):
"""Test that empty string converts to None for optional int fields."""
from config.settings import Settings
# Settings should handle NVIDIA_NIM_SEED="" gracefully
settings = Settings()
assert settings.nim.seed is None or isinstance(settings.nim.seed, int)
def test_model_setting(self):
"""Test model setting exists and is a string."""
from config.settings import Settings
settings = Settings()
assert isinstance(settings.model, str)
assert len(settings.model) > 0
def test_base_url_constant(self):
"""Test NVIDIA_NIM_BASE_URL is a constant."""
from config.settings import NVIDIA_NIM_BASE_URL
assert NVIDIA_NIM_BASE_URL == "https://integrate.api.nvidia.com/v1"
# --- NimSettings Validation Tests ---
class TestNimSettingsValidBounds:
"""Test that valid values within bounds are accepted."""
@pytest.mark.parametrize("top_k", [-1, 0, 1, 100])
def test_top_k_valid(self, top_k):
"""top_k >= -1 should be accepted."""
s = NimSettings(top_k=top_k)
assert s.top_k == top_k
@pytest.mark.parametrize("temp", [0.0, 0.5, 1.0, 2.0])
def test_temperature_valid(self, temp):
s = NimSettings(temperature=temp)
assert s.temperature == temp
@pytest.mark.parametrize("top_p", [0.0, 0.5, 1.0])
def test_top_p_valid(self, top_p):
s = NimSettings(top_p=top_p)
assert s.top_p == top_p
@pytest.mark.parametrize("effort", ["low", "medium", "high"])
def test_reasoning_effort_valid(self, effort):
s = NimSettings(reasoning_effort=effort)
assert s.reasoning_effort == effort
def test_max_tokens_valid(self):
s = NimSettings(max_tokens=1)
assert s.max_tokens == 1
def test_min_tokens_valid(self):
s = NimSettings(min_tokens=0)
assert s.min_tokens == 0
@pytest.mark.parametrize("penalty", [-2.0, 0.0, 2.0])
def test_presence_penalty_valid(self, penalty):
s = NimSettings(presence_penalty=penalty)
assert s.presence_penalty == penalty
@pytest.mark.parametrize("penalty", [-2.0, 0.0, 2.0])
def test_frequency_penalty_valid(self, penalty):
s = NimSettings(frequency_penalty=penalty)
assert s.frequency_penalty == penalty
@pytest.mark.parametrize("min_p", [0.0, 0.5, 1.0])
def test_min_p_valid(self, min_p):
s = NimSettings(min_p=min_p)
assert s.min_p == min_p
class TestNimSettingsInvalidBounds:
"""Test that out-of-range values raise ValidationError."""
@pytest.mark.parametrize("top_k", [-2, -100])
def test_top_k_below_lower_bound(self, top_k):
with pytest.raises((ValidationError, ValueError)):
NimSettings(top_k=top_k)
def test_temperature_negative(self):
with pytest.raises(ValidationError):
NimSettings(temperature=-0.1)
@pytest.mark.parametrize("top_p", [-0.1, 1.1])
def test_top_p_out_of_range(self, top_p):
with pytest.raises(ValidationError):
NimSettings(top_p=top_p)
@pytest.mark.parametrize("penalty", [-2.1, 2.1])
def test_presence_penalty_out_of_range(self, penalty):
with pytest.raises(ValidationError):
NimSettings(presence_penalty=penalty)
@pytest.mark.parametrize("penalty", [-2.1, 2.1])
def test_frequency_penalty_out_of_range(self, penalty):
with pytest.raises(ValidationError):
NimSettings(frequency_penalty=penalty)
@pytest.mark.parametrize("min_p", [-0.1, 1.1])
def test_min_p_out_of_range(self, min_p):
with pytest.raises(ValidationError):
NimSettings(min_p=min_p)
@pytest.mark.parametrize("max_tokens", [0, -1])
def test_max_tokens_too_low(self, max_tokens):
with pytest.raises(ValidationError):
NimSettings(max_tokens=max_tokens)
def test_min_tokens_negative(self):
with pytest.raises(ValidationError):
NimSettings(min_tokens=-1)
def test_reasoning_effort_invalid(self):
from typing import Any, cast
with pytest.raises(ValidationError):
NimSettings(reasoning_effort=cast(Any, "invalid"))
class TestNimSettingsValidators:
"""Test custom field validators in NimSettings."""
@pytest.mark.parametrize(
"seed_val,expected",
[("", None), (None, None), ("42", 42), (42, 42)],
ids=["empty_str", "none", "str_42", "int_42"],
)
def test_parse_optional_int(self, seed_val, expected):
s = NimSettings(seed=seed_val)
assert s.seed == expected
@pytest.mark.parametrize(
"stop_val,expected",
[("", None), ("STOP", "STOP"), (None, None)],
ids=["empty_str", "valid", "none"],
)
def test_parse_optional_str_stop(self, stop_val, expected):
s = NimSettings(stop=stop_val)
assert s.stop == expected
@pytest.mark.parametrize(
"chat_template_val,expected",
[("", None), ("template", "template")],
ids=["empty_str", "valid"],
)
def test_parse_optional_str_chat_template(self, chat_template_val, expected):
s = NimSettings(chat_template=chat_template_val)
assert s.chat_template == expected
def test_extra_forbid_rejects_unknown_field(self):
"""NimSettings with extra='forbid' rejects unknown fields."""
from typing import Any, cast
with pytest.raises(ValidationError):
NimSettings(**cast(Any, {"unknown_field": "value"}))
class TestSettingsOptionalStr:
"""Test Settings parse_optional_str validator."""
def test_empty_telegram_token_to_none(self, monkeypatch):
from config.settings import Settings
monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "")
s = Settings()
assert s.telegram_bot_token is None
def test_valid_telegram_token_preserved(self, monkeypatch):
from config.settings import Settings
monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "abc123")
s = Settings()
assert s.telegram_bot_token == "abc123"
def test_empty_allowed_user_id_to_none(self, monkeypatch):
from config.settings import Settings
monkeypatch.setenv("ALLOWED_TELEGRAM_USER_ID", "")
s = Settings()
assert s.allowed_telegram_user_id is None