578/240 — rustc-0004/vertx-0001/asterisk-0003/bitcoin-0001/actix-web-0003/hazelcast-0001+0002/rabbitmq-0005/nginx-0003/haproxy-0003/envoy-0003/istio-0003
This commit is contained in:
parent
dde5ec97fb
commit
e4ee168b1e
50 changed files with 4775 additions and 5 deletions
111
defects/vertx/unit/HAManagerNodeLeftAlgorithm.java
Normal file
111
defects/vertx/unit/HAManagerNodeLeftAlgorithm.java
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test — vertx-0001
|
||||
*
|
||||
* HAManager.nodeLeft() scans clusterMap (C entries) and calls nodes.contains() on a
|
||||
* List<String> for each entry → O(C × N) = O(N²) in cluster size.
|
||||
*
|
||||
* Fix: convert nodes List to HashSet before the loop → O(N) total.
|
||||
*/
|
||||
public class HAManagerNodeLeftAlgorithm {
|
||||
|
||||
// Simulated clusterMap: nodeId -> haInfo (one entry per cluster node)
|
||||
static Map<String, String> buildClusterMap(int clusterSize) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
for (int i = 0; i < clusterSize; i++) {
|
||||
map.put("node-" + i, "{\"group\":\"default\",\"id\":\"node-" + i + "\"}");
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// Simulated getNodes() — returns a List (as per ClusteredNode SPI contract)
|
||||
static List<String> buildNodesList(int clusterSize) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (int i = 0; i < clusterSize; i++) {
|
||||
list.add("node-" + i);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// SLOW: original pattern — List.contains inside loop
|
||||
static long slowNodeLeft(Map<String, String> clusterMap, List<String> nodes, String leftNodeID) {
|
||||
long slowOps = 0;
|
||||
for (Map.Entry<String, String> entry : clusterMap.entrySet()) {
|
||||
if (!leftNodeID.equals(entry.getKey())) {
|
||||
// O(N) scan per iteration — the defect
|
||||
for (String n : nodes) {
|
||||
slowOps++;
|
||||
if (n.equals(entry.getKey())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return slowOps;
|
||||
}
|
||||
|
||||
// FAST: fixed pattern — HashSet.contains inside loop
|
||||
static long fastNodeLeft(Map<String, String> clusterMap, List<String> nodes, String leftNodeID) {
|
||||
Set<String> nodesSet = new HashSet<>(nodes); // O(N) once
|
||||
long fastOps = 0;
|
||||
for (Map.Entry<String, String> entry : clusterMap.entrySet()) {
|
||||
if (!leftNodeID.equals(entry.getKey())) {
|
||||
// O(1) lookup
|
||||
fastOps++;
|
||||
nodesSet.contains(entry.getKey());
|
||||
}
|
||||
}
|
||||
return fastOps;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] sizes = {100, 250, 500};
|
||||
int pass = 0;
|
||||
int fail = 0;
|
||||
double minRatio = Double.MAX_VALUE;
|
||||
|
||||
for (int N : sizes) {
|
||||
Map<String, String> clusterMap = buildClusterMap(N);
|
||||
List<String> nodes = buildNodesList(N);
|
||||
String leftNodeID = "node-" + (N - 1);
|
||||
|
||||
long slowOps = slowNodeLeft(clusterMap, nodes, leftNodeID);
|
||||
long fastOps = fastNodeLeft(clusterMap, nodes, leftNodeID);
|
||||
|
||||
// Expected: slow ≈ triangular number sum of scan depths ≈ N*(N-1)/2
|
||||
// fast = O(N-1) operations (one per remaining entry, O(1) each)
|
||||
long expectedSlow = (long) N * (N - 1) / 2; // approximate
|
||||
long expectedFast = N - 1;
|
||||
|
||||
double ratio = (double) slowOps / fastOps;
|
||||
|
||||
// Verify ordering
|
||||
boolean ok = slowOps > fastOps && ratio >= 5.0;
|
||||
if (ok) {
|
||||
pass++;
|
||||
} else {
|
||||
fail++;
|
||||
System.out.printf("FAIL N=%d: slowOps=%d fastOps=%d ratio=%.1f%n",
|
||||
N, slowOps, fastOps, ratio);
|
||||
}
|
||||
|
||||
System.out.printf("N=%d: slowOps=%d fastOps=%d ratio=%.1fx [%s]%n",
|
||||
N, slowOps, fastOps, ratio, ok ? "PASS" : "FAIL");
|
||||
|
||||
minRatio = Math.min(minRatio, ratio);
|
||||
}
|
||||
|
||||
System.out.printf("%d/%d PASS (min ratio=%.1fx)%n", pass, pass + fail, minRatio);
|
||||
if (fail > 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue