Ejemplo n.º 1
0
/* If commitidx > lastApplied: increment lastApplied, apply log[lastApplied]
 * to state machine (§5.3) */
void TestRaft_server_increment_lastApplied_when_lastApplied_lt_commitidx(
    CuTest* tc)
{
    raft_entry_t ety;

    void *r = raft_new();

    /* must be follower */
    raft_set_state(r, RAFT_STATE_FOLLOWER);
    raft_set_current_term(r, 1);
    raft_set_commit_idx(r, 1);
    raft_set_last_applied_idx(r, 0);

    /* need at least one entry */
    ety.term = 1;
    ety.id = 1;
    ety.data.buf = "aaa";
    ety.data.len = 3;
    raft_append_entry(r, &ety);

    /* let time lapse */
    raft_periodic(r, 1);
    CuAssertTrue(tc, 0 != raft_get_last_applied_idx(r));
    CuAssertTrue(tc, 1 == raft_get_last_applied_idx(r));
}
Ejemplo n.º 2
0
/* TODO: check if test case is needed */
void
TestRaft_follower_recv_appendentries_updates_currentterm_if_term_gt_currentterm(
    CuTest * tc)
{
    msg_appendentries_t ae;
    msg_appendentries_response_t aer;

    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    /*  older currentterm */
    raft_set_current_term(r, 1);
    CuAssertTrue(tc, -1 == raft_get_current_leader(r));

    /*  newer term for appendentry */
    memset(&ae, 0, sizeof(msg_appendentries_t));
    /* no prev log idx */
    ae.prev_log_idx = 0;
    ae.term = 2;

    /*  appendentry has newer term, so we change our currentterm */
    raft_recv_appendentries(r, 1, &ae, &aer);
    CuAssertTrue(tc, 1 == aer.success);
    /* term has been updated */
    CuAssertTrue(tc, 2 == raft_get_current_term(r));
    /* and leader has been updated */
    CuAssertTrue(tc, 1 == raft_get_current_leader(r));
}
Ejemplo n.º 3
0
void TestRaft_scenario_leader_appears(CuTest * tc)
{
    unsigned long i, j;
    raft_server_t *r[3];
    void* sender[3];

    senders_new();

    for (j = 0; j < 3; j++)
        sender[j] = sender_new((void*)j);

    for (j = 0; j < 3; j++)
    {
        r[j] = raft_new();
        sender_set_raft(sender[j], r[j]);
        raft_set_election_timeout(r[j], 500);
        raft_add_node(r[j], sender[0], 1, j==0);
        raft_add_node(r[j], sender[1], 2, j==1);
        raft_add_node(r[j], sender[2], 3, j==2);
        raft_set_callbacks(r[j],
                           &((raft_cbs_t) {
                                 .send_requestvote = sender_requestvote,
                                 .send_appendentries = sender_appendentries,
                                 .persist_term = __raft_persist_term,
                                 .persist_vote = __raft_persist_vote,
                                 .log = NULL
                             }), sender[j]);
    }
Ejemplo n.º 4
0
void TestRaft_follower_recv_appendentries_add_new_entries_not_already_in_log(
    CuTest * tc)
{
    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);
    raft_set_current_term(r, 1);

    msg_appendentries_t ae;
    msg_appendentries_response_t aer;

    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 1;
    ae.prev_log_idx = 0;
    ae.prev_log_term = 1;
    /* include entries */
    msg_entry_t e[2];
    memset(&e, 0, sizeof(msg_entry_t) * 2);
    e[0].id = 1;
    e[1].id = 2;
    ae.entries = e;
    ae.n_entries = 2;
    raft_recv_appendentries(r, 1, &ae, &aer);

    CuAssertTrue(tc, 1 == aer.success);
    CuAssertTrue(tc, 2 == raft_get_log_count(r));
}
Ejemplo n.º 5
0
void TestRaft_election_start_increments_term(CuTest * tc)
{
    void *r = raft_new();
    raft_set_current_term(r, 1);
    raft_election_start(r);
    CuAssertTrue(tc, 2 == raft_get_current_term(r));
}
Ejemplo n.º 6
0
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_increments_current_term(CuTest * tc)
{
    void *r = raft_new();
    CuAssertTrue(tc, 0 == raft_get_current_term(r));
    raft_become_candidate(r);
    CuAssertTrue(tc, 1 == raft_get_current_term(r));
}
Ejemplo n.º 7
0
void TestRaft_server_entry_is_retrieveable_using_idx(CuTest* tc)
{
    raft_entry_t e1;
    raft_entry_t e2;
    raft_entry_t *ety_appended;
    char *str = "aaa";
    char *str2 = "bbb";

    void *r = raft_new();

    e1.term = 1;
    e1.id = 1;
    e1.data.buf = str;
    e1.data.len = 3;
    raft_append_entry(r, &e1);

    /* different ID so we can be successful */
    e2.term = 1;
    e2.id = 2;
    e2.data.buf = str2;
    e2.data.len = 3;
    raft_append_entry(r, &e2);

    CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 2)));
    CuAssertTrue(tc, !strncmp(ety_appended->data.buf, str2, 3));
}
Ejemplo n.º 8
0
/* 5.1 */
void
TestRaft_follower_recv_appendentries_reply_false_if_term_less_than_currentterm(
    CuTest * tc)
{
    msg_appendentries_t ae;
    msg_appendentries_response_t aer, *aerr;

    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);
    void *sender = sender_new(NULL);
    /* no leader known at this point */
    CuAssertTrue(tc, -1 == raft_get_current_leader(r));

    /* term is low */
    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 1;

    /*  higher current term */
    raft_set_current_term(r, 5);
    raft_recv_appendentries(r, 1, &ae, &aer);

    aerr = sender_poll_msg_data(sender);
    CuAssertTrue(tc, NULL != aerr);
    CuAssertTrue(tc, 0 == aerr->success);
    /* rejected appendentries doesn't change the current leader. */
    CuAssertTrue(tc, -1 == raft_get_current_leader(r));
}
Ejemplo n.º 9
0
/* Candidate 5.2 */
void TestRaft_follower_dont_grant_vote_if_candidate_has_a_less_complete_log(
    CuTest * tc)
{
    msg_requestvote_t rv;
    msg_requestvote_response_t rvr;

    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    /*  request vote */
    /*  vote indicates candidate's log is not complete compared to follower */
    memset(&rv, 0, sizeof(msg_requestvote_t));
    rv.term = 1;
    rv.candidate_id = 1;
    rv.last_log_idx = 1;
    rv.last_log_term = 1;

    /* server's term and idx are more up-to-date */
    raft_set_current_term(r, 1);
    raft_entry_t ety;
    ety.term = 1;
    ety.id = 100;
    ety.data.len = 4;
    ety.data.buf = (unsigned char*)"aaa";
    raft_append_entry(r, &ety);
    ety.id = 101;
    raft_append_entry(r, &ety);

    /* vote not granted */
    raft_recv_requestvote(r, 1, &rv, &rvr);
    CuAssertTrue(tc, 0 == rvr.vote_granted);
}
Ejemplo n.º 10
0
void TestRaft_follower_recv_appendentries_does_not_log_if_no_entries_are_specified(
    CuTest * tc)
{
    msg_appendentries_t ae;
    msg_appendentries_response_t aer;

    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    raft_set_state(r, RAFT_STATE_FOLLOWER);

    /*  log size s */
    CuAssertTrue(tc, 0 == raft_get_log_count(r));

    /* receive an appendentry with commit */
    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 1;
    ae.prev_log_term = 1;
    ae.prev_log_idx = 4;
    ae.leader_commit = 5;
    ae.n_entries = 0;

    raft_recv_appendentries(r, 1, &ae, &aer);
    CuAssertTrue(tc, 0 == raft_get_log_count(r));
}
Ejemplo n.º 11
0
void TestRaft_server_voting_results_in_voting(CuTest * tc)
{
    void *r = raft_new();
    raft_vote(r, 1);
    CuAssertTrue(tc, 1 == raft_get_voted_for(r));
    raft_vote(r, 9);
    CuAssertTrue(tc, 9 == raft_get_voted_for(r));
}
Ejemplo n.º 12
0
void TestRaft_follower_becomes_follower_clears_voted_for(CuTest * tc)
{
    void *r = raft_new();
    raft_vote(r, 1);
    CuAssertTrue(tc, 1 == raft_get_voted_for(r));
    raft_become_follower(r);
    CuAssertTrue(tc, -1 == raft_get_voted_for(r));
}
Ejemplo n.º 13
0
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_votes_for_self(CuTest * tc)
{
    void *r = raft_new();
    CuAssertTrue(tc, -1 == raft_get_voted_for(r));
    raft_become_candidate(r);
    CuAssertTrue(tc, raft_get_nodeid(r) == raft_get_voted_for(r));
    CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
}
Ejemplo n.º 14
0
void TestRaft_server_cfg_sets_num_nodes(CuTest * tc)
{
    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    CuAssertTrue(tc, 2 == raft_get_num_nodes(r));
}
Ejemplo n.º 15
0
/* 5.3 */
void
TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_entries(
    CuTest * tc)
{
    msg_appendentries_t ae;
    msg_appendentries_response_t aer;
    raft_entry_t *ety_appended;

    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    raft_set_current_term(r, 1);

    raft_entry_t ety;

    /* increase log size */
    char *str1 = "111";
    ety.data.buf = str1;
    ety.data.len = 3;
    ety.id = 1;
    ety.term = 1;
    raft_append_entry(r, &ety);
    CuAssertTrue(tc, 1 == raft_get_log_count(r));

    /* this log will be overwritten by the appendentries below */
    char *str2 = "222";
    ety.data.buf = str2;
    ety.data.len = 3;
    ety.id = 2;
    ety.term = 1;
    raft_append_entry(r, &ety);
    CuAssertTrue(tc, 2 == raft_get_log_count(r));
    CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 2)));
    CuAssertTrue(tc, !strncmp(ety_appended->data.buf, str2, 3));

    /* pass a appendentry that is newer  */
    msg_entry_t mety;

    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 2;
    ae.prev_log_idx = 1;
    ae.prev_log_term = 1;
    /* include one entry */
    memset(&mety, 0, sizeof(msg_entry_t));
    char *str3 = "333";
    mety.data.buf = str3;
    mety.data.len = 3;
    mety.id = 3;
    ae.entries = &mety;
    ae.n_entries = 1;

    raft_recv_appendentries(r, 1, &ae, &aer);
    CuAssertTrue(tc, 1 == aer.success);
    CuAssertTrue(tc, 2 == raft_get_log_count(r));
    CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 1)));
    CuAssertTrue(tc, !strncmp(ety_appended->data.buf, str1, 3));
}
Ejemplo n.º 16
0
void TestRaft_server_cant_get_node_we_dont_have(CuTest * tc)
{
    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    CuAssertTrue(tc, NULL != raft_get_node(r, 0));
    CuAssertTrue(tc, NULL != raft_get_node(r, 1));
    CuAssertTrue(tc, NULL == raft_get_node(r, 2));
}
Ejemplo n.º 17
0
void
TestRaft_server_election_timeout_sets_to_zero_when_elapsed_time_greater_than_timeout(
    CuTest * tc)
{
    void *r = raft_new();
    raft_set_election_timeout(r, 1000);

    /* greater than 1000 */
    raft_periodic(r, 2000);
    /* less than 1000 as the timeout would be randomised */
    CuAssertTrue(tc, raft_get_timeout_elapsed(r) < 1000);
}
Ejemplo n.º 18
0
void TestRaft_server_periodic_elapses_election_timeout(CuTest * tc)
{
    void *r = raft_new();
    /* we don't want to set the timeout to zero */
    raft_set_election_timeout(r, 1000);
    CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));

    raft_periodic(r, 0);
    CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));

    raft_periodic(r, 100);
    CuAssertTrue(tc, 100 == raft_get_timeout_elapsed(r));
}
Ejemplo n.º 19
0
void TestRaft_server_idx_starts_at_1(CuTest * tc)
{
    void *r = raft_new();
    CuAssertTrue(tc, 0 == raft_get_current_idx(r));

    raft_entry_t ety;
    ety.data.buf = "aaa";
    ety.data.len = 3;
    ety.id = 1;
    ety.term = 1;
    raft_append_entry(r, &ety);
    CuAssertTrue(tc, 1 == raft_get_current_idx(r));
}
Ejemplo n.º 20
0
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_resets_election_timeout(CuTest * tc)
{
    void *r = raft_new();
    raft_set_election_timeout(r, 1000);
    CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));

    raft_periodic(r, 900);
    CuAssertTrue(tc, 900 == raft_get_timeout_elapsed(r));

    raft_become_candidate(r);
    /* time is selected randomly */
    CuAssertTrue(tc, raft_get_timeout_elapsed(r) < 900);
}
Ejemplo n.º 21
0
void TestRaft_server_append_entry_means_entry_gets_current_term(CuTest* tc)
{
    raft_entry_t ety;
    char *str = "aaa";

    ety.data.buf = str;
    ety.data.len = 3;
    ety.id = 1;
    ety.term = 1;

    void *r = raft_new();
    CuAssertTrue(tc, 0 == raft_get_current_idx(r));
    raft_append_entry(r, &ety);
    CuAssertTrue(tc, 1 == raft_get_current_idx(r));
}
Ejemplo n.º 22
0
void TestRaft_server_entry_append_cant_append_if_id_is_zero(CuTest* tc)
{
    raft_entry_t ety;
    char *str = "aaa";

    ety.data.buf = str;
    ety.data.len = 3;
    ety.id = 0;
    ety.term = 1;

    void *r = raft_new();
    CuAssertTrue(tc, 0 == raft_get_current_idx(r));
    raft_append_entry(r, &ety);
    CuAssertTrue(tc, 0 == raft_get_current_idx(r));
}
Ejemplo n.º 23
0
bool RaftConsensus::initialize(const Options& options)
{
  if (_raft)
  {
    return true;
  }
  
  _raft = raft_new();
  if (!_raft)
  {
    return false;
  }
  
  //
  // Seed the random number generator
  //
  rc_seed_random();
  
  //
  // Initialize callbacks
  //
  rc_init_func();
  raft_set_callbacks(_raft, &rc_funcs, this);
  
  //
  // add self
  //
  _opt = options;
  if (!addNode(_opt.node_id))
  {
    return false;
  }
  
  //
  // Start as master
  //
  if (_opt.is_master)
  {
    becomeMaster();
  }
  
  //
  // Set the election timeout
  //
  raft_set_election_timeout(_raft, _opt.election_timeout_ms);
   
  return true;
}
Ejemplo n.º 24
0
void TestRaft_follower_recv_appendentries_resets_election_timeout(
    CuTest * tc)
{
    void *r = raft_new();
    raft_set_election_timeout(r, 1000);

    raft_periodic(r, 900);

    msg_appendentries_t ae;
    msg_appendentries_response_t aer;

    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 1;
    raft_recv_appendentries(r, 1, &ae, &aer);
    CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));
}
Ejemplo n.º 25
0
void TestRaft_server_increase_votes_for_me_when_receive_request_vote_response(
    CuTest * tc
    )
{
    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);
    raft_set_current_term(r, 1);
    CuAssertTrue(tc, 0 == raft_get_nvotes_for_me(r));

    msg_requestvote_response_t rvr;
    memset(&rvr, 0, sizeof(msg_requestvote_response_t));
    rvr.term = 1;
    rvr.vote_granted = 1;
    raft_recv_requestvote_response(r, 1, &rvr);
    CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
}
Ejemplo n.º 26
0
void TestRaft_follower_becomes_candidate_when_election_timeout_occurs(
    CuTest * tc)
{
    void *r = raft_new();

    /*  1 second election timeout */
    raft_set_election_timeout(r, 1000);

    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    /*  1.001 seconds have passed */
    raft_periodic(r, 1001);

    /* is a candidate now */
    CuAssertTrue(tc, 1 == raft_is_candidate(r));
}
Ejemplo n.º 27
0
void TestRaft_server_apply_entry_increments_last_applied_idx(CuTest* tc)
{
    raft_entry_t ety;
    char *str = "aaa";

    ety.term = 1;

    void *r = raft_new();
    raft_set_commit_idx(r, 1);
    raft_set_last_applied_idx(r, 0);

    ety.id = 1;
    ety.data.buf = str;
    ety.data.len = 3;
    raft_append_entry(r, &ety);
    raft_apply_entry(r);
    CuAssertTrue(tc, 1 == raft_get_last_applied_idx(r));
}
Ejemplo n.º 28
0
/* Reply false if term < currentTerm (§5.1) */
void TestRaft_server_recv_requestvote_reply_false_if_term_less_than_current_term(
    CuTest * tc
    )
{
    msg_requestvote_response_t rvr;

    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);
    raft_set_current_term(r, 2);

    /* term is less than current term */
    msg_requestvote_t rv;
    memset(&rv, 0, sizeof(msg_requestvote_t));
    rv.term = 1;
    raft_recv_requestvote(r, 1, &rv, &rvr);

    CuAssertTrue(tc, 0 == rvr.vote_granted);
}
Ejemplo n.º 29
0
void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than_current_term(
    CuTest * tc
    )
{
    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);
    raft_become_candidate(r);
    raft_set_current_term(r, 1);

    /* current term is less than term */
    msg_requestvote_t rv;
    memset(&rv, 0, sizeof(msg_requestvote_t));
    rv.term = 2;
    rv.last_log_idx = 1;
    msg_requestvote_response_t rvr;
    raft_recv_requestvote(r, 1, &rv, &rvr);
    CuAssertTrue(tc, 1 == raft_is_follower(r));
}
Ejemplo n.º 30
0
void TestRaft_follower_recv_appendentries_set_commitidx_to_LeaderCommit(
    CuTest * tc)
{
    void *r = raft_new();
    raft_add_node(r, (void*)1, 1);
    raft_add_node(r, (void*)2, 0);

    msg_appendentries_t ae;
    msg_appendentries_response_t aer;

    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 1;
    ae.prev_log_idx = 0;
    ae.prev_log_term = 1;
    /* include entries */
    msg_entry_t e[4];
    memset(&e, 0, sizeof(msg_entry_t) * 4);
    e[0].term = 1;
    e[0].id = 1;
    e[1].term = 1;
    e[1].id = 2;
    e[2].term = 1;
    e[2].id = 3;
    e[3].term = 1;
    e[3].id = 4;
    ae.entries = e;
    ae.n_entries = 4;
    raft_recv_appendentries(r, 1, &ae, &aer);

    /* receive an appendentry with commit */
    memset(&ae, 0, sizeof(msg_appendentries_t));
    ae.term = 1;
    ae.prev_log_term = 1;
    ae.prev_log_idx = 3;
    ae.leader_commit = 3;
    /* receipt of appendentries changes commit idx */
    raft_recv_appendentries(r, 1, &ae, &aer);

    CuAssertTrue(tc, 1 == aer.success);
    /* set to 3 because leaderCommit is lower */
    CuAssertTrue(tc, 3 == raft_get_commit_idx(r));
}