public void testCandidateVotesForSelfOnRequest() throws Throwable { runOnServer( () -> { int self = serverState.getAddress().hashCode(); serverState.setTerm(2); state.startElection(); assertEquals(serverState.getTerm(), 3L); VoteRequest request = VoteRequest.builder() .withTerm(3) .withCandidate(self) .withLogIndex(0) .withLogTerm(0) .build(); VoteResponse response = state.vote(request).get(); assertEquals(response.status(), Response.Status.OK); assertTrue(response.voted()); assertEquals(serverState.getTerm(), 3L); assertEquals(serverState.getLastVotedFor(), self); assertEquals(response.term(), 3L); }); }
public void testCandidateRejectsVoteAndTransitionsOnTerm() throws Throwable { runOnServer( () -> { int candidate = serverState.getCluster().getActiveMembers().iterator().next().getAddress().hashCode(); serverState.setTerm(1); append(2, 1); state.startElection(); assertEquals(serverState.getTerm(), 2L); VoteRequest request = VoteRequest.builder() .withTerm(3) .withCandidate(candidate) .withLogTerm(0) .withLogIndex(0) .build(); VoteResponse response = state.vote(request).get(); assertEquals(response.status(), Response.Status.OK); assertFalse(response.voted()); assertEquals(serverState.getTerm(), 3L); assertEquals(serverState.getLastVotedFor(), 0); assertEquals(response.term(), 3L); assertEquals(serverState.getState(), RaftServer.State.FOLLOWER); }); }
@SuppressWarnings("unchecked") public void testAppendUpdatesLeaderAndTerm() throws Throwable { runOnServer( () -> { serverContext.setTerm(1); AppendRequest request = AppendRequest.builder() .withTerm(2) .withLeader(members.get(1).hashCode()) .withEntries(Collections.EMPTY_LIST) .withLogIndex(0) .withLogTerm(0) .withCommitIndex(0) .withGlobalIndex(0) .build(); AppendResponse response = state.append(request).get(); threadAssertEquals(serverContext.getTerm(), 2L); threadAssertEquals( serverContext.getLeader().serverAddress(), members.get(1).serverAddress()); threadAssertEquals(serverContext.getLastVotedFor(), 0); threadAssertEquals(response.term(), 2L); threadAssertTrue(response.succeeded()); }); }
@SuppressWarnings("unchecked") public void testAppendTermAndLeaderUpdated() throws Throwable { runOnServer( () -> { int leader = serverContext .getClusterState() .getActiveMemberStates() .iterator() .next() .getMember() .id(); serverContext.setTerm(1); AppendRequest request = AppendRequest.builder() .withTerm(2) .withLeader(leader) .withEntries(Collections.EMPTY_LIST) .withCommitIndex(0) .withGlobalIndex(0) .build(); AppendResponse response = state.append(request).get(); assertEquals(response.status(), Status.OK); assertTrue(response.succeeded()); assertEquals(serverContext.getTerm(), 2L); assertEquals(serverContext.getLeader().hashCode(), leader); assertEquals(response.term(), 2L); }); }
public void testAppendOnNonEmptyLog() throws Throwable { runOnServer( () -> { serverContext.setTerm(1); append(1, 1); AppendRequest request = AppendRequest.builder() .withTerm(1) .withLeader( serverContext .getClusterState() .getActiveMemberStates() .iterator() .next() .getMember() .id()) .withLogIndex(0) .withLogTerm(0) .withCommitIndex(2) .withGlobalIndex(0) .withEntries(new TestEntry().setIndex(2).setTerm(1)) .build(); AppendResponse response = state.append(request).get(); assertEquals(response.status(), Status.OK); assertTrue(response.succeeded()); assertEquals(response.term(), 1L); assertEquals(response.logIndex(), 2L); assertEquals(serverContext.getLog().length(), 2L); assertNotNull(get(2)); }); }
@SuppressWarnings("unchecked") public void testRejectAppendOnTerm() throws Throwable { runOnServer( () -> { serverContext.setTerm(2); append(2, 2); AppendRequest request = AppendRequest.builder() .withTerm(1) .withLeader( serverContext .getClusterState() .getActiveMemberStates() .iterator() .next() .getMember() .id()) .withEntries(Collections.EMPTY_LIST) .withLogIndex(2) .withLogTerm(2) .withCommitIndex(0) .withGlobalIndex(0) .build(); AppendResponse response = state.append(request).get(); assertEquals(response.status(), Status.OK); assertFalse(response.succeeded()); assertEquals(response.term(), 2L); assertEquals(response.logIndex(), 2L); }); }
public void testLeaveWithoutLeader() throws Throwable { runOnServer( () -> { LeaveRequest request = LeaveRequest.builder().withMember(members.get(0)).build(); LeaveResponse response = state.leave(request).get(); assertNoLeaderError(response); }); }
public void testJoinWithoutLeader() throws Throwable { runOnServer( () -> { JoinRequest request = JoinRequest.builder().withMember(members.get(0)).build(); JoinResponse response = state.join(request).get(); assertNoLeaderError(response); }); }
public void testQueryWithoutLeader() throws Throwable { runOnServer( () -> { QueryRequest request = QueryRequest.builder().withSession(1).withQuery(new TestQuery()).build(); QueryResponse response = state.query(request).get(); assertNoLeaderError(response); }); }
public void testCommandWithoutLeader() throws Throwable { runOnServer( () -> { CommandRequest request = CommandRequest.builder().withSession(1).withCommand(new TestCommand("test")).build(); CommandResponse response = state.command(request).get(); assertNoLeaderError(response); }); }
public void testCandidateIncrementsTermVotesForSelfOnElection() throws Throwable { runOnServer( () -> { int self = serverState.getAddress().hashCode(); serverState.setTerm(2); state.startElection(); assertEquals(serverState.getTerm(), 3L); assertEquals(serverState.getLastVotedFor(), self); }); }
public void testCandidateTransitionsToFollowerOnRejection() throws Throwable { serverState.onStateChange( state -> { if (state == RaftServer.State.FOLLOWER) resume(); }); runOnServer( () -> { for (MemberState member : serverState.getCluster().getActiveMembers()) { Server server = transport.server(); server .listen( member.getAddress(), c -> { c.handler( VoteRequest.class, request -> CompletableFuture.completedFuture( VoteResponse.builder().withTerm(2).withVoted(false).build())); }) .thenRunAsync(this::resume); } }); await(1000, serverState.getCluster().getActiveMembers().size()); runOnServer( () -> { int self = serverState.getAddress().hashCode(); serverState.setTerm(1); state.startElection(); assertEquals(serverState.getTerm(), 2L); assertEquals(serverState.getLastVotedFor(), self); }); await(1000); }
public void testVote() throws Throwable { runOnServer( () -> { VoteRequest request = VoteRequest.builder() .withCandidate(1) .withLogIndex(1) .withLogTerm(1) .withTerm(1) .build(); VoteResponse response = state.vote(request).get(); assertIllegalMemberStateError(response); }); }
public void testCandidateAppendAndTransitionOnTerm() throws Throwable { runOnServer( () -> { int leader = serverState.getCluster().getActiveMembers().iterator().next().getAddress().hashCode(); serverState.setTerm(1); AppendRequest request = AppendRequest.builder() .withTerm(2) .withLeader(leader) .withCommitIndex(0) .withGlobalIndex(0) .build(); AppendResponse response = state.append(request).get(); assertEquals(response.status(), Response.Status.OK); assertTrue(response.succeeded()); assertEquals(serverState.getTerm(), 2L); assertEquals(serverState.getLeader().hashCode(), leader); assertEquals(response.term(), 2L); assertEquals(serverState.getState(), RaftServer.State.FOLLOWER); }); }