package lsr.paxos.recovery; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import lsr.paxos.Paxos; import lsr.paxos.Proposer; import lsr.paxos.Proposer.ProposerState; import lsr.paxos.messages.Message; import lsr.paxos.messages.Recovery; import lsr.paxos.messages.RecoveryAnswer; import lsr.paxos.network.Network; import lsr.paxos.storage.Log; import lsr.paxos.storage.Storage; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; public class ViewRecoveryRequestHandlerTest { private Paxos paxos; private Proposer proposer; private MockDispatcher dispatcher; private Log log; private Storage storage; private Network network; private ViewRecoveryRequestHandler requestHandler; @Before public void setUp() { paxos = mock(Paxos.class); proposer = mock(Proposer.class); dispatcher = new MockDispatcher(); log = mock(Log.class); storage = mock(Storage.class); network = mock(Network.class); requestHandler = new ViewRecoveryRequestHandler(paxos); when(paxos.getDispatcher()).thenReturn(dispatcher); when(paxos.getProposer()).thenReturn(proposer); when(paxos.getStorage()).thenReturn(storage); when(paxos.getNetwork()).thenReturn(network); when(storage.getLog()).thenReturn(log); } // process 0 is sending Recovery<5> to process 1 // process 1 is in view 8 @Test public void shouldRespondWhenNotALeader() { when(paxos.getLeaderId()).thenReturn(2); when(paxos.isLeader()).thenReturn(false); when(storage.getView()).thenReturn(8); when(log.getNextId()).thenReturn(111); Recovery recovery = new Recovery(5, -1); requestHandler.onMessageReceived(recovery, 0); dispatcher.execute(); ArgumentCaptor<Message> messageArgument = ArgumentCaptor.forClass(Message.class); verify(network).sendMessage(messageArgument.capture(), eq(0)); RecoveryAnswer recoveryAnswer = (RecoveryAnswer) messageArgument.getValue(); assertEquals(8, recoveryAnswer.getView()); assertEquals(111, recoveryAnswer.getNextId()); } // process 0 is sending Recovery<5> to process 1 // process 1 is in view 7 @Test public void shouldRespondWhenPreparedLeader() { when(paxos.getLeaderId()).thenReturn(1); when(paxos.isLeader()).thenReturn(true); when(storage.getView()).thenReturn(7); when(log.getNextId()).thenReturn(111); when(proposer.getState()).thenReturn(ProposerState.PREPARED); Recovery recovery = new Recovery(5, -1); requestHandler.onMessageReceived(recovery, 0); dispatcher.execute(); ArgumentCaptor<Message> messageArgument = ArgumentCaptor.forClass(Message.class); verify(network).sendMessage(messageArgument.capture(), eq(0)); RecoveryAnswer recoveryAnswer = (RecoveryAnswer) messageArgument.getValue(); assertEquals(7, recoveryAnswer.getView()); assertEquals(111, recoveryAnswer.getNextId()); } // process 0 is sending Recovery<7> to process 1 // process 1 is in view 6 @Test public void shouldNotRespondWhenSenderIsLeader() { when(paxos.getLeaderId()).thenReturn(0); when(paxos.isLeader()).thenReturn(false); when(storage.getView()).thenReturn(6); Recovery recovery = new Recovery(7, -1); requestHandler.onMessageReceived(recovery, 0); dispatcher.execute(); verify(network, never()).sendMessage(any(Message.class), anyInt()); } // process 0 is sending Recovery<7> to process 1 // process 1 is in view 7 @Test public void shouldNotRespondWhenNotPreparedLeader() { when(paxos.getLeaderId()).thenReturn(1); when(paxos.isLeader()).thenReturn(true); when(storage.getView()).thenReturn(7); when(proposer.getState()).thenReturn(ProposerState.PREPARING); Recovery recovery = new Recovery(5, -1); requestHandler.onMessageReceived(recovery, 0); dispatcher.execute(); verify(network, never()).sendMessage(any(Message.class), anyInt()); } // process 0 is sending Recovery<10> to process 1 // process 1 is in view 8 @Test public void shouldAdvanceTheView() { when(paxos.getLeaderId()).thenReturn(2); when(paxos.isLeader()).thenReturn(false); when(storage.getView()).thenReturn(8); Recovery recovery = new Recovery(10, -1); requestHandler.onMessageReceived(recovery, 0); dispatcher.execute(); verify(paxos).advanceView(10); verify(network, never()).sendMessage(any(Message.class), anyInt()); } }