Files
cad-agent/tests/test_cad_tools.py
T

107 lines
4.0 KiB
Python
Raw Normal View History

"""`dwg_review.cad_tools` 单元测试。"""
from dwg_review.cad_tools import READ_ONLY_TOOLS, CadTools, is_write_tool
from dwg_review.mcp_client import result_json
from tests.fakes import FakeMcpClient, ok_text, tool_schema
# ---------------------------------------------------------------------------
# 写类工具判定
# ---------------------------------------------------------------------------
def test_write_prefixes_detected():
for name in ("add_leader_annotation", "delete_entities", "draw_line", "set_layer"):
assert is_write_tool(name) is True
def test_write_exact_names_detected():
assert is_write_tool("set_entity_properties") is True
assert is_write_tool("highlight_entities") is True
def test_readonly_tools_are_not_write():
for name in ("query_entities", "get_text_content", "zoom_to_window",
"find_zero_length", "find_collisions"):
assert is_write_tool(name) is False
def test_find_collisions_is_whitelisted():
assert "find_collisions" in READ_ONLY_TOOLS
# ---------------------------------------------------------------------------
# 注册表
# ---------------------------------------------------------------------------
def test_registry_built_from_client():
client = FakeMcpClient()
tools = CadTools(client)
assert "query_entities" in tools.names
assert tools.has("get_viewport_screenshot") is True
assert tools.has("__nope__") is False
assert tools.names == sorted(tools.names)
def test_describe_returns_tool_dict():
client = FakeMcpClient()
tools = CadTools(client)
desc = tools.describe("query_entities")
assert desc["name"] == "query_entities"
assert "inputSchema" in desc
def test_refresh_picks_up_new_tools():
client = FakeMcpClient(tools=[tool_schema("a")])
tools = CadTools(client)
assert tools.names == ["a"]
client._tools = [tool_schema("a"), tool_schema("b")]
tools.refresh()
assert tools.names == ["a", "b"]
# ---------------------------------------------------------------------------
# openai_tools
# ---------------------------------------------------------------------------
def test_openai_tools_format():
client = FakeMcpClient(tools=[tool_schema("query_entities", "查询", {"window": {"type": "object"}})])
entry = CadTools(client).openai_tools()[0]
assert entry["type"] == "function"
assert entry["function"]["name"] == "query_entities"
assert entry["function"]["description"] == "查询"
assert entry["function"]["parameters"]["properties"] == {"window": {"type": "object"}}
def test_openai_tools_defaults_schema_when_missing():
client = FakeMcpClient(tools=[{"name": "bare", "description": ""}])
entry = CadTools(client).openai_tools()[0]
assert entry["function"]["parameters"] == {"type": "object", "properties": {}}
def test_openai_tools_names_filter():
client = FakeMcpClient()
names = CadTools(client).openai_tools(names={"query_entities", "get_layers"})
assert sorted(n["function"]["name"] for n in names) == ["get_layers", "query_entities"]
# ---------------------------------------------------------------------------
# call
# ---------------------------------------------------------------------------
def test_call_returns_normalized_response():
client = FakeMcpClient(responses={"query_entities": ok_text({"total": 7})})
tools = CadTools(client)
assert result_json(tools.call("query_entities", {"window": {}})) == {"total": 7}
assert client.calls[-1]["name"] == "query_entities"
assert client.calls[-1]["arguments"] == {"window": {}}
def test_call_marks_write_tools():
client = FakeMcpClient()
tools = CadTools(client)
tools.call("add_leader_annotation", {"text": "x"})
tools.call("query_entities", {"window": {}})
assert client.calls[0]["is_write"] is True
assert client.calls[1]["is_write"] is False
def test_call_explicit_is_write_overrides_inference():
client = FakeMcpClient()
CadTools(client).call("query_entities", {}, is_write=True)
assert client.calls[-1]["is_write"] is True