java-topology/defects/loki/unit/LokiTest.java
russell@unturf.com 689ec25d05 grafana: 3 CWE-407 defects; loki: 1 CWE-407 defect; 4/4 PASS
grafana-0001: getDashboardsSharedWithUser dashboard UID dedup O(P^2) MEDIUM 2.5x
grafana-0002: folder UID dedup slices.Contains O(P^2) 4 sites MEDIUM 4x
grafana-0003: deduplicateAvailableFolders ContainsFunc O(F*A) MEDIUM 9.3x
loki-0001: DAG AddEdge/Eliminate slices.Contains O(E^2) LOW 2.1x
2026-03-30 13:17:58 -04:00

125 lines
4.5 KiB
Java

import java.util.*;
/**
* Java simulation unit test for Loki CWE-407 defect.
* Simulates the O(E^2) edge dedup pattern in Loki's DAG implementation.
*
* loki-0001: DAG AddEdge slices.Contains on children/parents O(E^2)
*
* In practice, Loki query plans have small fan-out (1-3 children per node),
* so this is LOW severity. The test uses synthetic high fan-out to
* demonstrate the algorithmic defect.
*/
public class LokiTest {
// ---------------------------------------------------------------
// loki-0001: DAG AddEdge edge dedup O(E^2) vs O(E)
// ---------------------------------------------------------------
/** BEFORE: linear scan of children list for uniqueness */
static class DagBefore {
Map<String, List<String>> children = new HashMap<>();
Map<String, List<String>> parents = new HashMap<>();
void addEdge(String parent, String child) {
children.computeIfAbsent(parent, k -> new ArrayList<>());
parents.computeIfAbsent(child, k -> new ArrayList<>());
List<String> ch = children.get(parent);
if (!ch.contains(child)) { // O(E) linear scan
ch.add(child);
}
List<String> pa = parents.get(child);
if (!pa.contains(parent)) { // O(E) linear scan
pa.add(parent);
}
}
}
/** AFTER: parallel set for O(1) membership */
static class DagAfter {
Map<String, List<String>> children = new HashMap<>();
Map<String, List<String>> parents = new HashMap<>();
Map<String, Set<String>> childrenSet = new HashMap<>();
Map<String, Set<String>> parentSet = new HashMap<>();
void addEdge(String parent, String child) {
children.computeIfAbsent(parent, k -> new ArrayList<>());
parents.computeIfAbsent(child, k -> new ArrayList<>());
childrenSet.computeIfAbsent(parent, k -> new HashSet<>());
parentSet.computeIfAbsent(child, k -> new HashSet<>());
if (childrenSet.get(parent).add(child)) {
children.get(parent).add(child);
}
if (parentSet.get(child).add(parent)) {
parents.get(child).add(parent);
}
}
}
static void testLoki0001() {
int E = 500; // edges from one parent to many children
String parent = "root";
// Warm up
for (int w = 0; w < 3; w++) {
DagBefore db = new DagBefore();
DagAfter da = new DagAfter();
for (int i = 0; i < E; i++) {
db.addEdge(parent, "child-" + i);
da.addEdge(parent, "child-" + i);
}
}
int ITER = 200;
long t0 = System.nanoTime();
for (int it = 0; it < ITER; it++) {
DagBefore db = new DagBefore();
for (int i = 0; i < E; i++) {
db.addEdge(parent, "child-" + i);
}
// Also add duplicates to exercise the contains path
for (int i = 0; i < E; i++) {
db.addEdge(parent, "child-" + i);
}
}
long befNs = System.nanoTime() - t0;
t0 = System.nanoTime();
for (int it = 0; it < ITER; it++) {
DagAfter da = new DagAfter();
for (int i = 0; i < E; i++) {
da.addEdge(parent, "child-" + i);
}
for (int i = 0; i < E; i++) {
da.addEdge(parent, "child-" + i);
}
}
long aftNs = System.nanoTime() - t0;
// Correctness check
DagBefore db = new DagBefore();
DagAfter da = new DagAfter();
for (int i = 0; i < E; i++) {
db.addEdge(parent, "child-" + i);
da.addEdge(parent, "child-" + i);
}
assert db.children.get(parent).size() == da.children.get(parent).size()
: "loki-0001 correctness: children sizes differ";
assert db.children.get(parent).equals(da.children.get(parent))
: "loki-0001 correctness: children order differs";
double ratio = (double) befNs / aftNs;
System.out.printf("loki-0001 dag-edge-dedup BEFORE=%,dns AFTER=%,dns ratio=%.1fx %s%n",
befNs, aftNs, ratio, ratio > 2.0 ? "PASS" : "FAIL");
assert ratio > 2.0 : "loki-0001: expected >2x speedup, got " + ratio;
}
// ---------------------------------------------------------------
public static void main(String[] args) {
testLoki0001();
System.out.println("\nAll 1 Loki CWE-407 test PASSED.");
}
}