Improved test coverage

This commit is contained in:
Alishahryar1
2026-02-16 15:58:16 -08:00
parent b4b902619d
commit b8d1bfecbb
11 changed files with 1328 additions and 0 deletions
+143
View File
@@ -210,3 +210,146 @@ def test_app_lifespan_cleanup_continues_if_platform_stop_raises(tmp_path):
fake_platform.stop.assert_awaited_once()
cli_manager.stop_all.assert_awaited_once()
cleanup_provider.assert_awaited_once()
def test_app_lifespan_messaging_import_error_no_crash(tmp_path, caplog):
"""Messaging import failure logs warning and continues without crash."""
from api.app import create_app
app = create_app()
settings = SimpleNamespace(
messaging_platform="telegram",
telegram_bot_token="token",
allowed_telegram_user_id="123",
discord_bot_token=None,
allowed_discord_channels=None,
allowed_dir=str(tmp_path / "workspace"),
claude_workspace=str(tmp_path / "data"),
host="127.0.0.1",
port=8082,
max_cli_sessions=1,
log_file=str(tmp_path / "server.log"),
)
api_app_mod = importlib.import_module("api.app")
cleanup_provider = AsyncMock()
with (
patch.object(api_app_mod, "get_settings", return_value=settings),
patch.object(api_app_mod, "cleanup_provider", new=cleanup_provider),
patch(
"messaging.factory.create_messaging_platform",
side_effect=ImportError("discord not installed"),
),
):
with TestClient(app):
pass
assert getattr(app.state, "messaging_platform", None) is None
cleanup_provider.assert_awaited_once()
def test_app_lifespan_platform_start_exception_cleanup_still_runs(tmp_path):
"""Exception during platform.start() logs error, cleanup still runs."""
from api.app import create_app
app = create_app()
settings = SimpleNamespace(
messaging_platform="telegram",
telegram_bot_token="token",
allowed_telegram_user_id="123",
discord_bot_token=None,
allowed_discord_channels=None,
allowed_dir=str(tmp_path / "workspace"),
claude_workspace=str(tmp_path / "data"),
host="127.0.0.1",
port=8082,
max_cli_sessions=1,
log_file=str(tmp_path / "server.log"),
)
fake_platform = MagicMock()
fake_platform.name = "fake"
fake_platform.on_message = MagicMock()
fake_platform.start = AsyncMock(side_effect=RuntimeError("start failed"))
fake_platform.stop = AsyncMock()
session_store = MagicMock()
session_store.get_all_trees.return_value = []
session_store.get_node_mapping.return_value = {}
session_store.sync_from_tree_data = MagicMock()
cli_manager = MagicMock()
cli_manager.stop_all = AsyncMock()
api_app_mod = importlib.import_module("api.app")
cleanup_provider = AsyncMock()
with (
patch.object(api_app_mod, "get_settings", return_value=settings),
patch.object(api_app_mod, "cleanup_provider", new=cleanup_provider),
patch(
"messaging.factory.create_messaging_platform",
return_value=fake_platform,
),
patch("messaging.session.SessionStore", return_value=session_store),
patch("cli.manager.CLISessionManager", return_value=cli_manager),
):
with TestClient(app):
pass
cleanup_provider.assert_awaited_once()
def test_app_lifespan_flush_pending_save_exception_warning_only(tmp_path):
"""Session store flush exception on shutdown is logged as warning, no crash."""
from api.app import create_app
app = create_app()
settings = SimpleNamespace(
messaging_platform="telegram",
telegram_bot_token="token",
allowed_telegram_user_id="123",
discord_bot_token=None,
allowed_discord_channels=None,
allowed_dir=str(tmp_path / "workspace"),
claude_workspace=str(tmp_path / "data"),
host="127.0.0.1",
port=8082,
max_cli_sessions=1,
log_file=str(tmp_path / "server.log"),
)
fake_platform = MagicMock()
fake_platform.name = "fake"
fake_platform.on_message = MagicMock()
fake_platform.start = AsyncMock()
fake_platform.stop = AsyncMock()
session_store = MagicMock()
session_store.get_all_trees.return_value = []
session_store.get_node_mapping.return_value = {}
session_store.sync_from_tree_data = MagicMock()
session_store.flush_pending_save = MagicMock(side_effect=IOError("disk full"))
cli_manager = MagicMock()
cli_manager.stop_all = AsyncMock()
api_app_mod = importlib.import_module("api.app")
cleanup_provider = AsyncMock()
with (
patch.object(api_app_mod, "get_settings", return_value=settings),
patch.object(api_app_mod, "cleanup_provider", new=cleanup_provider),
patch(
"messaging.factory.create_messaging_platform",
return_value=fake_platform,
),
patch("messaging.session.SessionStore", return_value=session_store),
patch("cli.manager.CLISessionManager", return_value=cli_manager),
):
with TestClient(app):
pass
session_store.flush_pending_save.assert_called_once()
cleanup_provider.assert_awaited_once()
+80
View File
@@ -0,0 +1,80 @@
"""Edge case tests for api/detection.py."""
from unittest.mock import patch
from api.detection import (
is_prefix_detection_request,
is_filepath_extraction_request,
)
from api.models.anthropic import MessagesRequest, Message
def _make_request(content: str, **kwargs) -> MessagesRequest:
return MessagesRequest(
model="claude-3-sonnet",
max_tokens=100,
messages=[Message(role="user", content=content)],
**kwargs,
)
class TestIsPrefixDetectionRequest:
def test_output_marker_handling(self):
"""Content with Command: but Output: after cmd_start; output has < or \\n\\n."""
content = "<policy_spec> Command:\nls -la\nOutput:\na.txt\nb.txt\n\nmore"
req = _make_request(content)
is_req, cmd = is_prefix_detection_request(req)
assert is_req is True
assert "ls -la" in cmd
def test_prefix_detection_with_empty_command_section(self):
"""Command: at end with no content returns empty command."""
req = _make_request("<policy_spec> Command: ")
is_req, cmd = is_prefix_detection_request(req)
assert is_req is True
assert cmd == ""
def test_exception_in_try_returns_false(self):
"""Exception in try block (e.g. content slice) returns False, ''."""
req = _make_request("<policy_spec> Command: x")
# Return object that raises when sliced - triggers except in is_prefix_detection_request
class BadStr(str):
def __getitem__(self, key):
raise TypeError("bad slice")
with patch(
"api.detection.extract_text_from_content",
return_value=BadStr("<policy_spec> Command: x"),
):
is_req, cmd = is_prefix_detection_request(req)
assert is_req is False
assert cmd == ""
class TestIsFilepathExtractionRequest:
def test_output_marker_minus_one_returns_false(self):
"""Output: not found after Command: returns False."""
content = "Command:\nls\nfilepaths"
req = _make_request(content)
is_fp, cmd, out = is_filepath_extraction_request(req)
assert is_fp is False
assert cmd == ""
assert out == ""
def test_output_has_angle_bracket_splits(self):
"""Output containing < is split and first part used."""
content = "Command:\nls\nOutput:\na.txt b.txt <extra>\nfilepaths"
req = _make_request(content)
is_fp, cmd, out = is_filepath_extraction_request(req)
assert is_fp is True
assert "<" not in out
assert out == "a.txt b.txt"
def test_output_has_double_newline_splits(self):
"""Output containing \\n\\n is split and first part used."""
content = "Command:\nls\nOutput:\na.txt\nb.txt\n\nmore text\nfilepaths"
req = _make_request(content)
is_fp, cmd, out = is_filepath_extraction_request(req)
assert is_fp is True
assert "more" not in out
+201
View File
@@ -0,0 +1,201 @@
"""Tests for messaging/discord_markdown.py."""
from messaging.discord_markdown import (
escape_discord,
escape_discord_code,
discord_bold,
discord_code_inline,
format_status_discord,
format_status,
render_markdown_to_discord,
_is_gfm_table_header_line,
_normalize_gfm_tables,
)
class TestEscapeDiscord:
"""Tests for escape_discord."""
def test_empty_string(self):
assert escape_discord("") == ""
def test_plain_text_unchanged(self):
assert escape_discord("hello world") == "hello world"
def test_special_chars_escaped(self):
for ch in "\\*_`~|>":
assert escape_discord(ch) == f"\\{ch}"
def test_mixed_special_and_plain(self):
assert escape_discord("a*b_c") == "a\\*b\\_c"
def test_unicode_preserved(self):
assert escape_discord("café 日本語") == "café 日本語"
class TestEscapeDiscordCode:
"""Tests for escape_discord_code."""
def test_empty_string(self):
assert escape_discord_code("") == ""
def test_backslash_escaped(self):
assert escape_discord_code("\\") == "\\\\"
def test_backtick_escaped(self):
assert escape_discord_code("`") == "\\`"
def test_both_escaped(self):
assert escape_discord_code("`\\") == "\\`\\\\"
class TestDiscordBold:
"""Tests for discord_bold."""
def test_simple(self):
assert discord_bold("hello") == "**hello**"
def test_escapes_inner(self):
assert discord_bold("a*b") == "**a\\*b**"
class TestDiscordCodeInline:
"""Tests for discord_code_inline."""
def test_simple(self):
assert discord_code_inline("x") == "`x`"
def test_escapes_backtick(self):
assert discord_code_inline("`") == "`\\``"
class TestFormatStatusDiscord:
"""Tests for format_status_discord."""
def test_label_only(self):
assert format_status_discord("Running") == "**Running**"
def test_label_with_suffix(self):
# Parentheses not in DISCORD_SPECIAL, so unchanged
assert (
format_status_discord("Queued", "(position 2)") == "**Queued** (position 2)"
)
class TestFormatStatus:
"""Tests for format_status."""
def test_label_only(self):
assert format_status("🔄", "Running") == "🔄 **Running**"
def test_label_with_suffix(self):
assert format_status("", "Waiting", "5/10") == "⏳ **Waiting** 5/10"
class TestIsGfmTableHeaderLine:
"""Tests for _is_gfm_table_header_line."""
def test_no_pipe_returns_false(self):
assert _is_gfm_table_header_line("hello world") is False
def test_separator_only_returns_false(self):
assert _is_gfm_table_header_line("|---|") is False
assert _is_gfm_table_header_line("|:---|:---|") is False
def test_valid_header(self):
assert _is_gfm_table_header_line("| A | B |") is True
assert _is_gfm_table_header_line("A | B") is True
def test_single_column_returns_false(self):
assert _is_gfm_table_header_line("| A |") is False
class TestNormalizeGfmTables:
"""Tests for _normalize_gfm_tables."""
def test_single_line_unchanged(self):
assert _normalize_gfm_tables("hello") == "hello"
def test_two_lines_no_table_unchanged(self):
assert _normalize_gfm_tables("a\nb") == "a\nb"
def test_table_gets_blank_line_before(self):
text = "para\n| A | B |\n|---|\n| 1 | 2 |"
result = _normalize_gfm_tables(text)
assert "para" in result
assert "| A | B |" in result
def test_table_inside_fence_unchanged(self):
text = "```\n| A | B |\n|---|\n```"
result = _normalize_gfm_tables(text)
assert result == text
class TestRenderMarkdownToDiscord:
"""Tests for render_markdown_to_discord."""
def test_empty_string(self):
assert render_markdown_to_discord("") == ""
def test_plain_paragraph(self):
assert "hello" in render_markdown_to_discord("hello")
def test_headings(self):
result = render_markdown_to_discord("# Title\n## Sub")
assert "Title" in result
assert "Sub" in result
def test_bold_italic(self):
result = render_markdown_to_discord("**bold** *italic*")
assert "bold" in result
assert "italic" in result
def test_strikethrough(self):
result = render_markdown_to_discord("~~strike~~")
assert "strike" in result
def test_inline_code(self):
result = render_markdown_to_discord("use `code` here")
assert "`" in result
assert "code" in result
def test_code_block(self):
result = render_markdown_to_discord("```\nprint(1)\n```")
assert "print(1)" in result
assert "```" in result
def test_blockquote(self):
result = render_markdown_to_discord("> quote")
assert "quote" in result
def test_bullet_list(self):
result = render_markdown_to_discord("- a\n- b")
assert "a" in result
assert "b" in result
def test_ordered_list(self):
result = render_markdown_to_discord("1. first\n2. second")
assert "first" in result
assert "second" in result
def test_link(self):
result = render_markdown_to_discord("[text](https://example.com)")
assert "text" in result
assert "https://example.com" in result
def test_image_with_alt(self):
result = render_markdown_to_discord("![alt](https://img.png)")
assert "alt" in result
assert "https://img.png" in result
def test_image_without_alt(self):
result = render_markdown_to_discord("![](https://img.png)")
assert "https://img.png" in result
def test_gfm_table(self):
text = "| A | B |\n|---|---|\n| 1 | 2 |"
result = render_markdown_to_discord(text)
assert "A" in result
assert "B" in result
assert "1" in result
assert "2" in result
+267
View File
@@ -1,15 +1,29 @@
"""Tests for Discord platform adapter."""
import asyncio
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from messaging.discord import (
DiscordPlatform,
_parse_allowed_channels,
_get_discord,
DISCORD_AVAILABLE,
)
class TestGetDiscord:
"""Tests for _get_discord helper."""
def test_raises_when_discord_not_available(self):
import messaging.discord as discord_mod
with patch.object(discord_mod, "DISCORD_AVAILABLE", False):
with patch.object(discord_mod, "_discord_module", None):
with pytest.raises(ImportError, match="discord.py is required"):
_get_discord()
class TestParseAllowedChannels:
"""Tests for _parse_allowed_channels helper."""
@@ -17,6 +31,9 @@ class TestParseAllowedChannels:
assert _parse_allowed_channels("") == set()
assert _parse_allowed_channels(None) == set()
def test_whitespace_only_returns_empty_set(self):
assert _parse_allowed_channels(" ") == set()
def test_single_channel(self):
assert _parse_allowed_channels("123456789") == {"123456789"}
@@ -66,6 +83,22 @@ class TestDiscordPlatform:
short = "hello"
assert platform._truncate(short) == short
def test_truncate_exactly_at_limit_unchanged(self):
platform = DiscordPlatform(bot_token="token")
exact = "x" * 2000
assert platform._truncate(exact) == exact
def test_truncate_one_over_limit_truncates(self):
platform = DiscordPlatform(bot_token="token")
over = "x" * 2001
result = platform._truncate(over)
assert len(result) == 2000
assert result.endswith("...")
def test_truncate_empty_string(self):
platform = DiscordPlatform(bot_token="token")
assert platform._truncate("") == ""
@pytest.mark.asyncio
async def test_send_message_returns_message_id(self):
platform = DiscordPlatform(bot_token="token")
@@ -92,3 +125,237 @@ class TestDiscordPlatform:
):
await platform.edit_message("123", "456", "Updated text")
mock_msg.edit.assert_called_once_with(content="Updated text")
@pytest.mark.asyncio
async def test_send_message_channel_not_found_raises(self):
platform = DiscordPlatform(bot_token="token")
platform._connected = True
with patch.object(
platform._client, "get_channel", MagicMock(return_value=None)
):
with pytest.raises(RuntimeError, match="Channel"):
await platform.send_message("123", "Hello")
@pytest.mark.asyncio
async def test_send_message_channel_no_send_raises(self):
platform = DiscordPlatform(bot_token="token")
platform._connected = True
mock_channel = MagicMock(spec=[]) # No send attr
with patch.object(
platform._client, "get_channel", MagicMock(return_value=mock_channel)
):
with pytest.raises(RuntimeError, match="Channel"):
await platform.send_message("123", "Hello")
@pytest.mark.asyncio
async def test_queue_send_message_without_limiter_calls_send_message(self):
platform = DiscordPlatform(bot_token="token")
platform._limiter = None
platform._connected = True
mock_channel = AsyncMock()
mock_msg = MagicMock()
mock_msg.id = 42
mock_channel.send = AsyncMock(return_value=mock_msg)
with patch.object(
platform._client, "get_channel", MagicMock(return_value=mock_channel)
):
result = await platform.queue_send_message("123", "hi")
assert result == "42"
mock_channel.send.assert_awaited_once()
@pytest.mark.asyncio
async def test_queue_edit_message_without_limiter_calls_edit_message(self):
platform = DiscordPlatform(bot_token="token")
platform._limiter = None
platform._connected = True
mock_msg = AsyncMock()
mock_channel = AsyncMock()
mock_channel.fetch_message = AsyncMock(return_value=mock_msg)
with patch.object(
platform._client, "get_channel", MagicMock(return_value=mock_channel)
):
await platform.queue_edit_message("123", "456", "Updated")
mock_msg.edit.assert_called_once_with(content="Updated")
@pytest.mark.asyncio
async def test_on_discord_message_bot_ignored(self):
platform = DiscordPlatform(bot_token="token", allowed_channel_ids="123")
handler = AsyncMock()
platform.on_message(handler)
msg = MagicMock()
msg.author.bot = True
msg.content = "hello"
msg.channel.id = 123
await platform._on_discord_message(msg)
handler.assert_not_called()
@pytest.mark.asyncio
async def test_on_discord_message_empty_content_ignored(self):
platform = DiscordPlatform(bot_token="token", allowed_channel_ids="123")
handler = AsyncMock()
platform.on_message(handler)
msg = MagicMock()
msg.author.bot = False
msg.content = ""
msg.channel.id = 123
await platform._on_discord_message(msg)
handler.assert_not_called()
@pytest.mark.asyncio
async def test_on_discord_message_channel_not_allowed_ignored(self):
platform = DiscordPlatform(bot_token="token", allowed_channel_ids="123")
handler = AsyncMock()
platform.on_message(handler)
msg = MagicMock()
msg.author.bot = False
msg.content = "hello"
msg.channel.id = 999
await platform._on_discord_message(msg)
handler.assert_not_called()
@pytest.mark.asyncio
async def test_on_discord_message_valid_calls_handler(self):
platform = DiscordPlatform(bot_token="token", allowed_channel_ids="123")
handler = AsyncMock()
platform.on_message(handler)
msg = MagicMock()
msg.author.bot = False
msg.author.id = 456
msg.author.display_name = "User"
msg.content = "hello"
msg.channel.id = 123
msg.id = 789
msg.reference = None
await platform._on_discord_message(msg)
handler.assert_awaited_once()
call = handler.call_args[0][0]
assert call.text == "hello"
assert call.chat_id == "123"
assert call.user_id == "456"
assert call.message_id == "789"
assert call.platform == "discord"
@pytest.mark.asyncio
async def test_send_message_with_reply_to(self):
platform = DiscordPlatform(bot_token="token")
mock_msg = MagicMock()
mock_msg.id = 999
mock_channel = AsyncMock()
mock_channel.send = AsyncMock(return_value=mock_msg)
platform._connected = True
with patch.object(
platform._client, "get_channel", MagicMock(return_value=mock_channel)
):
with patch("messaging.discord._get_discord") as mock_get:
mock_discord = MagicMock()
mock_get.return_value = mock_discord
msg_id = await platform.send_message("123", "Hello", reply_to="456")
assert msg_id == "999"
mock_channel.send.assert_awaited_once()
call_kw = mock_channel.send.call_args[1]
assert call_kw.get("reference") is not None
@pytest.mark.asyncio
async def test_edit_message_not_found_returns_gracefully(self):
import discord as discord_pkg
platform = DiscordPlatform(bot_token="token")
mock_channel = AsyncMock()
mock_resp = MagicMock()
mock_resp.status = 404
mock_channel.fetch_message = AsyncMock(
side_effect=discord_pkg.NotFound(mock_resp, "Not found")
)
platform._connected = True
with patch.object(
platform._client, "get_channel", MagicMock(return_value=mock_channel)
):
await platform.edit_message("123", "456", "Updated")
# Should not raise - NotFound is caught and we return
@pytest.mark.asyncio
async def test_delete_message(self):
platform = DiscordPlatform(bot_token="token")
mock_msg = AsyncMock()
mock_channel = AsyncMock()
mock_channel.fetch_message = AsyncMock(return_value=mock_msg)
platform._connected = True
with patch.object(
platform._client, "get_channel", MagicMock(return_value=mock_channel)
):
with patch("messaging.discord._get_discord") as mock_get:
mock_get.return_value = MagicMock()
await platform.delete_message("123", "456")
mock_msg.delete.assert_awaited_once()
@pytest.mark.asyncio
async def test_fire_and_forget_with_coroutine(self):
platform = DiscordPlatform(bot_token="token")
async def _task():
pass
coro = _task()
with patch("asyncio.create_task") as mock_create:
def _run(c):
return asyncio.ensure_future(c)
mock_create.side_effect = _run
platform.fire_and_forget(coro)
mock_create.assert_called_once()
await asyncio.sleep(0)
def test_on_message_registers_handler(self):
platform = DiscordPlatform(bot_token="token")
handler = AsyncMock()
platform.on_message(handler)
assert platform._message_handler is handler
@pytest.mark.asyncio
async def test_start_requires_token(self):
with patch.dict("os.environ", {"DISCORD_BOT_TOKEN": ""}, clear=False):
platform = DiscordPlatform(bot_token="")
with pytest.raises(ValueError, match="DISCORD_BOT_TOKEN"):
await platform.start()
@pytest.mark.asyncio
async def test_start_connects(self):
platform = DiscordPlatform(bot_token="token")
async def _fake_start(_token):
platform._connected = True
with patch.object(
platform._client, "start", new_callable=AsyncMock, side_effect=_fake_start
):
with patch(
"messaging.limiter.MessagingRateLimiter.get_instance",
new_callable=AsyncMock,
):
await platform.start()
assert platform.is_connected is True
@pytest.mark.asyncio
async def test_stop_when_already_closed(self):
platform = DiscordPlatform(bot_token="token")
platform._connected = True
with patch.object(
platform._client, "is_closed", new_callable=MagicMock, return_value=True
):
await platform.stop()
assert platform.is_connected is False
@pytest.mark.asyncio
async def test_stop_closes_client(self):
platform = DiscordPlatform(bot_token="token")
platform._connected = True
mock_close = AsyncMock()
with patch.object(
platform._client, "is_closed", new_callable=MagicMock, return_value=False
):
with patch.object(platform._client, "close", mock_close):
platform._start_task = None
await platform.stop()
mock_close.assert_awaited_once()
assert platform.is_connected is False
+41
View File
@@ -11,6 +11,47 @@ def handler(mock_platform, mock_cli_manager, mock_session_store):
return ClaudeMessageHandler(mock_platform, mock_cli_manager, mock_session_store)
def test_get_initial_status_new_conversation_with_slot(handler):
"""New conversation when slots available returns launching message."""
handler.cli_manager.get_stats.return_value = {
"active_sessions": 0,
"max_sessions": 5,
}
result = handler._get_initial_status(None, None)
assert "Launching" in result
def test_get_initial_status_new_conversation_at_capacity(handler):
"""New conversation at capacity returns waiting message."""
handler.cli_manager.get_stats.return_value = {
"active_sessions": 5,
"max_sessions": 5,
}
result = handler._get_initial_status(None, None)
assert "Waiting" in result
assert "5/5" in result
def test_get_initial_status_reply_tree_busy_queued(handler):
"""Reply to tree when busy returns queued message."""
mock_queue = MagicMock()
mock_queue.is_node_tree_busy.return_value = True
mock_queue.get_queue_size.return_value = 2
handler.tree_queue = mock_queue
result = handler._get_initial_status(MagicMock(), "parent_1")
assert "Queued" in result
assert "position 3" in result
def test_get_initial_status_reply_tree_not_busy_continuing(handler):
"""Reply to tree when not busy returns continuing message."""
mock_queue = MagicMock()
mock_queue.is_node_tree_busy.return_value = False
handler.tree_queue = mock_queue
result = handler._get_initial_status(MagicMock(), "parent_1")
assert "Continuing" in result
@pytest.mark.asyncio
async def test_handle_message_stop_command(
handler, mock_platform, incoming_message_factory
+101
View File
@@ -0,0 +1,101 @@
"""Tests for providers/nvidia_nim/request.py."""
from unittest.mock import MagicMock
from providers.nvidia_nim.request import (
_set_if_not_none,
_set_extra,
build_request_body,
)
from config.nim import NimSettings
class TestSetIfNotNone:
def test_value_not_none_sets(self):
body = {}
_set_if_not_none(body, "key", "value")
assert body["key"] == "value"
def test_value_none_skips(self):
body = {}
_set_if_not_none(body, "key", None)
assert "key" not in body
class TestSetExtra:
def test_key_in_extra_body_skips(self):
extra = {"top_k": 42}
_set_extra(extra, "top_k", 10)
assert extra["top_k"] == 42
def test_value_none_skips(self):
extra = {}
_set_extra(extra, "top_k", None)
assert "top_k" not in extra
def test_value_equals_ignore_value_skips(self):
extra = {}
_set_extra(extra, "top_k", -1, ignore_value=-1)
assert "top_k" not in extra
def test_value_set_when_valid(self):
extra = {}
_set_extra(extra, "top_k", 10, ignore_value=-1)
assert extra["top_k"] == 10
class TestBuildRequestBody:
def test_max_tokens_capped_by_nim(self):
"""Request max_tokens exceeds nim.max_tokens -> capped."""
req = MagicMock()
req.model = "test"
req.messages = [MagicMock(role="user", content="hi")]
req.max_tokens = 100000
req.system = None
req.temperature = None
req.top_p = None
req.stop_sequences = None
req.tools = None
req.tool_choice = None
req.extra_body = None
req.top_k = None
nim = NimSettings(max_tokens=4096)
body = build_request_body(req, nim)
assert body["max_tokens"] == 4096
def test_presence_penalty_included_when_nonzero(self):
req = MagicMock()
req.model = "test"
req.messages = [MagicMock(role="user", content="hi")]
req.max_tokens = 100
req.system = None
req.temperature = None
req.top_p = None
req.stop_sequences = None
req.tools = None
req.tool_choice = None
req.extra_body = None
req.top_k = None
nim = NimSettings(presence_penalty=0.5)
body = build_request_body(req, nim)
assert body["presence_penalty"] == 0.5
def test_parallel_tool_calls_included(self):
req = MagicMock()
req.model = "test"
req.messages = [MagicMock(role="user", content="hi")]
req.max_tokens = 100
req.system = None
req.temperature = None
req.top_p = None
req.stop_sequences = None
req.tools = None
req.tool_choice = None
req.extra_body = None
req.top_k = None
nim = NimSettings(parallel_tool_calls=False)
body = build_request_body(req, nim)
assert body["parallel_tool_calls"] is False
+149
View File
@@ -204,3 +204,152 @@ async def test_stream_response_reasoning_content(open_router_provider):
if "Thinking..." in e:
found_thinking = True
assert found_thinking
@pytest.mark.asyncio
async def test_stream_response_empty_choices_skipped(open_router_provider):
"""Chunks with empty choices are skipped."""
req = MockRequest()
async def mock_stream():
yield MagicMock(choices=[], usage=None)
yield MagicMock(
choices=[
MagicMock(
delta=MagicMock(content="ok", reasoning_content=None),
finish_reason="stop",
)
],
usage=MagicMock(completion_tokens=2),
)
with patch.object(
open_router_provider._client.chat.completions, "create", new_callable=AsyncMock
) as mock_create:
mock_create.return_value = mock_stream()
events = []
async for event in open_router_provider.stream_response(req):
events.append(event)
assert any("content_block_delta" in e and "ok" in e for e in events)
@pytest.mark.asyncio
async def test_stream_response_delta_none_skipped(open_router_provider):
"""Chunks with delta=None are skipped."""
req = MockRequest()
async def mock_stream():
yield MagicMock(
choices=[MagicMock(delta=None, finish_reason=None)],
usage=None,
)
yield MagicMock(
choices=[
MagicMock(
delta=MagicMock(content="x", reasoning_content=None),
finish_reason="stop",
)
],
usage=MagicMock(completion_tokens=1),
)
with patch.object(
open_router_provider._client.chat.completions, "create", new_callable=AsyncMock
) as mock_create:
mock_create.return_value = mock_stream()
events = []
async for event in open_router_provider.stream_response(req):
events.append(event)
assert any("x" in e for e in events)
@pytest.mark.asyncio
async def test_stream_response_reasoning_details(open_router_provider):
"""Streaming with reasoning_details (stepfun format)."""
req = MockRequest()
mock_chunk = MagicMock()
mock_chunk.choices = [
MagicMock(
delta=MagicMock(
content=None,
reasoning_content=None,
reasoning_details=[{"text": "Step 1"}],
),
finish_reason=None,
)
]
mock_chunk.usage = None
async def mock_stream():
yield mock_chunk
yield MagicMock(
choices=[
MagicMock(
delta=MagicMock(
content=None,
reasoning_content=None,
reasoning_details=None,
),
finish_reason="stop",
)
],
usage=MagicMock(completion_tokens=5),
)
with patch.object(
open_router_provider._client.chat.completions, "create", new_callable=AsyncMock
) as mock_create:
mock_create.return_value = mock_stream()
events = []
async for event in open_router_provider.stream_response(req):
events.append(event)
assert any("Step 1" in e for e in events)
@pytest.mark.asyncio
async def test_stream_response_error_path(open_router_provider):
"""Stream raises exception -> error event emitted."""
req = MockRequest()
async def mock_stream():
raise RuntimeError("API failed")
yield # unreachable, makes it a generator
with patch.object(
open_router_provider._client.chat.completions, "create", new_callable=AsyncMock
) as mock_create:
mock_create.return_value = mock_stream()
events = []
async for event in open_router_provider.stream_response(req):
events.append(event)
# Error is emitted; message_stop/done indicates stream completed
assert any("API failed" in e for e in events)
assert any("message_stop" in e for e in events)
@pytest.mark.asyncio
async def test_stream_response_finish_reason_only(open_router_provider):
"""Chunk with finish_reason but no content still completes."""
req = MockRequest()
async def mock_stream():
yield MagicMock(
choices=[
MagicMock(
delta=MagicMock(content=None, reasoning_content=None),
finish_reason="stop",
)
],
usage=MagicMock(completion_tokens=0),
)
with patch.object(
open_router_provider._client.chat.completions, "create", new_callable=AsyncMock
) as mock_create:
mock_create.return_value = mock_stream()
events = []
async for event in open_router_provider.stream_response(req):
events.append(event)
assert any("message_delta" in e for e in events)
assert any("message_stop" in e for e in events)
+219
View File
@@ -0,0 +1,219 @@
"""Tests for api/optimization_handlers.py."""
from unittest.mock import patch
from api.optimization_handlers import (
try_prefix_detection,
try_quota_mock,
try_title_skip,
try_suggestion_skip,
try_filepath_mock,
try_optimizations,
)
from api.models.anthropic import MessagesRequest, Message, ContentBlockText
from config.settings import Settings
def _make_request(
messages_content: str, max_tokens: int | None = None
) -> MessagesRequest:
"""Create a MessagesRequest with a single user message."""
return MessagesRequest(
model="claude-3-sonnet",
max_tokens=max_tokens if max_tokens is not None else 100,
messages=[Message(role="user", content=messages_content)],
)
class TestTryPrefixDetection:
def test_disabled_returns_none(self):
settings = Settings()
settings.fast_prefix_detection = False
req = _make_request("x")
with patch(
"api.optimization_handlers.is_prefix_detection_request",
return_value=(True, "/ask"),
):
assert try_prefix_detection(req, settings) is None
def test_enabled_and_match_returns_response(self):
settings = Settings()
settings.fast_prefix_detection = True
req = _make_request("x")
with patch(
"api.optimization_handlers.is_prefix_detection_request",
return_value=(True, "/ask"),
):
with patch(
"api.optimization_handlers.extract_command_prefix",
return_value="/ask",
):
result = try_prefix_detection(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert block.text == "/ask"
def test_enabled_but_no_match_returns_none(self):
settings = Settings()
settings.fast_prefix_detection = True
req = _make_request("x")
with patch(
"api.optimization_handlers.is_prefix_detection_request",
return_value=(False, ""),
):
assert try_prefix_detection(req, settings) is None
class TestTryQuotaMock:
def test_disabled_returns_none(self):
settings = Settings()
settings.enable_network_probe_mock = False
req = _make_request("quota", max_tokens=1)
with patch(
"api.optimization_handlers.is_quota_check_request",
return_value=True,
):
assert try_quota_mock(req, settings) is None
def test_enabled_and_match_returns_response(self):
settings = Settings()
settings.enable_network_probe_mock = True
req = _make_request("quota", max_tokens=1)
with patch(
"api.optimization_handlers.is_quota_check_request",
return_value=True,
):
result = try_quota_mock(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert "Quota check passed" in block.text
class TestTryTitleSkip:
def test_disabled_returns_none(self):
settings = Settings()
settings.enable_title_generation_skip = False
req = _make_request("write a 5-10 word title")
with patch(
"api.optimization_handlers.is_title_generation_request",
return_value=True,
):
assert try_title_skip(req, settings) is None
def test_enabled_and_match_returns_response(self):
settings = Settings()
settings.enable_title_generation_skip = True
req = _make_request("x")
with patch(
"api.optimization_handlers.is_title_generation_request",
return_value=True,
):
result = try_title_skip(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert block.text == "Conversation"
class TestTrySuggestionSkip:
def test_disabled_returns_none(self):
settings = Settings()
settings.enable_suggestion_mode_skip = False
req = _make_request("[SUGGESTION MODE: x]")
with patch(
"api.optimization_handlers.is_suggestion_mode_request",
return_value=True,
):
assert try_suggestion_skip(req, settings) is None
def test_enabled_and_match_returns_response(self):
settings = Settings()
settings.enable_suggestion_mode_skip = True
req = _make_request("x")
with patch(
"api.optimization_handlers.is_suggestion_mode_request",
return_value=True,
):
result = try_suggestion_skip(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert block.text == ""
class TestTryFilepathMock:
def test_disabled_returns_none(self):
settings = Settings()
settings.enable_filepath_extraction_mock = False
req = _make_request("Command:\nls\nOutput:\nfilepaths")
with patch(
"api.optimization_handlers.is_filepath_extraction_request",
return_value=(True, "ls", "out"),
):
assert try_filepath_mock(req, settings) is None
def test_enabled_and_match_returns_response(self):
settings = Settings()
settings.enable_filepath_extraction_mock = True
req = _make_request("x")
with patch(
"api.optimization_handlers.is_filepath_extraction_request",
return_value=(True, "ls", "a.txt b.txt"),
):
with patch(
"api.optimization_handlers.extract_filepaths_from_command",
return_value="a.txt\nb.txt",
):
result = try_filepath_mock(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert block.text == "a.txt\nb.txt"
def test_extract_filepaths_empty_list_still_returns_response(self):
settings = Settings()
settings.enable_filepath_extraction_mock = True
req = _make_request("x")
with patch(
"api.optimization_handlers.is_filepath_extraction_request",
return_value=(True, "ls", "out"),
):
with patch(
"api.optimization_handlers.extract_filepaths_from_command",
return_value="",
):
result = try_filepath_mock(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert block.text == ""
class TestTryOptimizations:
def test_first_match_wins(self):
"""Quota mock is first in OPTIMIZATION_HANDLERS; it should win over prefix."""
settings = Settings()
settings.enable_network_probe_mock = True
settings.fast_prefix_detection = True
req = _make_request("quota", max_tokens=1)
with patch(
"api.optimization_handlers.is_quota_check_request",
return_value=True,
):
result = try_optimizations(req, settings)
assert result is not None
block = result.content[0]
assert isinstance(block, ContentBlockText)
assert "Quota check passed" in block.text
def test_no_match_returns_none(self):
settings = Settings()
settings.fast_prefix_detection = False
settings.enable_network_probe_mock = False
settings.enable_title_generation_skip = False
settings.enable_suggestion_mode_skip = False
settings.enable_filepath_extraction_mock = False
req = _make_request("random user message")
assert try_optimizations(req, settings) is None
+44
View File
@@ -1,4 +1,48 @@
import os
from unittest.mock import patch
def test_process_registry_register_pid_zero_noop():
"""register_pid(0) is a no-op (early return)."""
from cli import process_registry as pr
before = len(pr._pids)
pr.register_pid(0)
assert len(pr._pids) == before
def test_process_registry_unregister_pid_zero_noop():
"""unregister_pid(0) is a no-op."""
from cli import process_registry as pr
pr.register_pid(99999)
pr.unregister_pid(0)
assert 99999 in pr._pids
pr.unregister_pid(99999)
def test_process_registry_ensure_atexit_idempotent():
"""Second call to ensure_atexit_registered is idempotent."""
from cli import process_registry as pr
pr.ensure_atexit_registered()
pr.ensure_atexit_registered()
# Should not raise; atexit handler registered once
def test_process_registry_kill_all_exception_logged_no_raise(monkeypatch):
"""Exception in os.kill/taskkill is logged but does not raise."""
from cli import process_registry as pr
monkeypatch.setattr(pr, "_pids", {99999})
monkeypatch.setattr(os, "name", "posix", raising=False)
def _kill_raises(pid, sig):
raise ProcessLookupError("no such process")
with patch("os.kill", _kill_raises):
pr.kill_all_best_effort()
# Should not raise
def test_process_registry_register_unregister_does_not_crash():
+69
View File
@@ -183,3 +183,72 @@ class TestProviderRateLimiter:
f"Rolling window violated at i={i}: "
f"dt={acquired[i + rate_limit] - acquired[i]:.3f}s"
)
@pytest.mark.asyncio
async def test_init_rate_limit_zero_raises(self):
"""rate_limit <= 0 raises ValueError."""
GlobalRateLimiter.reset_instance()
with pytest.raises(ValueError, match="rate_limit must be > 0"):
GlobalRateLimiter(rate_limit=0, rate_window=60)
@pytest.mark.asyncio
async def test_init_rate_window_zero_raises(self):
"""rate_window <= 0 raises ValueError."""
GlobalRateLimiter.reset_instance()
with pytest.raises(ValueError, match="rate_window must be > 0"):
GlobalRateLimiter(rate_limit=10, rate_window=0)
@pytest.mark.asyncio
async def test_execute_with_retry_exhaust_retries_raises(self):
"""When all 429 retries exhausted, last exception is raised."""
import openai
from httpx import Response, Request
GlobalRateLimiter.reset_instance()
limiter = GlobalRateLimiter.get_instance(rate_limit=100, rate_window=60)
def make_429():
return openai.RateLimitError(
"rate limited",
response=Response(429, request=Request("POST", "http://x")),
body={},
)
async def fail():
raise make_429()
with pytest.raises(openai.RateLimitError):
await limiter.execute_with_retry(
fail, max_retries=2, base_delay=0.01, max_delay=0.1, jitter=0
)
@pytest.mark.asyncio
async def test_execute_with_retry_succeeds_on_retry(self):
"""429 then success returns result."""
import openai
from httpx import Response, Request
GlobalRateLimiter.reset_instance()
limiter = GlobalRateLimiter.get_instance(rate_limit=100, rate_window=60)
def make_429():
return openai.RateLimitError(
"rate limited",
response=Response(429, request=Request("POST", "http://x")),
body={},
)
call_count = 0
async def fail_then_ok():
nonlocal call_count
call_count += 1
if call_count == 1:
raise make_429()
return "ok"
result = await limiter.execute_with_retry(
fail_then_ok, max_retries=2, base_delay=0.01, max_delay=0.1, jitter=0
)
assert result == "ok"
assert call_count == 2
+14
View File
@@ -97,6 +97,20 @@ def test_count_tokens_endpoint(client):
assert response.json()["input_tokens"] == 5
def test_count_tokens_error_returns_500(client):
"""When get_token_count raises, count_tokens returns 500."""
payload = {
"model": "claude-3-sonnet",
"messages": [{"role": "user", "content": "hello"}],
}
with patch("api.routes.get_token_count", side_effect=RuntimeError("token error")):
response = client.post("/v1/messages/count_tokens", json=payload)
assert response.status_code == 500
assert "token error" in response.json()["detail"]
def test_stop_cli_with_handler(client):
mock_handler = MagicMock()
# Mock the async method to return a completed future or just mock it since TestClient