diff options
Diffstat (limited to 'src/test/java/protocols')
| -rw-r--r-- | src/test/java/protocols/VSAbstractProtocolTest.java | 368 | ||||
| -rw-r--r-- | src/test/java/protocols/implementations/VSPingPongProtocolTest.java | 262 |
2 files changed, 630 insertions, 0 deletions
diff --git a/src/test/java/protocols/VSAbstractProtocolTest.java b/src/test/java/protocols/VSAbstractProtocolTest.java new file mode 100644 index 0000000..28b2fc2 --- /dev/null +++ b/src/test/java/protocols/VSAbstractProtocolTest.java @@ -0,0 +1,368 @@ +package protocols; + +import core.VSInternalProcess; +import core.VSMessage; +import core.VSMessageStub; +import core.VSTask; +import events.internal.VSProtocolScheduleEvent; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import prefs.VSPrefs; +import simulator.VSSimulatorVisualization; +import core.VSTaskManager; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * Unit tests for VSAbstractProtocol. + */ +class VSAbstractProtocolTest { + + @Mock + private VSInternalProcess mockProcess; + + @Mock + private VSSimulatorVisualization mockCanvas; + + @Mock + private VSTaskManager mockTaskManager; + + @Mock + private VSMessage mockMessage; + + @Mock + private VSMessageStub mockMessageStub; + + @Mock + private VSPrefs mockPrefs; + + @Mock + private ObjectOutputStream mockOutputStream; + + @Mock + private ObjectInputStream mockInputStream; + + private TestProtocol testProtocol; + + /** + * Test implementation of VSAbstractProtocol. + */ + private static class TestProtocol extends VSAbstractProtocol { + boolean clientInitCalled = false; + boolean serverInitCalled = false; + boolean clientResetCalled = false; + boolean serverResetCalled = false; + boolean clientScheduleCalled = false; + boolean serverScheduleCalled = false; + boolean clientRecvCalled = false; + boolean serverRecvCalled = false; + VSMessage lastClientMessage = null; + VSMessage lastServerMessage = null; + + TestProtocol(boolean hasOnServerStart) { + super(hasOnServerStart); + } + + @Override + public void onClientInit() { + clientInitCalled = true; + } + + @Override + public void onClientReset() { + clientResetCalled = true; + } + + @Override + public void onClientSchedule() { + clientScheduleCalled = true; + } + + @Override + public void onClientRecv(VSMessage message) { + clientRecvCalled = true; + lastClientMessage = message; + } + + @Override + public void onServerInit() { + serverInitCalled = true; + } + + @Override + public void onServerReset() { + serverResetCalled = true; + } + + @Override + public void onServerRecv(VSMessage message) { + serverRecvCalled = true; + lastServerMessage = message; + } + + @Override + public void onServerSchedule() { + serverScheduleCalled = true; + } + } + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + testProtocol = new TestProtocol(true); + + // Setup mock chain + when(mockProcess.getSimulatorCanvas()).thenReturn(mockCanvas); + when(mockCanvas.getTaskManager()).thenReturn(mockTaskManager); + when(mockCanvas.getNumProcesses()).thenReturn(5); + when(mockPrefs.getString(anyString())).thenReturn("TestString"); + + testProtocol.prefs = mockPrefs; + } + + @Test + void testConstructor() { + TestProtocol serverStartProtocol = new TestProtocol(true); + assertTrue(serverStartProtocol.hasOnServerStart()); + + TestProtocol clientStartProtocol = new TestProtocol(false); + assertFalse(clientStartProtocol.hasOnServerStart()); + } + + @Test + void testServerClientFlags() { + assertFalse(testProtocol.isServer()); + assertFalse(testProtocol.isClient()); + + testProtocol.isServer(true); + assertTrue(testProtocol.isServer()); + + testProtocol.isClient(true); + assertTrue(testProtocol.isClient()); + } + + @Test + void testSendMessage() { + testProtocol.process = mockProcess; + testProtocol.currentContextIsServer(true); + + testProtocol.sendMessage(mockMessage); + + verify(mockProcess).increaseLamportTime(); + verify(mockProcess).increaseVectorTime(); + verify(mockProcess).sendMessage(mockMessage); + } + + @Test + void testSendMessageWithNullProcess() { + testProtocol.process = null; + + // Should not throw exception + assertDoesNotThrow(() -> testProtocol.sendMessage(mockMessage)); + + // Should not interact with anything + verifyNoInteractions(mockProcess); + } + + @Test + void testOnStartWithServerMode() { + testProtocol = new TestProtocol(true); // Has server start + testProtocol.process = mockProcess; + testProtocol.isServer(true); + testProtocol.prefs = mockPrefs; + + testProtocol.onStart(); + + assertTrue(testProtocol.serverInitCalled); + assertFalse(testProtocol.clientInitCalled); + } + + @Test + void testOnStartWithClientMode() { + testProtocol = new TestProtocol(false); // Has client start + testProtocol.process = mockProcess; + testProtocol.isClient(true); + testProtocol.prefs = mockPrefs; + + testProtocol.onStart(); + + assertTrue(testProtocol.clientInitCalled); + assertFalse(testProtocol.serverInitCalled); + } + + @Test + void testOnInit() { + testProtocol.process = mockProcess; + testProtocol.isServer(true); + testProtocol.isClient(true); + + testProtocol.onInit(); + + assertTrue(testProtocol.serverInitCalled); + assertTrue(testProtocol.clientInitCalled); + } + + @Test + void testOnMessageRecvWithCorrectProtocol() { + when(mockMessage.getProtocolClassname()).thenReturn(testProtocol.getClassname()); + when(mockMessage.isServerMessage()).thenReturn(false); // Client message + + testProtocol.process = mockProcess; + testProtocol.isServer(true); + + testProtocol.onMessageRecvStart(mockMessage); + + assertTrue(testProtocol.serverRecvCalled); + assertEquals(mockMessage, testProtocol.lastServerMessage); + } + + @Test + void testOnMessageRecvWithIncorrectProtocol() { + when(mockMessage.getProtocolClassname()).thenReturn("DifferentProtocol"); + + testProtocol.process = mockProcess; + testProtocol.isServer(true); + + testProtocol.onMessageRecvStart(mockMessage); + + assertFalse(testProtocol.serverRecvCalled); + assertNull(testProtocol.lastServerMessage); + } + + @Test + void testIsRelevantMessage() { + when(mockMessage.getProtocolClassname()).thenReturn(testProtocol.getClassname()); + + // Server receiving client message - should be relevant + when(mockMessage.isServerMessage()).thenReturn(false); + testProtocol.isServer(true); + testProtocol.isClient(false); + assertTrue(testProtocol.isRelevantMessage(mockMessage)); + + // Client receiving server message - should be relevant + when(mockMessage.isServerMessage()).thenReturn(true); + testProtocol.isServer(false); + testProtocol.isClient(true); + assertTrue(testProtocol.isRelevantMessage(mockMessage)); + + // Server receiving server message - should NOT be relevant + when(mockMessage.isServerMessage()).thenReturn(true); + testProtocol.isServer(true); + testProtocol.isClient(false); + assertFalse(testProtocol.isRelevantMessage(mockMessage)); + } + + @Test + void testScheduleAt() { + testProtocol.process = mockProcess; + testProtocol.currentContextIsServer(true); + + long scheduleTime = 100L; + testProtocol.scheduleAt(scheduleTime); + + ArgumentCaptor<VSTask> taskCaptor = ArgumentCaptor.forClass(VSTask.class); + verify(mockTaskManager).addTask(taskCaptor.capture()); + + VSTask capturedTask = taskCaptor.getValue(); + assertNotNull(capturedTask); + assertEquals(mockProcess, capturedTask.getProcess()); + } + + @Test + void testRemoveSchedules() { + testProtocol.process = mockProcess; + testProtocol.currentContextIsServer(true); + + // First add a schedule + testProtocol.scheduleAt(100L); + + // Then remove it + testProtocol.removeSchedules(); + + verify(mockTaskManager).removeAllTasks(any()); + } + + @Test + void testReset() { + testProtocol.isServer(true); + testProtocol.isClient(true); + + testProtocol.reset(); + + assertFalse(testProtocol.isServer()); + assertFalse(testProtocol.isClient()); + assertTrue(testProtocol.serverResetCalled); + assertTrue(testProtocol.clientResetCalled); + } + + @Test + void testGetNumProcesses() { + testProtocol.process = mockProcess; + + assertEquals(5, testProtocol.getNumProcesses()); + + testProtocol.process = null; + assertEquals(0, testProtocol.getNumProcesses()); + } + + @Test + void testToString() { + testProtocol.process = mockProcess; + testProtocol.currentContextIsServer(true); + + String result = testProtocol.toString(); + + assertNotNull(result); + assertTrue(result.contains("TestString")); + + // Test with null process + testProtocol.process = null; + assertEquals("", testProtocol.toString()); + } + + @Test + void testOnClientScheduleStart() { + testProtocol.isClient(true); + + testProtocol.onClientScheduleStart(); + + assertTrue(testProtocol.clientScheduleCalled); + assertFalse(testProtocol.serverScheduleCalled); + } + + @Test + void testOnServerScheduleStart() { + testProtocol.isServer(true); + + testProtocol.onServerScheduleStart(); + + assertTrue(testProtocol.serverScheduleCalled); + assertFalse(testProtocol.clientScheduleCalled); + } + + @Test + void testSerialization() throws IOException, ClassNotFoundException { + testProtocol.serialize(null, mockOutputStream); + + verify(mockOutputStream, times(2)).writeObject(Boolean.FALSE); + verify(mockOutputStream).writeObject(Boolean.TRUE); // hasOnServerStart + } + + @Test + void testDeserialization() throws IOException, ClassNotFoundException { + when(mockInputStream.readObject()).thenReturn(Boolean.FALSE, Boolean.TRUE, Boolean.FALSE); + + testProtocol.deserialize(null, mockInputStream); + + verify(mockInputStream, times(3)).readObject(); + } +}
\ No newline at end of file diff --git a/src/test/java/protocols/implementations/VSPingPongProtocolTest.java b/src/test/java/protocols/implementations/VSPingPongProtocolTest.java new file mode 100644 index 0000000..9735a01 --- /dev/null +++ b/src/test/java/protocols/implementations/VSPingPongProtocolTest.java @@ -0,0 +1,262 @@ +package protocols.implementations; + +import core.VSInternalProcess; +import core.VSMessage; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import prefs.VSPrefs; +import simulator.VSSimulatorVisualization; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Unit tests for VSPingPongProtocol. + */ +class VSPingPongProtocolTest { + + @Mock + private VSInternalProcess mockProcess; + + @Mock + private VSSimulatorVisualization mockCanvas; + + @Mock + private VSPrefs mockPrefs; + + private VSPingPongProtocol protocol; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + protocol = new VSPingPongProtocol(); + protocol.process = mockProcess; + protocol.prefs = mockPrefs; + + // Setup mock chain + when(mockProcess.getSimulatorCanvas()).thenReturn(mockCanvas); + when(mockPrefs.getString(anyString())).thenReturn("TestString"); + } + + @Test + void testConstructor() { + VSPingPongProtocol newProtocol = new VSPingPongProtocol(); + assertFalse(newProtocol.hasOnServerStart()); // Should use client start + assertNotNull(newProtocol.getClassname()); + assertTrue(newProtocol.getClassname().contains("VSPingPongProtocol")); + } + + @Test + void testClientInit() { + // Should do nothing but not throw exception + assertDoesNotThrow(() -> protocol.onClientInit()); + } + + @Test + void testServerInit() { + // Should do nothing but not throw exception + assertDoesNotThrow(() -> protocol.onServerInit()); + } + + @Test + void testClientReset() { + // First send some messages to increment counter + protocol.isClient(true); + protocol.onClientStart(); + protocol.onClientStart(); + + // Reset should clear counter + protocol.onClientReset(); + + // Verify counter was reset by checking next message + ArgumentCaptor<VSMessage> messageCaptor = ArgumentCaptor.forClass(VSMessage.class); + protocol.onClientStart(); + + verify(mockProcess, atLeast(1)).sendMessage(messageCaptor.capture()); + VSMessage lastMessage = messageCaptor.getValue(); + assertEquals(1, lastMessage.getInteger("counter")); + } + + @Test + void testServerReset() { + // Set up server mode + protocol.isServer(true); + protocol.currentContextIsServer(true); + + // Create a mock client message + VSMessage clientMessage = new VSMessage(); + clientMessage.setBoolean("fromClient", true); + clientMessage.setInteger("counter", 1); + + // Process some messages to increment counter + protocol.onServerRecv(clientMessage); + protocol.onServerRecv(clientMessage); + + // Reset should clear counter + protocol.onServerReset(); + + // Verify counter was reset by checking next message + ArgumentCaptor<VSMessage> messageCaptor = ArgumentCaptor.forClass(VSMessage.class); + protocol.onServerRecv(clientMessage); + + verify(mockProcess, atLeast(1)).sendMessage(messageCaptor.capture()); + VSMessage lastMessage = messageCaptor.getValue(); + assertEquals(1, lastMessage.getInteger("counter")); + } + + @Test + void testClientStart() { + protocol.isClient(true); + + ArgumentCaptor<VSMessage> messageCaptor = ArgumentCaptor.forClass(VSMessage.class); + + protocol.onClientStart(); + + verify(mockProcess).sendMessage(messageCaptor.capture()); + + VSMessage sentMessage = messageCaptor.getValue(); + assertTrue(sentMessage.getBoolean("fromClient")); + assertEquals(1, sentMessage.getInteger("counter")); + + // Test counter increment + protocol.onClientStart(); + + verify(mockProcess, times(2)).sendMessage(messageCaptor.capture()); + sentMessage = messageCaptor.getValue(); + assertEquals(2, sentMessage.getInteger("counter")); + } + + @Test + void testClientRecv() { + protocol.isClient(true); + + // Create a valid server message + VSMessage serverMessage = new VSMessage(); + serverMessage.setBoolean("fromServer", true); + serverMessage.setInteger("counter", 5); + + ArgumentCaptor<VSMessage> messageCaptor = ArgumentCaptor.forClass(VSMessage.class); + + protocol.onClientRecv(serverMessage); + + verify(mockProcess).sendMessage(messageCaptor.capture()); + + VSMessage sentMessage = messageCaptor.getValue(); + assertTrue(sentMessage.getBoolean("fromClient")); + assertEquals(1, sentMessage.getInteger("counter")); + } + + @Test + void testClientRecvIgnoresNonServerMessage() { + protocol.isClient(true); + + // Create an invalid message (not from server) + VSMessage invalidMessage = new VSMessage(); + invalidMessage.setBoolean("fromServer", false); + invalidMessage.setInteger("counter", 5); + + protocol.onClientRecv(invalidMessage); + + // Should not send any message + verify(mockProcess, never()).sendMessage(any()); + } + + @Test + void testServerRecv() { + protocol.isServer(true); + protocol.currentContextIsServer(true); + + // Create a valid client message + VSMessage clientMessage = new VSMessage(); + clientMessage.setBoolean("fromClient", true); + clientMessage.setInteger("counter", 3); + + ArgumentCaptor<VSMessage> messageCaptor = ArgumentCaptor.forClass(VSMessage.class); + + protocol.onServerRecv(clientMessage); + + verify(mockProcess).sendMessage(messageCaptor.capture()); + + VSMessage sentMessage = messageCaptor.getValue(); + assertTrue(sentMessage.getBoolean("fromServer")); + assertEquals(1, sentMessage.getInteger("counter")); + } + + @Test + void testServerRecvIgnoresNonClientMessage() { + protocol.isServer(true); + protocol.currentContextIsServer(true); + + // Create an invalid message (not from client) + VSMessage invalidMessage = new VSMessage(); + invalidMessage.setBoolean("fromClient", false); + invalidMessage.setInteger("counter", 5); + + protocol.onServerRecv(invalidMessage); + + // Should not send any message + verify(mockProcess, never()).sendMessage(any()); + } + + @Test + void testClientSchedule() { + // Should do nothing but not throw exception + assertDoesNotThrow(() -> protocol.onClientSchedule()); + } + + @Test + void testServerSchedule() { + // Should do nothing but not throw exception + assertDoesNotThrow(() -> protocol.onServerSchedule()); + } + + @Test + void testToString() { + String result = protocol.toString(); + + assertNotNull(result); + assertTrue(result.contains("New message afterwards")); + assertTrue(result.contains("TestString")); + } + + @Test + void testPingPongInteraction() { + // Test a full ping-pong interaction + protocol.isClient(true); + protocol.isServer(true); + + ArgumentCaptor<VSMessage> messageCaptor = ArgumentCaptor.forClass(VSMessage.class); + + // Client starts the ping + protocol.currentContextIsServer(false); + protocol.onClientStart(); + + verify(mockProcess, times(1)).sendMessage(messageCaptor.capture()); + VSMessage ping = messageCaptor.getValue(); + assertTrue(ping.getBoolean("fromClient")); + assertEquals(1, ping.getInteger("counter")); + + // Server receives ping and sends pong + protocol.currentContextIsServer(true); + protocol.onServerRecv(ping); + + verify(mockProcess, times(2)).sendMessage(messageCaptor.capture()); + VSMessage pong = messageCaptor.getValue(); + assertTrue(pong.getBoolean("fromServer")); + assertEquals(1, pong.getInteger("counter")); + + // Client receives pong and sends another ping + protocol.currentContextIsServer(false); + protocol.onClientRecv(pong); + + verify(mockProcess, times(3)).sendMessage(messageCaptor.capture()); + VSMessage ping2 = messageCaptor.getValue(); + assertTrue(ping2.getBoolean("fromClient")); + assertEquals(2, ping2.getInteger("counter")); + } +}
\ No newline at end of file |
