test(mcp): cover CLI index name override

Signed-off-by: Blank_Answer <97771966+blankanswer@users.noreply.github.com>
This commit is contained in:
Blank_Answer
2026-07-08 03:21:46 +00:00
parent b637e3330c
commit 6908ea5075
+139
View File
@@ -4125,6 +4125,144 @@ TEST(readonly_query_succeeds_on_readonly_fs) {
#undef ROQ_PROJECT
/* ══════════════════════════════════════════════════════════════════
* #823 — CLI/supervised index_repository must preserve name override
* ══════════════════════════════════════════════════════════════════ */
enum {
IDX823_OK = 0,
IDX823_NO_SERVER = 61,
IDX823_NO_RESULT = 62,
IDX823_NOT_INDEXED = 63,
IDX823_RESPONSE_NAME_MISSING = 64,
IDX823_LIST_NAME_MISSING = 65,
IDX823_SEARCH_FAILED = 66,
};
#ifndef _WIN32 /* helper used only by the POSIX fork harness below */
static int idx823_supervised_name_override_check(const char *repo_dir, const char *custom_name) {
/* Match the real CLI/MCP server state: a marked host with the supervisor
* enabled. The worker receives the same args JSON the CLI forwards. */
cbm_index_supervisor_mark_host();
cbm_unsetenv("CBM_INDEX_SUPERVISOR");
cbm_setenv("CBM_INDEX_MAX_RESTARTS", "1", 1);
cbm_setenv("CBM_INDEX_WORKER_TIMEOUT_S", "30", 1);
cbm_mcp_server_t *srv = cbm_mcp_server_new(NULL);
if (!srv) {
return IDX823_NO_SERVER;
}
char args[1024];
snprintf(args, sizeof(args), "{\"repo_path\":\"%s\",\"mode\":\"fast\",\"name\":\"%s\"}",
repo_dir, custom_name);
char *resp = cbm_mcp_handle_tool(srv, "index_repository", args);
int code = IDX823_OK;
if (!resp) {
code = IDX823_NO_RESULT;
} else if (!response_contains_json_fragment(resp, "\"status\":\"indexed\"")) {
code = IDX823_NOT_INDEXED;
} else {
char expected[256];
snprintf(expected, sizeof(expected), "\"project\":\"%s\"", custom_name);
if (!response_contains_json_fragment(resp, expected)) {
code = IDX823_RESPONSE_NAME_MISSING;
}
}
free(resp);
if (code == IDX823_OK) {
char *projects = cbm_mcp_handle_tool(srv, "list_projects", "{}");
char expected[256];
snprintf(expected, sizeof(expected), "\"name\":\"%s\"", custom_name);
if (!projects || !response_contains_json_fragment(projects, expected)) {
code = IDX823_LIST_NAME_MISSING;
}
free(projects);
}
if (code == IDX823_OK) {
char q[512];
snprintf(q, sizeof(q),
"{\"project\":\"%s\",\"name_pattern\":\"idx823_fn\",\"label\":\"Function\"}",
custom_name);
char *sr = cbm_mcp_handle_tool(srv, "search_graph", q);
if (!sr || !strstr(sr, "idx823_fn")) {
code = IDX823_SEARCH_FAILED;
}
free(sr);
}
cbm_mcp_server_free(srv);
return code;
}
#endif
TEST(index_repository_cli_name_override_issue823) {
#ifdef _WIN32
SKIP_PLATFORM("POSIX fork harness required to isolate supervisor host mark");
#else
char tmp_dir[256];
snprintf(tmp_dir, sizeof(tmp_dir), "/tmp/cbm-idx823-repo-XXXXXX");
if (!cbm_mkdtemp(tmp_dir)) {
FAIL("cbm_mkdtemp repo failed");
}
char cache[256];
snprintf(cache, sizeof(cache), "/tmp/cbm-idx823-cache-XXXXXX");
if (!cbm_mkdtemp(cache)) {
th_rmtree(tmp_dir);
FAIL("cbm_mkdtemp cache failed");
}
const char *saved_cache = getenv("CBM_CACHE_DIR");
char *saved_cache_copy = saved_cache ? strdup(saved_cache) : NULL;
cbm_setenv("CBM_CACHE_DIR", cache, 1);
char src_path[512];
snprintf(src_path, sizeof(src_path), "%s/main.py", tmp_dir);
ASSERT_EQ(th_write_file(src_path, "def idx823_fn():\n return 823\n"), 0);
const char *custom_name = "issue823-custom-project";
int code = -1;
bool signalled = false;
int sig = 0;
fflush(NULL);
pid_t pid = fork();
if (pid == 0) {
alarm(60);
_exit(idx823_supervised_name_override_check(tmp_dir, custom_name));
}
ASSERT_TRUE(pid > 0);
int status = 0;
(void)waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
code = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
signalled = true;
sig = WTERMSIG(status);
}
char *path_project = cbm_project_name_from_path(tmp_dir);
cleanup_project_db(cache, custom_name);
cleanup_project_db(cache, path_project);
free(path_project);
restore_cache_dir(saved_cache_copy);
free(saved_cache_copy);
th_rmtree(cache);
th_rmtree(tmp_dir);
if (signalled) {
printf(" child killed by signal %d (alarm => worker hang)\n", sig);
} else if (code != IDX823_OK) {
printf(" child exit code %d (64=response name, 65=list name, 66=search)\n", code);
}
ASSERT_FALSE(signalled);
ASSERT_EQ(code, IDX823_OK);
PASS();
#endif
}
/* ══════════════════════════════════════════════════════════════════
* #845 — supervisor gate must not wrap embedders of cbm_mcp_handle_tool
* ══════════════════════════════════════════════════════════════════ */
@@ -5083,6 +5221,7 @@ SUITE(mcp) {
RUN_TEST(tool_manage_adr_unified_backend_issue256);
RUN_TEST(tool_index_repository_reports_store_backed_adr);
RUN_TEST(tool_index_repository_dot_uses_absolute_project_key_and_preserves_adr);
RUN_TEST(index_repository_cli_name_override_issue823);
RUN_TEST(index_supervisor_gate_requires_marked_host_issue845);
RUN_TEST(index_bg_paths_route_through_supervisor_issue832);
RUN_TEST(index_recovery_parallel_quarantines_crasher);