"""Tests for tool filtering module.""" import pytest from gitea_mcp_remote.filtering import ToolFilter class TestToolFilter: """Test ToolFilter class.""" def test_init_with_both_lists_logs_warning(self, caplog): """Test that specifying both enabled and disabled lists logs warning.""" import logging with caplog.at_level(logging.WARNING): filter = ToolFilter(enabled_tools=["tool1"], disabled_tools=["tool2"]) assert "Both enabled_tools and disabled_tools specified" in caplog.text assert "Disabled list takes precedence" in caplog.text # Verify disabled list takes precedence assert not filter.should_include_tool("tool2") def test_passthrough_mode(self): """Test passthrough mode (no filtering).""" filter = ToolFilter() assert filter.should_include_tool("any_tool") assert filter.should_include_tool("another_tool") stats = filter.get_filter_stats() assert stats["mode"] == "passthrough" def test_whitelist_mode(self): """Test whitelist mode (enabled_tools).""" filter = ToolFilter(enabled_tools=["tool1", "tool2"]) assert filter.should_include_tool("tool1") assert filter.should_include_tool("tool2") assert not filter.should_include_tool("tool3") assert not filter.should_include_tool("tool4") stats = filter.get_filter_stats() assert stats["mode"] == "whitelist" assert stats["enabled_count"] == 2 assert "tool1" in stats["enabled_tools"] assert "tool2" in stats["enabled_tools"] def test_blacklist_mode(self): """Test blacklist mode (disabled_tools).""" filter = ToolFilter(disabled_tools=["tool1", "tool2"]) assert not filter.should_include_tool("tool1") assert not filter.should_include_tool("tool2") assert filter.should_include_tool("tool3") assert filter.should_include_tool("tool4") stats = filter.get_filter_stats() assert stats["mode"] == "blacklist" assert stats["disabled_count"] == 2 assert "tool1" in stats["disabled_tools"] assert "tool2" in stats["disabled_tools"] def test_filter_tools_list(self): """Test filtering a list of tool definitions.""" filter = ToolFilter(enabled_tools=["tool1", "tool3"]) tools = [ {"name": "tool1", "description": "First tool"}, {"name": "tool2", "description": "Second tool"}, {"name": "tool3", "description": "Third tool"}, {"name": "tool4", "description": "Fourth tool"}, ] filtered = filter.filter_tools_list(tools) assert len(filtered) == 2 assert filtered[0]["name"] == "tool1" assert filtered[1]["name"] == "tool3" def test_filter_tools_response(self): """Test filtering an MCP list_tools response.""" filter = ToolFilter(disabled_tools=["tool2"]) response = { "tools": [ {"name": "tool1", "description": "First tool"}, {"name": "tool2", "description": "Second tool"}, {"name": "tool3", "description": "Third tool"}, ], "other_data": "preserved", } filtered = filter.filter_tools_response(response) assert len(filtered["tools"]) == 2 assert filtered["tools"][0]["name"] == "tool1" assert filtered["tools"][1]["name"] == "tool3" assert filtered["other_data"] == "preserved" def test_filter_tools_response_no_tools_key(self): """Test filtering response without 'tools' key.""" filter = ToolFilter(enabled_tools=["tool1"]) response = {"other_data": "value"} filtered = filter.filter_tools_response(response) assert filtered == response def test_filter_tools_response_immutable(self): """Test that original response is not mutated.""" filter = ToolFilter(enabled_tools=["tool1"]) original = { "tools": [ {"name": "tool1"}, {"name": "tool2"}, ] } filtered = filter.filter_tools_response(original) # Original should still have 2 tools assert len(original["tools"]) == 2 # Filtered should have 1 tool assert len(filtered["tools"]) == 1 def test_empty_tool_list(self): """Test filtering empty tool list.""" filter = ToolFilter(enabled_tools=["tool1"]) result = filter.filter_tools_list([]) assert result == [] def test_tool_with_no_name(self): """Test handling tool without name field.""" filter = ToolFilter(enabled_tools=["tool1"]) tools = [ {"name": "tool1"}, {"description": "No name"}, {"name": "tool2"}, ] filtered = filter.filter_tools_list(tools) # Only tool1 should match, tool without name is excluded assert len(filtered) == 1 assert filtered[0]["name"] == "tool1"