package unit; import java.util.*; /** * Standalone unit test for prometheus-0001: CWE-407. * * prometheus-0001: Builder.Labels() del-slice membership — O(n²) * slow() uses a List for the "deleted" set; contains() is O(D). * For each of L base labels: O(D) del-check + O(A) add-check → O(L×(D+A)). * fast() uses a HashSet for both del and add; contains() is O(1). * For each of L base labels: O(1) del-check + O(1) add-check → O(L). * Assert: slowOps > fastOps * 10x for L=500 labels with D=250 deleted. */ public class PrometheusTest { /** * Slow path — Builder.Labels() with []string del-set: O(L * D) membership tests. */ static long slowBuilderLabels(List base, List del, List add) { long ops = 0; List result = new ArrayList<>(base.size()); for (String label : base) { // slices.Contains(del, label) — O(D) linear scan boolean inDel = false; for (String d : del) { ops++; if (d.equals(label)) { inDel = true; break; } } if (inDel) continue; // contains(add, label) — O(A) linear scan boolean inAdd = false; for (String a : add) { ops++; if (a.equals(label)) { inAdd = true; break; } } if (inAdd) continue; result.add(label); } return ops; } /** * Fast path — Builder.Labels() with map-based del/add sets: O(L) total. */ static long fastBuilderLabels(List base, List del, List add) { long ops = 0; // Build O(1) sets — cost O(D + A) Set delSet = new HashSet<>(del); for (String ignored : del) ops++; Set addSet = new HashSet<>(add); for (String ignored : add) ops++; List result = new ArrayList<>(base.size()); for (String label : base) { ops++; // single O(1) hash lookup if (delSet.contains(label)) continue; ops++; if (addSet.contains(label)) continue; result.add(label); } return ops; } static void testBuilderLabels() { int L = 500; // base label count int D = 250; // deleted label count (worst case: half of base) int A = 50; // added label count List base = new ArrayList<>(L); for (int i = 0; i < L; i++) base.add("label_" + i); List del = new ArrayList<>(D); for (int i = 0; i < D; i++) del.add("label_" + i); // delete first D List add = new ArrayList<>(A); for (int i = 0; i < A; i++) add.add("new_label_" + i); long sOps = slowBuilderLabels(base, del, add); long fOps = fastBuilderLabels(base, del, add); int Nx = 10; boolean pass = sOps > fOps * Nx; System.out.printf("prometheus-0001 [L=%d D=%d A=%d]: slow=%d fast=%d ratio=%.1fx — %s%n", L, D, A, sOps, fOps, (double) sOps / fOps, pass ? "PASS" : "FAIL"); if (!pass) throw new AssertionError("prometheus-0001 FAIL: slow=" + sOps + " fast=" + fOps); } public static void main(String[] args) { testBuilderLabels(); System.out.println("1/1 PASS"); } }