java-topology/defects/scala/unit/ScalaCheckableTest.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

100 lines
3.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.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* ScalaCheckableTest — CWE-407 unit test for scala-0001
*
* Models the O(n²) nested scan in Checkable.propagateKnownTypes:
*
* from.baseClasses foreach { bc => if (to.baseClasses.contains(bc)) { ... } }
*
* Both 'from.baseClasses' and 'to.baseClasses' are List[Symbol].
* The outer foreach × inner contains = O(M×N) element comparisons.
*
* slow(): simulates the original — outer list.forEach × inner list.contains.
* fast(): simulates the fix — pre-build Set from to.baseClasses, then O(1) lookup.
*
* We use SIZE=200 base classes (realistic for trait-heavy Scala frameworks).
* We assert slow() uses >= 5x more comparisons than fast().
*/
public class ScalaCheckableTest {
static final int SIZE = 200; // number of base classes (e.g. deep trait hierarchy)
static final int N = 5; // minimum speedup factor required
/**
* Simulates a Symbol as an integer identifier.
* In Scala, Symbol equality is reference identity (object identity).
* Here we use Integer.equals for equivalence; both slow and fast use
* the same equality semantics.
*/
/**
* slow(): mirrors: from.baseClasses foreach { bc => if (to.baseClasses.contains(bc)) }
* All elements of from.baseClasses are also in to.baseClasses (worst case —
* every contains() call walks the full list before finding the element at end).
* Returns total element comparisons.
*/
static long slow() {
// from.baseClasses: SIZE symbols, ids 0..SIZE-1
List<Integer> fromBases = new ArrayList<>();
for (int i = 0; i < SIZE; i++) fromBases.add(i);
// to.baseClasses: same SIZE symbols, but in reverse order
// so every contains() call scans to the end (worst case)
List<Integer> toBases = new ArrayList<>();
for (int i = SIZE - 1; i >= 0; i--) toBases.add(i);
long ops = 0;
for (Integer bc : fromBases) {
// contains() on List — O(n) scan
for (int j = 0; j < toBases.size(); j++) {
ops++;
if (toBases.get(j).equals(bc)) break;
}
}
return ops;
}
/**
* fast(): mirrors fix — val toBaseSet = to.baseClasses.toSet
* then: from.baseClasses foreach { bc => if (toBaseSet.contains(bc)) }
* One-time O(n) build + O(1) per lookup.
*/
static long fast() {
List<Integer> fromBases = new ArrayList<>();
for (int i = 0; i < SIZE; i++) fromBases.add(i);
List<Integer> toBases = new ArrayList<>();
for (int i = SIZE - 1; i >= 0; i--) toBases.add(i);
// One-time set build — O(n)
HashSet<Integer> toBaseSet = new HashSet<>(toBases);
long ops = toBases.size(); // count the build cost
// O(1) per lookup
for (Integer bc : fromBases) {
ops++; // one hash probe per lookup
toBaseSet.contains(bc);
}
return ops;
}
public static void main(String[] args) {
long sOps = slow();
long fOps = fast();
System.out.println("slow ops: " + sOps);
System.out.println("fast ops: " + fOps);
System.out.println("ratio: " + sOps + "/" + fOps + " = " + (sOps / fOps) + "x");
if (sOps < fOps * N) {
System.out.println("1/1 FAIL — expected slowOps >= " + N + "x fastOps, got ratio=" + (sOps / fOps));
System.exit(1);
}
System.out.println("1/1 PASS");
}
}