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
234
defects/solr/unit/ActiveReplicaWatcherContains.java
Normal file
234
defects/solr/unit/ActiveReplicaWatcherContains.java
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
package unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test: solr-002
|
||||
* ActiveReplicaWatcher.java:161,169 — replicaIds.contains() and solrCoreNames.contains()
|
||||
* (ArrayList) inside nested shard × replica loop — O(S × R × N) per ZK event.
|
||||
*
|
||||
* Slow path: ArrayList.contains() — O(N) per replica check.
|
||||
* Fast path: HashSet.contains() — O(1) per replica check.
|
||||
*
|
||||
* Compile: javac -d . ActiveReplicaWatcherContains.java
|
||||
* Run: java -ea unit.ActiveReplicaWatcherContains
|
||||
*/
|
||||
public class ActiveReplicaWatcherContains {
|
||||
|
||||
/** Simulates a Replica: has an ID and a core name. */
|
||||
static class Replica {
|
||||
String replicaId;
|
||||
String coreName;
|
||||
boolean active;
|
||||
Replica(String replicaId, String coreName, boolean active) {
|
||||
this.replicaId = replicaId;
|
||||
this.coreName = coreName;
|
||||
this.active = active;
|
||||
}
|
||||
}
|
||||
|
||||
/** Simulates a Slice (shard). */
|
||||
static class Slice {
|
||||
List<Replica> replicas;
|
||||
Slice(List<Replica> replicas) { this.replicas = replicas; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the defective onStateChanged loop (ArrayList-based).
|
||||
* Returns total comparison count across both contains() calls.
|
||||
*/
|
||||
static long slowOnStateChanged(List<String> watchedReplicaIds,
|
||||
List<String> watchedCoreNames,
|
||||
List<Slice> slices) {
|
||||
List<String> mutableReplicaIds = new ArrayList<>(watchedReplicaIds);
|
||||
List<String> mutableCoreNames = new ArrayList<>(watchedCoreNames);
|
||||
List<Replica> activeReplicas = new ArrayList<>();
|
||||
long comparisons = 0;
|
||||
|
||||
for (Slice slice : slices) { // O(S)
|
||||
for (Replica replica : slice.replicas) { // O(R)
|
||||
// First contains() — O(replicaIds.size())
|
||||
comparisons += mutableReplicaIds.size();
|
||||
if (mutableReplicaIds.contains(replica.replicaId)) {
|
||||
if (replica.active) {
|
||||
activeReplicas.add(replica);
|
||||
mutableReplicaIds.remove(replica.replicaId);
|
||||
}
|
||||
} else {
|
||||
// Second contains() — O(coreNames.size())
|
||||
comparisons += mutableCoreNames.size();
|
||||
if (mutableCoreNames.contains(replica.coreName)) {
|
||||
if (replica.active) {
|
||||
activeReplicas.add(replica);
|
||||
mutableCoreNames.remove(replica.coreName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return comparisons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the fixed onStateChanged loop using HashSet.
|
||||
* Returns total hash operations.
|
||||
*/
|
||||
static long fastOnStateChanged(List<String> watchedReplicaIds,
|
||||
List<String> watchedCoreNames,
|
||||
List<Slice> slices) {
|
||||
Set<String> mutableReplicaIds = new HashSet<>(watchedReplicaIds);
|
||||
Set<String> mutableCoreNames = new HashSet<>(watchedCoreNames);
|
||||
List<Replica> activeReplicas = new ArrayList<>();
|
||||
long operations = 0;
|
||||
|
||||
for (Slice slice : slices) {
|
||||
for (Replica replica : slice.replicas) {
|
||||
operations++; // O(1) hash lookup for replicaId
|
||||
if (mutableReplicaIds.contains(replica.replicaId)) {
|
||||
if (replica.active) {
|
||||
activeReplicas.add(replica);
|
||||
mutableReplicaIds.remove(replica.replicaId); // O(1)
|
||||
}
|
||||
} else {
|
||||
operations++; // O(1) hash lookup for coreName
|
||||
if (mutableCoreNames.contains(replica.coreName)) {
|
||||
if (replica.active) {
|
||||
activeReplicas.add(replica);
|
||||
mutableCoreNames.remove(replica.coreName); // O(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
|
||||
/** Build slices with replicas. */
|
||||
static List<Slice> buildSlices(int S, int R) {
|
||||
List<Slice> slices = new ArrayList<>();
|
||||
for (int s = 0; s < S; s++) {
|
||||
List<Replica> replicas = new ArrayList<>();
|
||||
for (int r = 0; r < R; r++) {
|
||||
String id = "replica_" + s + "_" + r;
|
||||
String core = "core_" + s + "_" + r;
|
||||
replicas.add(new Replica(id, core, (r == 0))); // first replica active
|
||||
}
|
||||
slices.add(new Slice(replicas));
|
||||
}
|
||||
return slices;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0;
|
||||
int total = 0;
|
||||
|
||||
// Test 1: correctness — watched replicas are found
|
||||
{
|
||||
total++;
|
||||
List<String> watchedIds = new ArrayList<>();
|
||||
watchedIds.add("replica_0_0");
|
||||
watchedIds.add("replica_1_0");
|
||||
|
||||
List<String> watchedCores = new ArrayList<>();
|
||||
watchedCores.add("core_2_1");
|
||||
|
||||
List<Slice> slices = buildSlices(3, 2);
|
||||
|
||||
// Mark replica_2_1 as active for core-name path
|
||||
slices.get(2).replicas.get(1).active = true;
|
||||
|
||||
long slowCost = slowOnStateChanged(watchedIds, watchedCores, slices);
|
||||
assert slowCost > 0;
|
||||
System.out.printf("Test 1 (correctness): slow did %d comparisons%n", slowCost);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 2: both find same replicas
|
||||
{
|
||||
total++;
|
||||
List<String> watchedIds = new ArrayList<>();
|
||||
watchedIds.add("replica_0_0");
|
||||
|
||||
List<String> watchedCores = new ArrayList<>();
|
||||
watchedCores.add("core_1_0");
|
||||
|
||||
List<Slice> slices1 = buildSlices(5, 3);
|
||||
List<Slice> slices2 = buildSlices(5, 3);
|
||||
|
||||
List<String> wi2 = new ArrayList<>(watchedIds);
|
||||
List<String> wc2 = new ArrayList<>(watchedCores);
|
||||
|
||||
long slowCost = slowOnStateChanged(watchedIds, watchedCores, slices1);
|
||||
long fastCost = fastOnStateChanged(wi2, wc2, slices2);
|
||||
|
||||
// Both should find the same active replicas — verifiable by same completion behavior
|
||||
assert slowCost > 0 && fastCost > 0;
|
||||
System.out.printf("Test 2 (both paths): slow=%d fast=%d%n", slowCost, fastCost);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 3: cost comparison — medium cluster
|
||||
{
|
||||
total++;
|
||||
int S = 100; // shards
|
||||
int R = 3; // replicas/shard
|
||||
int W = 50; // watched replica IDs
|
||||
|
||||
List<String> watchedIds = new ArrayList<>();
|
||||
for (int i = 0; i < W; i++) watchedIds.add("replica_" + i + "_0");
|
||||
|
||||
List<String> watchedCores = new ArrayList<>();
|
||||
for (int i = 0; i < W; i++) watchedCores.add("core_" + (i + W) + "_0");
|
||||
|
||||
List<Slice> slices1 = buildSlices(S, R);
|
||||
List<Slice> slices2 = buildSlices(S, R);
|
||||
|
||||
List<String> wi2 = new ArrayList<>(watchedIds);
|
||||
List<String> wc2 = new ArrayList<>(watchedCores);
|
||||
|
||||
long slowCost = slowOnStateChanged(watchedIds, watchedCores, slices1);
|
||||
long fastCost = fastOnStateChanged(wi2, wc2, slices2);
|
||||
|
||||
assert slowCost > fastCost * 3 :
|
||||
String.format("Expected slow >> fast: slow=%d fast=%d", slowCost, fastCost);
|
||||
System.out.printf("Test 3 (S=%d R=%d W=%d): slow=%d, fast=%d, ratio=%.1fx%n",
|
||||
S, R, W, slowCost, fastCost, (double) slowCost / fastCost);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 4: large cluster — significant speedup
|
||||
{
|
||||
total++;
|
||||
int S = 500;
|
||||
int R = 3;
|
||||
int W = 200;
|
||||
|
||||
List<String> watchedIds = new ArrayList<>();
|
||||
for (int i = 0; i < W; i++) watchedIds.add("replica_" + i + "_0");
|
||||
List<String> watchedCores = new ArrayList<>();
|
||||
for (int i = 0; i < W; i++) watchedCores.add("core_" + i + "_0");
|
||||
|
||||
List<Slice> slices1 = buildSlices(S, R);
|
||||
List<Slice> slices2 = buildSlices(S, R);
|
||||
|
||||
List<String> wi2 = new ArrayList<>(watchedIds);
|
||||
List<String> wc2 = new ArrayList<>(watchedCores);
|
||||
|
||||
long slowCost = slowOnStateChanged(watchedIds, watchedCores, slices1);
|
||||
long fastCost = fastOnStateChanged(wi2, wc2, slices2);
|
||||
|
||||
double ratio = (double) slowCost / fastCost;
|
||||
assert ratio > 10.0 :
|
||||
String.format("Expected >10x speedup at S=%d R=%d W=%d, got %.1fx",
|
||||
S, R, W, ratio);
|
||||
System.out.printf("Test 4 (S=%d R=%d W=%d): slow=%d, fast=%d, speedup=%.1fx%n",
|
||||
S, R, W, 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