java-topology/defects/consul/unit/ConsulAlgorithmTest.java

109 lines
3.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<String> 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);
}
}
}