Files
codebase-memory-mcp/tests/test_main.c
T
Martin Vogel e89aa776a7 feat(index): report per-file indexing failures via skipped[] + logfile (Stage 2/B2-B4)
index_repository silently dropped files that failed to index: CBMFileResult.has_error
was set but never read, oversized files (>100 MB) were dropped with no signal, and
read/extract failures only bumped a logged-only counter — a file that couldn't be
indexed just vanished from the graph.

Collect and surface them:
- New retained {path, reason, phase} error list on struct cbm_pipeline (mirrors the
  excluded_dirs pattern) + accessor + a back-pointer on cbm_pipeline_ctx_t so both
  extraction paths can append. Wired in BOTH the sequential (pass_definitions) and
  parallel (per-worker, merged lock-free) paths — small repos take the sequential
  path, so wiring only one would leave the guard vacuous.
- Feeds: read-fail, extract-fail, the newly-CONSUMED has_error (parse timeout /
  parse failed, with error_msg), and oversized. The cross_lsp phase is reserved for
  the crash supervisor (Track C) and not fed here (the cross-LSP passes are
  best-effort with no failure return; feeding the no-source case would be false
  positives).
- MCP/CLI response gains top-level "skipped_count" (0 on clean) and, when >0, a
  capped "skipped":{files[<=50],count,truncated} + "logfile". Status stays "indexed"
  — a reported skip is the expected, handled outcome, not a degradation.
- Per-run logfile (full uncapped list) written ONLY when >=1 file is skipped:
  $CBM_INDEX_LOG override else <cache_dir>/logs/<project>-<epoch>.log.
- Generous env-configurable caps (src/foundation/limits.c): CBM_MAX_FILE_BYTES,
  default raised 100 MB -> 512 MiB; over-cap files are REPORTED (phase oversized) +
  WARNed, never silently dropped.

Reproduce-first: tests/test_index_resilience.c (gating) — an oversized file (cap
lowered via env) must appear in skipped[] with the 2 good files still indexed and a
logfile written; a clean run has skipped_count 0 and no logfile. Genuine guard:
no-op'ing the recorder makes the oversized file silently vanish (RED). Full suite
5750/0, no ASan/UBSan.

Part of the resilient-indexing effort (Track B surfacing layer). Refs #668.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-02 22:11:00 +02:00

294 lines
8.8 KiB
C

