import java.util.*; /** * CWE-407 unit tests for Nomad new defects. * * nomad-0005: scheduler/reconciler/reconcile_cluster.go ~line 1337 * handleReconnectingAllocs() builds a []string replacements slice by following * the NextAllocation linked list, then iterates all allocs with: * slices.Contains(replacements, replacementAlloc.ID) * This is O(|all| × |replacements|) = O(A × R). * In a deployment with many reconnecting allocations and a large alloc set, * this becomes effectively O(A²). * Fix: map[string]struct{} built from the linked-list walk → O(1) membership. * * Note: nomad-0001 through nomad-0004 (bitmap port alloc, stream namespace * filter, vault secrets dedup, checkstore difference) were found in a prior * scan and carry UNDF-2026-000000476 through UNDF-2026-000000479. * nomad-0005 is the reconnect reconciler defect first identified here. */ public class NomadTest { // --- nomad-0005 simulation --- static boolean containsReplacements_slice(List replacements, String allocID) { return replacements.contains(allocID); // O(R) — defect } static boolean containsReplacements_map(Set replacementsSet, String allocID) { return replacementsSet.contains(allocID); // O(1) — fix } static void testNomad0005() throws Exception { int A = 2000; // total allocations in a large deployment int R = 500; // length of replacement chain per reconnecting alloc List replacementsSlice = new ArrayList<>(R); Set replacementsSet = new HashSet<>(R); for (int i = 0; i < R; i++) { String id = "alloc-replace-" + i; replacementsSlice.add(id); replacementsSet.add(id); } // alloc IDs that the outer loop iterates over all allocations List allAllocIDs = new ArrayList<>(A); for (int i = 0; i < A; i++) allAllocIDs.add("alloc-" + i); // worst-case candidate: last entry in replacements (tail of chain) String targetID = "alloc-replace-" + (R - 1); long t0 = System.nanoTime(); int hitSlice = 0; for (String id : allAllocIDs) { if (containsReplacements_slice(replacementsSlice, targetID)) hitSlice++; } long sliceNs = System.nanoTime() - t0; long t1 = System.nanoTime(); int hitMap = 0; for (String id : allAllocIDs) { if (containsReplacements_map(replacementsSet, targetID)) hitMap++; } long mapNs = System.nanoTime() - t1; if (hitSlice != hitMap) throw new AssertionError("result mismatch: " + hitSlice + " vs " + hitMap); double ratio = (double) sliceNs / Math.max(mapNs, 1); System.out.printf("nomad-0005 PASS A=%d R=%d slice=%dns map=%dns ratio=%.1fx%n", A, R, sliceNs, mapNs, ratio); if (ratio < 5.0) throw new AssertionError("expected speedup >= 5x, got " + ratio); } public static void main(String[] args) throws Exception { testNomad0005(); System.out.println("ALL PASS"); } }