package unit; import java.util.*; /** * IstioTest — CWE-407 benchmark for istio-0001 * * istio-0001: virtualHostMatch slices.Contains(vh.Domains, domainName) * called inside VirtualHost × patch nested loop → O(VH × P × D) * * Model: * VH = number of VirtualHosts in a route config * P = number of EnvoyFilter patches * D = number of domain aliases per VirtualHost * * SLOW: for each VH, for each patch, slices.Contains(vh.domains) → O(VH × P × D) * FAST: build domain→VH map once, O(VH×D) setup, then O(VH×P) matching → O(VH×P) */ public class IstioTest { // ------------------------------------------------------------------------- // Data model // ------------------------------------------------------------------------- static class VirtualHost { final String name; final List domains; VirtualHost(String name, int domainCount) { this.name = name; this.domains = new ArrayList<>(domainCount); // e.g. "svc.ns.svc.cluster.local", "svc.ns", "svc", "svc:80", ... for (int i = 0; i < domainCount; i++) { domains.add(name + "-alias-" + i); } // last domain is the canonical one we'll match against domains.add(name + ".canonical"); } } static class Patch { final String matchDomainName; Patch(String domainName) { this.matchDomainName = domainName; } } // ------------------------------------------------------------------------- // SLOW: slices.Contains per virtualHostMatch call // ------------------------------------------------------------------------- static long patchRouteConfig_slow(List virtualHosts, List patches) { long ops = 0; for (VirtualHost vh : virtualHosts) { for (Patch p : patches) { // virtualHostMatch: slices.Contains(vh.domains, p.matchDomainName) if (!p.matchDomainName.isEmpty()) { for (String d : vh.domains) { ops++; if (d.equals(p.matchDomainName)) break; } } } } return ops; } // ------------------------------------------------------------------------- // FAST: domain→VH map built once before the loop // ------------------------------------------------------------------------- static long patchRouteConfig_fast(List virtualHosts, List patches) { long ops = 0; // Build index: O(VH × D) — counted once Map domainIndex = new HashMap<>(); for (VirtualHost vh : virtualHosts) { for (String d : vh.domains) { ops++; domainIndex.put(d, vh); } } // Now matching: O(1) per lookup for (VirtualHost vh : virtualHosts) { for (Patch p : patches) { if (!p.matchDomainName.isEmpty()) { ops++; // map.get — O(1) domainIndex.get(p.matchDomainName); } } } return ops; } // ------------------------------------------------------------------------- // Helpers // ------------------------------------------------------------------------- static List makeVirtualHosts(int count, int domainsEach) { List list = new ArrayList<>(count); for (int i = 0; i < count; i++) { list.add(new VirtualHost("svc-" + i, domainsEach)); } return list; } static List makePatches(int count, List vhs) { List patches = new ArrayList<>(count); for (int i = 0; i < count; i++) { // each patch targets the canonical domain of some VH String target = vhs.get(i % vhs.size()).name + ".canonical"; patches.add(new Patch(target)); } return patches; } static void bench(String label, long sOps, long fOps) { System.out.printf(" %-55s slow=%9d fast=%7d ratio=%5.1fx%n", label, sOps, fOps, (double) sOps / Math.max(fOps, 1)); } // ------------------------------------------------------------------------- // Main // ------------------------------------------------------------------------- public static void main(String[] args) { System.out.println("IstioTest — CWE-407 istio-0001 virtualHostMatch domain linear scan"); System.out.println(); // --- VH=100, P=5, D=10 --- { int VH = 100, P = 5, D = 10; List vhs = makeVirtualHosts(VH, D); List patches = makePatches(P, vhs); long sOps = patchRouteConfig_slow(vhs, patches); long fOps = patchRouteConfig_fast(vhs, patches); bench("VH=100 P=5 D=10", sOps, fOps); assert sOps > fOps * 2 : "Expected slow >> fast, got slow=" + sOps + " fast=" + fOps; } // --- VH=500, P=20, D=15 --- { int VH = 500, P = 20, D = 15; List vhs = makeVirtualHosts(VH, D); List patches = makePatches(P, vhs); long sOps = patchRouteConfig_slow(vhs, patches); long fOps = patchRouteConfig_fast(vhs, patches); bench("VH=500 P=20 D=15", sOps, fOps); assert sOps > fOps * 5 : "Expected slow >> fast, got slow=" + sOps + " fast=" + fOps; } // --- VH=1000, P=50, D=20 (large mesh) --- { int VH = 1000, P = 50, D = 20; List vhs = makeVirtualHosts(VH, D); List patches = makePatches(P, vhs); long sOps = patchRouteConfig_slow(vhs, patches); long fOps = patchRouteConfig_fast(vhs, patches); bench("VH=1000 P=50 D=20 (large mesh)", sOps, fOps); assert sOps > fOps * 10 : "Expected slow >> fast, got slow=" + sOps + " fast=" + fOps; } // --- VH=2000, P=100, D=25 (stress) --- { int VH = 2000, P = 100, D = 25; List vhs = makeVirtualHosts(VH, D); List patches = makePatches(P, vhs); long sOps = patchRouteConfig_slow(vhs, patches); long fOps = patchRouteConfig_fast(vhs, patches); bench("VH=2000 P=100 D=25 (stress)", sOps, fOps); assert sOps > fOps * 10 : "Expected slow >> fast, got slow=" + sOps + " fast=" + fOps; } System.out.println(); System.out.println("All assertions passed."); } }