W21: anthropic Stream+Tools + --prompt batch + sanitizer fix + plugin unit tests (W21.1-W21.6)
- W21.1: ci-sanitize preset 独立 Linux-clang + ci-threadsan (TSan) - W21.2: anthropic tool_use content_block 解析 + configure 缓存 tools_json - W21.3: --prompt 非交互批处理模式 - W21.4: session auto-save 失败告警 + 当前目录 fallback - W21.5: smoke 补 tool_calls 边界用例 4 块 12 断言 - W21.6: anthropic 11 块 78 CHECK + deepseek 12 块 78 CHECK Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,13 @@ static int g_regression_failures = 0;
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// ---- W21.5 mock tool handler (qa-xu) ----
|
||||
static int g_mock_tool_called = 0;
|
||||
static char* mock_tool_handler(const char* /*args_json*/) {
|
||||
g_mock_tool_called++;
|
||||
return dstalk_strdup("{\"mock_result\":\"ok\"}");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const auto dir = std::filesystem::temp_directory_path() / "dstalk-smoke-test";
|
||||
@@ -560,6 +567,103 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// W21.5 Tool Calls 边界测试 (qa-xu 徐磊)
|
||||
// 覆盖: null tool_calls_json / 空数组 "[]" / 有效 tool_calls mock 验证
|
||||
// ========================================================================
|
||||
std::cout << "\n--- Tool Calls Boundary Tests (W21.5) ---\n";
|
||||
|
||||
if (tools && session) {
|
||||
// ---- W21.5-1: null tool_calls_json → 正常处理(不崩溃)----
|
||||
{
|
||||
int before = 0;
|
||||
session->history(&before);
|
||||
|
||||
dstalk_message_t msg_null_tc = {
|
||||
"assistant", "content with null tool_calls_json", nullptr, nullptr
|
||||
};
|
||||
session->add(&msg_null_tc);
|
||||
|
||||
int after = 0;
|
||||
const dstalk_message_t* hist = session->history(&after);
|
||||
REGCHECK(after == before + 1,
|
||||
"W21.5-1a: null tool_calls_json add — count +1 (no crash)");
|
||||
if (hist && after > 0) {
|
||||
REGCHECK(hist[after - 1].tool_calls_json == nullptr,
|
||||
"W21.5-1b: null tool_calls_json — retrieved field is nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
// ---- W21.5-2: 空 JSON 数组 "[]" → 正常处理(不崩溃)----
|
||||
{
|
||||
int before = 0;
|
||||
session->history(&before);
|
||||
|
||||
dstalk_message_t msg_empty = {
|
||||
"assistant", "content with empty [] tool_calls", nullptr, "[]"
|
||||
};
|
||||
session->add(&msg_empty);
|
||||
|
||||
int after = 0;
|
||||
const dstalk_message_t* hist = session->history(&after);
|
||||
REGCHECK(after == before + 1,
|
||||
"W21.5-2a: empty [] tool_calls_json add — count +1 (no crash)");
|
||||
if (hist && after > 0) {
|
||||
REGCHECK(hist[after - 1].tool_calls_json != nullptr &&
|
||||
std::strcmp(hist[after - 1].tool_calls_json, "[]") == 0,
|
||||
"W21.5-2b: empty [] tool_calls_json — retrieved as \"[]\"");
|
||||
}
|
||||
}
|
||||
|
||||
// ---- W21.5-3: 有效 tool_calls JSON → 验证 execute 被调用 (mock) ----
|
||||
{
|
||||
g_mock_tool_called = 0;
|
||||
int reg = tools->register_tool(
|
||||
"__w21_5_mock",
|
||||
"W21.5 mock tool for boundary test",
|
||||
"{}",
|
||||
mock_tool_handler
|
||||
);
|
||||
REGCHECK(reg == 0, "W21.5-3a: register mock tool ok");
|
||||
|
||||
char* result = tools->execute("__w21_5_mock", "{}");
|
||||
REGCHECK(g_mock_tool_called == 1,
|
||||
"W21.5-3b: mock tool handler was called (execute works)");
|
||||
if (result) {
|
||||
REGCHECK(std::strstr(result, "mock_result") != nullptr,
|
||||
"W21.5-3c: execute returned mock result json");
|
||||
dstalk_free(result);
|
||||
}
|
||||
|
||||
tools->unregister_tool("__w21_5_mock");
|
||||
|
||||
// 验证已注销的工具返回 error 而非崩溃
|
||||
char* err_result = tools->execute("__w21_5_mock", "{}");
|
||||
REGCHECK(err_result && std::strstr(err_result, "error") != nullptr,
|
||||
"W21.5-3d: unregistered tool returns error (not crash)");
|
||||
if (err_result) dstalk_free(err_result);
|
||||
}
|
||||
|
||||
// ---- W21.5-4: save/load 往返保留 tool_calls_json ----
|
||||
if (file_io) {
|
||||
const auto rtt_path = dir / "w21_5_tc_rtt.jsonl";
|
||||
int ret = session->save(rtt_path.string().c_str());
|
||||
REGCHECK(ret == 0, "W21.5-4a: session save with tool_calls msgs ok");
|
||||
|
||||
session->clear();
|
||||
ret = session->load(rtt_path.string().c_str());
|
||||
REGCHECK(ret == 0, "W21.5-4b: session load round-trip ok");
|
||||
|
||||
int count = 0;
|
||||
session->history(&count);
|
||||
REGCHECK(count > 0, "W21.5-4c: history non-empty after load round-trip");
|
||||
}
|
||||
|
||||
session->clear();
|
||||
} else {
|
||||
std::cerr << "[WARN] W21.5: tools or session service not available\n";
|
||||
}
|
||||
|
||||
// 清理
|
||||
dstalk_shutdown();
|
||||
std::cout << "[OK] dstalk_shutdown succeeded\n";
|
||||
|
||||
Reference in New Issue
Block a user