package lsr.paxos;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.BitSet;
import lsr.common.ProcessDescriptorHelper;
import lsr.paxos.messages.Prepare;
import lsr.paxos.messages.PrepareOK;
import lsr.paxos.storage.ConsensusInstance;
import lsr.paxos.storage.InMemoryStorage;
import lsr.paxos.storage.Storage;
import org.junit.Before;
import org.junit.Test;
public class EpochPrepareRetransmitterTest {
private Retransmitter retransmitter;
private Prepare prepare;
private BitSet acceptors;
private PrepareRetransmitter prepareRetransmitter;
private Storage storage;
@Before
public void setUp() {
ProcessDescriptorHelper.initialize(3, 0);
retransmitter = mock(Retransmitter.class);
storage = new InMemoryStorage();
prepare = new Prepare(3, 10);
acceptors = new BitSet();
storage.setEpoch(new long[] {0, 0, 0});
prepareRetransmitter = new EpochPrepareRetransmitter(retransmitter, storage);
}
@Test
public void shouldStartTransmittingAMessage() {
prepareRetransmitter.startTransmitting(prepare, acceptors);
verify(retransmitter).startTransmitting(prepare, acceptors);
}
@Test
public void shouldUpdateEpoch() {
RetransmittedMessage retransmittedMessage = mock(RetransmittedMessage.class);
when(retransmitter.startTransmitting(prepare, acceptors)).thenReturn(retransmittedMessage);
prepareRetransmitter.startTransmitting(prepare, acceptors);
PrepareOK prepareOk1 = new PrepareOK(1, new ConsensusInstance[] {}, new long[] {1, 3, 2});
prepareRetransmitter.update(prepareOk1, 1);
assertArrayEquals(new long[] {1, 3, 2}, storage.getEpoch());
}
@Test
public void shouldStopTransmittingAfterReceivingPrepareOk() {
RetransmittedMessage retransmittedMessage = mock(RetransmittedMessage.class);
when(retransmitter.startTransmitting(prepare, acceptors)).thenReturn(retransmittedMessage);
prepareRetransmitter.startTransmitting(prepare, acceptors);
assertFalse(prepareRetransmitter.isMajority());
PrepareOK prepareOk1 = new PrepareOK(1, new ConsensusInstance[] {}, new long[] {1, 1, 1});
prepareRetransmitter.update(prepareOk1, 1);
verify(retransmittedMessage).stop(1);
assertFalse(prepareRetransmitter.isMajority());
PrepareOK prepareOk2 = new PrepareOK(1, new ConsensusInstance[] {}, new long[] {1, 1, 1});
prepareRetransmitter.update(prepareOk2, 2);
verify(retransmittedMessage).stop(2);
assertTrue(prepareRetransmitter.isMajority());
}
@Test
public void shouldDiscardResponsesWithOldEpoch() {
RetransmittedMessage retransmittedMessage = mock(RetransmittedMessage.class);
when(retransmitter.startTransmitting(prepare, acceptors)).thenReturn(retransmittedMessage);
prepareRetransmitter.startTransmitting(prepare, acceptors);
assertFalse(prepareRetransmitter.isMajority());
PrepareOK prepareOk1 = new PrepareOK(1, new ConsensusInstance[] {}, new long[] {1, 1, 1});
prepareRetransmitter.update(prepareOk1, 1);
verify(retransmittedMessage).stop(1);
assertFalse(prepareRetransmitter.isMajority());
PrepareOK prepareOk2 = new PrepareOK(1, new ConsensusInstance[] {}, new long[] {1, 2, 1});
prepareRetransmitter.update(prepareOk2, 2);
verify(retransmittedMessage).stop(2);
verify(retransmittedMessage).start(1);
assertFalse(prepareRetransmitter.isMajority());
PrepareOK prepareOk3 = new PrepareOK(1, new ConsensusInstance[] {}, new long[] {1, 2, 1});
prepareRetransmitter.update(prepareOk3, 1);
verify(retransmittedMessage, times(2)).stop(2);
assertTrue(prepareRetransmitter.isMajority());
verify(retransmittedMessage, never()).stop();
}
@Test
public void shouldStopTransmitting() {
RetransmittedMessage retransmittedMessage = mock(RetransmittedMessage.class);
when(retransmitter.startTransmitting(prepare, acceptors)).thenReturn(retransmittedMessage);
prepareRetransmitter.startTransmitting(prepare, acceptors);
prepareRetransmitter.stop();
verify(retransmittedMessage).stop();
}
}