java-topology/defects/swift/unit/SwiftRequirementMachineAlgorithm.java

124 lines
4.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.*;
/**
* CWE-407 unit test: Swift RequirementMachine isInMinimizationDomain
*
* Models the Swift compiler's RewriteSystem where:
* - Protos = list of protocol declarations in the minimization domain
* - Rules = rewrite rules over those protocols
*
* The defect: isInMinimizationDomain() does a linear scan over Protos
* on every call, and is called once per rule in loops over all rules.
* Total cost: O(R × P) where R = rule count, P = protocol count.
*
* The fix: replace the linear scan with a HashSet lookup — O(1) per call.
*
* Test measures ops count (comparisons) at N=800 (protos and rules both N).
*/
public class SwiftRequirementMachineAlgorithm {
// ---- Defective version: std::find equivalent (linear scan) ----------------
static long defectiveIsInDomain(List<Integer> protos, int proto) {
// models: std::find(Protos.begin(), Protos.end(), proto)
// returns ops performed
long ops = 0;
for (Integer p : protos) {
ops++;
if (p.equals(proto)) return ops;
}
return ops;
}
/**
* Simulate the rule-loop pattern from HomotopyReduction.cpp:611
* for (const auto &rule : getLocalRules()) {
* if (!isInMinimizationDomain(rule.getLHS().getRootProtocol())) continue;
* ...
* }
*/
static long defectiveMinimize(List<Integer> protos, List<Integer> rules) {
long totalOps = 0;
for (int rule : rules) {
// Each rule references a protocol; check membership linearly
totalOps += defectiveIsInDomain(protos, rule % protos.size());
}
return totalOps;
}
// ---- Fixed version: HashSet O(1) lookup -----------------------------------
static long fixedMinimize(Set<Integer> protoSet, List<Integer> rules) {
long totalOps = 0;
for (int rule : rules) {
// O(1) hash set lookup
totalOps++;
protoSet.contains(rule % protoSet.size());
}
return totalOps;
}
// ---- Test harness ----------------------------------------------------------
static final int N = 800;
public static void main(String[] args) {
int passed = 0;
int total = 0;
// Build protos list (P = N protocols) and rules list (R = N rules)
List<Integer> protos = new ArrayList<>(N);
for (int i = 0; i < N; i++) protos.add(i);
List<Integer> rules = new ArrayList<>(N);
for (int i = 0; i < N; i++) rules.add(i);
Set<Integer> protoSet = new HashSet<>(protos);
// Test 1: defective version is O(R*P) — ops >= N*N/2 on average
total++;
long slowOps = defectiveMinimize(protos, rules);
// Each rule on average scans half the protos list
long expectedMinSlow = (long) N * N / 4; // conservative lower bound
assert slowOps >= expectedMinSlow
: "Slow ops " + slowOps + " unexpectedly low, expected >= " + expectedMinSlow;
System.out.println("PASS test1: defective ops=" + slowOps + " (O(N^2) confirmed, N=" + N + ")");
passed++;
// Test 2: fixed version is O(R) — ops == N exactly
total++;
long fastOps = fixedMinimize(protoSet, rules);
assert fastOps == N
: "Fast ops should be exactly N=" + N + ", got " + fastOps;
System.out.println("PASS test2: fixed ops=" + fastOps + " (O(N) confirmed, N=" + N + ")");
passed++;
// Test 3: speedup is at least 10x
total++;
double speedup = (double) slowOps / fastOps;
assert speedup >= 10.0
: "Expected speedup >= 10x, got " + speedup;
System.out.printf("PASS test3: speedup=%.1fx%n", speedup);
passed++;
// Test 4: correctness — both find the same items in domain
total++;
List<Integer> smallProtos = Arrays.asList(10, 20, 30, 40, 50);
Set<Integer> smallSet = new HashSet<>(smallProtos);
// Probe 5 different values
int[] probeVals = {10, 25, 30, 99, 50};
for (int v : probeVals) {
boolean defectResult = defectiveIsInDomain(smallProtos, v) > 0 && smallProtos.contains(v);
boolean fixedResult = smallSet.contains(v);
assert defectResult == fixedResult
: "Mismatch for value " + v + ": defect=" + defectResult + " fixed=" + fixedResult;
}
System.out.println("PASS test4: correctness — defective and fixed agree on all probes");
passed++;
System.out.println(passed + "/" + total + " PASS");
}
}