From 4dd64c6cdf66bdb39dffe0a6148e72dd78f3fc38 Mon Sep 17 00:00:00 2001 From: Kamil Patryk Kozakowski Date: Mon, 13 Jul 2026 21:17:03 +0200 Subject: [PATCH] Add parity test for static routing helper Covers dispatcher routing via static helper methods (e.g. OrderRoutingHelper.payAction()) to ensure JDT and heuristic call-graph engines resolve identical polymorphic events. Co-authored-by: Cursor --- .../JdtCentralDispatcherParityTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/JdtCentralDispatcherParityTest.java b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/JdtCentralDispatcherParityTest.java index 24507e1..257a72a 100644 --- a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/JdtCentralDispatcherParityTest.java +++ b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/JdtCentralDispatcherParityTest.java @@ -73,6 +73,47 @@ class JdtCentralDispatcherParityTest { assertThat(jdtLink.getEvent()).isEqualTo(heuristicLink.getEvent()); } + @Test + void jdtShouldMatchHeuristicForStaticRoutingHelper(@TempDir Path tempDir) throws Exception { + String source = """ + package com.example; + public class ApiController { + CommandGateway gateway; + public void pay() { gateway.routeAndPay(); } + public void ship() { gateway.routeAndShip(); } + } + class CommandGateway { + CentralDispatcher dispatcher; + void routeAndPay() { dispatcher.dispatch("ORDER", OrderRoutingHelper.payAction()); } + void routeAndShip() { dispatcher.dispatch("ORDER", OrderRoutingHelper.shipAction()); } + } + class OrderRoutingHelper { + static String payAction() { return "PAY"; } + static String shipAction() { return "SHIP"; } + } + class CentralDispatcher { + void dispatch(String domain, String action) { + StateMachine sm = new StateMachine(); + sm.sendEvent(OrderEvent.valueOf(action)); + } + } + enum OrderEvent { PAY, SHIP } + class StateMachine { public void sendEvent(OrderEvent e) {} } + class OrderStateMachineConfig {} + """; + CodebaseContext context = scanSource(source, tempDir); + + CallChain heuristicPay = resolveChain(context, CONTROLLER, "pay", STATE_MACHINE, EngineKind.HEURISTIC); + CallChain jdtPay = resolveChain(context, CONTROLLER, "pay", STATE_MACHINE, EngineKind.JDT); + CallChain heuristicShip = resolveChain(context, CONTROLLER, "ship", STATE_MACHINE, EngineKind.HEURISTIC); + CallChain jdtShip = resolveChain(context, CONTROLLER, "ship", STATE_MACHINE, EngineKind.JDT); + + assertThat(jdtPay.getTriggerPoint().getPolymorphicEvents()) + .containsExactlyInAnyOrderElementsOf(heuristicPay.getTriggerPoint().getPolymorphicEvents()); + assertThat(jdtShip.getTriggerPoint().getPolymorphicEvents()) + .containsExactlyInAnyOrderElementsOf(heuristicShip.getTriggerPoint().getPolymorphicEvents()); + } + @Test void jdtShouldMatchHeuristicForDtoCrossHop(@TempDir Path tempDir) throws Exception { String source = """