b4269ecd88
Tests cover: - assemble_tool_pool returns ToolPool with correct types - Default mode produces non-empty tools - simple_mode and include_mcp flags stored correctly - simple_mode reduces tool set to BashTool/FileReadTool/FileEditTool - include_mcp=False excludes MCP tools - Permission context filters blocked tools - as_markdown includes header, flags, and tool count - as_markdown shows at most 15 tools - Empty tools tuple renders correctly - Tool lines contain name and source_hint - Frozen dataclass prevents mutation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: abdoelsayed2016 <27821589+abdoelsayed2016@users.noreply.github.com>
107 lines
4.2 KiB
Python
107 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from src.models import PortingModule
|
|
from src.permissions import ToolPermissionContext
|
|
from src.tool_pool import ToolPool, assemble_tool_pool
|
|
|
|
|
|
class TestAssembleToolPool(unittest.TestCase):
|
|
def test_returns_tool_pool_with_tools(self) -> None:
|
|
pool = assemble_tool_pool()
|
|
self.assertIsInstance(pool, ToolPool)
|
|
self.assertIsInstance(pool.tools, tuple)
|
|
self.assertTrue(all(isinstance(t, PortingModule) for t in pool.tools))
|
|
|
|
def test_default_mode_includes_tools(self) -> None:
|
|
pool = assemble_tool_pool()
|
|
self.assertGreater(len(pool.tools), 0)
|
|
|
|
def test_simple_mode_flag_stored(self) -> None:
|
|
pool_default = assemble_tool_pool()
|
|
pool_simple = assemble_tool_pool(simple_mode=True)
|
|
self.assertFalse(pool_default.simple_mode)
|
|
self.assertTrue(pool_simple.simple_mode)
|
|
|
|
def test_include_mcp_flag_stored(self) -> None:
|
|
pool_default = assemble_tool_pool()
|
|
pool_no_mcp = assemble_tool_pool(include_mcp=False)
|
|
self.assertTrue(pool_default.include_mcp)
|
|
self.assertFalse(pool_no_mcp.include_mcp)
|
|
|
|
def test_simple_mode_reduces_tools(self) -> None:
|
|
pool_full = assemble_tool_pool(simple_mode=False)
|
|
pool_simple = assemble_tool_pool(simple_mode=True)
|
|
self.assertGreater(len(pool_full.tools), len(pool_simple.tools))
|
|
simple_names = {t.name for t in pool_simple.tools}
|
|
self.assertTrue(simple_names.issubset({'BashTool', 'FileReadTool', 'FileEditTool'}))
|
|
|
|
def test_include_mcp_false_excludes_mcp_tools(self) -> None:
|
|
pool = assemble_tool_pool(include_mcp=False)
|
|
for tool in pool.tools:
|
|
self.assertNotIn('mcp', tool.name.lower())
|
|
self.assertNotIn('mcp', tool.source_hint.lower())
|
|
|
|
def test_permission_context_filters_blocked_tools(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(deny_names=['BashTool'])
|
|
pool = assemble_tool_pool(permission_context=ctx)
|
|
tool_names = {t.name for t in pool.tools}
|
|
self.assertNotIn('BashTool', tool_names)
|
|
|
|
pool_unfiltered = assemble_tool_pool()
|
|
unfiltered_names = {t.name for t in pool_unfiltered.tools}
|
|
self.assertIn('BashTool', unfiltered_names)
|
|
|
|
|
|
class TestToolPoolAsMarkdown(unittest.TestCase):
|
|
def test_includes_header_and_tool_count(self) -> None:
|
|
pool = assemble_tool_pool()
|
|
md = pool.as_markdown()
|
|
self.assertIn('# Tool Pool', md)
|
|
self.assertIn(f'Tool count: {len(pool.tools)}', md)
|
|
|
|
def test_includes_mode_flags(self) -> None:
|
|
pool = assemble_tool_pool(simple_mode=True, include_mcp=False)
|
|
md = pool.as_markdown()
|
|
self.assertIn('Simple mode: True', md)
|
|
self.assertIn('Include MCP: False', md)
|
|
|
|
def test_shows_at_most_15_tools(self) -> None:
|
|
pool = assemble_tool_pool()
|
|
self.assertGreater(len(pool.tools), 15, 'Need >15 tools for this test')
|
|
md = pool.as_markdown()
|
|
tool_lines = [line for line in md.splitlines() if line.startswith('- ')]
|
|
self.assertEqual(len(tool_lines), 15)
|
|
|
|
def test_empty_tools_renders_correctly(self) -> None:
|
|
pool = ToolPool(tools=(), simple_mode=False, include_mcp=True)
|
|
md = pool.as_markdown()
|
|
self.assertIn('# Tool Pool', md)
|
|
self.assertIn('Tool count: 0', md)
|
|
self.assertIn('Simple mode: False', md)
|
|
self.assertIn('Include MCP: True', md)
|
|
tool_lines = [line for line in md.splitlines() if line.startswith('- ')]
|
|
self.assertEqual(len(tool_lines), 0)
|
|
|
|
def test_tool_lines_contain_name_and_source_hint(self) -> None:
|
|
tool = PortingModule(
|
|
name='TestTool',
|
|
responsibility='testing',
|
|
source_hint='test/path.ts',
|
|
)
|
|
pool = ToolPool(tools=(tool,), simple_mode=False, include_mcp=False)
|
|
md = pool.as_markdown()
|
|
self.assertIn('- TestTool — test/path.ts', md)
|
|
|
|
|
|
class TestToolPoolFrozen(unittest.TestCase):
|
|
def test_cannot_mutate_fields(self) -> None:
|
|
pool = ToolPool(tools=(), simple_mode=False, include_mcp=True)
|
|
with self.assertRaises(AttributeError):
|
|
pool.simple_mode = True # type: ignore[misc]
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|