java-topology/defects/maven/unit/MavenLifecycleStandardSetTest.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

73 lines
2.6 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.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* maven-0001 — DefaultLifecycleExecutionPlanCalculator: List.of().contains() rebuilt per mojo
*
* Demonstrates CWE-407: O(n) linear list membership inside a hot loop.
*
* slow(): models the defective path — List.of(STANDARD_LIFECYCLES).contains() called N times,
* allocating a new List and scanning it on every call.
* fast(): models the fix — a precomputed Set<String> constant, O(1) per lookup.
*
* Asserts that slow() performs strictly more element comparisons than fast().
*/
public class MavenLifecycleStandardSetTest {
static final String[] STANDARD_LIFECYCLES = {"clean", "default", "site"};
/** Counts how many element comparisons the slow path performs for N lookups. */
static long slow(String[] lifecycleIds) {
long ops = 0;
for (String id : lifecycleIds) {
// Rebuild list and scan linearly — defective pattern
List<String> list = Arrays.asList(STANDARD_LIFECYCLES);
for (int i = 0; i < list.size(); i++) {
ops++;
if (list.get(i).equals(id)) break;
}
}
return ops;
}
/** Counts how many element comparisons the fast path performs for N lookups. */
static long fast(String[] lifecycleIds) {
long ops = 0;
// Precomputed constant set — the fix
Set<String> standardSet = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(STANDARD_LIFECYCLES)));
for (String id : lifecycleIds) {
ops++; // HashSet.contains = 1 hash + at most 1 comparison
standardSet.contains(id);
}
return ops;
}
public static void main(String[] args) {
// Simulate M=200 modules × N=50 mojos = 10 000 calculateLifecycleMappings calls
// Mix of matches and misses; worst case is always a miss (scans full list)
int iterations = 10_000;
String[] ids = new String[iterations];
String[] pool = {"clean", "default", "site", "unknown-lifecycle", "custom"};
for (int i = 0; i < iterations; i++) {
ids[i] = pool[i % pool.length];
}
long sOps = slow(ids);
long fOps = fast(ids);
// Expect slow to do at least 2x the comparisons of fast
int Nx = 2;
boolean pass = sOps > fOps * Nx;
System.out.printf("maven-0001: slow=%d ops fast=%d ops ratio=%.1fx %s%n",
sOps, fOps, (double) sOps / fOps, pass ? "PASS" : "FAIL");
if (!pass) {
System.exit(1);
}
}
}