java-topology/tests/unit/ClosureComplexityTest.java
russell@unturf.com 0a580b313d undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
2026-03-26 17:11:57 -04:00

180 lines
7.7 KiB
Java

package unit;
import support.ClosureAlgorithm;
import support.ClosureAlgorithm.Result;
import java.util.Set;
/**
* Unit tests for DEFECT 0002b: InferenceGraph.Node.closure() uncached DFS.
*
* Proves:
* 1. Both implementations produce identical closure sets (correctness).
* 2. Defective version visits exactly K*V nodes for K calls on a V-node chain.
* 3. Fixed version visits exactly V+(K-1) nodes for the same K calls.
* 4. Doubling K doubles defective work; fixed is nearly constant.
*
* No build tool required. Compile and run:
*
* cd tests
* java -m jdk.compiler/com.sun.tools.javac.Main -cp . \
* support/ClosureAlgorithm.java unit/ClosureComplexityTest.java
* java -cp . unit.ClosureComplexityTest
*/
public class ClosureComplexityTest {
private static int passed = 0;
private static int failed = 0;
public static void main(String[] args) {
System.out.println("=== ClosureComplexityTest (DEFECT 0002b) ===\n");
System.out.println("-- Correctness: both versions return same closure set --");
testCorrectnessSmall();
testCorrectnessMedium();
System.out.println("\n-- Complexity: defective visits K*V nodes --");
testDefectiveExactCounts();
System.out.println("\n-- Complexity: fixed visits V+(K-1) nodes --");
testFixedExactCounts();
System.out.println("\n-- Complexity: growth ratio proves linear vs constant in K --");
testGrowthRatioInK();
System.out.printf("\n%d passed, %d failed%n", passed, failed);
if (failed > 0) System.exit(1);
}
// ─── Correctness ─────────────────────────────────────────────────────────
static void testCorrectnessSmall() {
int v = 5, k = 3;
ClosureAlgorithm.Node startDef = ClosureAlgorithm.buildLinearChain(v);
ClosureAlgorithm.Node startFix = ClosureAlgorithm.buildLinearChain(v);
Result def = ClosureAlgorithm.closureDefective(startDef, k);
Result fix = ClosureAlgorithm.closureFixed(startFix, k);
assertEqual("small: defective closure size", v, def.closure.size());
assertEqual("small: fixed closure size", v, fix.closure.size());
}
static void testCorrectnessMedium() {
int v = 20, k = 5;
ClosureAlgorithm.Node startDef = ClosureAlgorithm.buildLinearChain(v);
ClosureAlgorithm.Node startFix = ClosureAlgorithm.buildLinearChain(v);
Result def = ClosureAlgorithm.closureDefective(startDef, k);
Result fix = ClosureAlgorithm.closureFixed(startFix, k);
assertEqual("medium: defective closure size", v, def.closure.size());
assertEqual("medium: fixed closure size", v, fix.closure.size());
}
// ─── Exact node-visit counts ──────────────────────────────────────────────
/**
* PROVES DEFECT: K calls on a V-node chain visit exactly K*V nodes total.
* Each call reruns the full DFS with no memory of previous calls.
*/
static void testDefectiveExactCounts() {
System.out.println("[defective] closureDefective(chain(V), K) — expected K*V:");
int[][] cases = {{10, 5}, {20, 5}, {10, 10}, {20, 10}, {50, 20}};
for (int[] c : cases) {
int v = c[0], k = c[1];
ClosureAlgorithm.Node start = ClosureAlgorithm.buildLinearChain(v);
Result r = ClosureAlgorithm.closureDefective(start, k);
long expected = (long) k * v;
System.out.printf(" V=%-4d K=%-4d actual=%-8d expected=%-8d %s%n",
v, k, r.nodeVisits, expected,
r.nodeVisits == expected ? "PASS" : "FAIL expected=" + expected);
assertEqual("defective V=" + v + " K=" + k, expected, r.nodeVisits);
}
}
/**
* PROVES FIX: K calls on a V-node chain visit exactly V+(K-1) nodes total.
* First call runs the DFS (V visits), each of the K-1 subsequent calls
* finds the cached result (1 visit each).
*/
static void testFixedExactCounts() {
System.out.println("[fixed] closureFixed(chain(V), K) — expected V+(K-1):");
int[][] cases = {{10, 5}, {20, 5}, {10, 10}, {20, 10}, {50, 20}};
for (int[] c : cases) {
int v = c[0], k = c[1];
ClosureAlgorithm.Node start = ClosureAlgorithm.buildLinearChain(v);
Result r = ClosureAlgorithm.closureFixed(start, k);
long expected = v + (k - 1);
System.out.printf(" V=%-4d K=%-4d actual=%-8d expected=%-8d %s%n",
v, k, r.nodeVisits, expected,
r.nodeVisits == expected ? "PASS" : "FAIL expected=" + expected);
assertEqual("fixed V=" + v + " K=" + k, expected, r.nodeVisits);
}
}
// ─── Growth ratio (in K dimension) ────────────────────────────────────────
/**
* PROVES LINEAR GROWTH OF DEFECT IN K:
* Doubling K → defective visits double (≈2x), fixed barely changes.
*
* Math (V=100 fixed):
* defective(K) = K*V → doubles when K doubles
* defective(2K) = 2K*V → ratio = 2.0 (exact)
*
* fixed(K) = V + (K-1)
* fixed(2K) = V + (2K-1)
* ratio = (V+2K-1)/(V+K-1) → 1 as V≫K (nearly constant)
*/
static void testGrowthRatioInK() {
int v = 100;
int[][] kPairs = {{5, 10}, {10, 20}, {20, 40}};
for (int[] pair : kPairs) {
int k1 = pair[0], k2 = pair[1];
ClosureAlgorithm.Node startDef1 = ClosureAlgorithm.buildLinearChain(v);
ClosureAlgorithm.Node startDef2 = ClosureAlgorithm.buildLinearChain(v);
ClosureAlgorithm.Node startFix1 = ClosureAlgorithm.buildLinearChain(v);
ClosureAlgorithm.Node startFix2 = ClosureAlgorithm.buildLinearChain(v);
long def1 = ClosureAlgorithm.closureDefective(startDef1, k1).nodeVisits;
long def2 = ClosureAlgorithm.closureDefective(startDef2, k2).nodeVisits;
long fix1 = ClosureAlgorithm.closureFixed(startFix1, k1).nodeVisits;
long fix2 = ClosureAlgorithm.closureFixed(startFix2, k2).nodeVisits;
double defRatio = (double) def2 / def1;
double fixRatio = (double) fix2 / fix1;
System.out.printf(" V=%d K %d→%d: defective ratio=%.2f (expect 2.0) fixed ratio=%.2f (expect <1.2)%n",
v, k1, k2, defRatio, fixRatio);
// Defective doubles exactly when K doubles (defective = K*V)
assertTrue("defective K=" + k1 + "" + k2 + " ratio = 2.0", defRatio == 2.0);
// Fixed changes very little (V dominates K for V=100)
assertTrue("fixed K=" + k1 + "" + k2 + " ratio < 1.2", fixRatio < 1.2);
}
}
// ─── Helpers ─────────────────────────────────────────────────────────────
static void assertEqual(String name, long expected, long actual) {
if (expected == actual) {
System.out.printf(" PASS %s%n", name);
passed++;
} else {
System.out.printf(" FAIL %s expected=%d actual=%d%n", name, expected, actual);
failed++;
}
}
static void assertTrue(String name, boolean condition) {
if (condition) {
System.out.printf(" PASS %s%n", name);
passed++;
} else {
System.out.printf(" FAIL %s%n", name);
failed++;
}
}
}