wave8c: 452/202 — envoy/cilium, graph-dbs, elixir/nim, k8s/maven + PDF
This commit is contained in:
parent
c4330be5b0
commit
3c0b3edc79
49 changed files with 3820 additions and 8 deletions
136
defects/dgraph/unit/DgraphTest.java
Normal file
136
defects/dgraph/unit/DgraphTest.java
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for dgraph-0001: CWE-407 O(P) route.indexOf inside k-shortest-path neighbour loop.
|
||||
*
|
||||
* Slow path: ArrayList<Long> path, indexOf = O(P) linear scan.
|
||||
* Fast path: HashMap<Long,Boolean> visited alongside path, lookup = O(1).
|
||||
*
|
||||
* Both produce identical cycle-detection results; the test confirms op counts diverge as N grows.
|
||||
*/
|
||||
public class DgraphTest {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Slow path: simulates route.indexOf — linear scan of path slice
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static long slowIndexOf(List<Long> path, long uid) {
|
||||
for (long val : path) {
|
||||
if (val == uid) return 0; // found
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate k-shortest-paths neighbour expansion with O(P) cycle detection.
|
||||
* Returns total indexOf scan operations performed.
|
||||
*
|
||||
* Graph: linear chain 0→1→2→...→(n-1) plus a back-edge n-1→0 to force cycle checks.
|
||||
* Each dequeue: process n neighbours, call indexOf once per neighbour.
|
||||
* Dequeue n items (one per node). Path grows by 1 per hop.
|
||||
*/
|
||||
static long slowOps(int n) {
|
||||
long ops = 0;
|
||||
// Simulate dequeuing n items with path lengths 1..n
|
||||
for (int hop = 1; hop <= n; hop++) {
|
||||
// path length at this hop = hop
|
||||
int pathLen = hop;
|
||||
// process n neighbours per dequeue
|
||||
for (int nb = 0; nb < n; nb++) {
|
||||
// indexOf scans entire path
|
||||
ops += pathLen;
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Fast path: O(1) HashMap lookup for cycle detection
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static long fastOps(int n) {
|
||||
long ops = 0;
|
||||
// Simulate dequeuing n items with path lengths 1..n
|
||||
for (int hop = 1; hop <= n; hop++) {
|
||||
// n neighbours per dequeue, each is O(1) map lookup = 1 op
|
||||
for (int nb = 0; nb < n; nb++) {
|
||||
ops += 1;
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Correctness check: both strategies agree on cycle detection result
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static boolean slowContains(List<Long> path, long uid) {
|
||||
return slowIndexOf(path, uid) != -1;
|
||||
}
|
||||
|
||||
static boolean fastContains(Map<Long, Boolean> visited, long uid) {
|
||||
return visited.containsKey(uid);
|
||||
}
|
||||
|
||||
static void testCorrectness() {
|
||||
List<Long> path = new ArrayList<>(Arrays.asList(10L, 20L, 30L, 40L));
|
||||
Map<Long, Boolean> visited = new HashMap<>();
|
||||
for (long v : path) visited.put(v, Boolean.TRUE);
|
||||
|
||||
// uid present in path
|
||||
assert slowContains(path, 30L) == fastContains(visited, 30L)
|
||||
: "FAIL: mismatch for uid in path";
|
||||
// uid absent from path
|
||||
assert slowContains(path, 99L) == fastContains(visited, 99L)
|
||||
: "FAIL: mismatch for uid not in path";
|
||||
|
||||
System.out.println("1/2 PASS correctness: slow and fast agree on cycle detection");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Complexity check: slow grows O(n²), fast grows O(n)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static void testComplexity() {
|
||||
int n1 = 100;
|
||||
int n2 = 1000;
|
||||
|
||||
long slowN1 = slowOps(n1);
|
||||
long slowN2 = slowOps(n2);
|
||||
long fastN1 = fastOps(n1);
|
||||
long fastN2 = fastOps(n2);
|
||||
|
||||
// Slow should grow ~100x (10x nodes → 10x*10x = 100x ops)
|
||||
double slowRatio = (double) slowN2 / slowN1;
|
||||
// Fast should grow ~10x (linear in n²: n*n neighbours each 1 op)
|
||||
// Actually fast is also n*n ops but each is 1, while slow is n*n*pathLen
|
||||
// The ratio slowN2/fastN2 should be >> 1 at n2 (slow pays pathLen = n per op)
|
||||
double overhead = (double) slowN2 / fastN2;
|
||||
|
||||
System.out.printf(" slow ops n=%d: %,d%n", n1, slowN1);
|
||||
System.out.printf(" slow ops n=%d: %,d%n", n2, slowN2);
|
||||
System.out.printf(" fast ops n=%d: %,d%n", n1, fastN1);
|
||||
System.out.printf(" fast ops n=%d: %,d%n", n2, fastN2);
|
||||
System.out.printf(" slow/fast overhead at n=%d: %.1fx%n", n2, overhead);
|
||||
|
||||
// slow is O(n³) here: n hops * n neighbours * n path length
|
||||
// fast is O(n²): n hops * n neighbours * 1
|
||||
// overhead should be ~n2 = 1000
|
||||
assert slowRatio > 50.0
|
||||
: "FAIL: slow ops did not grow super-linearly: ratio=" + slowRatio;
|
||||
assert overhead > 100.0
|
||||
: "FAIL: slow not significantly worse than fast: overhead=" + overhead;
|
||||
|
||||
System.out.printf("2/2 PASS complexity: slow/fast=%.0fx (expected ~%d)%n",
|
||||
overhead, n2);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("dgraph-0001: route.indexOf O(P) cycle check in k-shortest-paths");
|
||||
testCorrectness();
|
||||
testComplexity();
|
||||
System.out.println("2/2 PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue