/** Tests a membership group. */ private void testMembershipGroup( Atomix client1, Atomix client2, Function<Atomix, DistributedMembershipGroup> factory) throws Throwable { DistributedMembershipGroup group1 = factory.apply(client1); DistributedMembershipGroup group2 = factory.apply(client2); LocalGroupMember localMember = group2.join().get(); assertEquals(group2.members().size(), 1); group1 .join() .thenRun( () -> { threadAssertEquals(group1.members().size(), 2); threadAssertEquals(group2.members().size(), 2); resume(); }); await(5000); group1.onLeave(member -> resume()); localMember.leave().thenRun(this::resume); await(5000, 2); }
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); }