Something went wrong. Try again.
A single-model (Bonsai-27B) inference engine for Intel Arc GPUs
Something went wrong. Try again.
C++
at extra-debug
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168/* M3.4 gate: unit-test the tool-call block parser (qxmx_tool_call.h). * * ./tool_call_test (no args, no GPU, no model) * * Covers: string/number/bool/object parameter values, multi-line values, * quoted strings, multiple <function> blocks in one TC pair, parameterless * calls, and the malformed structures that must fall back to plain content. * Exits non-zero on the first failing check. */#include "qxmx_tool_call.h"
#include <cstdio>#include <string>#include <vector>
using namespace qx;
static int failures = 0;
#define CHECK(cond, msg) \ do { \ if (!(cond)) { \ std::fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, \ msg); \ failures++; \ } \ } while (0)
/* Parse body, requiring success; returns the calls (fatal-checks count). */static std::vector<chat_tool_call> must_parse(const std::string& body, size_t expect_n) { std::vector<chat_tool_call> calls; bool ok = parse_tool_call_block(body, &calls); CHECK(ok, "parse_tool_call_block returned false"); CHECK(calls.size() == expect_n, "wrong number of parsed calls"); return calls;}
/* Re-parse an arguments string and fetch one key (nullptr if absent). */static const jval* arg_of(const std::string& args_json, const char* key, jval& storage) { if (!jparse(args_json, storage) || storage.t != jval::OBJ) return nullptr; return storage.find(key);}
int main() { /* 1. simple call: string + number + bool + object values */ { std::string body = "\n<function=get_weather>\n" "<parameter=city>\nParis\n</parameter>\n" "<parameter=days>\n3\n</parameter>\n" "<parameter=metric>\ntrue\n</parameter>\n" "<parameter=options>\n{\"wind\": true, \"hours\": [1, 2]}\n</parameter>\n" "</function>\n"; auto calls = must_parse(body, 1); if (!calls.empty()) { CHECK(calls[0].name == "get_weather", "name mismatch"); jval a; const jval* city = arg_of(calls[0].arguments_json, "city", a); CHECK(city && city->t == jval::STR && city->s == "Paris", "city not a string 'Paris'"); const jval* days = arg_of(calls[0].arguments_json, "days", a); CHECK(days && days->t == jval::NUM && days->s == "3", "days not number 3"); const jval* metric = arg_of(calls[0].arguments_json, "metric", a); CHECK(metric && metric->t == jval::BOOL && metric->b, "metric not bool true"); const jval* opts = arg_of(calls[0].arguments_json, "options", a); CHECK(opts && opts->t == jval::OBJ && opts->find("wind") && opts->find("hours"), "options not an object"); } }
/* 2. multi-line value keeps interior newlines */ { std::string body = "\n<function=write_file>\n" "<parameter=text>\nline one\nline two\nline three\n</parameter>\n" "</function>\n"; auto calls = must_parse(body, 1); if (!calls.empty()) { jval a; const jval* t = arg_of(calls[0].arguments_json, "text", a); CHECK(t && t->t == jval::STR && t->s == "line one\nline two\nline three", "multi-line value mangled"); } }
/* 3. quoted string stays a string; bare word stays a string */ { std::string body = "\n<function=f>\n" "<parameter=a>\n\"quoted\"\n</parameter>\n" "<parameter=b>\nParis, Texas\n</parameter>\n" "</function>\n"; auto calls = must_parse(body, 1); if (!calls.empty()) { jval a; const jval* qa = arg_of(calls[0].arguments_json, "a", a); CHECK(qa && qa->t == jval::STR && qa->s == "quoted", "quoted string mismatch"); const jval* qb = arg_of(calls[0].arguments_json, "b", a); CHECK(qb && qb->t == jval::STR && qb->s == "Paris, Texas", "bare string mismatch"); } }
/* 4. two <function> blocks in one TC pair (parallel calls) */ { std::string body = "\n<function=f1>\n<parameter=x>\n1\n</parameter>\n</function>\n" "<function=f2>\n<parameter=y>\n2\n</parameter>\n</function>\n"; auto calls = must_parse(body, 2); if (calls.size() == 2) { CHECK(calls[0].name == "f1" && calls[1].name == "f2", "parallel call names mismatch"); } }
/* 5. parameterless call -> "{}" */ { std::string body = "\n<function=no_args>\n</function>\n"; auto calls = must_parse(body, 1); if (!calls.empty()) CHECK(calls[0].arguments_json == "{}", "empty args not {}"); }
/* 6. malformed blocks must return false and leave out unchanged */ { const char* bad[] = { "", /* empty */ "\nno function here\n", /* no <function= */ "\n<function=>\nx\n</function>\n", /* empty name */ "\n<function=f\n", /* unclosed name */ "\n<function=f>\n<parameter=k>\nv\n</function>\n", /* unclosed param */ "\n<function=f>\n<parameter=>\nv\n</parameter>\n</function>\n", /* empty key */ "\n<function=f>\n", /* no </function> */ }; for (const char* b : bad) { std::vector<chat_tool_call> calls; CHECK(!parse_tool_call_block(b, &calls) && calls.empty(), "malformed block parsed"); } }
/* 7. empty-parameter edge: <parameter=k>\n\n</parameter> -> "" */ { std::string body = "\n<function=f>\n<parameter=k>\n\n</parameter>\n</function>\n"; auto calls = must_parse(body, 1); if (!calls.empty()) { jval a; const jval* k = arg_of(calls[0].arguments_json, "k", a); CHECK(k && k->t == jval::STR && k->s.empty(), "empty param not empty string"); } }
if (failures) { std::fprintf(stderr, "tool_call_test: %d FAILURE(S)\n", failures); return 1; } std::printf("tool_call_test: all checks passed\n"); return 0;}