package unit; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * consul CWE-407 unit tests: * * consul-0001: ExcludeBasedOnChecks — slices.Contains(IgnoreCheckIDs) per check * * No JUnit, no external deps. * Compile: javac -d . ConsulAlgorithmTest.java * Run: java -ea unit.ConsulAlgorithmTest */ public class ConsulAlgorithmTest { static int passed = 0; static int total = 0; // ----------------------------------------------------------------------- // consul-0001: ExcludeBasedOnChecks // // Called in health query hot path for every service node returned. // Outer loop = all checks on the node (C checks). // Inner scan = slices.Contains(opts.IgnoreCheckIDs, check.CheckID) → O(I). // Total for one node: O(C × I). // Total for a health query returning N nodes: O(N × C × I). // ----------------------------------------------------------------------- /** * Slow: mirrors Go ExcludeBasedOnChecks — linear scan over ignoreIDs per check. */ static long slowExcludeBasedOnChecks(String[] checks, String[] ignoreIDs) { long ops = 0; for (String check : checks) { ops++; // slices.Contains linear scan boolean ignored = false; for (String id : ignoreIDs) { ops++; if (id.equals(check)) { ignored = true; break; } } if (!ignored) { // would call ExcludeBasedOnStatus — simulate with a no-op } } return ops; } /** * Fast: pre-build HashSet from ignoreIDs → O(I + C) per node. */ static long fastExcludeBasedOnChecks(String[] checks, String[] ignoreIDs) { long ops = 0; Set ignoreSet = new HashSet<>(); for (String id : ignoreIDs) { ignoreSet.add(id); ops++; } for (String check : checks) { ops++; if (!ignoreSet.contains(check)) { // would call ExcludeBasedOnStatus } } return ops; } static void testExcludeBasedOnChecks() { System.out.println("--- consul-0001: ExcludeBasedOnChecks ---"); // Simulate: many nodes, each with C checks, I ignore IDs int[] ignoreCounts = {20, 50, 100}; int checksPerNode = 30; int nodeCount = 500; for (int i : ignoreCounts) { String[] ignoreIDs = new String[i]; for (int j = 0; j < i; j++) ignoreIDs[j] = "ignore-" + j; // Build checks array for nodeCount nodes × checksPerNode String[] allChecks = new String[nodeCount * checksPerNode]; for (int n = 0; n < nodeCount * checksPerNode; n++) { allChecks[n] = "check-" + (n % (checksPerNode * 2)); // some overlap with ignore } long slowOps = slowExcludeBasedOnChecks(allChecks, ignoreIDs); long fastOps = fastExcludeBasedOnChecks(allChecks, ignoreIDs); double ratio = (double) slowOps / fastOps; boolean pass = ratio > (double) i / 3.0; total++; if (pass) passed++; System.out.printf(" nodes=%-3d checks/node=%d ignoreIDs=%-3d slow=%,10d fast=%,8d ratio=%6.1fx %s%n", nodeCount, checksPerNode, i, slowOps, fastOps, ratio, pass ? "PASS" : "FAIL"); assert pass : "consul-0001 FAIL: ratio=" + ratio; } } // ----------------------------------------------------------------------- public static void main(String[] args) { System.out.println("=== Consul CWE-407 unit tests ==="); testExcludeBasedOnChecks(); System.out.printf("%n%d/%d PASS%n", passed, total); if (passed != total) { System.exit(1); } } }