test(extract): bind the Java interface/enum method dedup fix (#1234)

Regression coverage for #1234: Java interface and enum methods were
emitted as both a Method node and a duplicate top-level Function node.
The production fix landed via 87a0e3f (language-agnostic class-body
routing); this adds the missing test coverage so it cannot silently
regress:

- java_interface_no_duplicate_function_issue1234: interface methods
  produce Method nodes only, zero Function nodes
- java_enum_dedup_preserves_calls_issue1234: enum methods dedup'd while
  cross-class CALLS edges survive
- cp_interface_method_no_dup_function: convergence probe asserting the
  surviving Method still carries its CALLS edge end-to-end

Distilled from PR #1327.

Co-Authored-By: Harshita Joshi <j.harshitaa06@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin VogelandHarshita Joshi committed 2026-08-04 16:37:06 +02:00
1 parent 66e9aec28d
commit 5eae0a4371
2 files changed
+79

No files matched your search

+28
View File
@@ -1166,6 +1166,32 @@ TEST(cp_enum_method_java) {
PASS();
}
/* D6d — Java interface method call (#1234).
* Prevention in push_class_body_children stops duplicate Function nodes
* from being minted for interface methods. The surviving Method node
* must still carry its CALLS edge. */
TEST(cp_interface_method_no_dup_function) {
static const CP_File f[] = {
{"Svc.java",
"package app;\n\n"
"interface Greeter {\n"
" String greet(String name);\n}\n\n"
"class SimpleGreeter implements Greeter {\n"
" public String greet(String name) { return \"Hello \" + name; }\n}\n\n"
"class App {\n"
" static String run(Greeter g) {\n"
" return g.greet(\"world\");\n }\n}\n"}};
CP_Proj lp;
cbm_store_t *store = cp_index_files(&lp, f, 1);
int calls = cp_edges(store, lp.project, "CALLS");
int fns = cp_count_label(store, lp.project, "Function");
if (calls < 1) cp_diag(store, lp.project, "interface_dedup/java_1234");
cp_cleanup(&lp, store);
ASSERT_TRUE(fns == 0);
ASSERT_TRUE(calls >= 1);
PASS();
}
/* ══════════════════════════════════════════════════════════════════
* AREA E — Node-creation corners
* ══════════════════════════════════════════════════════════════════ */
@@ -1596,6 +1622,8 @@ SUITE(convergence_probe) {
RUN_TEST(cp_enum_variant_rust_impl);
/* D6c Java enum method — EXPECTED UNCERTAIN */
RUN_TEST(cp_enum_method_java);
/* D6d Java interface method — #1234 regression */
RUN_TEST(cp_interface_method_no_dup_function);
/* ── AREA E1: Nested classes (3 cases) ──────────── */
/* E1a Python inner class — EXPECTED GREEN */
+51
View File
@@ -431,6 +431,55 @@ TEST(java_interface) {
PASS();
}
/* Regression for #1234: Java interface/enum methods were emitted as both a
* Method node (correct, via extract_class_methods) and a duplicate Function
* node (incorrect, via walk_defs). Prevention in push_class_body_children
* (gated to Java) recognizes interface_body and enum_body as class body
* containers, stopping the fallback path from re-walking method_declaration
* children as top-level functions. */
TEST(java_interface_no_duplicate_function_issue1234) {
CBMFileResult *r =
extract("public interface MarketplaceService {\n"
" ReservationDTO createReservation(Authentication auth, RequestDTO req);\n"
" void cancelReservation(long id);\n"
"}\n",
CBM_LANG_JAVA, "t", "MarketplaceService.java");
ASSERT_NOT_NULL(r);
ASSERT_FALSE(r->has_error);
ASSERT(has_def(r, "Interface", "MarketplaceService"));
ASSERT(has_def(r, "Method", "createReservation"));
ASSERT(has_def(r, "Method", "cancelReservation"));
ASSERT_EQ(count_defs_with_label(r, "Function"), 0);
cbm_free_result(r);
PASS();
}
TEST(java_enum_dedup_preserves_calls_issue1234) {
CBMFileResult *r =
extract("package app;\n\nenum Day {\n"
" MON, TUE, WED, THU, FRI, SAT, SUN;\n\n"
" public boolean isWeekend() { return this == SAT || this == SUN; }\n"
" public String label() { return name().toLowerCase(); }\n}\n\n"
"class DayUtil {\n"
" static String describe(Day d) {\n"
" return d.label() + (d.isWeekend() ? \"(rest)\" : \"(work)\");\n }\n}\n",
CBM_LANG_JAVA, "t", "Day.java");
ASSERT_NOT_NULL(r);
ASSERT_FALSE(r->has_error);
ASSERT(has_def(r, "Enum", "Day"));
ASSERT(has_def(r, "Method", "isWeekend"));
ASSERT(has_def(r, "Method", "label"));
ASSERT(has_def(r, "Class", "DayUtil"));
ASSERT(has_def(r, "Method", "describe"));
ASSERT_EQ(count_defs_with_label(r, "Function"), 0);
cbm_free_result(r);
PASS();
}
/* Regression for #279: a Java class declaring both `extends` and
* `implements` must produce one INHERITS edge per base — the extends parent
* AND every implements interface — with bare type names (not the keyword
@@ -5183,6 +5232,8 @@ SUITE(extraction) {
RUN_TEST(java_class);
RUN_TEST(java_method);
RUN_TEST(java_interface);
RUN_TEST(java_interface_no_duplicate_function_issue1234);
RUN_TEST(java_enum_dedup_preserves_calls_issue1234);
RUN_TEST(java_class_extends_and_implements);
RUN_TEST(python_class_base_extracted_bare);
RUN_TEST(php_class);