Package org.robotninjas.barge.state

Source Code of org.robotninjas.barge.state.ReplicaManagerTest

package org.robotninjas.barge.state;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import static junit.framework.Assert.*;

import org.junit.Before;
import org.junit.Test;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;

import org.mockito.Mock;

import static org.mockito.Mockito.*;

import org.mockito.MockitoAnnotations;

import org.robotninjas.barge.ClusterConfig;
import org.robotninjas.barge.ClusterConfigStub;
import org.robotninjas.barge.Replica;
import org.robotninjas.barge.api.AppendEntries;
import org.robotninjas.barge.api.AppendEntriesResponse;
import org.robotninjas.barge.api.Entry;
import org.robotninjas.barge.log.GetEntriesResult;
import org.robotninjas.barge.log.RaftLog;
import org.robotninjas.barge.rpc.Client;

import java.util.Collections;


@SuppressWarnings("unchecked")
public class ReplicaManagerTest {

  private static final ClusterConfig config = ClusterConfigStub.getStub();
  private static final Replica SELF = config.local();
  private static final Replica FOLLOWER = config.getReplica("remote");

  private @Mock Client mockClient;
  private @Mock RaftLog mockRaftLog;

  @Before
  public void initMocks() {

    MockitoAnnotations.initMocks(this);

    when(mockRaftLog.self()).thenReturn(SELF);
    when(mockRaftLog.lastLogTerm()).thenReturn(0L);
    when(mockRaftLog.lastLogIndex()).thenReturn(0L);
    when(mockRaftLog.currentTerm()).thenReturn(1L);

  }

  @Test
  public void testInitialSendOutstanding() {

    ListenableFuture<AppendEntriesResponse> mockResponse = mock(ListenableFuture.class);
    when(mockClient.appendEntries(eq(FOLLOWER), any(AppendEntries.class))).thenReturn(mockResponse);

    GetEntriesResult entriesResult = new GetEntriesResult(0L, 0L, Collections.<Entry>emptyList());
    when(mockRaftLog.getEntriesFrom(anyLong(), anyInt())).thenReturn(entriesResult);

    ReplicaManager replicaManager = new ReplicaManager(mockClient, mockRaftLog, FOLLOWER);
    ListenableFuture f1 = replicaManager.requestUpdate();

    AppendEntries appendEntries = AppendEntries.newBuilder()
        .setLeaderId(SELF.toString())
        .setCommitIndex(0)
        .setPrevLogIndex(0)
        .setPrevLogTerm(0)
        .setTerm(1)
        .build();

    verify(mockClient, times(1)).appendEntries(FOLLOWER, appendEntries);
    verifyNoMoreInteractions(mockClient);

    verify(mockRaftLog, times(1)).getEntriesFrom(1, 1);

    assertTrue(replicaManager.isRunning());
    assertFalse(replicaManager.isRequested());
    assertEquals(1, replicaManager.getNextIndex());

    ListenableFuture f2 = replicaManager.requestUpdate();

    assertNotSame(f1, f2);
    assertTrue(replicaManager.isRunning());
    assertTrue(replicaManager.isRequested());
    assertEquals(1, replicaManager.getNextIndex());

  }

  @Test
  public void testFailedAppend() {

    SettableFuture<AppendEntriesResponse> response = SettableFuture.create();
    when(mockClient.appendEntries(eq(FOLLOWER), any(AppendEntries.class))).thenReturn(response)
      .thenReturn(mock(ListenableFuture.class));


    GetEntriesResult entriesResult = new GetEntriesResult(0L, 0L, Collections.<Entry>emptyList());
    when(mockRaftLog.getEntriesFrom(anyLong(), anyInt())).thenReturn(entriesResult);

    ReplicaManager replicaManager = new ReplicaManager(mockClient, mockRaftLog, FOLLOWER);

    replicaManager.requestUpdate();

    AppendEntries appendEntries = AppendEntries.newBuilder()
        .setLeaderId(SELF.toString())
        .setCommitIndex(0)
        .setPrevLogIndex(0)
        .setPrevLogTerm(0)
        .setTerm(1)
        .build();

    assertTrue(replicaManager.isRunning());
    assertFalse(replicaManager.isRequested());
    assertEquals(1, replicaManager.getNextIndex());

    AppendEntriesResponse appendEntriesResponse = AppendEntriesResponse.newBuilder()
        .setLastLogIndex(0L)
        .setTerm(1)
        .setSuccess(false)
        .build();

    response.set(appendEntriesResponse);

    verify(mockClient, times(2)).appendEntries(FOLLOWER, appendEntries);
    verifyNoMoreInteractions(mockClient);

    verify(mockRaftLog, times(2)).getEntriesFrom(1, 1);

    assertTrue(replicaManager.isRunning());
    assertFalse(replicaManager.isRequested());
    assertEquals(1, replicaManager.getNextIndex());

  }

  @Test
  public void updatesNextIndexBeyondCurrentEntryGivenAppendIsSuccessful() {

    SettableFuture<AppendEntriesResponse> response = SettableFuture.create();
    when(mockClient.appendEntries(eq(FOLLOWER), any(AppendEntries.class))).thenReturn(response)
      .thenReturn(mock(ListenableFuture.class));

    Entry entry = Entry.newBuilder().setTerm(1).setCommand(new byte[0]).build();

    GetEntriesResult entriesResult = new GetEntriesResult(0L, 0L, Lists.newArrayList(entry));
    when(mockRaftLog.getEntriesFrom(anyLong(), anyInt())).thenReturn(entriesResult);

    ReplicaManager replicaManager = new ReplicaManager(mockClient, mockRaftLog, FOLLOWER);

    replicaManager.requestUpdate();

    AppendEntries appendEntries = AppendEntries.newBuilder()
        .setLeaderId(SELF.toString())
        .setCommitIndex(0)
        .setPrevLogIndex(0)
        .setPrevLogTerm(0)
        .setTerm(1)
        .addEntry(entry)
        .build();

    assertTrue(replicaManager.isRunning());
    assertFalse(replicaManager.isRequested());
    assertEquals(1, replicaManager.getNextIndex());

    AppendEntriesResponse appendEntriesResponse = AppendEntriesResponse.newBuilder()
        .setLastLogIndex(0L)
        .setTerm(1)
        .setSuccess(true)
        .build();

    response.set(appendEntriesResponse);

    verify(mockClient, times(1)).appendEntries(FOLLOWER, appendEntries);
    verifyNoMoreInteractions(mockClient);

    verify(mockRaftLog, times(1)).getEntriesFrom(1, 1);

    assertFalse(replicaManager.isRunning());
    assertFalse(replicaManager.isRequested());
    assertEquals(2, replicaManager.getNextIndex());

  }


}
TOP

Related Classes of org.robotninjas.barge.state.ReplicaManagerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.