/*
* test_main.c — Test runner entry point for pure C rewrite.
*
* Includes all test suites and runs them sequentially.
*/
/* Global test counters (declared extern in test_framework.h) */
int tf_pass_count = 0;
int tf_fail_count = 0;
int tf_skip_count = 0;
#include "test_framework.h"
#include <sqlite3.h>
#include <stdbool.h>
#include <string.h>
static int g_suite_argc = 0;
static char **g_suite_argv = NULL;
static bool suite_requested(const char *name) {
if (g_suite_argc <= 1) {
return true;
}
for (int i = 1; i < g_suite_argc; i++) {
if (strcmp(g_suite_argv[i], name) == 0) {
return true;
}
}
return false;
}
#define RUN_SELECTED_SUITE(name) \
do { \
if (suite_requested(#name)) { \
RUN_SUITE(name); \
} \
} while (0)
/* Forward declarations of suite functions */
extern void suite_arena(void);
extern void suite_hash_table(void);
extern void suite_dyn_array(void);
extern void suite_str_intern(void);
extern void suite_log(void);
extern void suite_str_util(void);
extern void suite_platform(void);
extern void suite_extraction(void);
extern void suite_extraction_inheritance(void);
extern void suite_extraction_imports(void);
extern void suite_grammar_regression(void);
extern void suite_grammar_labels(void);
extern void suite_grammar_imports(void);
extern void suite_ac(void);
extern void suite_store_nodes(void);
extern void suite_store_edges(void);
extern void suite_store_search(void);
extern void suite_cypher(void);
extern void suite_mcp(void);
extern void suite_language(void);
extern void suite_userconfig(void);
extern void suite_gitignore(void);
extern void suite_git_context(void);
extern void suite_discover(void);
extern void suite_graph_buffer(void);
extern void suite_registry(void);
extern void suite_pipeline(void);
extern void suite_index_resilience(void);
extern void suite_fqn(void);
extern void suite_route_canon(void);
extern void suite_path_alias(void);
extern void suite_watcher(void);
extern void suite_lz4(void);
extern void suite_zstd(void);
extern void suite_artifact(void);
extern void suite_sqlite_writer(void);
extern void suite_go_lsp(void);
extern void suite_c_lsp(void);
extern void suite_php_lsp(void);
extern void suite_cs_lsp(void);
extern void suite_cs_lsp_bench(void);
extern void suite_scope(void);
extern void suite_type_rep(void);
extern void suite_py_lsp(void);
extern void suite_py_lsp_bench(void);
extern void suite_py_lsp_stress(void);
extern void suite_py_lsp_scale(void);
extern void suite_ts_lsp(void);
extern void suite_java_lsp(void);
extern void suite_java_lsp_coverage(void);
extern void suite_kotlin_lsp(void);
extern void suite_rust_lsp(void);
extern void suite_store_arch(void);
extern void suite_store_bulk(void);
extern void suite_store_pragmas(void);
extern void suite_store_checkpoint(void);
extern void suite_traces(void);
extern void suite_configlink(void);
extern void suite_infrascan(void);
extern void suite_cli(void);
extern void suite_system_info(void);
extern void suite_worker_pool(void);
extern void suite_parallel(void);
extern void suite_mem(void);
extern void suite_ui(void);
extern void suite_httpd(void);
extern void suite_security(void);
extern void suite_yaml(void);
extern void suite_integration(void);
extern void suite_lang_contract(void);
extern void suite_edge_imports(void);
extern void suite_edge_structural(void);
extern void suite_lsp_resolution_probe(void);
extern void suite_node_creation_probe(void);
extern void suite_edge_types_probe(void);
extern void suite_convergence_probe(void);
extern void suite_matrix_known_classes(void);
extern void suite_matrix_new_constructs(void);
extern void suite_grammar_probe_a(void);
extern void suite_grammar_probe_b(void);
extern void suite_grammar_probe_c(void);
extern void suite_grammar_probe_d(void);
extern void suite_grammar_probe_e(void);
extern void suite_grammar_probe_f(void);
extern void suite_grammar_probe_g(void);
extern void suite_incremental(void);
extern void suite_simhash(void);
extern void suite_stack_overflow(void);
extern void suite_dump_verify(void);
extern void suite_dump_verify_io(void);
/* Free the main thread's thread-local node-type bitset cache before exit so
* LeakSanitizer (Linux x64) doesn't report it. Worker threads free their own
* caches at thread teardown (pass_parallel.c). */
extern void cbm_kind_in_set_free_cache(void);
int main(int argc, char **argv) {
g_suite_argc = argc;
g_suite_argv = argv;
printf("\n codebase-memory-mcp C test suite\n");
/* Foundation */
RUN_SELECTED_SUITE(arena);
RUN_SELECTED_SUITE(hash_table);
RUN_SELECTED_SUITE(dyn_array);
RUN_SELECTED_SUITE(str_intern);
RUN_SELECTED_SUITE(log);
RUN_SELECTED_SUITE(str_util);
RUN_SELECTED_SUITE(platform);
RUN_SELECTED_SUITE(dump_verify);
/* Existing C code regression tests */
RUN_SELECTED_SUITE(ac);
RUN_SELECTED_SUITE(extraction);
RUN_SELECTED_SUITE(extraction_inheritance);
RUN_SELECTED_SUITE(extraction_imports);
RUN_SELECTED_SUITE(grammar_regression);
RUN_SELECTED_SUITE(grammar_labels);
RUN_SELECTED_SUITE(grammar_imports);
/* Store (M5) */
RUN_SELECTED_SUITE(store_nodes);
RUN_SELECTED_SUITE(store_edges);
RUN_SELECTED_SUITE(store_search);
RUN_SELECTED_SUITE(store_bulk);
RUN_SELECTED_SUITE(store_pragmas);
RUN_SELECTED_SUITE(store_checkpoint);
RUN_SELECTED_SUITE(dump_verify_io);
/* Cypher (M6) */
RUN_SELECTED_SUITE(cypher);
/* MCP Server (M9) */
RUN_SELECTED_SUITE(mcp);
/* Discover (M2) */
RUN_SELECTED_SUITE(language);
RUN_SELECTED_SUITE(userconfig);
RUN_SELECTED_SUITE(gitignore);
RUN_SELECTED_SUITE(git_context);
RUN_SELECTED_SUITE(discover);
/* Graph Buffer (M7) */
RUN_SELECTED_SUITE(graph_buffer);
/* Pipeline (M8) */
RUN_SELECTED_SUITE(registry);
RUN_SELECTED_SUITE(pipeline);
RUN_SELECTED_SUITE(index_resilience);
RUN_SELECTED_SUITE(fqn);
RUN_SELECTED_SUITE(route_canon);
RUN_SELECTED_SUITE(path_alias);
/* Watcher (M10) */
RUN_SELECTED_SUITE(watcher);
/* LZ4 + zstd + SQLite writer */
RUN_SELECTED_SUITE(lz4);
RUN_SELECTED_SUITE(zstd);
RUN_SELECTED_SUITE(sqlite_writer);
/* Persistent artifact export/import */
RUN_SELECTED_SUITE(artifact);
/* LSP resolvers */
RUN_SELECTED_SUITE(scope);
RUN_SELECTED_SUITE(type_rep);
RUN_SELECTED_SUITE(go_lsp);
RUN_SELECTED_SUITE(c_lsp);
RUN_SELECTED_SUITE(php_lsp);
RUN_SELECTED_SUITE(cs_lsp);
RUN_SELECTED_SUITE(cs_lsp_bench);
RUN_SELECTED_SUITE(py_lsp);
RUN_SELECTED_SUITE(kotlin_lsp);
RUN_SELECTED_SUITE(rust_lsp);
RUN_SELECTED_SUITE(py_lsp_bench);
RUN_SELECTED_SUITE(py_lsp_stress);
RUN_SELECTED_SUITE(py_lsp_scale);
RUN_SELECTED_SUITE(ts_lsp);
RUN_SELECTED_SUITE(java_lsp);
RUN_SELECTED_SUITE(java_lsp_coverage);
/* Architecture + ADR + Louvain */
RUN_SELECTED_SUITE(store_arch);
/* HTTP link */
/* Traces helpers */
RUN_SELECTED_SUITE(traces);
/* Config link */
RUN_SELECTED_SUITE(configlink);
/* Infrastructure scanning */
RUN_SELECTED_SUITE(infrascan);
/* CLI (install, update, config) */
RUN_SELECTED_SUITE(cli);
/* System info + worker pool (parallelism) */
RUN_SELECTED_SUITE(system_info);
RUN_SELECTED_SUITE(worker_pool);
/* Parallel pipeline */
RUN_SELECTED_SUITE(parallel);
/* mem + arena + slab integration */
RUN_SELECTED_SUITE(mem);
/* UI (config, embedded assets, layout) */
RUN_SELECTED_SUITE(ui);
/* UI HTTP server (transport + routing) */
RUN_SELECTED_SUITE(httpd);
/* Security defenses */
RUN_SELECTED_SUITE(security);
/* YAML parser */
RUN_SELECTED_SUITE(yaml);
/* SimHash / SIMILAR_TO */
RUN_SELECTED_SUITE(simhash);
/* Stack overflow regression (GitHub #199) */
RUN_SELECTED_SUITE(stack_overflow);
/* Integration (end-to-end) */
RUN_SELECTED_SUITE(integration);
/* Per-language graph contracts (node/edge types, attribution, no-crash) */
RUN_SELECTED_SUITE(lang_contract);
RUN_SELECTED_SUITE(edge_imports);
RUN_SELECTED_SUITE(edge_structural);
RUN_SELECTED_SUITE(lsp_resolution_probe);
RUN_SELECTED_SUITE(node_creation_probe);
RUN_SELECTED_SUITE(edge_types_probe);
RUN_SELECTED_SUITE(convergence_probe);
RUN_SELECTED_SUITE(matrix_known_classes);
RUN_SELECTED_SUITE(matrix_new_constructs);
RUN_SELECTED_SUITE(grammar_probe_a);
RUN_SELECTED_SUITE(grammar_probe_b);
RUN_SELECTED_SUITE(grammar_probe_c);
RUN_SELECTED_SUITE(grammar_probe_d);
RUN_SELECTED_SUITE(grammar_probe_e);
RUN_SELECTED_SUITE(grammar_probe_f);
RUN_SELECTED_SUITE(grammar_probe_g);
RUN_SELECTED_SUITE(incremental);
/* Release process-lifetime caches so LeakSanitizer reports no leaks. */
cbm_kind_in_set_free_cache();
sqlite3_shutdown();
TEST_SUMMARY();
}