summaryrefslogtreecommitdiff
path: root/src/test/java/core
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-20 16:44:44 +0300
committerPaul Buetow <paul@buetow.org>2025-06-20 16:44:44 +0300
commitedf34c8f2b28666ab0275921e4a3c23524ef7baf (patch)
tree284e8d0ecca9c5ed1bffe5468bdef9ec8ac0a5b4 /src/test/java/core
parent62d1d3b956854a0e0991fad153aee6ce2c217b24 (diff)
Add comprehensive unit test coverage for core components
- Add test structure with 133 unit tests (124 passing) - Test coverage for core classes: VSTask, VSMessage - Test coverage for event system: VSAbstractEvent, VSRegisteredEvents, and implementations - Test coverage for protocol framework: VSAbstractProtocol, VSPingPongProtocol - Some protocol tests fail due to complex mocking requirements, but core functionality is well tested This establishes a solid foundation for safe refactoring and future development. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'src/test/java/core')
-rw-r--r--src/test/java/core/VSMessageTest.java315
-rw-r--r--src/test/java/core/VSTaskTest.java510
2 files changed, 825 insertions, 0 deletions
diff --git a/src/test/java/core/VSMessageTest.java b/src/test/java/core/VSMessageTest.java
new file mode 100644
index 0000000..0826244
--- /dev/null
+++ b/src/test/java/core/VSMessageTest.java
@@ -0,0 +1,315 @@
+package core;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.DisplayName;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import core.time.VSVectorTime;
+import events.VSRegisteredEvents;
+import prefs.VSPrefs;
+
+/**
+ * Unit tests for VSMessage class.
+ * Tests message creation, initialization, and various getter/setter functionality.
+ *
+ * @author Test Suite
+ */
+class VSMessageTest {
+
+ @Mock
+ private VSInternalProcess mockSendingProcess;
+
+ @Mock
+ private VSPrefs mockPrefs;
+
+ @Mock
+ private VSVectorTime mockVectorTime;
+
+ @Mock
+ private VSVectorTime mockVectorTimeCopy;
+
+ private VSMessage message;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+
+ // Setup common mocks
+ when(mockSendingProcess.getPrefs()).thenReturn(mockPrefs);
+ when(mockSendingProcess.getLamportTime()).thenReturn(42L);
+ when(mockSendingProcess.getVectorTime()).thenReturn(mockVectorTime);
+ when(mockVectorTime.getCopy()).thenReturn(mockVectorTimeCopy);
+
+ when(mockPrefs.getString("lang.protocol")).thenReturn("Protocol");
+
+ message = new VSMessage();
+ }
+
+ @Test
+ @DisplayName("Test VSMessage constructor creates unique message IDs")
+ void testConstructorCreatesUniqueIds() {
+ // Given/When
+ VSMessage message1 = new VSMessage();
+ VSMessage message2 = new VSMessage();
+ VSMessage message3 = new VSMessage();
+
+ // Then
+ assertNotEquals(message1.getMessageID(), message2.getMessageID());
+ assertNotEquals(message2.getMessageID(), message3.getMessageID());
+ assertNotEquals(message1.getMessageID(), message3.getMessageID());
+ assertTrue(message2.getMessageID() > message1.getMessageID());
+ assertTrue(message3.getMessageID() > message2.getMessageID());
+ }
+
+ @Test
+ @DisplayName("Test init method for server message")
+ void testInitServerMessage() {
+ // Given
+ String protocolClassname = "test.protocol.MyProtocol";
+
+ // When
+ message.init(mockSendingProcess, protocolClassname, VSMessage.IS_SERVER_MESSAGE);
+
+ // Then
+ assertEquals(mockSendingProcess, message.getSendingProcess());
+ assertEquals(protocolClassname, message.getProtocolClassname());
+ assertTrue(message.isServerMessage());
+ assertEquals(42L, message.getLamportTime());
+ assertEquals(mockVectorTimeCopy, message.getVectorTime());
+ }
+
+ @Test
+ @DisplayName("Test init method for client message")
+ void testInitClientMessage() {
+ // Given
+ String protocolClassname = "test.protocol.ClientProtocol";
+
+ // When
+ message.init(mockSendingProcess, protocolClassname, VSMessage.IS_CLIENT_MESSAGE);
+
+ // Then
+ assertEquals(mockSendingProcess, message.getSendingProcess());
+ assertEquals(protocolClassname, message.getProtocolClassname());
+ assertFalse(message.isServerMessage());
+ }
+
+ @Test
+ @DisplayName("Test getName method")
+ void testGetName() {
+ // Given
+ String protocolClassname = "test.protocol.MyProtocol";
+ String expectedName = "My Protocol";
+ message.init(mockSendingProcess, protocolClassname, VSMessage.IS_SERVER_MESSAGE);
+
+ // Mock static method behavior
+ try (var mockedStatic = mockStatic(VSRegisteredEvents.class)) {
+ mockedStatic.when(() -> VSRegisteredEvents.getNameByClassname(protocolClassname))
+ .thenReturn(expectedName);
+
+ // When
+ String name = message.getName();
+
+ // Then
+ assertEquals(expectedName, name);
+ }
+ }
+
+ @Test
+ @DisplayName("Test getMessageID returns correct ID")
+ void testGetMessageID() {
+ // Given - message created in setUp
+
+ // When
+ long messageId = message.getMessageID();
+
+ // Then
+ assertTrue(messageId > 0);
+ }
+
+ @Test
+ @DisplayName("Test getSendingProcess returns correct process")
+ void testGetSendingProcess() {
+ // Given
+ message.init(mockSendingProcess, "test.Protocol", VSMessage.IS_SERVER_MESSAGE);
+
+ // When
+ VSAbstractProcess process = message.getSendingProcess();
+
+ // Then
+ assertEquals(mockSendingProcess, process);
+ }
+
+ @Test
+ @DisplayName("Test getLamportTime returns correct time")
+ void testGetLamportTime() {
+ // Given
+ when(mockSendingProcess.getLamportTime()).thenReturn(100L);
+ message.init(mockSendingProcess, "test.Protocol", VSMessage.IS_SERVER_MESSAGE);
+
+ // When
+ long lamportTime = message.getLamportTime();
+
+ // Then
+ assertEquals(100L, lamportTime);
+ }
+
+ @Test
+ @DisplayName("Test getVectorTime returns correct vector time")
+ void testGetVectorTime() {
+ // Given
+ message.init(mockSendingProcess, "test.Protocol", VSMessage.IS_SERVER_MESSAGE);
+
+ // When
+ VSVectorTime vectorTime = message.getVectorTime();
+
+ // Then
+ assertEquals(mockVectorTimeCopy, vectorTime);
+ }
+
+ @Test
+ @DisplayName("Test toString method")
+ void testToString() {
+ // Given
+ String protocolClassname = "test.protocol.MyProtocol";
+ String shortname = "MP";
+ message.init(mockSendingProcess, protocolClassname, VSMessage.IS_SERVER_MESSAGE);
+
+ try (var mockedStatic = mockStatic(VSRegisteredEvents.class)) {
+ mockedStatic.when(() -> VSRegisteredEvents.getShortnameByClassname(protocolClassname))
+ .thenReturn(shortname);
+
+ // When
+ String result = message.toString();
+
+ // Then
+ assertTrue(result.contains("ID: " + message.getMessageID()));
+ assertTrue(result.contains("Protocol"));
+ assertTrue(result.contains(shortname));
+ }
+ }
+
+ @Test
+ @DisplayName("Test toStringFull method includes parent toString")
+ void testToStringFull() {
+ // Given
+ String protocolClassname = "test.protocol.MyProtocol";
+ message.init(mockSendingProcess, protocolClassname, VSMessage.IS_SERVER_MESSAGE);
+
+ // Setup some preferences in the message
+ message.setInteger("test.value", 123);
+
+ // When
+ String result = message.toStringFull();
+
+ // Then
+ assertTrue(result.contains("ID: " + message.getMessageID()));
+ assertTrue(result.contains("test.value"));
+ assertTrue(result.contains("123"));
+ }
+
+ @Test
+ @DisplayName("Test equals method with same message ID")
+ void testEqualsWithSameId() {
+ // Given
+ VSMessage message1 = new VSMessage();
+ VSMessage message2 = message1; // Same reference
+
+ // When/Then
+ assertTrue(message1.equals(message2));
+ }
+
+ @Test
+ @DisplayName("Test equals method with different message IDs")
+ void testEqualsWithDifferentIds() {
+ // Given
+ VSMessage message1 = new VSMessage();
+ VSMessage message2 = new VSMessage();
+
+ // When/Then
+ assertFalse(message1.equals(message2));
+ }
+
+ @Test
+ @DisplayName("Test message inherits VSPrefs functionality")
+ void testPrefsInheritance() {
+ // Given
+ message.init(mockSendingProcess, "test.Protocol", VSMessage.IS_SERVER_MESSAGE);
+
+ // When - Test some VSPrefs methods
+ message.setInteger("test.int", 42);
+ message.setString("test.string", "Hello");
+ message.setBoolean("test.bool", true);
+
+ // Then
+ assertEquals(42, message.getInteger("test.int"));
+ assertEquals("Hello", message.getString("test.string"));
+ assertTrue(message.getBoolean("test.bool"));
+ }
+
+ @Test
+ @DisplayName("Test message initialization captures timestamps at send time")
+ void testTimestampsCapturedAtInit() {
+ // Given
+ when(mockSendingProcess.getLamportTime()).thenReturn(10L);
+ VSVectorTime firstVectorTime = mock(VSVectorTime.class);
+ VSVectorTime firstCopy = mock(VSVectorTime.class);
+ when(mockSendingProcess.getVectorTime()).thenReturn(firstVectorTime);
+ when(firstVectorTime.getCopy()).thenReturn(firstCopy);
+
+ // When - Initialize message
+ message.init(mockSendingProcess, "test.Protocol", VSMessage.IS_SERVER_MESSAGE);
+
+ // Change process times after initialization
+ when(mockSendingProcess.getLamportTime()).thenReturn(20L);
+ VSVectorTime secondVectorTime = mock(VSVectorTime.class);
+ when(mockSendingProcess.getVectorTime()).thenReturn(secondVectorTime);
+
+ // Then - Message should retain original timestamps
+ assertEquals(10L, message.getLamportTime());
+ assertEquals(firstCopy, message.getVectorTime());
+ }
+
+ @Test
+ @DisplayName("Test server message flag")
+ void testServerMessageFlag() {
+ // Given/When - Server message
+ message.init(mockSendingProcess, "test.Protocol", VSMessage.IS_SERVER_MESSAGE);
+
+ // Then
+ assertTrue(message.isServerMessage());
+
+ // Given/When - Client message
+ VSMessage clientMessage = new VSMessage();
+ clientMessage.init(mockSendingProcess, "test.Protocol", VSMessage.IS_CLIENT_MESSAGE);
+
+ // Then
+ assertFalse(clientMessage.isServerMessage());
+ }
+
+ @Test
+ @DisplayName("Test multiple messages can be created with different protocols")
+ void testMultipleMessagesWithDifferentProtocols() {
+ // Given
+ VSMessage message1 = new VSMessage();
+ VSMessage message2 = new VSMessage();
+ VSMessage message3 = new VSMessage();
+
+ // When
+ message1.init(mockSendingProcess, "protocol.One", VSMessage.IS_SERVER_MESSAGE);
+ message2.init(mockSendingProcess, "protocol.Two", VSMessage.IS_CLIENT_MESSAGE);
+ message3.init(mockSendingProcess, "protocol.Three", VSMessage.IS_SERVER_MESSAGE);
+
+ // Then
+ assertEquals("protocol.One", message1.getProtocolClassname());
+ assertEquals("protocol.Two", message2.getProtocolClassname());
+ assertEquals("protocol.Three", message3.getProtocolClassname());
+ assertTrue(message1.isServerMessage());
+ assertFalse(message2.isServerMessage());
+ assertTrue(message3.isServerMessage());
+ }
+} \ No newline at end of file
diff --git a/src/test/java/core/VSTaskTest.java b/src/test/java/core/VSTaskTest.java
new file mode 100644
index 0000000..3fbec3c
--- /dev/null
+++ b/src/test/java/core/VSTaskTest.java
@@ -0,0 +1,510 @@
+package core;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.DisplayName;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import events.VSAbstractEvent;
+import events.implementations.VSProcessCrashEvent;
+import events.implementations.VSProcessRecoverEvent;
+import events.internal.VSMessageReceiveEvent;
+import events.internal.VSProtocolEvent;
+import exceptions.VSEventNotCopyableException;
+import prefs.VSPrefs;
+import protocols.VSAbstractProtocol;
+import serialize.VSSerialize;
+
+/**
+ * Unit tests for VSTask class.
+ * Tests task creation, execution, comparison, and serialization functionality.
+ *
+ * @author Test Suite
+ */
+class VSTaskTest {
+
+ @Mock
+ private VSInternalProcess mockProcess;
+
+ @Mock
+ private VSAbstractEvent mockEvent;
+
+ @Mock
+ private VSPrefs mockPrefs;
+
+ @Mock
+ private VSAbstractProtocol mockProtocol;
+
+ private VSTask task;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ when(mockProcess.getPrefs()).thenReturn(mockPrefs);
+ when(mockPrefs.getString("lang.task")).thenReturn("Task");
+ when(mockProcess.getProcessID()).thenReturn(1);
+ }
+
+ @Test
+ @DisplayName("Test VSTask constructor with local timing")
+ void testConstructorLocalTiming() {
+ // Given
+ long taskTime = 1000L;
+
+ // When
+ task = new VSTask(taskTime, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // Then
+ assertEquals(taskTime, task.getTaskTime());
+ assertEquals(mockProcess, task.getProcess());
+ assertEquals(mockEvent, task.getEvent());
+ assertFalse(task.isGlobalTimed());
+ assertTrue(task.getTaskNum() > 0);
+ }
+
+ @Test
+ @DisplayName("Test VSTask constructor with global timing")
+ void testConstructorGlobalTiming() {
+ // Given
+ long taskTime = 2000L;
+
+ // When
+ task = new VSTask(taskTime, mockProcess, mockEvent, VSTask.GLOBAL);
+
+ // Then
+ assertEquals(taskTime, task.getTaskTime());
+ assertTrue(task.isGlobalTimed());
+ }
+
+ @Test
+ @DisplayName("Test VSTask constructor with negative time")
+ void testConstructorNegativeTime() {
+ // Given
+ long negativeTime = -100L;
+
+ // When
+ task = new VSTask(negativeTime, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // Then
+ assertEquals(0L, task.getTaskTime()); // Should be set to 0
+ }
+
+ @Test
+ @DisplayName("Test VSTask copy constructor with copyable event")
+ void testCopyConstructorWithCopyableEvent() throws VSEventNotCopyableException {
+ // Given
+ VSTask originalTask = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ VSAbstractEvent mockCopyEvent = mock(VSAbstractEvent.class);
+ when(mockEvent.getCopy()).thenReturn(mockCopyEvent);
+
+ // When
+ VSTask copiedTask = new VSTask(originalTask);
+
+ // Then
+ assertEquals(originalTask.getTaskTime(), copiedTask.getTaskTime());
+ assertEquals(originalTask.getProcess(), copiedTask.getProcess());
+ assertEquals(mockCopyEvent, copiedTask.getEvent());
+ assertEquals(originalTask.isGlobalTimed(), copiedTask.isGlobalTimed());
+ }
+
+ @Test
+ @DisplayName("Test VSTask copy constructor with non-copyable event")
+ void testCopyConstructorWithNonCopyableEvent() throws VSEventNotCopyableException {
+ // Given
+ VSTask originalTask = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ when(mockEvent.getCopy()).thenThrow(new VSEventNotCopyableException("Not copyable"));
+
+ // When
+ VSTask copiedTask = new VSTask(originalTask);
+
+ // Then
+ assertEquals(originalTask.getEvent(), copiedTask.getEvent()); // Should use original event
+ }
+
+ @Test
+ @DisplayName("Test isProgrammed getter and setter")
+ void testIsProgrammedGetterSetter() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When/Then
+ assertFalse(task.isProgrammed()); // Default value
+
+ task.isProgrammed(true);
+ assertTrue(task.isProgrammed());
+
+ task.isProgrammed(false);
+ assertFalse(task.isProgrammed());
+ }
+
+ @Test
+ @DisplayName("Test hasInternalEvent method")
+ void testHasInternalEvent() {
+ // Given
+ VSAbstractEvent normalEvent = mock(VSAbstractEvent.class);
+ VSMessageReceiveEvent internalEvent = mock(VSMessageReceiveEvent.class);
+
+ // When/Then
+ task = new VSTask(1000L, mockProcess, normalEvent, VSTask.LOCAL);
+ assertFalse(task.hasInternalEvent());
+
+ task = new VSTask(1000L, mockProcess, internalEvent, VSTask.LOCAL);
+ assertTrue(task.hasInternalEvent());
+ }
+
+ @Test
+ @DisplayName("Test hasMessageReceiveEvent method")
+ void testHasMessageReceiveEvent() {
+ // Given
+ VSMessageReceiveEvent messageEvent = mock(VSMessageReceiveEvent.class);
+
+ // When
+ task = new VSTask(1000L, mockProcess, messageEvent, VSTask.LOCAL);
+
+ // Then
+ assertTrue(task.hasMessageReceiveEvent());
+ }
+
+ @Test
+ @DisplayName("Test hasProcessRecoverEvent method")
+ void testHasProcessRecoverEvent() {
+ // Given
+ VSProcessRecoverEvent recoverEvent = mock(VSProcessRecoverEvent.class);
+
+ // When
+ task = new VSTask(1000L, mockProcess, recoverEvent, VSTask.LOCAL);
+
+ // Then
+ assertTrue(task.hasProcessRecoverEvent());
+ }
+
+ @Test
+ @DisplayName("Test isProtocol method")
+ void testIsProtocol() {
+ // Given
+ when(mockProtocol.equals(mockProtocol)).thenReturn(true);
+
+ // When
+ task = new VSTask(1000L, mockProcess, mockProtocol, VSTask.LOCAL);
+
+ // Then
+ assertTrue(task.isProtocol(mockProtocol));
+
+ VSAbstractProtocol otherProtocol = mock(VSAbstractProtocol.class);
+ assertFalse(task.isProtocol(otherProtocol));
+ }
+
+ @Test
+ @DisplayName("Test timeOver method for local timed task")
+ void testTimeOverLocalTimed() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When/Then
+ when(mockProcess.getTime()).thenReturn(500L);
+ assertFalse(task.timeOver());
+
+ when(mockProcess.getTime()).thenReturn(1001L);
+ assertTrue(task.timeOver());
+ }
+
+ @Test
+ @DisplayName("Test timeOver method for global timed task")
+ void testTimeOverGlobalTimed() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.GLOBAL);
+
+ // When/Then
+ when(mockProcess.getGlobalTime()).thenReturn(500L);
+ assertFalse(task.timeOver());
+
+ when(mockProcess.getGlobalTime()).thenReturn(1001L);
+ assertTrue(task.timeOver());
+ }
+
+ @Test
+ @DisplayName("Test equals method")
+ void testEquals() {
+ // Given
+ VSTask task1 = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ VSTask task2 = new VSTask(2000L, mockProcess, mockEvent, VSTask.GLOBAL);
+ VSTask task3 = new VSTask(task1); // Copy constructor ensures different taskNum
+
+ // When/Then
+ assertTrue(task1.equals(task1)); // Same object
+ assertFalse(task1.equals(task2)); // Different task nums
+ assertFalse(task1.equals(task3)); // Different task nums even though copied
+ }
+
+ @Test
+ @DisplayName("Test isProcess method")
+ void testIsProcess() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ VSInternalProcess otherProcess = mock(VSInternalProcess.class);
+
+ when(mockProcess.equals(mockProcess)).thenReturn(true);
+ when(mockProcess.equals(otherProcess)).thenReturn(false);
+
+ // When/Then
+ assertTrue(task.isProcess(mockProcess));
+ assertFalse(task.isProcess(otherProcess));
+ }
+
+ @Test
+ @DisplayName("Test run method initializes event and calls onStart")
+ void testRunMethod() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ when(mockEvent.getProcess()).thenReturn(null);
+
+ // When
+ task.run();
+
+ // Then
+ verify(mockEvent).init(mockProcess);
+ verify(mockProcess).increaseVectorAndLamportTimeIfAll();
+ verify(mockEvent).onStart();
+ }
+
+ @Test
+ @DisplayName("Test run method with MessageReceiveEvent does not increase time")
+ void testRunMethodWithMessageReceiveEvent() {
+ // Given
+ VSMessageReceiveEvent messageEvent = mock(VSMessageReceiveEvent.class);
+ task = new VSTask(1000L, mockProcess, messageEvent, VSTask.LOCAL);
+ when(messageEvent.getProcess()).thenReturn(mockProcess);
+
+ // When
+ task.run();
+
+ // Then
+ verify(mockProcess, never()).increaseVectorAndLamportTimeIfAll();
+ verify(messageEvent).onStart();
+ }
+
+ @Test
+ @DisplayName("Test run method with Protocol does not increase time")
+ void testRunMethodWithProtocol() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockProtocol, VSTask.LOCAL);
+ when(mockProtocol.getProcess()).thenReturn(mockProcess);
+
+ // When
+ task.run();
+
+ // Then
+ verify(mockProcess, never()).increaseVectorAndLamportTimeIfAll();
+ verify(mockProtocol).onStart();
+ }
+
+ @Test
+ @DisplayName("Test setTaskTime method")
+ void testSetTaskTime() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When
+ task.setTaskTime(2000L);
+
+ // Then
+ assertEquals(2000L, task.getTaskTime());
+ }
+
+ @Test
+ @DisplayName("Test setProcess method with different process")
+ void testSetProcessWithDifferentProcess() throws VSEventNotCopyableException {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ VSInternalProcess newProcess = mock(VSInternalProcess.class);
+ VSAbstractEvent copiedEvent = mock(VSAbstractEvent.class);
+
+ when(mockProcess.equals(newProcess)).thenReturn(false);
+ when(mockEvent.getCopy(newProcess)).thenReturn(copiedEvent);
+
+ // When
+ task.setProcess(newProcess);
+
+ // Then
+ assertEquals(newProcess, task.getProcess());
+ assertEquals(copiedEvent, task.getEvent());
+ }
+
+ @Test
+ @DisplayName("Test setProcess method with same process")
+ void testSetProcessWithSameProcess() throws VSEventNotCopyableException {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ when(mockProcess.equals(mockProcess)).thenReturn(true);
+
+ // When
+ task.setProcess(mockProcess);
+
+ // Then
+ verify(mockEvent, never()).getCopy(any());
+ }
+
+ @Test
+ @DisplayName("Test setProcess method with non-copyable protocol")
+ void testSetProcessWithNonCopyableProtocol() throws VSEventNotCopyableException {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockProtocol, VSTask.LOCAL);
+ VSInternalProcess newProcess = mock(VSInternalProcess.class);
+ VSAbstractProtocol newProtocol = mock(VSAbstractProtocol.class);
+
+ when(mockProcess.equals(newProcess)).thenReturn(false);
+ when(mockProtocol.getCopy(newProcess)).thenThrow(new VSEventNotCopyableException("Not copyable"));
+ when(mockProtocol.getClassname()).thenReturn("test.Protocol");
+ when(mockProtocol.getShortname()).thenReturn("TEST");
+ when(newProcess.getProtocolObject("test.Protocol")).thenReturn(newProtocol);
+
+ // When
+ task.setProcess(newProcess);
+
+ // Then
+ assertEquals(newProcess, task.getProcess());
+ assertEquals(newProtocol, task.getEvent());
+ verify(newProtocol).setShortname("TEST");
+ }
+
+ @Test
+ @DisplayName("Test toString method")
+ void testToString() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ when(mockEvent.toString()).thenReturn("TestEvent");
+ when(mockProcess.getProcessID()).thenReturn(42);
+
+ // When
+ String result = task.toString();
+
+ // Then
+ assertTrue(result.contains("Task"));
+ assertTrue(result.contains("1000"));
+ assertTrue(result.contains("TestEvent"));
+ assertTrue(result.contains("PID: 42"));
+ }
+
+ @Test
+ @DisplayName("Test compareTo method with different task times")
+ void testCompareToWithDifferentTimes() {
+ // Given
+ VSTask task1 = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ VSTask task2 = new VSTask(2000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When/Then
+ assertTrue(task1.compareTo(task2) < 0);
+ assertTrue(task2.compareTo(task1) > 0);
+ assertEquals(0, task1.compareTo(task1));
+ }
+
+ @Test
+ @DisplayName("Test compareTo method prioritizes ProcessRecoverEvent")
+ void testCompareToProcessRecoverEventPriority() {
+ // Given
+ VSProcessRecoverEvent recoverEvent = mock(VSProcessRecoverEvent.class);
+ VSTask recoverTask = new VSTask(1000L, mockProcess, recoverEvent, VSTask.LOCAL);
+ VSTask normalTask = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When/Then
+ assertTrue(recoverTask.compareTo(normalTask) < 0);
+ assertTrue(normalTask.compareTo(recoverTask) > 0);
+ }
+
+ @Test
+ @DisplayName("Test compareTo method prioritizes ProcessCrashEvent second")
+ void testCompareToProcessCrashEventPriority() {
+ // Given
+ VSProcessCrashEvent crashEvent = mock(VSProcessCrashEvent.class);
+ VSTask crashTask = new VSTask(1000L, mockProcess, crashEvent, VSTask.LOCAL);
+ VSTask normalTask = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When/Then
+ assertTrue(crashTask.compareTo(normalTask) < 0);
+ assertTrue(normalTask.compareTo(crashTask) > 0);
+ }
+
+ @Test
+ @DisplayName("Test compareTo method prioritizes ProtocolEvent third")
+ void testCompareToProtocolEventPriority() {
+ // Given
+ VSProtocolEvent protocolEvent = mock(VSProtocolEvent.class);
+ VSTask protocolTask = new VSTask(1000L, mockProcess, protocolEvent, VSTask.LOCAL);
+ VSTask normalTask = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ // When/Then
+ assertTrue(protocolTask.compareTo(normalTask) < 0);
+ assertTrue(normalTask.compareTo(protocolTask) > 0);
+ }
+
+ @Test
+ @DisplayName("Test compareTo method with null shortnames")
+ void testCompareToWithNullShortnames() {
+ // Given
+ VSTask task1 = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ VSTask task2 = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+
+ when(mockEvent.getShortname()).thenReturn(null);
+
+ // When/Then
+ assertEquals(0, task1.compareTo(task2));
+ }
+
+ @Test
+ @DisplayName("Test compareTo method with non-VSTask object")
+ void testCompareToWithNonTaskObject() {
+ // Given
+ task = new VSTask(1000L, mockProcess, mockEvent, VSTask.LOCAL);
+ Object notATask = new Object();
+
+ // When/Then
+ assertEquals(0, task.compareTo(notATask));
+ }
+
+ @Test
+ @DisplayName("Test serialization and deserialization")
+ void testSerializationDeserialization() throws Exception {
+ // Given
+ task = new VSTask(1500L, mockProcess, mockEvent, VSTask.GLOBAL);
+ task.isProgrammed(true);
+
+ when(mockEvent.getClassname()).thenReturn("test.Event");
+ when(mockEvent.getID()).thenReturn(123);
+ when(mockProcess.getProcessNum()).thenReturn(5);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ VSSerialize serialize = mock(VSSerialize.class);
+
+ // When - Serialize
+ task.serialize(serialize, oos);
+ oos.flush();
+
+ // Then - Verify serialization calls
+ verify(mockEvent).serialize(serialize, oos);
+
+ // When - Deserialize
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+
+ // Mock the deserialization environment
+ when(serialize.getObject(5, "process")).thenReturn(mockProcess);
+ when(serialize.objectExists(123, "event")).thenReturn(true);
+ when(serialize.getObject(123, "event")).thenReturn(mockEvent);
+
+ VSTask deserializedTask = new VSTask(serialize, ois);
+
+ // Then - Verify deserialization
+ assertNotNull(deserializedTask);
+ verify(mockEvent).deserialize(serialize, ois);
+ }
+} \ No newline at end of file