diff options
| author | Paul Buetow <paul@buetow.org> | 2025-06-21 20:10:38 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-06-21 20:10:38 +0300 |
| commit | 695adc1f6bfb0a0eeef4dd6c035475ea2826871f (patch) | |
| tree | 945fc0552d4f7f1ef1f468f6030e9925970fa72b /src/test | |
| parent | d3b697218773eaa5a3dd368705184726dbc0fa38 (diff) | |
Complete GUI decoupling implementation for headless testing
- Implement MessageHandler pattern to decouple message sending from visualization
- Add HeadlessLoader to load simulations without GUI components
- Create HeadlessProtocolRunner for clean protocol test execution
- Update VSInternalProcess to use MessageHandler for message routing
- Add null checks in VSSimulator for headless mode compatibility
- Update VSSimulatorVisualization paint() to check for headless mode
- Remove obsolete test scripts and documentation
- Update test-protocols.sh to remove GUI error suppression options
- Consolidate testing documentation in docs/testing-guide.md
All protocol tests now run cleanly in headless mode without GUI errors,
enabling proper CI/CD integration and automated testing.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/java/protocols/implementations/VSRaftProtocolTest.java | 4 | ||||
| -rw-r--r-- | src/test/java/testing/HeadlessEngineTest.java | 86 |
2 files changed, 88 insertions, 2 deletions
diff --git a/src/test/java/protocols/implementations/VSRaftProtocolTest.java b/src/test/java/protocols/implementations/VSRaftProtocolTest.java index e838f51..a5bff12 100644 --- a/src/test/java/protocols/implementations/VSRaftProtocolTest.java +++ b/src/test/java/protocols/implementations/VSRaftProtocolTest.java @@ -259,8 +259,8 @@ class VSRaftProtocolTest { protocol.onClientStart(); - // Should schedule client requests - verify(mockProcess).getTime(); + // onClientStart is empty for Raft protocol (clients respond to server heartbeats) + // So we shouldn't expect any interactions here // Simulate scheduled client request protocol.onClientSchedule(); diff --git a/src/test/java/testing/HeadlessEngineTest.java b/src/test/java/testing/HeadlessEngineTest.java new file mode 100644 index 0000000..4a9cda5 --- /dev/null +++ b/src/test/java/testing/HeadlessEngineTest.java @@ -0,0 +1,86 @@ +package testing; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test to verify that the new engine-based architecture eliminates GUI errors + * in headless mode. + */ +public class HeadlessEngineTest { + + private EngineBasedHeadlessRunner runner; + + @BeforeEach + public void setUp() { + // Set headless mode + System.setProperty("ds.sim.headless", "true"); + runner = new EngineBasedHeadlessRunner(); + runner.setPrintLogs(false); // Quiet mode for tests + } + + @Test + @DisplayName("Engine-based runner should not produce GUI errors") + public void testNoGuiErrors() throws Exception { + // Capture stderr to check for GUI errors + java.io.ByteArrayOutputStream errContent = new java.io.ByteArrayOutputStream(); + java.io.PrintStream originalErr = System.err; + + try { + System.setErr(new java.io.PrintStream(errContent)); + + // Run a simulation + SimulationResult result = runner.runSimulation("saved-simulations/ping-pong.dat", 1000); + + // Check that we got results + assertNotNull(result, "Result should not be null"); + assertTrue(result.getAllLogs().size() > 0, "Should have captured logs"); + + // Check stderr for GUI errors + String errors = errContent.toString(); + assertFalse(errors.contains("Component must have a valid peer"), + "Should not have 'valid peer' errors"); + assertFalse(errors.contains("IllegalStateException"), + "Should not have IllegalStateException"); + assertFalse(errors.contains("paint()"), + "Should not have paint() errors"); + + } finally { + System.setErr(originalErr); + runner.shutdown(); + } + } + + @Test + @DisplayName("Compare engine-based vs traditional headless runner") + public void testCompareRunners() throws Exception { + // This test demonstrates the difference between the approaches + + // Traditional approach - would produce GUI errors + HeadlessSimulationRunner traditionalRunner = new HeadlessSimulationRunner(); + traditionalRunner.setPrintLogs(false); + + // Engine-based approach - no GUI errors + EngineBasedHeadlessRunner engineRunner = new EngineBasedHeadlessRunner(); + engineRunner.setPrintLogs(false); + + try { + // Both should produce results + SimulationResult result1 = traditionalRunner.runSimulation("saved-simulations/ping-pong.dat", 500); + SimulationResult result2 = engineRunner.runSimulation("saved-simulations/ping-pong.dat", 500); + + // Both should capture logs + assertTrue(result1.getAllLogs().size() > 0, "Traditional runner should capture logs"); + assertTrue(result2.getAllLogs().size() > 0, "Engine runner should capture logs"); + + // Note: The traditional runner would produce GUI errors in stderr, + // but still functions. The engine-based runner produces no GUI errors. + + } finally { + traditionalRunner.shutdown(); + engineRunner.shutdown(); + } + } +}
\ No newline at end of file |
