mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-03 08:03:38 +08:00
test(pipeline): align exact scratch helper
Mirror the production exact-route path-alias and package-map setup in the test-only scratch builder so lower-level exact-delta tests exercise the same resolver inputs.\n\nAdd a Python package exact-delta regression that applies the lower-level scratch delta and compares the result with a fresh FAST rebuild. This proves the small synthetic package is safe while the larger FastAPI scoped-LSP mismatch remains covered by external benchmark artifacts and the production full-reindex guard.\n\nValidation:\n- CBM_ONLY_SUITE=pipeline CBM_ONLY_TEST=incremental_exact_scratch_python_package_matches_fresh_rebuild build/c/test-runner\n- CBM_ONLY_SUITE=pipeline build/c/test-runner\n- bash scripts/check-source-safety.sh\n- git diff --check Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
This commit is contained in:
@@ -9461,6 +9461,8 @@ static int pipeline_build_exact_scratch_for_changed_files(cbm_store_t *store,
|
||||
CBMFileResult **result_cache = calloc((size_t)changed_count, sizeof(*result_cache));
|
||||
cbm_gbuf_t *scratch = cbm_gbuf_new(project, repo_path);
|
||||
cbm_registry_t *registry = cbm_registry_new();
|
||||
cbm_path_alias_collection_t *path_aliases = NULL;
|
||||
CBMHashTable *pkgmap = NULL;
|
||||
atomic_int cancelled;
|
||||
atomic_init(&cancelled, 0);
|
||||
int rc = CBM_STORE_ERR;
|
||||
@@ -9476,6 +9478,10 @@ static int pipeline_build_exact_scratch_for_changed_files(cbm_store_t *store,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
path_aliases = cbm_load_path_aliases(repo_path);
|
||||
pkgmap = cbm_pkgmap_build_from_repo(repo_path, changed_files, changed_count, project);
|
||||
cbm_pipeline_set_pkgmap(pkgmap);
|
||||
|
||||
const double pipeline_default_threshold = 0.0; /* Pipeline constructor sentinel: use pass defaults. */
|
||||
cbm_pipeline_ctx_t ctx = {.project_name = project,
|
||||
.repo_path = repo_path,
|
||||
@@ -9488,6 +9494,7 @@ static int pipeline_build_exact_scratch_for_changed_files(cbm_store_t *store,
|
||||
.semantic_threshold = pipeline_default_threshold,
|
||||
.githistory_min_coupling = pipeline_default_threshold,
|
||||
.lsp_confidence_floor = pipeline_default_threshold,
|
||||
.path_aliases = path_aliases,
|
||||
.result_cache = result_cache,
|
||||
.store_backed_node_lookup = store,
|
||||
.store_backed_changed_paths = changed_paths,
|
||||
@@ -9536,6 +9543,11 @@ cleanup:
|
||||
}
|
||||
}
|
||||
free(result_cache);
|
||||
cbm_path_alias_collection_free(path_aliases);
|
||||
if (cbm_pipeline_get_pkgmap() == pkgmap) {
|
||||
cbm_pipeline_set_pkgmap(NULL);
|
||||
}
|
||||
cbm_pkgmap_free(pkgmap);
|
||||
cbm_registry_free(registry);
|
||||
cbm_gbuf_free(scratch);
|
||||
free(changed_paths);
|
||||
@@ -11929,6 +11941,137 @@ TEST(incremental_overlay_publish_python_scoped_lsp_gap_uses_full_reindex) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(incremental_exact_scratch_python_package_matches_fresh_rebuild) {
|
||||
if (setup_incremental_repo() != 0) {
|
||||
FAIL("setup failed");
|
||||
}
|
||||
|
||||
char fastapi_dir[CBM_PATH_MAX];
|
||||
int n = snprintf(fastapi_dir, sizeof(fastapi_dir), "%s/fastapi", g_incr_tmpdir);
|
||||
ASSERT(n >= 0 && (size_t)n < sizeof(fastapi_dir));
|
||||
ASSERT_EQ(cbm_mkdir(fastapi_dir), 0);
|
||||
|
||||
char init_path[CBM_PATH_MAX];
|
||||
char exceptions_path[CBM_PATH_MAX];
|
||||
char datastructures_path[CBM_PATH_MAX];
|
||||
char routing_path[CBM_PATH_MAX];
|
||||
n = snprintf(init_path, sizeof(init_path), "%s/fastapi/__init__.py", g_incr_tmpdir);
|
||||
ASSERT(n >= 0 && (size_t)n < sizeof(init_path));
|
||||
n = snprintf(exceptions_path, sizeof(exceptions_path), "%s/fastapi/exceptions.py", g_incr_tmpdir);
|
||||
ASSERT(n >= 0 && (size_t)n < sizeof(exceptions_path));
|
||||
n = snprintf(datastructures_path, sizeof(datastructures_path),
|
||||
"%s/fastapi/datastructures.py", g_incr_tmpdir);
|
||||
ASSERT(n >= 0 && (size_t)n < sizeof(datastructures_path));
|
||||
n = snprintf(routing_path, sizeof(routing_path), "%s/fastapi/routing.py", g_incr_tmpdir);
|
||||
ASSERT(n >= 0 && (size_t)n < sizeof(routing_path));
|
||||
|
||||
ASSERT_EQ(th_write_file(init_path,
|
||||
"from .datastructures import DefaultPlaceholder\n"
|
||||
"from .exceptions import HTTPException\n"),
|
||||
0);
|
||||
ASSERT_EQ(th_write_file(exceptions_path,
|
||||
"class HTTPException(Exception):\n"
|
||||
" pass\n"),
|
||||
0);
|
||||
ASSERT_EQ(th_write_file(datastructures_path,
|
||||
"class DefaultPlaceholder:\n"
|
||||
" pass\n"),
|
||||
0);
|
||||
ASSERT_EQ(th_write_file(routing_path,
|
||||
"from fastapi.datastructures import DefaultPlaceholder\n"
|
||||
"from fastapi.exceptions import HTTPException\n\n"
|
||||
"def serialize_response(field=None, response_content=None):\n"
|
||||
" return response_content\n\n"
|
||||
"def route_handler(response_field, raw_response):\n"
|
||||
" marker = DefaultPlaceholder()\n"
|
||||
" if marker:\n"
|
||||
" raise HTTPException()\n"
|
||||
" return raw_response\n"),
|
||||
0);
|
||||
|
||||
cbm_config_t *cfg = incremental_test_config(g_incr_tmpdir);
|
||||
ASSERT_NOT_NULL(cfg);
|
||||
cbm_pipeline_t *p = cbm_pipeline_new(g_incr_tmpdir, g_incr_dbpath, CBM_MODE_FAST);
|
||||
ASSERT_NOT_NULL(p);
|
||||
cbm_pipeline_apply_config(p, cfg);
|
||||
ASSERT_EQ(cbm_pipeline_run(p), 0);
|
||||
char pass_fingerprint[CBM_SZ_256];
|
||||
ASSERT_EQ(cbm_pipeline_current_pass_fingerprint(p, pass_fingerprint,
|
||||
sizeof(pass_fingerprint)),
|
||||
CBM_STORE_OK);
|
||||
char *project = cbm_strdup(cbm_pipeline_project_name(p));
|
||||
cbm_pipeline_free(p);
|
||||
ASSERT_NOT_NULL(project);
|
||||
|
||||
ASSERT_EQ(th_write_file(routing_path,
|
||||
"from fastapi.datastructures import DefaultPlaceholder\n"
|
||||
"from fastapi.exceptions import HTTPException\n\n"
|
||||
"def serialize_response(field=None, response_content=None, include=None, "
|
||||
"exclude=None, by_alias=True, exclude_unset=False, "
|
||||
"exclude_defaults=False, exclude_none=False):\n"
|
||||
" return response_content\n\n"
|
||||
"def route_handler(response_field, raw_response, response_model_include, "
|
||||
"response_model_exclude, response_model_by_alias, "
|
||||
"response_model_exclude_unset, response_model_exclude_defaults, "
|
||||
"response_model_exclude_none):\n"
|
||||
" marker = DefaultPlaceholder()\n"
|
||||
" if not marker:\n"
|
||||
" return raw_response\n"
|
||||
" return serialize_response(field=response_field, "
|
||||
"response_content=raw_response, include=response_model_include, "
|
||||
"exclude=response_model_exclude, by_alias=response_model_by_alias, "
|
||||
"exclude_unset=response_model_exclude_unset, "
|
||||
"exclude_defaults=response_model_exclude_defaults, "
|
||||
"exclude_none=response_model_exclude_none)\n"),
|
||||
0);
|
||||
|
||||
cbm_file_info_t changed = {
|
||||
.path = routing_path,
|
||||
.rel_path = "fastapi/routing.py",
|
||||
.language = CBM_LANG_PYTHON,
|
||||
};
|
||||
cbm_store_t *store = cbm_store_open_path(g_incr_dbpath);
|
||||
ASSERT_NOT_NULL(store);
|
||||
cbm_gbuf_t *scratch = NULL;
|
||||
cbm_pipeline_file_delta_t delta = {0};
|
||||
ASSERT_EQ(pipeline_build_exact_scratch_for_changed_files(store, g_incr_tmpdir, project,
|
||||
&changed, CBM_ALLOC_ONE, &scratch,
|
||||
&delta),
|
||||
CBM_STORE_OK);
|
||||
ASSERT_EQ(cbm_pipeline_attach_file_delta_metadata_with_fingerprint(&delta, &changed,
|
||||
pass_fingerprint),
|
||||
CBM_STORE_OK);
|
||||
int64_t generation = 0;
|
||||
ASSERT_EQ(cbm_store_reserve_index_generation(store, project, NULL, NULL, &generation),
|
||||
CBM_STORE_OK);
|
||||
ASSERT_GT(generation, CBM_PIPELINE_COMPAT_GENERATION);
|
||||
ASSERT_EQ(cbm_pipeline_file_delta_stamp_generation(&delta, generation), CBM_STORE_OK);
|
||||
const cbm_pipeline_file_delta_t *deltas[] = {&delta};
|
||||
cbm_pipeline_file_delta_plan_t plan = {0};
|
||||
ASSERT_EQ(cbm_pipeline_apply_file_delta_batch(store, deltas, CBM_ALLOC_ONE,
|
||||
CBM_PIPELINE_EXACT_DELTA_DEFAULT_MAX_AFFECTED_PATHS,
|
||||
&plan),
|
||||
CBM_STORE_OK);
|
||||
ASSERT_EQ(plan.route, CBM_PIPELINE_DELTA_ROUTE_EXACT_CANDIDATE);
|
||||
cbm_pipeline_file_delta_plan_free(&plan);
|
||||
cbm_store_close(store);
|
||||
|
||||
char diff_err[CBM_SZ_8K] = {0};
|
||||
int diff_rc = pipeline_compare_current_db_to_fresh_fast_rebuild(
|
||||
g_incr_tmpdir, g_incr_dbpath, project, cfg, diff_err, sizeof(diff_err));
|
||||
if (diff_rc != 0) {
|
||||
FAIL(diff_err[0] ? diff_err : "Python exact scratch delta differed from fresh rebuild");
|
||||
}
|
||||
ASSERT_EQ(diff_rc, 0);
|
||||
|
||||
cbm_pipeline_file_delta_free(&delta);
|
||||
cbm_gbuf_free(scratch);
|
||||
free(project);
|
||||
cbm_config_close(cfg);
|
||||
cleanup_incremental_repo();
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(incremental_overlay_first_preserves_inbound_edges_past_exact_frontier_cap) {
|
||||
if (setup_incremental_repo() != 0) {
|
||||
FAIL("setup failed");
|
||||
@@ -14494,6 +14637,7 @@ SUITE(pipeline) {
|
||||
RUN_TEST(incremental_overlay_producer_marks_dirty_ready_without_canonical_mutation);
|
||||
RUN_TEST(incremental_overlay_publish_small_deltas_keeps_canonical_base_visible);
|
||||
RUN_TEST(incremental_overlay_publish_python_scoped_lsp_gap_uses_full_reindex);
|
||||
RUN_TEST(incremental_exact_scratch_python_package_matches_fresh_rebuild);
|
||||
RUN_TEST(incremental_overlay_first_preserves_inbound_edges_past_exact_frontier_cap);
|
||||
RUN_TEST(incremental_overlay_publish_delete_keeps_canonical_base_visible);
|
||||
RUN_TEST(incremental_overlay_publish_repeated_update_keeps_active_view_idempotent);
|
||||
|
||||
Reference in New Issue
Block a user