diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-27 15:43:46 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-27 15:43:46 +0200 |
| commit | 73567cc1e5a3a02d4c60c534122e8db9e8a82949 (patch) | |
| tree | 31ffd4831ad86dda22b950ac33239149b3d13202 | |
| parent | 63b658f8fba0790aa5b6bf94d4c89012f552a7ca (diff) | |
Narrow replay task visibility fix
| -rw-r--r-- | saved-simulations/raft.dat | bin | 15305 -> 15305 bytes | |||
| -rw-r--r-- | src/main/java/core/VSTaskManager.java | 7 | ||||
| -rw-r--r-- | src/main/java/simulator/builder/SimulationBuilder.java | 2 | ||||
| -rw-r--r-- | src/test/java/core/VSTaskManagerCrashRecoveryIntegrationTest.java | 88 |
4 files changed, 90 insertions, 7 deletions
diff --git a/saved-simulations/raft.dat b/saved-simulations/raft.dat Binary files differindex c54c0c5..9f6c7ad 100644 --- a/saved-simulations/raft.dat +++ b/saved-simulations/raft.dat diff --git a/src/main/java/core/VSTaskManager.java b/src/main/java/core/VSTaskManager.java index c78af5b..bd95a4e 100644 --- a/src/main/java/core/VSTaskManager.java +++ b/src/main/java/core/VSTaskManager.java @@ -553,12 +553,7 @@ public class VSTaskManager implements VSSerializable { for (int i = 0; i < numTasks; ++i) { VSTask task = new VSTask(serialize, objectInputStream); - /* - * Serialized tasks define the replay state of a loaded simulation. - * Register them as programmed so they remain visible in the Event - * view and survive reset/replay after deserialization. - */ - addTask(task, PROGRAMMED); + addTask(task, task.isProgrammed()); } /** For later backwards compatibility, to add more stuff */ diff --git a/src/main/java/simulator/builder/SimulationBuilder.java b/src/main/java/simulator/builder/SimulationBuilder.java index cf5f962..ac78a68 100644 --- a/src/main/java/simulator/builder/SimulationBuilder.java +++ b/src/main/java/simulator/builder/SimulationBuilder.java @@ -308,7 +308,7 @@ public class SimulationBuilder { // Create task VSTask task = new VSTask(st.time, process, st.event, st.isGlobalTimed ? VSTask.GLOBAL : VSTask.LOCAL); - taskManager.addTask(task); + taskManager.addTask(task, VSTaskManager.PROGRAMMED); } } diff --git a/src/test/java/core/VSTaskManagerCrashRecoveryIntegrationTest.java b/src/test/java/core/VSTaskManagerCrashRecoveryIntegrationTest.java index 34908bb..eb4bc7b 100644 --- a/src/test/java/core/VSTaskManagerCrashRecoveryIntegrationTest.java +++ b/src/test/java/core/VSTaskManagerCrashRecoveryIntegrationTest.java @@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.FileOutputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Files; @@ -15,6 +17,8 @@ import org.junit.jupiter.api.Test; import events.implementations.VSProcessCrashEvent; import events.implementations.VSProcessRecoverEvent; +import prefs.VSSerializablePrefs; +import serialize.VSSerialize; import simulator.VSSimulator; import simulator.VSSimulatorVisualization; import simulator.builder.SimulationBuilder; @@ -148,6 +152,57 @@ class VSTaskManagerCrashRecoveryIntegrationTest { } @Test + @DisplayName("Loading preserves programmed replay tasks but not ordinary runtime tasks") + void loadingPreservesProgrammedReplayTasksWithoutPromotingRuntimeTasks() + throws Exception { + Path replayFile = Files.createTempFile("programmed-replay", ".dat"); + Path runtimeFile = Files.createTempFile("runtime-task", ".dat"); + + VSSimulator replaySimulator = new SimulationBuilder() + .withProcesses(3) + .withDuration(1000) + .addCrashEvent(0, 5) + .save(replayFile.toString()) + .getSimulator(); + simulatorToStop = replaySimulator; + + HeadlessLoader.LoadedSimulation replayLoaded = + HeadlessLoader.load(replayFile.toString(), replaySimulator.getPrefs()); + loadedSimulatorToStop = replayLoaded.getSimulator(); + + VSTaskManager replayTaskManager = replayLoaded.getVisualization().getTaskManager(); + assertEquals(1, replayTaskManager.getProcessGlobalTasks( + replayLoaded.getVisualization().getProcess(0)).size(), + "builder-authored replay task should remain visible after load"); + + loadedSimulatorToStop.getSimulatorCanvas().stopThread(); + loadedSimulatorToStop = null; + + VSSimulator runtimeSimulator = new SimulationBuilder() + .withProcesses(3) + .withDuration(1000) + .getSimulator(); + simulatorToStop = runtimeSimulator; + + VSSimulatorVisualization runtimeVisualization = runtimeSimulator.getSimulatorCanvas(); + VSInternalProcess runtimeProcess = runtimeVisualization.getProcess(0); + VSTask runtimeTask = new VSTask(5, runtimeProcess, new VSProcessCrashEvent(), VSTask.GLOBAL); + runtimeVisualization.getTaskManager().addTask(runtimeTask); + assertFalse(runtimeTask.isProgrammed(), "runtime task should remain non-programmed before save"); + + saveSimulation(runtimeFile, runtimeSimulator); + + HeadlessLoader.LoadedSimulation runtimeLoaded = + HeadlessLoader.load(runtimeFile.toString(), runtimeSimulator.getPrefs()); + loadedSimulatorToStop = runtimeLoaded.getSimulator(); + + VSTaskManager runtimeTaskManager = runtimeLoaded.getVisualization().getTaskManager(); + assertEquals(0, runtimeTaskManager.getProcessGlobalTasks( + runtimeLoaded.getVisualization().getProcess(0)).size(), + "ordinary non-programmed runtime task must stay hidden after load"); + } + + @Test @DisplayName("Live GUI-style event injection supports recover and later crash") void liveEventInjectionSupportsRecoverAndLaterCrash() throws Exception { VSSimulator simulator = new SimulationBuilder() @@ -214,4 +269,37 @@ class VSTaskManagerCrashRecoveryIntegrationTest { simulator.getSimulatorCanvas().stopThread(); } } + + private void saveSimulation(Path file, VSSimulator simulator) throws Exception { + VSSerialize serialize = new VSSerialize(); + try (FileOutputStream fos = new FileOutputStream(file.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos)) { + VSSerializablePrefs serializablePrefs = new VSSerializablePrefs(); + + for (String key : simulator.getPrefs().getIntegerKeySet()) { + serializablePrefs.initInteger(key, simulator.getPrefs().getInteger(key)); + } + for (String key : simulator.getPrefs().getBooleanKeySet()) { + serializablePrefs.initBoolean(key, simulator.getPrefs().getBoolean(key)); + } + for (String key : simulator.getPrefs().getStringKeySet()) { + serializablePrefs.initString(key, simulator.getPrefs().getString(key)); + } + for (String key : simulator.getPrefs().getFloatKeySet()) { + serializablePrefs.initFloat(key, simulator.getPrefs().getFloat(key)); + } + for (String key : simulator.getPrefs().getColorKeySet()) { + serializablePrefs.initColor(key, simulator.getPrefs().getColor(key)); + } + for (String key : simulator.getPrefs().getVectorKeySet()) { + serializablePrefs.initVector(key, simulator.getPrefs().getVector(key)); + } + for (String key : simulator.getPrefs().getLongKeySet()) { + serializablePrefs.initLong(key, simulator.getPrefs().getLong(key)); + } + + serializablePrefs.serialize(serialize, oos); + simulator.serialize(serialize, oos); + } + } } |
