whitepaper: 352/169 — wave4 MEDIUM (hadoop/hbase/nova/neutron/openstack) + fix odl-0002 dup
This commit is contained in:
parent
9934133dcf
commit
835ae73b0f
82 changed files with 5931 additions and 6 deletions
216
defects/puppet/unit/PuppetGraphTest.java
Normal file
216
defects/puppet/unit/PuppetGraphTest.java
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
package unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* PuppetGraphTest
|
||||
*
|
||||
* Models one CWE-407 defect in puppetlabs/puppet:
|
||||
*
|
||||
* PUP-001 (LOW, error path) — lib/puppet/graph/simple_graph.rb:214
|
||||
* paths_in_cycle() BFS: frame[1].member?(frame[0]) where frame[1] is a
|
||||
* growing Array. Each membership test is O(path_length); paths grow as
|
||||
* BFS expands; in a fully connected cycle of length N this produces
|
||||
* O(N^3) total comparisons.
|
||||
*
|
||||
* Fix: carry a parallel Set alongside the Array in each BFS frame.
|
||||
* frame[2].include?(frame[0]) is O(1) average. Array is retained for
|
||||
* ordered path output.
|
||||
*
|
||||
* All measurements are instrumented operation counts, not wall-clock timing.
|
||||
*/
|
||||
public class PuppetGraphTest {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// PUP-001 modelling helpers
|
||||
// Models BFS over a simple directed cycle: 0 -> 1 -> 2 -> ... -> (N-1) -> 0
|
||||
// BFS explores from vertex 0; paths grow until cycle is detected.
|
||||
//
|
||||
// Defective: frame path is ArrayList; membership test iterates the whole list.
|
||||
// Fixed: parallel HashSet; membership test is O(1).
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Simulates defective paths_in_cycle BFS on a simple cycle of length N.
|
||||
* Returns total membership-test comparisons performed.
|
||||
*
|
||||
* BFS frame = [vertex, path_as_ArrayList]
|
||||
* Cycle detection: path.contains(vertex) -- O(path.size()) per call
|
||||
*/
|
||||
static long pup001Defective(int cycleLen) {
|
||||
// Use pair representation: ArrayList<int[]> where int[0]=vertex, index into paths list
|
||||
// But model directly with operation counting
|
||||
|
||||
// BFS: frame = (vertex, path ArrayList)
|
||||
ArrayList<Object[]> stack = new ArrayList<>();
|
||||
ArrayList<Integer> emptyPath = new ArrayList<>();
|
||||
stack.add(new Object[]{0, emptyPath});
|
||||
|
||||
long comparisons = 0;
|
||||
int steps = 0;
|
||||
int maxSteps = cycleLen * cycleLen * 4; // safety bound
|
||||
|
||||
while (!stack.isEmpty() && steps < maxSteps) {
|
||||
steps++;
|
||||
Object[] frame = stack.remove(0); // shift (BFS)
|
||||
int vertex = (Integer) frame[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<Integer> path = (ArrayList<Integer>) frame[1];
|
||||
|
||||
// Defective: path.contains(vertex) -- O(path.size()) comparisons
|
||||
boolean inPath = false;
|
||||
for (Integer p : path) {
|
||||
comparisons++;
|
||||
if (p == vertex) {
|
||||
inPath = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inPath) {
|
||||
// cycle found — stop this branch
|
||||
} else {
|
||||
// extend path and push next vertex
|
||||
ArrayList<Integer> newPath = new ArrayList<>(path);
|
||||
newPath.add(vertex);
|
||||
int next = (vertex + 1) % cycleLen;
|
||||
stack.add(new Object[]{next, newPath});
|
||||
}
|
||||
}
|
||||
return comparisons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates fixed paths_in_cycle BFS on a simple cycle of length N.
|
||||
* Returns total membership-test operations (each O(1) hash lookup = 1 op).
|
||||
*
|
||||
* BFS frame = [vertex, path_ArrayList, path_HashSet]
|
||||
* Cycle detection: pathSet.contains(vertex) -- O(1) per call
|
||||
*/
|
||||
static long pup001Fixed(int cycleLen) {
|
||||
ArrayList<Object[]> stack = new ArrayList<>();
|
||||
ArrayList<Integer> emptyPath = new ArrayList<>();
|
||||
HashSet<Integer> emptySet = new HashSet<>();
|
||||
stack.add(new Object[]{0, emptyPath, emptySet});
|
||||
|
||||
long lookups = 0;
|
||||
int steps = 0;
|
||||
int maxSteps = cycleLen * cycleLen * 4;
|
||||
|
||||
while (!stack.isEmpty() && steps < maxSteps) {
|
||||
steps++;
|
||||
Object[] frame = stack.remove(0);
|
||||
int vertex = (Integer) frame[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<Integer> path = (ArrayList<Integer>) frame[1];
|
||||
@SuppressWarnings("unchecked")
|
||||
HashSet<Integer> pathSet = (HashSet<Integer>) frame[2];
|
||||
|
||||
// Fixed: pathSet.contains(vertex) -- O(1) lookup
|
||||
lookups++;
|
||||
boolean inPath = pathSet.contains(vertex);
|
||||
|
||||
if (inPath) {
|
||||
// cycle found — stop this branch
|
||||
} else {
|
||||
ArrayList<Integer> newPath = new ArrayList<>(path);
|
||||
newPath.add(vertex);
|
||||
@SuppressWarnings("unchecked")
|
||||
HashSet<Integer> newSet = (HashSet<Integer>) pathSet.clone();
|
||||
newSet.add(vertex);
|
||||
int next = (vertex + 1) % cycleLen;
|
||||
stack.add(new Object[]{next, newPath, newSet});
|
||||
}
|
||||
}
|
||||
return lookups;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 1 — PUP-001: defect costs more than fix at cycle_len=20
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
static void test1_pup001_pathMembershipSet() {
|
||||
int N = 20;
|
||||
long defectCost = pup001Defective(N);
|
||||
long fixedCost = pup001Fixed(N);
|
||||
double ratio = (double) defectCost / Math.max(1, fixedCost);
|
||||
|
||||
System.out.printf("test1 PUP-001: cycle_len=%d defect=%d fixed=%d ratio=%.1fx%n",
|
||||
N, defectCost, fixedCost, ratio);
|
||||
|
||||
assert defectCost > fixedCost
|
||||
: "defect must be more expensive than fix at cycle_len=" + N
|
||||
+ " (defect=" + defectCost + ", fixed=" + fixedCost + ")";
|
||||
assert ratio >= 8.0
|
||||
: "expected ratio >= 8x at cycle_len=" + N + ", got " + ratio;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 2 — PUP-001: scaling — doubling cycle length grows defect faster
|
||||
// than the fix (super-linear vs near-linear)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
static void test2_pup001_scalingGrowth() {
|
||||
int N1 = 15;
|
||||
int N2 = 30; // doubled
|
||||
|
||||
long d1 = pup001Defective(N1);
|
||||
long d2 = pup001Defective(N2);
|
||||
long f1 = pup001Fixed(N1);
|
||||
long f2 = pup001Fixed(N2);
|
||||
|
||||
double defectGrowth = (double) d2 / Math.max(1, d1);
|
||||
double fixedGrowth = (double) f2 / Math.max(1, f1);
|
||||
|
||||
System.out.printf("test2 PUP-001: N=%d→%d defect=%d→%d (%.2fx) fixed=%d→%d (%.2fx)%n",
|
||||
N1, N2, d1, d2, defectGrowth, f1, f2, fixedGrowth);
|
||||
|
||||
assert defectGrowth > 2.0
|
||||
: "defect should grow super-linearly on 2x cycle_len, got " + defectGrowth;
|
||||
assert fixedGrowth <= 3.0
|
||||
: "fixed should grow at most linearly (×2 ± slack) on 2x cycle_len, got " + fixedGrowth;
|
||||
assert defectGrowth > fixedGrowth
|
||||
: "defect growth " + defectGrowth + " should exceed fixed growth " + fixedGrowth;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 3 — PUP-001: ratio at cycle_len=25 exceeds 5x
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
static void test3_pup001_ratioAt25() {
|
||||
int N = 25;
|
||||
long defectOps = pup001Defective(N);
|
||||
long fixedOps = pup001Fixed(N);
|
||||
double ratio = (double) defectOps / Math.max(1, fixedOps);
|
||||
|
||||
System.out.printf("test3 PUP-001: cycle_len=%d defect=%d fixed=%d ratio=%.1fx%n",
|
||||
N, defectOps, fixedOps, ratio);
|
||||
|
||||
assert ratio > 5.0
|
||||
: "expected ratio > 5x at cycle_len=25, got " + ratio;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Main
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== PuppetGraphTest ===");
|
||||
System.out.println("Modelling CWE-407: PUP-001 (paths_in_cycle BFS Array#member? O(N^3))");
|
||||
System.out.println();
|
||||
|
||||
test1_pup001_pathMembershipSet();
|
||||
System.out.println(" PASS test1_pup001_pathMembershipSet");
|
||||
|
||||
test2_pup001_scalingGrowth();
|
||||
System.out.println(" PASS test2_pup001_scalingGrowth");
|
||||
|
||||
test3_pup001_ratioAt25();
|
||||
System.out.println(" PASS test3_pup001_ratioAt25");
|
||||
|
||||
System.out.println();
|
||||
System.out.println("3/3 PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue