MCPcopy Create free account
hub / github.com/ClickHouse/ai-sdk-cpp / TEST_P

Function TEST_P

tests/integration/multi_step_duplicate_execution_test.cpp:57–129  ·  view source on GitHub ↗

Test that tools are executed only once per step in multi-step mode

Source from the content-addressed store, hash-verified

55
56// Test that tools are executed only once per step in multi-step mode
57TEST_P(MultiStepDuplicateExecutionTest, ToolsExecutedOncePerStepNotTwice) {
58 if (!use_real_api_) {
59 GTEST_SKIP() << "No API key set for " << GetParam();
60 }
61
62 // Create a shared counter to track tool executions
63 auto execution_count = std::make_shared<std::atomic<int>>(0);
64
65 // Create a tool that increments the counter each time it's called
66 Tool counter_tool = create_simple_tool(
67 "get_counter", "Returns the current count", {{"message", "string"}},
68 [execution_count](const JsonValue& args,
69 const ToolExecutionContext& context) {
70 int count = execution_count->fetch_add(1) + 1;
71 std::string message = args["message"].get<std::string>();
72 ai::logger::log_info("Counter tool executed! Count: {}, Message: {}",
73 count, message);
74 return JsonValue{{"count", count}, {"message", message}};
75 });
76
77 ToolSet tools = {{"get_counter", counter_tool}};
78
79 // Configure options with multi-step mode enabled (max_steps > 1)
80 GenerateOptions options(model_,
81 "Please use the get_counter tool with message "
82 "'test' to get the current count.");
83 options.tools = tools;
84 options.max_steps = 2; // Enable multi-step mode
85 options.max_tokens = 300;
86
87 // Reset counter before test
88 execution_count->store(0);
89
90 // Execute the request
91 auto result = client_->generate_text(options);
92
93 // Verify result is successful
94 EXPECT_TRUE(result.is_success())
95 << "Expected successful result but got error: " << result.error_message();
96
97 // Verify the tool was called
98 EXPECT_TRUE(result.has_tool_calls()) << "Expected tool calls to be made";
99 EXPECT_GT(result.tool_calls.size(), 0) << "Expected at least one tool call";
100
101 // Verify tool results exist
102 EXPECT_TRUE(result.has_tool_results())
103 << "Expected tool results to be present";
104
105 // Log the execution count
106 int final_count = execution_count->load();
107 ai::logger::log_info(
108 "Final execution count: {} (expected 1 per tool call, got {})",
109 final_count, result.tool_calls.size());
110
111 // CRITICAL ASSERTION: Each tool call should be executed exactly once
112 // If this fails, it means tools are being executed multiple times
113 EXPECT_EQ(final_count, static_cast<int>(result.tool_calls.size()))
114 << "Tool execution count (" << final_count

Callers

nothing calls this directly

Calls 7

create_simple_toolFunction · 0.85
log_infoFunction · 0.85
generate_textMethod · 0.45
is_successMethod · 0.45
error_messageMethod · 0.45
has_tool_callsMethod · 0.45
has_tool_resultsMethod · 0.45

Tested by

no test coverage detected