cpp-mcp/test/test_mcp_tool.cpp

211 lines
7.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* @file test_mcp_tool.cpp
* @brief 测试MCP工具相关功能
*
* 本文件包含对MCP工具模块的单元测试基于规范2024-11-05。
*/
#include "mcp_tool.h"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <string>
// 测试工具结构体
TEST(McpToolTest, ToolStructTest) {
// 创建一个工具
mcp::tool tool;
tool.name = "test_tool";
tool.description = "测试工具";
tool.parameters_schema = {
{"type", "object"},
{"properties", {
{"param1", {
{"type", "string"},
{"description", "第一个参数"}
}},
{"param2", {
{"type", "number"},
{"description", "第二个参数"}
}}
}},
{"required", {"param1"}}
};
// 验证工具属性
EXPECT_EQ(tool.name, "test_tool");
EXPECT_EQ(tool.description, "测试工具");
// 验证转换为JSON
mcp::json json_tool = tool.to_json();
EXPECT_EQ(json_tool["name"], "test_tool");
EXPECT_EQ(json_tool["description"], "测试工具");
EXPECT_EQ(json_tool["parameters"]["type"], "object");
EXPECT_EQ(json_tool["parameters"]["properties"]["param1"]["type"], "string");
EXPECT_EQ(json_tool["parameters"]["properties"]["param1"]["description"], "第一个参数");
EXPECT_EQ(json_tool["parameters"]["properties"]["param2"]["type"], "number");
EXPECT_EQ(json_tool["parameters"]["required"][0], "param1");
}
// 测试工具构建器
TEST(McpToolTest, ToolBuilderTest) {
// 使用构建器创建工具
mcp::tool_builder builder("calculator");
mcp::tool tool = builder
.with_description("计算器工具")
.with_string_param("operation", "操作类型 (add, subtract, multiply, divide)")
.with_number_param("a", "第一个操作数")
.with_number_param("b", "第二个操作数")
.with_boolean_param("round_result", "是否四舍五入结果", false)
.build();
// 验证工具属性
EXPECT_EQ(tool.name, "calculator");
EXPECT_EQ(tool.description, "计算器工具");
// 验证参数架构
EXPECT_EQ(tool.parameters_schema["type"], "object");
// 验证参数属性
auto& properties = tool.parameters_schema["properties"];
EXPECT_EQ(properties["operation"]["type"], "string");
EXPECT_EQ(properties["operation"]["description"], "操作类型 (add, subtract, multiply, divide)");
EXPECT_EQ(properties["a"]["type"], "number");
EXPECT_EQ(properties["a"]["description"], "第一个操作数");
EXPECT_EQ(properties["b"]["type"], "number");
EXPECT_EQ(properties["b"]["description"], "第二个操作数");
EXPECT_EQ(properties["round_result"]["type"], "boolean");
EXPECT_EQ(properties["round_result"]["description"], "是否四舍五入结果");
// 验证必需参数
auto& required = tool.parameters_schema["required"];
EXPECT_THAT(required, ::testing::UnorderedElementsAre("operation", "a", "b"));
EXPECT_THAT(required, ::testing::Not(::testing::Contains("round_result")));
}
// 测试数组参数
TEST(McpToolTest, ArrayParamTest) {
// 使用构建器创建带有数组参数的工具
mcp::tool tool = mcp::tool_builder("list_processor")
.with_description("处理列表")
.with_array_param("items", "要处理的项目列表", "string")
.build();
// 验证数组参数
auto& properties = tool.parameters_schema["properties"];
EXPECT_EQ(properties["items"]["type"], "array");
EXPECT_EQ(properties["items"]["description"], "要处理的项目列表");
EXPECT_EQ(properties["items"]["items"]["type"], "string");
}
// 测试对象参数
TEST(McpToolTest, ObjectParamTest) {
// 创建对象属性
mcp::json user_properties = {
{"name", {
{"type", "string"},
{"description", "用户名"}
}},
{"age", {
{"type", "number"},
{"description", "年龄"}
}}
};
// 使用构建器创建带有对象参数的工具
mcp::tool tool = mcp::tool_builder("user_processor")
.with_description("处理用户信息")
.with_object_param("user", "用户对象", user_properties)
.build();
// 验证对象参数
auto& properties = tool.parameters_schema["properties"];
EXPECT_EQ(properties["user"]["type"], "object");
EXPECT_EQ(properties["user"]["description"], "用户对象");
EXPECT_EQ(properties["user"]["properties"]["name"]["type"], "string");
EXPECT_EQ(properties["user"]["properties"]["name"]["description"], "用户名");
EXPECT_EQ(properties["user"]["properties"]["age"]["type"], "number");
EXPECT_EQ(properties["user"]["properties"]["age"]["description"], "年龄");
}
// 测试工具注册表
TEST(McpToolTest, ToolRegistryTest) {
// 获取工具注册表实例
mcp::tool_registry& registry = mcp::tool_registry::instance();
// 创建一个测试工具
mcp::tool test_tool = mcp::tool_builder("test_registry_tool")
.with_description("测试注册表工具")
.with_string_param("input", "输入字符串")
.build();
// 创建一个处理函数
mcp::tool_handler handler = [](const mcp::json& params) -> mcp::json {
std::string input = params["input"];
return {{"output", "处理结果: " + input}};
};
// 注册工具
registry.register_tool(test_tool, handler);
// 获取所有工具
auto tools = registry.get_all_tools();
// 验证工具是否已注册
bool found = false;
for (const auto& tool : tools) {
if (tool.name == "test_registry_tool") {
found = true;
EXPECT_EQ(tool.description, "测试注册表工具");
break;
}
}
EXPECT_TRUE(found);
// 获取特定工具
auto tool_pair = registry.get_tool("test_registry_tool");
ASSERT_NE(tool_pair, nullptr);
EXPECT_EQ(tool_pair->first.name, "test_registry_tool");
// 调用工具
mcp::json call_params = {{"input", "测试输入"}};
mcp::json result = registry.call_tool("test_registry_tool", call_params);
EXPECT_EQ(result["output"], "处理结果: 测试输入");
// 注销工具
bool unregistered = registry.unregister_tool("test_registry_tool");
EXPECT_TRUE(unregistered);
// 验证工具已被注销
tool_pair = registry.get_tool("test_registry_tool");
EXPECT_EQ(tool_pair, nullptr);
}
// 测试create_tool辅助函数
TEST(McpToolTest, CreateToolHelperTest) {
// 使用辅助函数创建工具
std::vector<std::tuple<std::string, std::string, std::string, bool>> params = {
{"name", "姓名", "string", true},
{"age", "年龄", "number", true},
{"is_active", "是否活跃", "boolean", false}
};
mcp::tool tool = mcp::create_tool("user_tool", "用户工具", params);
// 验证工具属性
EXPECT_EQ(tool.name, "user_tool");
EXPECT_EQ(tool.description, "用户工具");
// 验证参数
auto& properties = tool.parameters_schema["properties"];
EXPECT_EQ(properties["name"]["type"], "string");
EXPECT_EQ(properties["name"]["description"], "姓名");
EXPECT_EQ(properties["age"]["type"], "number");
EXPECT_EQ(properties["age"]["description"], "年龄");
EXPECT_EQ(properties["is_active"]["type"], "boolean");
EXPECT_EQ(properties["is_active"]["description"], "是否活跃");
// 验证必需参数
auto& required = tool.parameters_schema["required"];
EXPECT_THAT(required, ::testing::UnorderedElementsAre("name", "age"));
EXPECT_THAT(required, ::testing::Not(::testing::Contains("is_active")));
}