Each MOAD now has a synthetic defective specimen and fixed specimen proven from first principles across three test tiers: Unit (tests/unit/Moad000X*.java): - Correctness: defective and fixed produce identical functional output - Defect behavior: defective specimen exhibits the defect (measurable) - Fix behavior: fixed specimen eliminates the defect Integration (tests/integration/AllMoadsIntegrationTest.java): - All 9 MOADs proven at medium scale (N=500-2000) - MOAD-0001: O(N^2) vs O(N) list scan at N=1000 - MOAD-0002: 500 sessions trample each other (defective) vs coexist (fixed) - MOAD-0003: 250 anonymous requests leak auth identity (defective) vs zero (fixed) - MOAD-0004: 3000 credential exposures across 1000 requests (defective) vs zero (fixed) - MOAD-0005: 500 computes for 500 concurrent misses vs exactly 1 - MOAD-0006: all 500 passwords extractable from DB (defective) vs unextractable (fixed) - MOAD-0007: N=2000 spatial objects, defective visits all 2000 vs O(log N + k) - MOAD-0009: 990 wasted firings for 1000 ticks / 10 events vs zero waste - MOAD-0011: 10240 NFA steps vs 13 steps on N=12 adversarial input (788x) Functional (tests/functional/AllMoadsFunctionalTest.java): - MOAD-0005: real-thread contention proves herd (defective >1 compute, fixed exactly 1) - MOAD-0007: N=50000 spatial objects, 50M defective probes vs 516K fixed (97x speedup) - MOAD-0009: 10000 ticks / 10 events, 9990 wasted firings vs zero (1000x ratio) - MOAD-0011: N=16 adversarial, 163840 defective steps vs 17 fixed (9638x ratio) Support algorithms (tests/support/Moad000X*.java): - Moad0002Algorithm: shared mutable global state (DefectiveAudioSystem / FixedAudioSystem + Context) - Moad0003Algorithm: ThreadLocal not cleared (handleDefective / handleFixed with finally) - Moad0004Algorithm: HTTP headers logged verbatim (logDefective / logFixed with CREDENTIAL_HEADERS denylist) - Moad0005Algorithm: get+null+compute+put (DefectiveCache HashMap / FixedCache ConcurrentHashMap.computeIfAbsent) - Moad0006Algorithm: Base64 password storage (DefectiveCredentialStore / FixedCredentialStore SHA-256+salt) - Moad0007Algorithm: linear spatial scan (queryDefective list / queryFixed sorted array + binary search) - Moad0009Algorithm: timer-driven polling (runDefectiveScheduler / runFixedEventDriven) - Moad0011Algorithm: PCRE nested quantifiers (matchDefective backtracking NFA / matchFixed linear NFA) Makefile: added unit-moad-0002 through unit-moad-0011 targets, integration-all-moads, functional-all-moads. integration and functional targets now depend on all-MOADs variants.
174 lines
8 KiB
Java
174 lines
8 KiB
Java
package unit;
|
|
|
|
import support.Moad0009Algorithm;
|
|
import support.Moad0009Algorithm.Event;
|
|
import support.Moad0009Algorithm.Result;
|
|
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Unit tests for MOAD-0009: A Metered Heart.
|
|
*
|
|
* Proves from first principles:
|
|
* 1. Defective scheduler fires on every timer tick (N firings for N ticks)
|
|
* even when only M events occur — N - M firings are wasted.
|
|
* 2. Fixed event-driven handler fires exactly once per event (M firings for M events).
|
|
* 3. Both correctly process the same set of events (same events handled).
|
|
* 4. Defective wastes fire count grows with poll interval; fixed stays constant.
|
|
* 5. Zero-event scenario: defective fires N times on empty queue; fixed fires 0.
|
|
*
|
|
* No build tool required. Compile and run:
|
|
*
|
|
* cd tests
|
|
* java -m jdk.compiler/com.sun.tools.javac.Main -cp . \
|
|
* support/Moad0009Algorithm.java unit/Moad0009UnitTest.java
|
|
* java -cp . unit.Moad0009UnitTest
|
|
*/
|
|
public class Moad0009UnitTest {
|
|
|
|
private static int passed = 0;
|
|
private static int failed = 0;
|
|
|
|
public static void main(String[] args) {
|
|
System.out.println("=== Moad0009UnitTest (A Metered Heart) ===\n");
|
|
|
|
System.out.println("-- Correctness: both process the same events --");
|
|
testBothProcessSameEvents();
|
|
testBothHandleNoEvents();
|
|
|
|
System.out.println("\n-- Defect: timer fires N times regardless of M events --");
|
|
testDefectiveFiresEveryTick();
|
|
testDefectiveWastedFiresN100M3();
|
|
testDefectiveZeroEventsStillFiresN();
|
|
|
|
System.out.println("\n-- Fix: fires exactly once per event --");
|
|
testFixedFiresExactlyMTimes();
|
|
testFixedZeroEventsZeroFirings();
|
|
testFixedFireCountEqualsEventCount();
|
|
|
|
System.out.println("\n-- Comparison: defective wastes grow with poll count; fixed stays M --");
|
|
testWastedFiresGrowWithPollCount();
|
|
|
|
System.out.printf("\n%d passed, %d failed%n", passed, failed);
|
|
if (failed > 0) System.exit(1);
|
|
}
|
|
|
|
// ── Correctness ───────────────────────────────────────────────────────────
|
|
|
|
static void testBothProcessSameEvents() {
|
|
List<Event> events = Moad0009Algorithm.buildEvents(3, 10);
|
|
Result def = Moad0009Algorithm.runDefectiveScheduler(20, events);
|
|
Result fix = Moad0009Algorithm.runFixedEventDriven(events);
|
|
|
|
assertEqual("correctness: both process same event count", def.eventsProcessed, fix.eventsProcessed);
|
|
assertEqual("correctness: both process all 3 events", 3, def.eventsProcessed);
|
|
}
|
|
|
|
static void testBothHandleNoEvents() {
|
|
List<Event> events = List.of();
|
|
Result def = Moad0009Algorithm.runDefectiveScheduler(10, events);
|
|
Result fix = Moad0009Algorithm.runFixedEventDriven(events);
|
|
|
|
assertEqual("correctness: both process 0 events from empty list", 0, def.eventsProcessed);
|
|
assertEqual("correctness: fixed: 0 events processed", 0, fix.eventsProcessed);
|
|
}
|
|
|
|
// ── Defect ────────────────────────────────────────────────────────────────
|
|
|
|
static void testDefectiveFiresEveryTick() {
|
|
int ticks = 50;
|
|
List<Event> events = Moad0009Algorithm.buildEvents(2, ticks);
|
|
Result result = Moad0009Algorithm.runDefectiveScheduler(ticks, events);
|
|
// DEFECT: fires every tick regardless of events
|
|
assertEqual("defective: fires exactly N=" + ticks + " times", ticks, result.firings);
|
|
}
|
|
|
|
static void testDefectiveWastedFiresN100M3() {
|
|
int ticks = 100;
|
|
int eventCount = 3;
|
|
List<Event> events = Moad0009Algorithm.buildEvents(eventCount, ticks);
|
|
Result result = Moad0009Algorithm.runDefectiveScheduler(ticks, events);
|
|
|
|
// DEFECT: 100 firings for 3 events = 97 wasted firings (97% waste)
|
|
int wasted = result.firings - result.eventsProcessed;
|
|
assertEqual("defective: 97 wasted firings (100 ticks, 3 events)", 97, wasted);
|
|
assertTrue("defective: waste ratio > 95%",
|
|
(double) wasted / result.firings > 0.95,
|
|
"wasted=" + wasted + " total=" + result.firings);
|
|
}
|
|
|
|
static void testDefectiveZeroEventsStillFiresN() {
|
|
int ticks = 60;
|
|
List<Event> events = List.of();
|
|
Result result = Moad0009Algorithm.runDefectiveScheduler(ticks, events);
|
|
// DEFECT: no events exist, but timer still fires 60 times — pure waste
|
|
assertEqual("defective: 0 events, fires N=" + ticks + " times (100% waste)", ticks, result.firings);
|
|
assertEqual("defective: 0 events processed", 0, result.eventsProcessed);
|
|
}
|
|
|
|
// ── Fix ───────────────────────────────────────────────────────────────────
|
|
|
|
static void testFixedFiresExactlyMTimes() {
|
|
List<Event> events = Moad0009Algorithm.buildEvents(5, 100);
|
|
Result result = Moad0009Algorithm.runFixedEventDriven(events);
|
|
assertEqual("fixed: fires exactly M=5 times (one per event)", 5, result.firings);
|
|
}
|
|
|
|
static void testFixedZeroEventsZeroFirings() {
|
|
List<Event> events = List.of();
|
|
Result result = Moad0009Algorithm.runFixedEventDriven(events);
|
|
assertEqual("fixed: 0 events → 0 firings (no wasted work)", 0, result.firings);
|
|
}
|
|
|
|
static void testFixedFireCountEqualsEventCount() {
|
|
for (int m : new int[]{1, 7, 23, 100}) {
|
|
List<Event> events = Moad0009Algorithm.buildEvents(m, 200);
|
|
Result result = Moad0009Algorithm.runFixedEventDriven(events);
|
|
assertEqual("fixed: M=" + m + " events → exactly M=" + m + " firings",
|
|
m, result.firings);
|
|
}
|
|
}
|
|
|
|
// ── Comparison ────────────────────────────────────────────────────────────
|
|
|
|
static void testWastedFiresGrowWithPollCount() {
|
|
List<Event> events = Moad0009Algorithm.buildEvents(2, 200);
|
|
|
|
// More ticks = more waste in defective; fixed stays at M=2
|
|
Result def50 = Moad0009Algorithm.runDefectiveScheduler(50, events);
|
|
Result def200 = Moad0009Algorithm.runDefectiveScheduler(200, events);
|
|
Result fix = Moad0009Algorithm.runFixedEventDriven(events);
|
|
|
|
assertTrue("defective: 50 ticks → 50 firings", def50.firings == 50, "got " + def50.firings);
|
|
assertTrue("defective: 200 ticks → 200 firings", def200.firings == 200, "got " + def200.firings);
|
|
assertTrue("fixed: always 2 firings regardless of tick count", fix.firings == 2, "got " + fix.firings);
|
|
|
|
// Wasted = defective.firings - events processed
|
|
int waste50 = def50.firings - def50.eventsProcessed;
|
|
int waste200 = def200.firings - def200.eventsProcessed;
|
|
assertTrue("defective: waste grows with tick count (200 > 50)",
|
|
waste200 > waste50, "waste50=" + waste50 + " waste200=" + waste200);
|
|
}
|
|
|
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
|
|
static void assertEqual(String label, int expected, int actual) {
|
|
if (expected == actual) {
|
|
System.out.printf(" PASS: %s%n", label);
|
|
passed++;
|
|
} else {
|
|
System.out.printf(" FAIL: %s — expected %d, got %d%n", label, expected, actual);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
static void assertTrue(String label, boolean condition, String detail) {
|
|
if (condition) {
|
|
System.out.printf(" PASS: %s%n", label);
|
|
passed++;
|
|
} else {
|
|
System.out.printf(" FAIL: %s — %s%n", label, detail);
|
|
failed++;
|
|
}
|
|
}
|
|
}
|