mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-28 07:03:20 +08:00
Merge pull request #1047 from DeusData/test/876-recursion-delegation-guards
test(extract): guard delegation-receiver recursion false positives
This commit is contained in:
@@ -3115,6 +3115,74 @@ TEST(complexity_go_method_receiver_self_recursion) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #876: the delegation/store bucket left open after #599 — same-named calls
|
||||
* whose receiver is a CALL RESULT (_get_store().get), a module singleton
|
||||
* (_default.check), or a local cursor inside a loop (cur.execute) are not
|
||||
* self-recursion. All three are the reporter's exact v0.8.1 false positives;
|
||||
* fixed by the receiver-aware narrowing (87091ed), guarded here so the
|
||||
* bucket never regresses. */
|
||||
TEST(complexity_delegation_receivers_not_recursive_issue876) {
|
||||
/* Store wrapper: _get_store().get() inside get — receiver is the call
|
||||
* result, a different object. */
|
||||
CBMFileResult *r = extract("def _get_store():\n"
|
||||
" return object()\n"
|
||||
"\n"
|
||||
"def get(collection, record_id):\n"
|
||||
" rec = _get_store().get(collection, record_id)\n"
|
||||
" return rec\n",
|
||||
CBM_LANG_PYTHON, "t", "soil.py");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
const CBMDefinition *d = find_def(r, "get");
|
||||
ASSERT_NOT_NULL(d);
|
||||
ASSERT_FALSE(d->is_recursive); /* _get_store() result is not this fn */
|
||||
ASSERT_FALSE(d->unguarded_recursion);
|
||||
cbm_free_result(r);
|
||||
|
||||
/* Module-singleton delegation: _default.check() inside check. */
|
||||
r = extract("class _Checker:\n"
|
||||
" def check(self, app_id, tool_name):\n"
|
||||
" return (True, \"ok\")\n"
|
||||
"\n"
|
||||
"_default = _Checker()\n"
|
||||
"\n"
|
||||
"def check(app_id, tool_name):\n"
|
||||
" return _default.check(app_id, tool_name)\n",
|
||||
CBM_LANG_PYTHON, "t", "gleipnir.py");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
/* The module-level wrapper (not the method) must stay clean. */
|
||||
d = NULL;
|
||||
for (int i = 0; i < r->defs.count; i++) {
|
||||
if (r->defs.items[i].name && strcmp(r->defs.items[i].name, "check") == 0 &&
|
||||
strcmp(r->defs.items[i].label, "Function") == 0) {
|
||||
d = &r->defs.items[i];
|
||||
}
|
||||
}
|
||||
ASSERT_NOT_NULL(d);
|
||||
ASSERT_FALSE(d->is_recursive); /* _default is not this fn */
|
||||
ASSERT_FALSE(d->unguarded_recursion);
|
||||
cbm_free_result(r);
|
||||
|
||||
/* Same-named method on a local, called inside a loop (willow.nuke case):
|
||||
* neither recursive nor recursion_in_loop. */
|
||||
r = extract("def execute(conn, paths):\n"
|
||||
" for p in paths:\n"
|
||||
" cur = conn.cursor()\n"
|
||||
" cur.execute(\"DELETE FROM t WHERE p = %s\", (p,))\n"
|
||||
" return True\n",
|
||||
CBM_LANG_PYTHON, "t", "nuke.py");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
d = find_def(r, "execute");
|
||||
ASSERT_NOT_NULL(d);
|
||||
ASSERT_FALSE(d->is_recursive); /* cur is not this fn */
|
||||
ASSERT_FALSE(d->unguarded_recursion);
|
||||
ASSERT_FALSE(d->recursion_in_loop);
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* Deep chained member access + parameter count structure smells. */
|
||||
TEST(complexity_access_depth_and_params) {
|
||||
CBMFileResult *r = extract("package p\n"
|
||||
@@ -3736,6 +3804,7 @@ SUITE(extraction) {
|
||||
RUN_TEST(complexity_self_receiver_still_recursive);
|
||||
RUN_TEST(complexity_chained_receiver_not_self);
|
||||
RUN_TEST(complexity_go_method_receiver_self_recursion);
|
||||
RUN_TEST(complexity_delegation_receivers_not_recursive_issue876);
|
||||
RUN_TEST(complexity_access_depth_and_params);
|
||||
RUN_TEST(walk_defs_no_truncation_over_4096_issue668);
|
||||
RUN_TEST(extract_rust_test_attr_marks_is_test_issue855);
|
||||
|
||||
Reference in New Issue
Block a user