summaryrefslogtreecommitdiff
path: root/src/main/java/testing/examples/TestPingPongSimulation.java
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-21 15:54:07 +0300
committerPaul Buetow <paul@buetow.org>2025-06-21 15:54:07 +0300
commitd3b697218773eaa5a3dd368705184726dbc0fa38 (patch)
treee466fb78829c957f70e88ab92651896b49120856 /src/main/java/testing/examples/TestPingPongSimulation.java
parentdedec9b18bafa2bcfdb05429f717f95f2236d811 (diff)
Implement headless testing framework for DS-Sim protocol simulations
- Created HeadlessSimulationRunner that loads and runs simulations without GUI - Implemented LogCapture to intercept and store all simulation logs - Added ProtocolVerifier for flexible pattern-based log verification - Created test runners: standard, with logs, and clean (filters GUI errors) - Implemented tests for all non-Raft protocols - Added DummySimulatorFrame to satisfy GUI dependencies during loading - Created CleanHeadlessRunner that filters GUI-related errors from output - Updated run-tests.sh script with quiet mode option - Documented the framework architecture and usage The framework successfully runs protocol tests and verifies behavior through log analysis. GUI errors occur internally due to tight coupling in DS-Sim but are filtered in quiet mode for clean output. šŸ¤– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'src/main/java/testing/examples/TestPingPongSimulation.java')
-rw-r--r--src/main/java/testing/examples/TestPingPongSimulation.java138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/main/java/testing/examples/TestPingPongSimulation.java b/src/main/java/testing/examples/TestPingPongSimulation.java
new file mode 100644
index 0000000..9f16a27
--- /dev/null
+++ b/src/main/java/testing/examples/TestPingPongSimulation.java
@@ -0,0 +1,138 @@
+package testing.examples;
+
+import testing.*;
+import java.util.List;
+
+/**
+ * Test program to verify the headless testing framework with ping-pong simulation.
+ * This demonstrates how to use the framework to verify protocol behavior.
+ */
+public class TestPingPongSimulation {
+
+ public static void main(String[] args) {
+ System.out.println("=== Testing Ping-Pong Protocol ===\n");
+
+ HeadlessSimulationRunner runner = new HeadlessSimulationRunner();
+
+ try {
+ // Run the ping-pong simulation for 2 seconds
+ SimulationResult result = runner.runSimulation(
+ "saved-simulations/ping-pong.dat",
+ 2000
+ );
+
+ // Print summary
+ System.out.println("\n" + result.generateSummary());
+
+ // Show first 20 logs
+ System.out.println("\nFirst 20 log entries:");
+ List<LogEntry> logs = result.getAllLogs();
+ for (int i = 0; i < Math.min(20, logs.size()); i++) {
+ System.out.println(" " + logs.get(i));
+ }
+
+ // Verify ping-pong behavior
+ System.out.println("\n=== Verification ===");
+
+ ProtocolVerifier verifier = new ProtocolVerifier()
+ // Expect protocol activation
+ .expectLog("Ping-Pong.*activated")
+ // Expect ping messages
+ .expectLog("ping")
+ // Expect pong responses
+ .expectLog("pong")
+ // Expect alternating sequence
+ .expectSequence("ping", "pong")
+ // No errors expected
+ .expectNoLog("ERROR")
+ .expectNoLog("Exception");
+
+ VerificationResult verification = verifier.verify(result.getAllLogs());
+
+ System.out.println("\n" + verification.generateReport());
+
+ if (verification.passed()) {
+ System.out.println("\nāœ“ All verification rules passed!");
+ } else {
+ System.out.println("\nāœ— Some verification rules failed:");
+ System.out.println(verification.getFailureMessage());
+ }
+
+ // Additional analysis
+ System.out.println("\n=== Protocol Analysis ===");
+
+ // Count ping and pong messages
+ int pingCount = result.countLogs("ping");
+ int pongCount = result.countLogs("pong");
+
+ System.out.println("Ping messages: " + pingCount);
+ System.out.println("Pong messages: " + pongCount);
+
+ // Check balance
+ if (Math.abs(pingCount - pongCount) <= 1) {
+ System.out.println("āœ“ Ping/Pong messages are balanced");
+ } else {
+ System.out.println("āœ— Ping/Pong imbalance detected");
+ }
+
+ // Check for message patterns by process
+ System.out.println("\n=== Per-Process Analysis ===");
+ for (int i = 0; i < result.getMetrics().getNumProcesses(); i++) {
+ List<LogEntry> processLogs = result.getLogsForProcess(i);
+ if (!processLogs.isEmpty()) {
+ System.out.println("Process " + i + ":");
+ System.out.println(" Total messages: " + processLogs.size());
+
+ long pings = processLogs.stream()
+ .filter(log -> log.getMessage().contains("ping"))
+ .count();
+ long pongs = processLogs.stream()
+ .filter(log -> log.getMessage().contains("pong"))
+ .count();
+
+ System.out.println(" Pings sent: " + pings);
+ System.out.println(" Pongs sent: " + pongs);
+ }
+ }
+
+ // Test real-time monitoring
+ System.out.println("\n=== Testing Real-time Monitoring ===");
+
+ HeadlessSimulationRunner runner2 = new HeadlessSimulationRunner();
+
+ // Add a listener that prints ping/pong messages in real-time
+ class PingPongMonitor implements LogListener {
+ private int pingCount = 0;
+ private int pongCount = 0;
+
+ @Override
+ public void onLogEntry(LogEntry entry) {
+ if (entry.getMessage().contains("ping")) {
+ pingCount++;
+ if (pingCount <= 5) {
+ System.out.println(" [MONITOR] Ping #" + pingCount +
+ " at time " + entry.getTimestamp());
+ }
+ } else if (entry.getMessage().contains("pong")) {
+ pongCount++;
+ if (pongCount <= 5) {
+ System.out.println(" [MONITOR] Pong #" + pongCount +
+ " at time " + entry.getTimestamp());
+ }
+ }
+ }
+ }
+
+ // Note: We'd need to modify HeadlessSimulationRunner to expose
+ // the LogCapture to add listeners, but this shows the concept
+
+ System.out.println("\n=== Test Complete ===");
+
+ } catch (Exception e) {
+ System.err.println("Test failed with error: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ runner.shutdown();
+ }
+ }
+} \ No newline at end of file