From edf34c8f2b28666ab0275921e4a3c23524ef7baf Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 20 Jun 2025 16:44:44 +0300 Subject: Add comprehensive unit test coverage for core components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- src/test/java/core/VSMessageTest.java | 315 +++++++++++++++++++++ src/test/java/core/VSTaskTest.java | 510 ++++++++++++++++++++++++++++++++++ 2 files changed, 825 insertions(+) create mode 100644 src/test/java/core/VSMessageTest.java create mode 100644 src/test/java/core/VSTaskTest.java (limited to 'src/test/java/core') 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 -- cgit v1.2.3