import java.util.*; /** * CWE-407 unit tests for Apache ActiveMQ defects 0002 and 0003. * * activemq-0002: DemandForwardingBridgeSupport.java duplicateSuppressionIsRequired() * candidateConsumers is an ArrayList; matchFound() calls candidateConsumers.contains() * — O(C) per alias per subscription — O(S×N×C) total per network connect. * Fix: convert candidateConsumers to HashSet before the outer sub-scan loop for O(1) lookup. * * activemq-0003: TransactionContext.java isInXATransaction() * ENDED_XA_TRANSACTION_CONTEXTS values are ArrayList; * transactions.contains(this) — O(C) linear scan per XA txn bucket. * Fix: change values to Set for O(1) contains. */ public class ActiveMQTest2 { // Simulate defect: matchFound with ArrayList candidateConsumers static boolean matchFound_list(List candidateConsumers, List networkConsumers) { for (Integer alias : networkConsumers) { if (candidateConsumers.contains(alias)) return true; // O(C) — defect } return false; } // Simulate fix: matchFound with HashSet candidateConsumers static boolean matchFound_set(Set candidateSet, List networkConsumers) { for (Integer alias : networkConsumers) { if (candidateSet.contains(alias)) return true; // O(1) } return false; } static void testActiveMQ0002() throws Exception { int C = 500; // candidateConsumers per remote subscription int S = 2000; // current subscriptions in the region int N = 3; // networkConsumerIds per existing sub (small, 1–3) List candidateList = new ArrayList<>(C); for (int i = 0; i < C; i++) candidateList.add(i); Set candidateSet = new HashSet<>(candidateList); // Build S existing subs, each with N networkConsumerIds (not overlapping — full scan) List> subs = new ArrayList<>(S); for (int s = 0; s < S; s++) { List nc = new ArrayList<>(N); for (int n = 0; n < N; n++) nc.add(C + s * N + n); // no overlap → full C scan each time subs.add(nc); } // correctness: last sub has a matching id → find it subs.get(S - 1).set(0, candidateList.get(0)); boolean r1 = false, r2 = false; for (List nc : subs) { if (matchFound_list(candidateList, nc)) { r1 = true; break; } } for (List nc : subs) { if (matchFound_set(candidateSet, nc)) { r2 = true; break; } } assert r1 == r2 : "list and set must agree: " + r1 + " vs " + r2; // Reset: no match case (worst case — full scan) subs.get(S - 1).set(0, C + S * N + 99); int REPS = 20; long t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) { for (List nc : subs) matchFound_list(candidateList, nc); } long tList = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) { for (List nc : subs) matchFound_set(candidateSet, nc); } long tSet = System.nanoTime() - t0; double ratio = (double) tList / tSet; System.out.printf("activemq-0002: list=%.3fs set=%.3fs ratio=%.1f×%n", tList / 1e9, tSet / 1e9, ratio); assert ratio > 4 : "Expected >4× speedup, got " + ratio; System.out.println("PASS activemq-0002"); } // Simulate defect: isInXATransaction with List values static boolean isInXATransaction_list(Map> endedContexts, int self) { for (List transactions : endedContexts.values()) { if (transactions.contains(self)) return true; // O(C) — defect } return false; } // Simulate fix: isInXATransaction with Set values static boolean isInXATransaction_set(Map> endedContexts, int self) { for (Set transactions : endedContexts.values()) { if (transactions.contains(self)) return true; // O(1) } return false; } static void testActiveMQ0003() throws Exception { int T = 50; // ended XA transaction buckets int C = 200; // contexts per bucket Map> listMap = new LinkedHashMap<>(); Map> setMap = new LinkedHashMap<>(); for (int t = 0; t < T; t++) { List lst = new ArrayList<>(C); Set set = new LinkedHashSet<>(C); for (int c = 0; c < C; c++) { int ctx = t * C + c; lst.add(ctx); set.add(ctx); } listMap.put(t, lst); setMap.put(t, set); } // self not in any bucket → worst case (full scan) int self = T * C + 999; // correctness: not present assert !isInXATransaction_list(listMap, self); assert !isInXATransaction_set(setMap, self); int REPS = 10_000; long t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) isInXATransaction_list(listMap, self); long tList = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) isInXATransaction_set(setMap, self); long tSet = System.nanoTime() - t0; double ratio = (double) tList / tSet; System.out.printf("activemq-0003: list=%.3fs set=%.3fs ratio=%.1f×%n", tList / 1e9, tSet / 1e9, ratio); assert ratio > 5 : "Expected >5× speedup, got " + ratio; System.out.println("PASS activemq-0003"); } public static void main(String[] args) throws Exception { testActiveMQ0002(); testActiveMQ0003(); System.out.println("ALL PASS"); } }