/** 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);
  }
Example #2
0
  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);
  }