package defects.xen.unit; import java.util.*; /** * Unit tests for xen-0001: credit2 balance_load O(V²) VCPU swap-search. */ public class Xen0001Test { static int passed = 0; static int failed = 0; static void assertTrue(String label, boolean condition) { if (condition) { System.out.println(" PASS: " + label); passed++; } else { System.out.println(" FAIL: " + label); failed++; } } public static void main(String[] args) { System.out.println("xen-0001 unit tests"); System.out.println("=".repeat(50)); testDefectiveIsQuadratic(); testFixedIsLinear(); testBothFindSameWinner(); testNoMigratable(); testSingleVcpu(); testLoadRatioAbove50x(); System.out.println(); System.out.printf("Result: %d passed, %d failed%n", passed, failed); if (failed > 0) System.exit(1); } static void testDefectiveIsQuadratic() { System.out.println("\n--- testDefectiveIsQuadratic ---"); Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad d = new Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad(); int v1 = 10, v2 = 20; List l1 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v1, 100, false); List o1 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v1, 50, false); d.findBestSwap(l1, o1, Xen0001CreditBalanceLoadAlgorithm.totalLoad(l1), Xen0001CreditBalanceLoadAlgorithm.totalLoad(o1)); int ops1 = d.comparisons; List l2 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v2, 100, false); List o2 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v2, 50, false); d.findBestSwap(l2, o2, Xen0001CreditBalanceLoadAlgorithm.totalLoad(l2), Xen0001CreditBalanceLoadAlgorithm.totalLoad(o2)); int ops2 = d.comparisons; // Doubling V should roughly quadruple ops double ratio = (double) ops2 / ops1; assertTrue("Defective ops grows quadratically (ratio ≈ 4×): " + ratio, ratio >= 3.5 && ratio <= 4.5); } static void testFixedIsLinear() { System.out.println("\n--- testFixedIsLinear ---"); Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad f = new Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad(); int v1 = 50, v2 = 100; List l1 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v1, 100, true); List o1 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v1, 50, true); f.findBestSwap(l1, o1, Xen0001CreditBalanceLoadAlgorithm.totalLoad(l1), Xen0001CreditBalanceLoadAlgorithm.totalLoad(o1)); int ops1 = f.comparisons; List l2 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v2, 100, true); List o2 = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v2, 50, true); f.findBestSwap(l2, o2, Xen0001CreditBalanceLoadAlgorithm.totalLoad(l2), Xen0001CreditBalanceLoadAlgorithm.totalLoad(o2)); int ops2 = f.comparisons; // Fixed ops should be O(1) or at most O(V) — not O(V²) assertTrue("Fixed ops does not grow quadratically (ops1=" + ops1 + " ops2=" + ops2 + ")", ops2 <= ops1 * 4); // generous bound: well below V² ratio of 4 assertTrue("Fixed ops is bounded (ops1 <= 4): " + ops1, ops1 <= 4); assertTrue("Fixed ops is bounded (ops2 <= 4): " + ops2, ops2 <= 4); } static void testBothFindSameWinner() { System.out.println("\n--- testBothFindSameWinner ---"); // Imbalanced runqueues: lrqd very heavy, orqd light List lrqd = new ArrayList<>(); lrqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(1, 1000, true)); lrqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(2, 500, true)); lrqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(3, 200, false)); List orqd = new ArrayList<>(); orqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(10, 100, true)); orqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(11, 50, true)); long lLoad = 1700, oLoad = 150; Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad def = new Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad(); Xen0001CreditBalanceLoadAlgorithm.SwapPair defPair = def.findBestSwap(lrqd, orqd, lLoad, oLoad); // Sorted descending by avgload for fixed List lrqdS = new ArrayList<>(lrqd); List orqdS = new ArrayList<>(orqd); lrqdS.sort((a, b) -> Long.compare(b.avgload, a.avgload)); orqdS.sort((a, b) -> Long.compare(b.avgload, a.avgload)); Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad fix = new Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad(); Xen0001CreditBalanceLoadAlgorithm.SwapPair fixPair = fix.findBestSwap(lrqdS, orqdS, lLoad, oLoad); assertTrue("Both defective and fixed find a swap pair", defPair != null && fixPair != null); // Both should choose the heaviest push (id=1, load=1000) assertTrue("Both push the heaviest VCPU (id=1)", defPair != null && defPair.push.id == 1 && fixPair != null && fixPair.push.id == 1); } static void testNoMigratable() { System.out.println("\n--- testNoMigratable ---"); List lrqd = new ArrayList<>(); lrqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(1, 500, false)); lrqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(2, 300, false)); List orqd = new ArrayList<>(); orqd.add(new Xen0001CreditBalanceLoadAlgorithm.Vcpu(10, 100, false)); Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad def = new Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad(); Xen0001CreditBalanceLoadAlgorithm.SwapPair defPair = def.findBestSwap(lrqd, orqd, 800, 100); assertTrue("No swap when no VCPUs are migratable (defective): pair=null", defPair == null); Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad fix = new Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad(); Xen0001CreditBalanceLoadAlgorithm.SwapPair fixPair = fix.findBestSwap(lrqd, orqd, 800, 100); assertTrue("No swap when no VCPUs are migratable (fixed): pair=null", fixPair == null); } static void testSingleVcpu() { System.out.println("\n--- testSingleVcpu ---"); List lrqd = List.of( new Xen0001CreditBalanceLoadAlgorithm.Vcpu(1, 200, true)); List orqd = List.of( new Xen0001CreditBalanceLoadAlgorithm.Vcpu(2, 50, true)); Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad def = new Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad(); def.findBestSwap(lrqd, orqd, 200, 50); assertTrue("Single VCPU: defective comparisons=1", def.comparisons == 1); Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad fix = new Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad(); fix.findBestSwap(lrqd, orqd, 200, 50); assertTrue("Single VCPU: fixed comparisons <= 2", fix.comparisons <= 2); } static void testLoadRatioAbove50x() { System.out.println("\n--- testLoadRatioAbove50x (V=100) ---"); int v = 100; Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad def = new Xen0001CreditBalanceLoadAlgorithm.DefectiveBalanceLoad(); Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad fix = new Xen0001CreditBalanceLoadAlgorithm.FixedBalanceLoad(); List lrqd = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v, 100, false); List orqd = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v, 50, false); long lLoad = Xen0001CreditBalanceLoadAlgorithm.totalLoad(lrqd); long oLoad = Xen0001CreditBalanceLoadAlgorithm.totalLoad(orqd); def.findBestSwap(lrqd, orqd, lLoad, oLoad); List lS = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v, 100, true); List oS = Xen0001CreditBalanceLoadAlgorithm.buildSvcList(v, 50, true); fix.findBestSwap(lS, oS, lLoad, oLoad); double ratio = (double) def.comparisons / Math.max(fix.comparisons, 1); System.out.printf(" defective=%d, fixed=%d, ratio=%.1f×%n", def.comparisons, fix.comparisons, ratio); assertTrue("Op-count ratio >= 50× at V=100: " + ratio, ratio >= 50.0); } }