wave6a/6b: elasticsearch/opensearch/solr/llvm-0004-5/linux-0005-6/gcc-0002/tokio/actix-web + love2d/raylib new defects
This commit is contained in:
parent
a4b0cf4edd
commit
3eebda37e1
38 changed files with 3651 additions and 0 deletions
195
defects/solr/unit/ClusterStatusLiveNodesContains.java
Normal file
195
defects/solr/unit/ClusterStatusLiveNodesContains.java
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
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: solr-001
|
||||
* ClusterStatus.java:303 — liveNodes.contains(node_name) (List) inside double
|
||||
* loop over shards × replicas — O(N × S × R) per CLUSTERSTATUS request.
|
||||
*
|
||||
* Slow path: List<String>.contains() — O(N) per replica.
|
||||
* Fast path: HashSet<String>.contains() — O(1) per replica.
|
||||
*
|
||||
* Compile: javac -d . ClusterStatusLiveNodesContains.java
|
||||
* Run: java -ea unit.ClusterStatusLiveNodesContains
|
||||
*/
|
||||
public class ClusterStatusLiveNodesContains {
|
||||
|
||||
/** Simulates a Replica record. */
|
||||
static class Replica {
|
||||
String nodeName;
|
||||
String state; // "active" or "down"
|
||||
Replica(String nodeName, String state) {
|
||||
this.nodeName = nodeName;
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
||||
/** Simulates a Shard record. */
|
||||
static class Shard {
|
||||
List<Replica> replicas;
|
||||
Shard(List<Replica> replicas) { this.replicas = replicas; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the defective crossCheckReplicaStateWithLiveNodes.
|
||||
* Returns total comparison count (liveNodes.contains() calls × avg scan length).
|
||||
*/
|
||||
static long slowCrossCheck(List<String> liveNodes, List<Shard> shards) {
|
||||
long comparisons = 0;
|
||||
for (Shard shard : shards) {
|
||||
for (Replica replica : shard.replicas) {
|
||||
if (!"down".equals(replica.state)) {
|
||||
// O(liveNodes.size()) scan
|
||||
comparisons += liveNodes.size();
|
||||
if (!liveNodes.contains(replica.nodeName)) {
|
||||
replica.state = "down";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return comparisons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the fixed crossCheckReplicaStateWithLiveNodes using HashSet.
|
||||
* Returns total hash operations (O(1) each).
|
||||
*/
|
||||
static long fastCrossCheck(List<String> liveNodes, List<Shard> shards) {
|
||||
Set<String> liveNodeSet = new HashSet<>(liveNodes); // O(N) once
|
||||
long operations = 0;
|
||||
for (Shard shard : shards) {
|
||||
for (Replica replica : shard.replicas) {
|
||||
if (!"down".equals(replica.state)) {
|
||||
operations++; // O(1) hash lookup
|
||||
if (!liveNodeSet.contains(replica.nodeName)) {
|
||||
replica.state = "down";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
|
||||
/** Build a test cluster: N live nodes, S shards, R replicas each. */
|
||||
static List<Shard> buildCluster(int S, int R, int N) {
|
||||
List<Shard> shards = new ArrayList<>();
|
||||
for (int s = 0; s < S; s++) {
|
||||
List<Replica> replicas = new ArrayList<>();
|
||||
for (int r = 0; r < R; r++) {
|
||||
// Distribute replicas across nodes; node (s*R+r) % N
|
||||
String nodeName = "node" + ((s * R + r) % N);
|
||||
replicas.add(new Replica(nodeName, "active"));
|
||||
}
|
||||
shards.add(new Shard(replicas));
|
||||
}
|
||||
return shards;
|
||||
}
|
||||
|
||||
static List<String> buildLiveNodes(int N) {
|
||||
List<String> nodes = new ArrayList<>();
|
||||
for (int i = 0; i < N; i++) nodes.add("node" + i);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0;
|
||||
int total = 0;
|
||||
|
||||
// Test 1: correctness — replicas on dead nodes get marked DOWN
|
||||
{
|
||||
total++;
|
||||
List<String> liveNodes = new ArrayList<>();
|
||||
liveNodes.add("node0");
|
||||
liveNodes.add("node1");
|
||||
// node2 is dead
|
||||
|
||||
List<Shard> shards = new ArrayList<>();
|
||||
List<Replica> r1 = new ArrayList<>();
|
||||
r1.add(new Replica("node0", "active"));
|
||||
r1.add(new Replica("node2", "active")); // should go DOWN
|
||||
r1.add(new Replica("node1", "active"));
|
||||
shards.add(new Shard(r1));
|
||||
|
||||
slowCrossCheck(liveNodes, shards);
|
||||
|
||||
assert "active".equals(shards.get(0).replicas.get(0).state) : "node0 should stay active";
|
||||
assert "down".equals(shards.get(0).replicas.get(1).state) : "node2 replica should be DOWN";
|
||||
assert "active".equals(shards.get(0).replicas.get(2).state) : "node1 should stay active";
|
||||
System.out.println("Test 1 (correctness): node2 replica correctly marked DOWN");
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 2: fast path correctness
|
||||
{
|
||||
total++;
|
||||
List<String> liveNodes = new ArrayList<>();
|
||||
liveNodes.add("node0");
|
||||
liveNodes.add("node1");
|
||||
|
||||
List<Shard> shards = new ArrayList<>();
|
||||
List<Replica> r1 = new ArrayList<>();
|
||||
r1.add(new Replica("node0", "active"));
|
||||
r1.add(new Replica("node99", "active")); // dead
|
||||
shards.add(new Shard(r1));
|
||||
|
||||
fastCrossCheck(liveNodes, shards);
|
||||
|
||||
assert "active".equals(shards.get(0).replicas.get(0).state);
|
||||
assert "down".equals(shards.get(0).replicas.get(1).state) : "node99 should be DOWN";
|
||||
System.out.println("Test 2 (fast correctness): node99 replica correctly marked DOWN");
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 3: cost comparison — medium cluster
|
||||
{
|
||||
total++;
|
||||
int N = 50; // live nodes
|
||||
int S = 100; // shards
|
||||
int R = 3; // replicas/shard
|
||||
|
||||
List<String> liveNodes = buildLiveNodes(N);
|
||||
List<Shard> slowShards = buildCluster(S, R, N);
|
||||
List<Shard> fastShards = buildCluster(S, R, N);
|
||||
|
||||
long slowCost = slowCrossCheck(liveNodes, slowShards);
|
||||
long fastCost = fastCrossCheck(liveNodes, fastShards);
|
||||
|
||||
assert slowCost > fastCost * 5 :
|
||||
String.format("Expected slow >> fast: slow=%d fast=%d", slowCost, fastCost);
|
||||
System.out.printf("Test 3 (N=%d S=%d R=%d): slow=%d, fast=%d, ratio=%.1fx%n",
|
||||
N, S, R, slowCost, fastCost, (double) slowCost / fastCost);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 4: production-scale cluster
|
||||
{
|
||||
total++;
|
||||
int N = 100; // live nodes
|
||||
int S = 500; // shards
|
||||
int R = 3; // replicas/shard
|
||||
|
||||
List<String> liveNodes = buildLiveNodes(N);
|
||||
List<Shard> slowShards = buildCluster(S, R, N);
|
||||
List<Shard> fastShards = buildCluster(S, R, N);
|
||||
|
||||
long slowCost = slowCrossCheck(liveNodes, slowShards);
|
||||
long fastCost = fastCrossCheck(liveNodes, fastShards);
|
||||
|
||||
double ratio = (double) slowCost / fastCost;
|
||||
assert ratio > 20.0 :
|
||||
String.format("Expected >20x speedup at N=%d S=%d R=%d, got %.1fx",
|
||||
N, S, R, ratio);
|
||||
System.out.printf("Test 4 (N=%d S=%d R=%d): slow=%d, fast=%d, speedup=%.1fx%n",
|
||||
N, S, R, slowCost, fastCost, ratio);
|
||||
passed++;
|
||||
}
|
||||
|
||||
System.out.printf("%n%d/%d PASS%n", passed, total);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue