java-topology/defects/kubernetes/unit/KubernetesTest.java
russell@unturf.com 9934133dcf whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
  HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
        vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
        tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
        allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
        mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
        linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
        perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002

  MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
          cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
          pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
          ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
          r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
          ovs-0001, onos-0003, odl-0002, jetty-0001

PDF: 976K
2026-03-27 15:23:43 -04:00

132 lines
5.5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package unit;
import java.util.*;
/**
* Standalone unit tests for kubernetes CWE-407 defects.
*
* kubernetes-0001: Job pod failure policy — O(n) exit-code set membership per container per rule
* slow() uses List.contains() (linear scan) per call.
* fast() uses HashSet (O(1) lookup per call) built once per requirement.
* Assert: slowOps > fastOps * 5x for V=500 values.
*
* kubernetes-0002: GC owner reference UID scan — O(refs × ownerUIDs) with linear scan
* slow() uses List.contains() per ref iteration.
* fast() uses HashSet built once before the loop.
* Assert: slowOps > fastOps * 5x for refs=200, ownerUIDs=200.
*/
public class KubernetesTest {
// ── kubernetes-0001 ───────────────────────────────────────────────────────
/** Simulate requirement.Values as a plain list — O(V) per Contains call. */
static long slowExitCodeMatching(List<Integer> values, int exitCode, int containers, int rules) {
long ops = 0;
for (int r = 0; r < rules; r++) {
for (int c = 0; c < containers; c++) {
// O(V) scan per call — mirrors slices.Contains(requirement.Values, exitCode)
for (int v = 0; v < values.size(); v++) {
ops++;
if (values.get(v).equals(exitCode)) break;
}
}
}
return ops;
}
/** Fix: build a HashSet once per requirement — O(V) build, O(1) per lookup. */
static long fastExitCodeMatching(List<Integer> values, int exitCode, int containers, int rules) {
long ops = 0;
for (int r = 0; r < rules; r++) {
// Build set once per rule (amortised across all containers)
Set<Integer> set = new HashSet<>(values);
ops += values.size(); // O(V) build cost counted once
for (int c = 0; c < containers; c++) {
ops++; // O(1) lookup
set.contains(exitCode); // constant time
}
}
return ops;
}
static void testExitCodeMatching() {
int V = 500; // values in requirement.Values
int C = 50; // containers per pod
int R = 10; // policy rules
// Worst case: exitCode not in list — full scan every time
int exitCode = -1;
List<Integer> values = new ArrayList<>(V);
for (int i = 0; i < V; i++) values.add(i);
long sOps = slowExitCodeMatching(values, exitCode, C, R);
long fOps = fastExitCodeMatching(values, exitCode, C, R);
int Nx = 5;
boolean pass = sOps > fOps * Nx;
System.out.printf("kubernetes-0001 [V=%d C=%d R=%d]: slow=%d fast=%d ratio=%.1fx — %s%n",
V, C, R, sOps, fOps, (double) sOps / fOps, pass ? "PASS" : "FAIL");
if (!pass) throw new AssertionError("kubernetes-0001 FAIL: slow=" + sOps + " fast=" + fOps);
}
// ── kubernetes-0002 ───────────────────────────────────────────────────────
/** Simulate deleteOwnerRefJSONMergePatch — O(refs × ownerUIDs) with linear scan. */
static long slowOwnerRefPatch(List<String> refs, List<String> ownerUIDs) {
long ops = 0;
List<String> result = new ArrayList<>();
for (String ref : refs) {
// slices.Contains(ownerUIDs, ref.UID) — O(U) per ref
for (int i = 0; i < ownerUIDs.size(); i++) {
ops++;
if (ownerUIDs.get(i).equals(ref)) break;
}
if (!ownerUIDs.contains(ref)) {
result.add(ref);
}
}
return ops;
}
/** Fix: build a HashSet from ownerUIDs before the loop — O(1) per ref. */
static long fastOwnerRefPatch(List<String> refs, List<String> ownerUIDs) {
long ops = 0;
Set<String> dropSet = new HashSet<>(ownerUIDs);
ops += ownerUIDs.size(); // O(U) build cost
List<String> result = new ArrayList<>();
for (String ref : refs) {
ops++; // O(1) lookup
if (!dropSet.contains(ref)) {
result.add(ref);
}
}
return ops;
}
static void testOwnerRefPatch() {
int N = 300; // refs count == ownerUIDs count — worst case all disjoint
List<String> refs = new ArrayList<>(N);
List<String> ownerUIDs = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
refs.add("ref-" + i);
ownerUIDs.add("uid-" + (N + i)); // no overlap → full scan every ref
}
long sOps = slowOwnerRefPatch(refs, ownerUIDs);
long fOps = fastOwnerRefPatch(refs, ownerUIDs);
int Nx = 5;
boolean pass = sOps > fOps * Nx;
System.out.printf("kubernetes-0002 [N=%d refs, N=%d uids]: slow=%d fast=%d ratio=%.1fx — %s%n",
N, N, sOps, fOps, (double) sOps / fOps, pass ? "PASS" : "FAIL");
if (!pass) throw new AssertionError("kubernetes-0002 FAIL: slow=" + sOps + " fast=" + fOps);
}
// ── main ──────────────────────────────────────────────────────────────────
public static void main(String[] args) {
testExitCodeMatching();
testOwnerRefPatch();
System.out.println("2/2 PASS");
}
}