whitepaper: 366/178 — wave5 defect tables + PDF rebuild
This commit is contained in:
parent
835ae73b0f
commit
a4b0cf4edd
79 changed files with 3829 additions and 17 deletions
167
defects/podman/unit/RunningPodsAlgorithm.java
Normal file
167
defects/podman/unit/RunningPodsAlgorithm.java
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test: podman GetRunningPods
|
||||
* File: libpod/runtime_pod.go:147 — GetRunningPods
|
||||
*
|
||||
* Slow: for each container, scan pods []string via slices.Contains → O(n²)
|
||||
* Fast: use map[string]bool for seen set → O(n)
|
||||
*
|
||||
* Run: javac -d . RunningPodsAlgorithm.java && java -ea unit.RunningPodsAlgorithm
|
||||
*/
|
||||
public class RunningPodsAlgorithm {
|
||||
|
||||
// ── Slow implementation (mirrors defective Go code) ───────────────────────
|
||||
static class SlowGetRunningPods {
|
||||
final long ops;
|
||||
final List<String> podIDs;
|
||||
|
||||
SlowGetRunningPods(List<String> containerPodIDs) {
|
||||
long count = 0;
|
||||
List<String> pods = new ArrayList<>();
|
||||
for (String podID : containerPodIDs) {
|
||||
// slices.Contains(pods, podID) — O(n) scan
|
||||
boolean found = false;
|
||||
for (String existing : pods) {
|
||||
count++;
|
||||
if (existing.equals(podID)) { found = true; break; }
|
||||
}
|
||||
if (!found) {
|
||||
pods.add(podID);
|
||||
}
|
||||
}
|
||||
this.ops = count;
|
||||
this.podIDs = pods;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Fast implementation (proposed fix) ────────────────────────────────────
|
||||
static class FastGetRunningPods {
|
||||
final long ops;
|
||||
final List<String> podIDs;
|
||||
|
||||
FastGetRunningPods(List<String> containerPodIDs) {
|
||||
long count = 0;
|
||||
Map<String, Boolean> seen = new HashMap<>(containerPodIDs.size() * 2);
|
||||
List<String> pods = new ArrayList<>();
|
||||
for (String podID : containerPodIDs) {
|
||||
count++; // O(1) map lookup
|
||||
if (!seen.getOrDefault(podID, false)) {
|
||||
seen.put(podID, true);
|
||||
pods.add(podID);
|
||||
}
|
||||
}
|
||||
this.ops = count;
|
||||
this.podIDs = pods;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Node / Result types ───────────────────────────────────────────────────
|
||||
static class Node {
|
||||
final String containerID;
|
||||
final String podID;
|
||||
Node(String containerID, String podID) {
|
||||
this.containerID = containerID;
|
||||
this.podID = podID;
|
||||
}
|
||||
}
|
||||
|
||||
static class Result {
|
||||
final long slowOps;
|
||||
final long fastOps;
|
||||
final List<String> slowPods;
|
||||
final List<String> fastPods;
|
||||
|
||||
Result(long slowOps, long fastOps, List<String> slowPods, List<String> fastPods) {
|
||||
this.slowOps = slowOps;
|
||||
this.fastOps = fastOps;
|
||||
this.slowPods = slowPods;
|
||||
this.fastPods = fastPods;
|
||||
}
|
||||
}
|
||||
|
||||
// ── test infrastructure ───────────────────────────────────────────────────
|
||||
static int passed = 0, total = 0;
|
||||
|
||||
static void test(String name, boolean condition) {
|
||||
total++;
|
||||
if (condition) { passed++; System.out.println("PASS: " + name); }
|
||||
else { System.out.println("FAIL: " + name); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a workload: nContainers containers spread across nPods pods.
|
||||
* containersPerPod = nContainers / nPods (worst case for dedup).
|
||||
*/
|
||||
static Result run(int nContainers, int nPods) {
|
||||
List<String> containerPodIDs = new ArrayList<>(nContainers);
|
||||
for (int i = 0; i < nContainers; i++) {
|
||||
containerPodIDs.add("pod-" + (i % nPods));
|
||||
}
|
||||
|
||||
SlowGetRunningPods slow = new SlowGetRunningPods(containerPodIDs);
|
||||
FastGetRunningPods fast = new FastGetRunningPods(containerPodIDs);
|
||||
return new Result(slow.ops, fast.ops, slow.podIDs, fast.podIDs);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// T1: 1000 containers, 100 pods (10 containers per pod)
|
||||
{
|
||||
Result r = run(1000, 100);
|
||||
// Slow: each of 1000 containers scans growing pods list — sum ~0+1+2+... per batch
|
||||
// Fast: 1000 O(1) lookups
|
||||
test("T1-slow-is-quadratic [N=1000,pods=100]",
|
||||
r.slowOps > 1000); // definitely more than linear
|
||||
test("T1-fast-is-linear [N=1000,pods=100]",
|
||||
r.fastOps <= 1000 + 5);
|
||||
double speedup = (double) r.slowOps / r.fastOps;
|
||||
test("T1-speedup>=10x", speedup >= 10.0);
|
||||
System.out.printf(" slow=%d ops, fast=%d ops, speedup=%.1fx%n",
|
||||
r.slowOps, r.fastOps, speedup);
|
||||
List<String> ss = new ArrayList<>(r.slowPods); Collections.sort(ss);
|
||||
List<String> fs = new ArrayList<>(r.fastPods); Collections.sort(fs);
|
||||
test("T1-results-match", ss.equals(fs));
|
||||
}
|
||||
|
||||
// T2: 5000 containers, 500 pods (10 per pod)
|
||||
{
|
||||
Result r = run(5000, 500);
|
||||
double speedup = (double) r.slowOps / r.fastOps;
|
||||
test("T2-slow-quadratic [N=5000,pods=500]", r.slowOps > 5000);
|
||||
test("T2-fast-linear [N=5000]", r.fastOps <= 5000 + 5);
|
||||
test("T2-speedup>=10x", speedup >= 10.0);
|
||||
System.out.printf(" slow=%d ops, fast=%d ops, speedup=%.1fx%n",
|
||||
r.slowOps, r.fastOps, speedup);
|
||||
List<String> ss = new ArrayList<>(r.slowPods); Collections.sort(ss);
|
||||
List<String> fs = new ArrayList<>(r.fastPods); Collections.sort(fs);
|
||||
test("T2-results-match", ss.equals(fs));
|
||||
}
|
||||
|
||||
// T3: 100 containers, all different pods (max dedup overhead)
|
||||
{
|
||||
Result r = run(100, 100);
|
||||
// Each container requires full scan of growing pods list
|
||||
// Total: 0+1+2+...+99 = 4950 ops for slow
|
||||
test("T3-slow-sum-series [N=100,pods=100]", r.slowOps >= 100L * 99 / 2);
|
||||
test("T3-fast-linear [N=100]", r.fastOps <= 100 + 5);
|
||||
double speedup = (double) r.slowOps / r.fastOps;
|
||||
test("T3-speedup>=40x [N=100]", speedup >= 40.0);
|
||||
System.out.printf(" slow=%d ops, fast=%d ops, speedup=%.1fx%n",
|
||||
r.slowOps, r.fastOps, speedup);
|
||||
}
|
||||
|
||||
// T4: Correctness — single pod, many containers
|
||||
{
|
||||
Result r = run(50, 1);
|
||||
test("T4-single-pod-result", r.fastPods.size() == 1);
|
||||
test("T4-single-pod-results-match",
|
||||
r.slowPods.equals(r.fastPods));
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.printf("%d/%d PASS%n", passed, total);
|
||||
if (passed != total) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue