diff options
Diffstat (limited to 'tests/unit/test_cvm_server.c')
| -rw-r--r-- | tests/unit/test_cvm_server.c | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/tests/unit/test_cvm_server.c b/tests/unit/test_cvm_server.c new file mode 100644 index 0000000..84583c6 --- /dev/null +++ b/tests/unit/test_cvm_server.c | |||
| @@ -0,0 +1,434 @@ | |||
| 1 | #include "test_framework.h" | ||
| 2 | #include "cJSON.h" | ||
| 3 | #include <stdbool.h> | ||
| 4 | #include <string.h> | ||
| 5 | #include <stdio.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | |||
| 8 | static char *build_initialize_response_test(const char *request_id_str) | ||
| 9 | { | ||
| 10 | cJSON *response = cJSON_CreateObject(); | ||
| 11 | cJSON_AddStringToObject(response, "jsonrpc", "2.0"); | ||
| 12 | cJSON_AddNumberToObject(response, "id", request_id_str ? atof(request_id_str) : 0); | ||
| 13 | |||
| 14 | cJSON *result = cJSON_CreateObject(); | ||
| 15 | cJSON_AddStringToObject(result, "protocolVersion", "2025-07-02"); | ||
| 16 | |||
| 17 | cJSON *capabilities = cJSON_CreateObject(); | ||
| 18 | cJSON_AddItemToObject(capabilities, "tools", cJSON_CreateObject()); | ||
| 19 | cJSON_AddItemToObject(result, "capabilities", capabilities); | ||
| 20 | |||
| 21 | cJSON *serverInfo = cJSON_CreateObject(); | ||
| 22 | cJSON_AddStringToObject(serverInfo, "name", "TollGate"); | ||
| 23 | cJSON_AddStringToObject(serverInfo, "version", "1.0.0"); | ||
| 24 | cJSON_AddItemToObject(result, "serverInfo", serverInfo); | ||
| 25 | |||
| 26 | cJSON_AddItemToObject(response, "result", result); | ||
| 27 | |||
| 28 | char *json = cJSON_PrintUnformatted(response); | ||
| 29 | cJSON_Delete(response); | ||
| 30 | return json; | ||
| 31 | } | ||
| 32 | |||
| 33 | static char *build_tools_list_response_test(const char *request_id_str) | ||
| 34 | { | ||
| 35 | cJSON *response = cJSON_CreateObject(); | ||
| 36 | cJSON_AddStringToObject(response, "jsonrpc", "2.0"); | ||
| 37 | cJSON_AddNumberToObject(response, "id", request_id_str ? atof(request_id_str) : 1); | ||
| 38 | |||
| 39 | cJSON *result = cJSON_CreateObject(); | ||
| 40 | cJSON *tools = cJSON_CreateArray(); | ||
| 41 | |||
| 42 | const char *tool_names[] = { | ||
| 43 | "get_config", "set_config", "get_balance", "wallet_send", | ||
| 44 | "get_sessions", "get_usage", "set_payout", "set_metric", | ||
| 45 | "set_price", "wallet_melt" | ||
| 46 | }; | ||
| 47 | |||
| 48 | for (int i = 0; i < 10; i++) { | ||
| 49 | cJSON *tool = cJSON_CreateObject(); | ||
| 50 | cJSON_AddStringToObject(tool, "name", tool_names[i]); | ||
| 51 | cJSON_AddItemToArray(tools, tool); | ||
| 52 | } | ||
| 53 | |||
| 54 | cJSON_AddItemToObject(result, "tools", tools); | ||
| 55 | cJSON_AddItemToObject(response, "result", result); | ||
| 56 | |||
| 57 | char *json = cJSON_PrintUnformatted(response); | ||
| 58 | cJSON_Delete(response); | ||
| 59 | return json; | ||
| 60 | } | ||
| 61 | |||
| 62 | static char *build_tool_call_response_test(const char *request_id_str, | ||
| 63 | bool success, const char *result_or_error) | ||
| 64 | { | ||
| 65 | cJSON *response = cJSON_CreateObject(); | ||
| 66 | cJSON_AddStringToObject(response, "jsonrpc", "2.0"); | ||
| 67 | cJSON_AddNumberToObject(response, "id", request_id_str ? atof(request_id_str) : 2); | ||
| 68 | |||
| 69 | if (success) { | ||
| 70 | cJSON *result = cJSON_CreateObject(); | ||
| 71 | cJSON *content_arr = cJSON_CreateArray(); | ||
| 72 | cJSON *text_item = cJSON_CreateObject(); | ||
| 73 | cJSON_AddStringToObject(text_item, "type", "text"); | ||
| 74 | cJSON_AddStringToObject(text_item, "text", result_or_error); | ||
| 75 | cJSON_AddItemToArray(content_arr, text_item); | ||
| 76 | cJSON_AddItemToObject(result, "content", content_arr); | ||
| 77 | cJSON_AddBoolToObject(result, "isError", false); | ||
| 78 | cJSON_AddItemToObject(response, "result", result); | ||
| 79 | } else { | ||
| 80 | cJSON *error = cJSON_CreateObject(); | ||
| 81 | cJSON_AddNumberToObject(error, "code", -32603); | ||
| 82 | cJSON_AddStringToObject(error, "message", result_or_error); | ||
| 83 | cJSON_AddItemToObject(response, "error", error); | ||
| 84 | } | ||
| 85 | |||
| 86 | char *json = cJSON_PrintUnformatted(response); | ||
| 87 | cJSON_Delete(response); | ||
| 88 | return json; | ||
| 89 | } | ||
| 90 | |||
| 91 | static char *build_ping_response_test(const char *request_id_str) | ||
| 92 | { | ||
| 93 | cJSON *response = cJSON_CreateObject(); | ||
| 94 | cJSON_AddStringToObject(response, "jsonrpc", "2.0"); | ||
| 95 | cJSON_AddNumberToObject(response, "id", request_id_str ? atof(request_id_str) : 0); | ||
| 96 | cJSON *result = cJSON_CreateObject(); | ||
| 97 | cJSON_AddItemToObject(response, "result", result); | ||
| 98 | char *json = cJSON_PrintUnformatted(response); | ||
| 99 | cJSON_Delete(response); | ||
| 100 | return json; | ||
| 101 | } | ||
| 102 | |||
| 103 | static char *build_announcement_11316_test(void) | ||
| 104 | { | ||
| 105 | cJSON *ann = cJSON_CreateObject(); | ||
| 106 | cJSON_AddStringToObject(ann, "protocolVersion", "2025-07-02"); | ||
| 107 | |||
| 108 | cJSON *caps = cJSON_CreateObject(); | ||
| 109 | cJSON *tools = cJSON_CreateObject(); | ||
| 110 | cJSON_AddBoolToObject(tools, "listChanged", true); | ||
| 111 | cJSON_AddItemToObject(caps, "tools", tools); | ||
| 112 | cJSON_AddItemToObject(ann, "capabilities", caps); | ||
| 113 | |||
| 114 | cJSON *info = cJSON_CreateObject(); | ||
| 115 | cJSON_AddStringToObject(info, "name", "TollGate"); | ||
| 116 | cJSON_AddStringToObject(info, "version", "1.0.0"); | ||
| 117 | cJSON_AddItemToObject(ann, "serverInfo", info); | ||
| 118 | |||
| 119 | char *json = cJSON_PrintUnformatted(ann); | ||
| 120 | cJSON_Delete(ann); | ||
| 121 | return json; | ||
| 122 | } | ||
| 123 | |||
| 124 | static char *build_announcement_11317_test(void) | ||
| 125 | { | ||
| 126 | cJSON *root = cJSON_CreateObject(); | ||
| 127 | cJSON *tools = cJSON_CreateArray(); | ||
| 128 | |||
| 129 | const char *names[] = { | ||
| 130 | "get_config", "set_config", "get_balance", "wallet_send", | ||
| 131 | "get_sessions", "get_usage", "set_payout", "set_metric", | ||
| 132 | "set_price", "wallet_melt" | ||
| 133 | }; | ||
| 134 | |||
| 135 | for (int i = 0; i < 10; i++) { | ||
| 136 | cJSON *t = cJSON_CreateObject(); | ||
| 137 | cJSON_AddStringToObject(t, "name", names[i]); | ||
| 138 | cJSON_AddStringToObject(t, "description", "test"); | ||
| 139 | cJSON *schema = cJSON_CreateObject(); | ||
| 140 | cJSON_AddStringToObject(schema, "type", "object"); | ||
| 141 | cJSON_AddItemToObject(t, "inputSchema", schema); | ||
| 142 | cJSON_AddItemToArray(tools, t); | ||
| 143 | } | ||
| 144 | |||
| 145 | cJSON_AddItemToObject(root, "tools", tools); | ||
| 146 | char *json = cJSON_PrintUnformatted(root); | ||
| 147 | cJSON_Delete(root); | ||
| 148 | return json; | ||
| 149 | } | ||
| 150 | |||
| 151 | static char *build_relay_list_10002_test(void) | ||
| 152 | { | ||
| 153 | cJSON *tags = cJSON_CreateArray(); | ||
| 154 | const char *relays[] = {"wss://relay.damus.io", "wss://nos.lol"}; | ||
| 155 | for (int i = 0; i < 2; i++) { | ||
| 156 | cJSON *r = cJSON_CreateArray(); | ||
| 157 | cJSON_AddItemToArray(r, cJSON_CreateString("r")); | ||
| 158 | cJSON_AddItemToArray(r, cJSON_CreateString(relays[i])); | ||
| 159 | cJSON_AddItemToArray(tags, r); | ||
| 160 | } | ||
| 161 | char *json = cJSON_PrintUnformatted(tags); | ||
| 162 | cJSON_Delete(tags); | ||
| 163 | return json; | ||
| 164 | } | ||
| 165 | |||
| 166 | static bool parse_mcp_from_25910(const char *content, char *method_out, size_t method_max, | ||
| 167 | char *params_out, size_t params_max) | ||
| 168 | { | ||
| 169 | cJSON *msg = cJSON_Parse(content); | ||
| 170 | if (!msg) return false; | ||
| 171 | |||
| 172 | cJSON *method = cJSON_GetObjectItem(msg, "method"); | ||
| 173 | if (!method || !cJSON_IsString(method)) { | ||
| 174 | cJSON_Delete(msg); | ||
| 175 | return false; | ||
| 176 | } | ||
| 177 | |||
| 178 | strncpy(method_out, method->valuestring, method_max - 1); | ||
| 179 | |||
| 180 | cJSON *params = cJSON_GetObjectItem(msg, "params"); | ||
| 181 | if (params) { | ||
| 182 | char *pjson = cJSON_PrintUnformatted(params); | ||
| 183 | strncpy(params_out, pjson, params_max - 1); | ||
| 184 | cJSON_free(pjson); | ||
| 185 | } | ||
| 186 | |||
| 187 | cJSON_Delete(msg); | ||
| 188 | return true; | ||
| 189 | } | ||
| 190 | |||
| 191 | static void test_initialize_response(void) | ||
| 192 | { | ||
| 193 | printf("\n=== MCP initialize response ===\n"); | ||
| 194 | char *json = build_initialize_response_test("0"); | ||
| 195 | ASSERT(json != NULL, "response created"); | ||
| 196 | |||
| 197 | cJSON *root = cJSON_Parse(json); | ||
| 198 | ASSERT(root != NULL, "valid JSON"); | ||
| 199 | ASSERT_EQ_STR("2.0", cJSON_GetObjectItem(root, "jsonrpc")->valuestring, "jsonrpc version"); | ||
| 200 | ASSERT_EQ_INT(0, (int)cJSON_GetObjectItem(root, "id")->valuedouble, "id=0"); | ||
| 201 | |||
| 202 | cJSON *result = cJSON_GetObjectItem(root, "result"); | ||
| 203 | ASSERT(result != NULL, "has result"); | ||
| 204 | ASSERT_EQ_STR("2025-07-02", cJSON_GetObjectItem(result, "protocolVersion")->valuestring, "protocol version"); | ||
| 205 | |||
| 206 | cJSON *caps = cJSON_GetObjectItem(result, "capabilities"); | ||
| 207 | ASSERT(caps != NULL, "has capabilities"); | ||
| 208 | ASSERT(cJSON_GetObjectItem(caps, "tools") != NULL, "has tools capability"); | ||
| 209 | |||
| 210 | cJSON *info = cJSON_GetObjectItem(result, "serverInfo"); | ||
| 211 | ASSERT(info != NULL, "has serverInfo"); | ||
| 212 | ASSERT_EQ_STR("TollGate", cJSON_GetObjectItem(info, "name")->valuestring, "server name"); | ||
| 213 | ASSERT_EQ_STR("1.0.0", cJSON_GetObjectItem(info, "version")->valuestring, "server version"); | ||
| 214 | |||
| 215 | cJSON_Delete(root); | ||
| 216 | free(json); | ||
| 217 | } | ||
| 218 | |||
| 219 | static void test_tools_list_response(void) | ||
| 220 | { | ||
| 221 | printf("\n=== MCP tools/list response ===\n"); | ||
| 222 | char *json = build_tools_list_response_test("1"); | ||
| 223 | ASSERT(json != NULL, "response created"); | ||
| 224 | |||
| 225 | cJSON *root = cJSON_Parse(json); | ||
| 226 | ASSERT_EQ_STR("2.0", cJSON_GetObjectItem(root, "jsonrpc")->valuestring, "jsonrpc version"); | ||
| 227 | |||
| 228 | cJSON *result = cJSON_GetObjectItem(root, "result"); | ||
| 229 | cJSON *tools = cJSON_GetObjectItem(result, "tools"); | ||
| 230 | ASSERT(tools != NULL, "has tools array"); | ||
| 231 | ASSERT_EQ_INT(10, cJSON_GetArraySize(tools), "10 tools"); | ||
| 232 | |||
| 233 | ASSERT_EQ_STR("get_config", cJSON_GetObjectItem(cJSON_GetArrayItem(tools, 0), "name")->valuestring, "tool 0"); | ||
| 234 | ASSERT_EQ_STR("wallet_melt", cJSON_GetObjectItem(cJSON_GetArrayItem(tools, 9), "name")->valuestring, "tool 9"); | ||
| 235 | |||
| 236 | cJSON_Delete(root); | ||
| 237 | free(json); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void test_tool_call_response_success(void) | ||
| 241 | { | ||
| 242 | printf("\n=== MCP tools/call success response ===\n"); | ||
| 243 | char *json = build_tool_call_response_test("2", true, "{\"balance\":500}"); | ||
| 244 | ASSERT(json != NULL, "response created"); | ||
| 245 | |||
| 246 | cJSON *root = cJSON_Parse(json); | ||
| 247 | cJSON *result = cJSON_GetObjectItem(root, "result"); | ||
| 248 | ASSERT(result != NULL, "has result"); | ||
| 249 | ASSERT(cJSON_GetObjectItem(result, "content") != NULL, "has content"); | ||
| 250 | ASSERT_EQ_INT(0, cJSON_GetObjectItem(result, "isError")->valueint, "isError=false"); | ||
| 251 | |||
| 252 | cJSON *content = cJSON_GetObjectItem(result, "content"); | ||
| 253 | cJSON *text = cJSON_GetArrayItem(content, 0); | ||
| 254 | ASSERT_EQ_STR("text", cJSON_GetObjectItem(text, "type")->valuestring, "content type=text"); | ||
| 255 | ASSERT(strstr(cJSON_GetObjectItem(text, "text")->valuestring, "balance") != NULL, "contains balance"); | ||
| 256 | |||
| 257 | cJSON_Delete(root); | ||
| 258 | free(json); | ||
| 259 | } | ||
| 260 | |||
| 261 | static void test_tool_call_response_error(void) | ||
| 262 | { | ||
| 263 | printf("\n=== MCP tools/call error response ===\n"); | ||
| 264 | char *json = build_tool_call_response_test("3", false, "Tool not found"); | ||
| 265 | ASSERT(json != NULL, "response created"); | ||
| 266 | |||
| 267 | cJSON *root = cJSON_Parse(json); | ||
| 268 | cJSON *error = cJSON_GetObjectItem(root, "error"); | ||
| 269 | ASSERT(error != NULL, "has error"); | ||
| 270 | ASSERT_EQ_INT(-32603, cJSON_GetObjectItem(error, "code")->valueint, "error code"); | ||
| 271 | ASSERT_EQ_STR("Tool not found", cJSON_GetObjectItem(error, "message")->valuestring, "error message"); | ||
| 272 | |||
| 273 | cJSON_Delete(root); | ||
| 274 | free(json); | ||
| 275 | } | ||
| 276 | |||
| 277 | static void test_ping_response(void) | ||
| 278 | { | ||
| 279 | printf("\n=== MCP ping response ===\n"); | ||
| 280 | char *json = build_ping_response_test("99"); | ||
| 281 | ASSERT(json != NULL, "response created"); | ||
| 282 | |||
| 283 | cJSON *root = cJSON_Parse(json); | ||
| 284 | ASSERT_EQ_STR("2.0", cJSON_GetObjectItem(root, "jsonrpc")->valuestring, "jsonrpc version"); | ||
| 285 | ASSERT(cJSON_GetObjectItem(root, "result") != NULL, "has result"); | ||
| 286 | |||
| 287 | cJSON_Delete(root); | ||
| 288 | free(json); | ||
| 289 | } | ||
| 290 | |||
| 291 | static void test_announcement_11316(void) | ||
| 292 | { | ||
| 293 | printf("\n=== Kind 11316 server announcement ===\n"); | ||
| 294 | char *json = build_announcement_11316_test(); | ||
| 295 | ASSERT(json != NULL, "announcement created"); | ||
| 296 | |||
| 297 | cJSON *root = cJSON_Parse(json); | ||
| 298 | ASSERT_EQ_STR("2025-07-02", cJSON_GetObjectItem(root, "protocolVersion")->valuestring, "protocol version"); | ||
| 299 | |||
| 300 | cJSON *caps = cJSON_GetObjectItem(root, "capabilities"); | ||
| 301 | ASSERT(cJSON_GetObjectItem(caps, "tools") != NULL, "has tools capability"); | ||
| 302 | |||
| 303 | cJSON *info = cJSON_GetObjectItem(root, "serverInfo"); | ||
| 304 | ASSERT_EQ_STR("TollGate", cJSON_GetObjectItem(info, "name")->valuestring, "name"); | ||
| 305 | ASSERT_EQ_STR("1.0.0", cJSON_GetObjectItem(info, "version")->valuestring, "version"); | ||
| 306 | |||
| 307 | cJSON_Delete(root); | ||
| 308 | free(json); | ||
| 309 | } | ||
| 310 | |||
| 311 | static void test_announcement_11317(void) | ||
| 312 | { | ||
| 313 | printf("\n=== Kind 11317 tools list ===\n"); | ||
| 314 | char *json = build_announcement_11317_test(); | ||
| 315 | ASSERT(json != NULL, "tools list created"); | ||
| 316 | |||
| 317 | cJSON *root = cJSON_Parse(json); | ||
| 318 | cJSON *tools = cJSON_GetObjectItem(root, "tools"); | ||
| 319 | ASSERT_EQ_INT(10, cJSON_GetArraySize(tools), "10 tools"); | ||
| 320 | |||
| 321 | cJSON *t0 = cJSON_GetArrayItem(tools, 0); | ||
| 322 | ASSERT_EQ_STR("get_config", cJSON_GetObjectItem(t0, "name")->valuestring, "tool 0 name"); | ||
| 323 | ASSERT(cJSON_GetObjectItem(t0, "inputSchema") != NULL, "tool has inputSchema"); | ||
| 324 | |||
| 325 | cJSON_Delete(root); | ||
| 326 | free(json); | ||
| 327 | } | ||
| 328 | |||
| 329 | static void test_relay_list_10002(void) | ||
| 330 | { | ||
| 331 | printf("\n=== Kind 10002 relay list ===\n"); | ||
| 332 | char *json = build_relay_list_10002_test(); | ||
| 333 | ASSERT(json != NULL, "relay list created"); | ||
| 334 | |||
| 335 | cJSON *tags = cJSON_Parse(json); | ||
| 336 | ASSERT(cJSON_IsArray(tags), "is array"); | ||
| 337 | ASSERT_EQ_INT(2, cJSON_GetArraySize(tags), "2 relay tags"); | ||
| 338 | |||
| 339 | cJSON *r0 = cJSON_GetArrayItem(tags, 0); | ||
| 340 | ASSERT_EQ_STR("r", cJSON_GetArrayItem(r0, 0)->valuestring, "tag type r"); | ||
| 341 | ASSERT_EQ_STR("wss://relay.damus.io", cJSON_GetArrayItem(r0, 1)->valuestring, "relay 0"); | ||
| 342 | |||
| 343 | cJSON *r1 = cJSON_GetArrayItem(tags, 1); | ||
| 344 | ASSERT_EQ_STR("wss://nos.lol", cJSON_GetArrayItem(r1, 1)->valuestring, "relay 1"); | ||
| 345 | |||
| 346 | cJSON_Delete(tags); | ||
| 347 | free(json); | ||
| 348 | } | ||
| 349 | |||
| 350 | static void test_mcp_parse_from_25910(void) | ||
| 351 | { | ||
| 352 | printf("\n=== Parse MCP from kind 25910 content ===\n"); | ||
| 353 | |||
| 354 | char method[64] = {0}; | ||
| 355 | char params[1024] = {0}; | ||
| 356 | |||
| 357 | bool ok = parse_mcp_from_25910( | ||
| 358 | "{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"initialize\",\"params\":{}}", | ||
| 359 | method, sizeof(method), params, sizeof(params)); | ||
| 360 | ASSERT(ok, "parsed initialize"); | ||
| 361 | ASSERT_EQ_STR("initialize", method, "method=initialize"); | ||
| 362 | |||
| 363 | ok = parse_mcp_from_25910( | ||
| 364 | "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"get_config\"}}", | ||
| 365 | method, sizeof(method), params, sizeof(params)); | ||
| 366 | ASSERT(ok, "parsed tools/call"); | ||
| 367 | ASSERT_EQ_STR("tools/call", method, "method=tools/call"); | ||
| 368 | ASSERT(strstr(params, "get_config") != NULL, "params has get_config"); | ||
| 369 | |||
| 370 | ok = parse_mcp_from_25910("{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}", | ||
| 371 | method, sizeof(method), params, sizeof(params)); | ||
| 372 | ASSERT(ok, "parsed notification"); | ||
| 373 | ASSERT_EQ_STR("notifications/initialized", method, "method=notifications/initialized"); | ||
| 374 | |||
| 375 | ok = parse_mcp_from_25910("not json", method, sizeof(method), params, sizeof(params)); | ||
| 376 | ASSERT(!ok, "garbage rejected"); | ||
| 377 | |||
| 378 | ok = parse_mcp_from_25910("{\"jsonrpc\":\"2.0\"}", method, sizeof(method), params, sizeof(params)); | ||
| 379 | ASSERT(!ok, "missing method rejected"); | ||
| 380 | } | ||
| 381 | |||
| 382 | static void test_auth_check(void) | ||
| 383 | { | ||
| 384 | printf("\n=== Auth check logic ===\n"); | ||
| 385 | |||
| 386 | const char *owner = "d6bfe100d1600c0d8f769501676fc74c3809500bd131c8a549f88cf616c21f35"; | ||
| 387 | const char *other = "0000000000000000000000000000000000000000000000000000000000000001"; | ||
| 388 | |||
| 389 | ASSERT(strcmp(owner, owner) == 0, "owner matches self"); | ||
| 390 | ASSERT(strcmp(owner, other) != 0, "owner differs from other"); | ||
| 391 | ASSERT(strcmp(other, owner) != 0, "other differs from owner"); | ||
| 392 | ASSERT(NULL == NULL, "two NULLs match (for safety check)"); | ||
| 393 | } | ||
| 394 | |||
| 395 | static void test_25910_event_content_roundtrip(void) | ||
| 396 | { | ||
| 397 | printf("\n=== Kind 25910 content roundtrip ===\n"); | ||
| 398 | |||
| 399 | cJSON *request = cJSON_CreateObject(); | ||
| 400 | cJSON_AddStringToObject(request, "jsonrpc", "2.0"); | ||
| 401 | cJSON_AddNumberToObject(request, "id", 42); | ||
| 402 | cJSON_AddStringToObject(request, "method", "tools/call"); | ||
| 403 | cJSON *params = cJSON_CreateObject(); | ||
| 404 | cJSON_AddStringToObject(params, "name", "get_balance"); | ||
| 405 | cJSON_AddItemToObject(request, "params", params); | ||
| 406 | char *content = cJSON_PrintUnformatted(request); | ||
| 407 | cJSON_Delete(request); | ||
| 408 | |||
| 409 | char method[64] = {0}; | ||
| 410 | char params_out[1024] = {0}; | ||
| 411 | bool ok = parse_mcp_from_25910(content, method, sizeof(method), params_out, sizeof(params_out)); | ||
| 412 | ASSERT(ok, "roundtrip parse succeeded"); | ||
| 413 | ASSERT_EQ_STR("tools/call", method, "method preserved"); | ||
| 414 | ASSERT(strstr(params_out, "get_balance") != NULL, "tool name preserved"); | ||
| 415 | |||
| 416 | free(content); | ||
| 417 | } | ||
| 418 | |||
| 419 | int main(void) | ||
| 420 | { | ||
| 421 | printf("=== test_cvm_server ===\n"); | ||
| 422 | test_initialize_response(); | ||
| 423 | test_tools_list_response(); | ||
| 424 | test_tool_call_response_success(); | ||
| 425 | test_tool_call_response_error(); | ||
| 426 | test_ping_response(); | ||
| 427 | test_announcement_11316(); | ||
| 428 | test_announcement_11317(); | ||
| 429 | test_relay_list_10002(); | ||
| 430 | test_mcp_parse_from_25910(); | ||
| 431 | test_auth_check(); | ||
| 432 | test_25910_event_content_roundtrip(); | ||
| 433 | TEST_SUMMARY(); | ||
| 434 | } | ||