Commit 03aa7488 authored by willem's avatar willem
Browse files

Merged tests into single file; More tests passing

parent 64bdc559
...@@ -2,13 +2,14 @@ CONTRIB_DIR = .. ...@@ -2,13 +2,14 @@ CONTRIB_DIR = ..
HASHMAP_DIR = $(CONTRIB_DIR)/CHashMapViaLinkedList HASHMAP_DIR = $(CONTRIB_DIR)/CHashMapViaLinkedList
BITSTREAM_DIR = $(CONTRIB_DIR)/CBitstream BITSTREAM_DIR = $(CONTRIB_DIR)/CBitstream
LLQUEUE_DIR = $(CONTRIB_DIR)/CLinkedListQueue LLQUEUE_DIR = $(CONTRIB_DIR)/CLinkedListQueue
AQUEUE_DIR = $(CONTRIB_DIR)/CArrayQueue
GCOV_OUTPUT = *.gcda *.gcno *.gcov GCOV_OUTPUT = *.gcda *.gcno *.gcov
GCOV_CCFLAGS = -fprofile-arcs -ftest-coverage GCOV_CCFLAGS = -fprofile-arcs -ftest-coverage
SHELL = /bin/bash SHELL = /bin/bash
CC = gcc CC = gcc
#CCFLAGS = -g -O2 -Wall -Werror -Werror=return-type -Werror=uninitialized -Wcast-align -fno-omit-frame-pointer -fno-common -fsigned-char $(GCOV_CCFLAGS) -I$(HASHMAP_DIR) -I$(BITSTREAM_DIR) -I$(LLQUEUE_DIR) #CCFLAGS = -g -O2 -Wall -Werror -Werror=return-type -Werror=uninitialized -Wcast-align -fno-omit-frame-pointer -fno-common -fsigned-char $(GCOV_CCFLAGS) -I$(HASHMAP_DIR) -I$(BITSTREAM_DIR) -I$(LLQUEUE_DIR)
CCFLAGS = -g -O2 -Werror -Werror=return-type -Werror=uninitialized -Wcast-align -fno-omit-frame-pointer -fno-common -fsigned-char $(GCOV_CCFLAGS) -I$(HASHMAP_DIR) -I$(BITSTREAM_DIR) -I$(LLQUEUE_DIR) CCFLAGS = -g -O2 -Werror -Werror=return-type -Werror=uninitialized -Wcast-align -fno-omit-frame-pointer -fno-common -fsigned-char $(GCOV_CCFLAGS) -I$(HASHMAP_DIR) -I$(BITSTREAM_DIR) -I$(LLQUEUE_DIR) -I$(AQUEUE_DIR)
all: tests_main all: tests_main
...@@ -36,7 +37,7 @@ main_test.c: ...@@ -36,7 +37,7 @@ main_test.c:
fi fi
sh make-tests.sh "test_*.c" > main_test.c sh make-tests.sh "test_*.c" > main_test.c
tests_main: main_test.c raft_server.c raft_candidate.c raft_follower.c raft_leader.c raft_peer.c test_server.c test_server_request_vote.c test_follower.c test_candidate.c test_leader.c test_peer.c mock_send_functions.c CuTest.c $(HASHMAP_DIR)/linked_list_hashmap.c $(LLQUEUE_DIR)/linked_list_queue.c tests_main: main_test.c raft_server.c raft_candidate.c raft_follower.c raft_leader.c raft_peer.c test_server.c test_server_request_vote.c test_follower.c test_candidate.c test_leader.c test_peer.c mock_send_functions.c CuTest.c $(HASHMAP_DIR)/linked_list_hashmap.c $(LLQUEUE_DIR)/linked_list_queue.c $(AQUEUE_DIR)/arrayqueue.c
$(CC) $(CCFLAGS) -o $@ $^ $(CC) $(CCFLAGS) -o $@ $^
./tests_main ./tests_main
......
...@@ -203,9 +203,13 @@ int raft_get_timeout_elapsed(raft_server_t* me); ...@@ -203,9 +203,13 @@ int raft_get_timeout_elapsed(raft_server_t* me);
void raft_set_commit_index(raft_server_t* me, int commit_idx); void raft_set_commit_index(raft_server_t* me, int commit_idx);
void raft_set_lastapplied_index(raft_server_t* me, int idx); void raft_set_last_applied_index(raft_server_t* me, int idx);
int raft_get_lastapplied_index(raft_server_t* me); void raft_set_state(raft_server_t* me_, int state);
void raft_set_request_timeout(raft_server_t* me_, int millisec);
int raft_get_last_applied_index(raft_server_t* me);
raft_peer_t* raft_peer_new(void* udata); raft_peer_t* raft_peer_new(void* udata);
......
...@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h> #include <assert.h>
#include "linked_list_hashmap.h" #include "linked_list_hashmap.h"
#include "arrayqueue.h"
#include "raft.h" #include "raft.h"
typedef struct { typedef struct {
...@@ -52,7 +53,8 @@ typedef struct { ...@@ -52,7 +53,8 @@ typedef struct {
int voted_for; int voted_for;
/* the log which is replicated */ /* the log which is replicated */
void* log; //void* log;
arrayqueue_t* log;
/* Volatile state: */ /* Volatile state: */
...@@ -60,7 +62,7 @@ typedef struct { ...@@ -60,7 +62,7 @@ typedef struct {
int commit_index; int commit_index;
/* Index of highest log entry applied to state machine */ /* Index of highest log entry applied to state machine */
int last_applied; int last_applied_index;
/* follower/leader/candidate indicator */ /* follower/leader/candidate indicator */
int state; int state;
...@@ -81,6 +83,7 @@ typedef struct { ...@@ -81,6 +83,7 @@ typedef struct {
int npeers; int npeers;
int election_timeout; int election_timeout;
int request_timeout;
// hashmap_t* peers; // hashmap_t* peers;
...@@ -111,10 +114,15 @@ raft_server_t* raft_new() ...@@ -111,10 +114,15 @@ raft_server_t* raft_new()
{ {
raft_server_private_t* me; raft_server_private_t* me;
me = calloc(1,sizeof(raft_server_private_t)); if (!(me = calloc(1,sizeof(raft_server_private_t))))
return NULL;
me->voted_for = -1; me->voted_for = -1;
me->current_index = 0; me->current_index = 0;
me->timeout_elapased = 0; me->timeout_elapased = 0;
me->log = arrayqueue_new();
raft_set_state((void*)me,RAFT_STATE_FOLLOWER);
raft_set_request_timeout((void*)me, 500);
raft_set_election_timeout((void*)me, 1000);
// me->peers = hashmap_new(__peer_hash, __peer_compare, 100); // me->peers = hashmap_new(__peer_hash, __peer_compare, 100);
return (void*)me; return (void*)me;
} }
...@@ -257,7 +265,7 @@ int raft_recv_appendentries(raft_server_t* me_, const int peer, msg_appendentrie ...@@ -257,7 +265,7 @@ int raft_recv_appendentries(raft_server_t* me_, const int peer, msg_appendentrie
if (raft_get_current_term(me_) < ae->term) if (raft_get_current_term(me_) < ae->term)
{ {
raft_set_current_term(me_,ae->term); raft_set_current_term(me_, ae->term);
} }
r.success = 1; r.success = 1;
...@@ -280,15 +288,22 @@ int raft_recv_requestvote(raft_server_t* me_, int peer, msg_requestvote_t* vr) ...@@ -280,15 +288,22 @@ int raft_recv_requestvote(raft_server_t* me_, int peer, msg_requestvote_t* vr)
raft_server_private_t* me = (void*)me_; raft_server_private_t* me = (void*)me_;
msg_requestvote_response_t r; msg_requestvote_response_t r;
if (-1 == me->voted_for) if (vr->term < raft_get_current_term(me_))
{
r.vote_granted = 0;
}
/* TODO: what's this for? */
else if (-1 == me->voted_for)
{ {
r.vote_granted = 0; r.vote_granted = 0;
} }
else else
{ {
me->voted_for = peer; me->voted_for = peer;
r.vote_granted = 1;
} }
r.term = raft_get_current_term(me_);
if (me->ext_func && me->ext_func->send) if (me->ext_func && me->ext_func->send)
me->ext_func->send(me->caller, NULL, peer, (void*)&r, me->ext_func->send(me->caller, NULL, peer, (void*)&r,
sizeof(msg_requestvote_response_t)); sizeof(msg_requestvote_response_t));
...@@ -299,8 +314,12 @@ int raft_recv_requestvote(raft_server_t* me_, int peer, msg_requestvote_t* vr) ...@@ -299,8 +314,12 @@ int raft_recv_requestvote(raft_server_t* me_, int peer, msg_requestvote_t* vr)
int raft_votes_is_majority(const int npeers, const int nvotes) int raft_votes_is_majority(const int npeers, const int nvotes)
{ {
int half; int half;
if (npeers < nvotes)
return 0;
half = npeers / 2; half = npeers / 2;
printf("%d %d %d\n", npeers, nvotes, half + 1);
return half + 1 <= nvotes; return half + 1 <= nvotes;
} }
...@@ -316,15 +335,17 @@ int raft_recv_requestvote_response(raft_server_t* me_, int peer, msg_requestvote ...@@ -316,15 +335,17 @@ int raft_recv_requestvote_response(raft_server_t* me_, int peer, msg_requestvote
return 0; return 0;
if (1 == r->vote_granted) if (1 == r->vote_granted)
me->votes_for_me[peer] = 1; {
int votes;
int votes; me->votes_for_me[peer] = 1;
votes = raft_get_nvotes_for_me(me_); votes = raft_get_nvotes_for_me(me_);
if (raft_votes_is_majority(me->npeers, votes)) if (raft_votes_is_majority(me->npeers, votes))
{ {
raft_become_leader(me_); raft_become_leader(me_);
}
} }
return 0; return 0;
...@@ -342,16 +363,20 @@ void raft_set_election_timeout(raft_server_t* me_, int millisec) ...@@ -342,16 +363,20 @@ void raft_set_election_timeout(raft_server_t* me_, int millisec)
void raft_set_request_timeout(raft_server_t* me_, int millisec) void raft_set_request_timeout(raft_server_t* me_, int millisec)
{ {
raft_server_private_t* me = (void*)me_;
me->request_timeout = millisec;
} }
int raft_get_election_timeout(raft_server_t* me_) int raft_get_election_timeout(raft_server_t* me_)
{ {
return 0; raft_server_private_t* me = (void*)me_;
return me->election_timeout;
} }
int raft_get_request_timeout(raft_server_t* me_) int raft_get_request_timeout(raft_server_t* me_)
{ {
return 0; raft_server_private_t* me = (void*)me_;
return me->request_timeout;
} }
int raft_vote(raft_server_t* me_, int peer) int raft_vote(raft_server_t* me_, int peer)
...@@ -462,6 +487,14 @@ int raft_send_requestvote(raft_server_t* me_, int peer) ...@@ -462,6 +487,14 @@ int raft_send_requestvote(raft_server_t* me_, int peer)
int raft_append_command(raft_server_t* me_, unsigned char* data, int len) int raft_append_command(raft_server_t* me_, unsigned char* data, int len)
{ {
raft_server_private_t* me = (void*)me_;
char* d;
d = malloc(len);
memcpy(d,data,len);
arrayqueue_offer(me->log,d);
me->current_index += 1;
return 0; return 0;
} }
...@@ -469,13 +502,16 @@ void raft_set_commit_index(raft_server_t* me_, int commit_idx) ...@@ -469,13 +502,16 @@ void raft_set_commit_index(raft_server_t* me_, int commit_idx)
{ {
} }
void raft_set_lastapplied_index(raft_server_t* me_, int idx) void raft_set_last_applied_index(raft_server_t* me_, int idx)
{ {
raft_server_private_t* me = (void*)me_;
me->last_applied_index = idx;
} }
int raft_get_lastapplied_index(raft_server_t* me_) int raft_get_last_applied_index(raft_server_t* me_)
{ {
return 0; raft_server_private_t* me = (void*)me_;
return me->last_applied_index;
} }
int raft_get_commit_index(raft_server_t* me_) int raft_get_commit_index(raft_server_t* me_)
......
...@@ -9,325 +9,3 @@ ...@@ -9,325 +9,3 @@
#include "raft.h" #include "raft.h"
#include "mock_send_functions.h" #include "mock_send_functions.h"
void TestRaft_candidate_becomes_candidate_is_candidate(CuTest * tc)
{
void *r;
r = raft_new();
raft_become_candidate(r);
CuAssertTrue(tc, raft_is_candidate(r));
}
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_increments_current_term(CuTest * tc)
{
void *r;
r = raft_new();
CuAssertTrue(tc, 0 == raft_get_current_term(r));
raft_become_candidate(r);
CuAssertTrue(tc, 1 == raft_get_current_term(r));
}
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_votes_for_self(CuTest * tc)
{
void *r;
r = raft_new();
CuAssertTrue(tc, -1 == raft_get_voted_for(r));
raft_become_candidate(r);
CuAssertTrue(tc, 0 == raft_get_voted_for(r));
CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
}
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_resets_election_timeout(CuTest * tc)
{
void *r;
r = raft_new();
raft_set_election_timeout(r, 1000);
CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));
raft_periodic(r, 100);
CuAssertTrue(tc, 100 == raft_get_timeout_elapsed(r));
raft_become_candidate(r);
CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));
}
/* Candidate 5.2 */
void TestRaft_follower_becoming_candidate_requests_votes_from_other_servers(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
raft_peer_configuration_t cfg[] = {
/* 2 peers */
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_requestvote_t* rv;
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* set term so we can check it gets included in the outbound message */
raft_set_current_term(r,2);
raft_set_current_index(r,5);
/* becoming candidate triggers vote requests */
raft_become_candidate(r);
/* 2 peers = 2 vote requests */
rv = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != rv);
CuAssertTrue(tc, 3 == rv->term);
/* TODO: there should be more items */
rv = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != rv);
CuAssertTrue(tc, 3 == rv->term);
}
/* Candidate 5.2 */
void TestRaft_candidate_election_timeout_and_no_leader_results_in_new_election(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_requestvote_response_t vr;
memset(&vr,0,sizeof(msg_requestvote_response_t));
vr.term = 1;
vr.vote_granted = 1;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
raft_set_election_timeout(r,1000);
/* server wants to be leader, so becomes candidate */
raft_become_candidate(r);
CuAssertTrue(tc, 1 == raft_get_current_term(r));
/* clock over (ie. 1000 + 1), causing new election */
raft_periodic(r,1001);
CuAssertTrue(tc, 2 == raft_get_current_term(r));
/* receiving this vote gives the server majority */
// raft_recv_requestvote_response(r,1,&vr);
// CuAssertTrue(tc, 1 == raft_is_leader(r));
}
/* Candidate 5.2 */
void TestRaft_candidate_receives_majority_of_votes_becomes_leader(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),(void*)3},
{(-1),(void*)4},
{(-1),(void*)5},
{(-1),NULL}};
msg_requestvote_response_t vr;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
CuAssertTrue(tc, 5 == raft_get_npeers(r));
raft_set_external_functions(r,&funcs,sender);
raft_become_candidate(r);
CuAssertTrue(tc, 1 == raft_get_current_term(r));
/* a vote for us */
memset(&vr,0,sizeof(msg_requestvote_response_t));
vr.term = 1;
vr.vote_granted = 1;
/* get one vote */
raft_recv_requestvote_response(r,1,&vr);
CuAssertTrue(tc, 2 == raft_get_nvotes_for_me(r));
CuAssertTrue(tc, 0 == raft_is_leader(r));
/* get another vote
* now has majority (ie. 3/5 votes) */
raft_recv_requestvote_response(r,2,&vr);
CuAssertTrue(tc, 3 == raft_get_nvotes_for_me(r));
CuAssertTrue(tc, 1 == raft_is_leader(r));
}
/* Candidate 5.2 */
void TestRaft_candidate_will_not_respond_to_voterequest_if_it_has_already_voted(CuTest * tc)
{
void *r;
void *sender;
void *msg;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_requestvote_response_t* rvr;
msg_requestvote_t rv;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
raft_vote(r,1);
memset(&rv,0,sizeof(msg_requestvote_t));
raft_recv_requestvote(r,1,&rv);
rvr = sender_poll_msg(sender);
CuAssertTrue(tc, 0 == rvr->vote_granted);
}
/* Candidate 5.2 */
void TestRaft_candidate_requestvote_includes_logIndex(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_requestvote_t* rv;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_state(r,RAFT_STATE_CANDIDATE);
raft_set_external_functions(r,&funcs,sender);
raft_set_current_term(r,5);
raft_set_current_index(r,3);
raft_send_requestvote(r,1);
rv = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != rv);
CuAssertTrue(tc, 3 == rv->last_log_index);
CuAssertTrue(tc, 5 == rv->term);
}
/* Candidate 5.2 */
void TestRaft_candidate_recv_appendentries_frm_leader_results_in_follower(CuTest * tc)
{
void *r;
void *sender;
void *msg;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t ae;
memset(&ae,0,sizeof(msg_appendentries_t));
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
raft_set_state(r,RAFT_STATE_CANDIDATE);
CuAssertTrue(tc, 0 == raft_is_follower(r));
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 1 == raft_is_follower(r));
}
/* Candidate 5.2 */
void TestRaft_candidate_recv_appendentries_frm_invalid_leader_doesnt_result_in_follower(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t ae;
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* server's log is newer */
raft_set_current_term(r,1);
raft_set_current_index(r,2);
/* is a candidate */
raft_set_state(r,RAFT_STATE_CANDIDATE);
CuAssertTrue(tc, 0 == raft_is_follower(r));
/* invalid leader determined by "leaders" old log */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 1;
ae.prev_log_index = 1;
ae.prev_log_term = 1;
/* appendentry from invalid leader doesn't make candidate become follower */
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 1 == raft_is_candidate(r));
}
...@@ -10,417 +10,3 @@ ...@@ -10,417 +10,3 @@
#include "mock_send_functions.h" #include "mock_send_functions.h"
void TestRaft_follower_becomes_follower_is_follower(CuTest * tc)
{
void *r;
r = raft_new();
raft_become_follower(r);
CuAssertTrue(tc, raft_is_follower(r));
}
/* 5.1 */
void TestRaft_follower_recv_appendentries_reply_false_if_term_less_than_currentterm(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_appendentries_t ae;
msg_appendentries_response_t *aer;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
r = raft_new();
raft_set_configuration(r,cfg);
sender = sender_new();
raft_set_external_functions(r,&funcs,sender);
/* 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);
/* response is false */
aer = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != aer);
CuAssertTrue(tc, 0 == aer->success);
}
/* TODO: check if test case is needed */
void TestRaft_follower_recv_appendentries_updates_currentterm_if_term_gt_currentterm(CuTest * tc)
{
void *r;
msg_appendentries_t ae;
msg_appendentries_response_t *aer;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
/* newer term */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 2;
r = raft_new();
raft_set_configuration(r,cfg);
/* older currentterm */
raft_set_current_term(r,1);
/* appendentry has newer term, so we change our currentterm */
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 2 == raft_get_current_term(r));
}
/* 5.3 */
void TestRaft_follower_recv_appendentries_reply_false_if_doesnt_have_log_at_prev_log_index_which_matches_prev_log_term(CuTest * tc)
{
void *r;
void *sender;
void *msg;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t ae;
msg_appendentries_response_t *aer;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
/* log index that server doesn't have */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 5;
ae.prev_log_index = 5;
/* current term is old */
raft_set_current_term(r,5);
/* trigger reply */
raft_recv_appendentries(r,1,&ae);
aer = sender_poll_msg(sender);
/* reply is false */
CuAssertTrue(tc, NULL != aer);
CuAssertTrue(tc, 0 == aer->success);
}
/* 5.3 */
void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_entries(CuTest * tc)
{
void *r;
msg_appendentries_t ae;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_current_term(r,2);
/* first append entry */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 1;
ae.prev_log_index = 0;
ae.prev_log_term = 0;
/* increase log size */
raft_append_command(r, "111", 3);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
/* pass a appendentry that is newer */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 2;
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 0 == raft_get_log_count(r));
}
void TestRaft_follower_recv_appendentries_add_new_entries_not_already_in_log(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_appendentries_t ae;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
/* appendentries has multiple entries */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 2;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_current_term(r,1);
raft_set_external_functions(r,&funcs,sender);
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 0);
// msg = sender_poll_msg(sender);
// CuAssertTrue(tc, aer);
// CuAssertTrue(tc, 1 == sender_msg_is_appendentries(msg));
// CuAssertTrue(tc, 1 == sender_msg_is_false(msg));
}
//If leaderCommit > commitIndex, set commitIndex =
//min(leaderCommit, last log index)
void TestRaft_follower_recv_appendentries_set_commitindex_to_prevLogIdx(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_appendentries_t ae;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
/* receive an appendentry with commit */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 1;
ae.prev_log_term = 1;
ae.prev_log_index = 4;
ae.leader_commit = 5;
/* receipt of appendentries changes commit index */
raft_recv_appendentries(r,1,&ae);
/* set to 4 because prevLogIdx is lower */
CuAssertTrue(tc, 4 == raft_get_commit_index(r));
}
void TestRaft_follower_recv_appendentries_set_commitindex_to_LeaderCommit(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_appendentries_t ae;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
/* receive an appendentry with commit */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 1;
ae.prev_log_term = 1;
ae.prev_log_index = 4;
ae.leader_commit = 3;
/* receipt of appendentries changes commit index */
raft_recv_appendentries(r,1,&ae);
/* set to 3 because leaderCommit is lower */
CuAssertTrue(tc, 3 == raft_get_commit_index(r));
}
void TestRaft_follower_increases_log_after_appendentry(CuTest * tc)
{
void *r;
msg_appendentries_t ae;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
/* appendentry */
memset(&ae,0,sizeof(msg_appendentries_t));
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_state(r,RAFT_STATE_FOLLOWER);
/* log size s */
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
}
void TestRaft_follower_rejects_appendentries_if_idx_and_term_dont_match_preceding_ones(CuTest * tc)
{
void *r;
msg_appendentries_t ae;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_current_term(r,1);
/* first append entry */
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 1;
ae.prev_log_index = 0;
ae.prev_log_term = 0;
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
}
#if 0
void T_estRaft_follower_resends_command_if_request_from_leader_timesout(CuTest * tc)
{
void *r;
msg_appendentries_t ae;
/* appendentry */
memset(&ae,0,sizeof(msg_appendentries_t));
r = raft_new();
/* three nodes */
peer = raft_add_peer(r,(void*)1);
raft_add_peer(r,(void*)2);
raft_set_state(r,RAFT_STATE_FOLLOWER);
/* log size s */
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_recv_appendentries(r,peer,&ae);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
}
#endif
void TestRaft_follower_becomes_candidate_when_election_timeout_occurs(CuTest * tc)
{
void *r;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
r = raft_new();
/* 1 second election timeout */
raft_set_election_timeout(r, 1000);
raft_set_configuration(r,cfg);
/* 1.001 seconds have passed */
raft_periodic(r, 1001);
/* is a candidate now */
CuAssertTrue(tc, 1 == raft_is_candidate(r));
}
/* Candidate 5.2 */
void TestRaft_follower_dont_grant_vote_if_candidate_has_a_less_complete_log(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_requestvote_t rv;
msg_requestvote_response_t *rvr;
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* 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 = 0;
rv.last_log_index = 1;
rv.last_log_term = 1;
/* server's term and index are more up-to-date */
raft_set_current_term(r,1);
raft_set_current_index(r,2);
/* vote not granted */
raft_recv_requestvote(r,1,&rv);
rvr = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != rvr);
CuAssertTrue(tc, 0 == rvr->vote_granted);
}
...@@ -9,294 +9,3 @@ ...@@ -9,294 +9,3 @@
#include "raft.h" #include "raft.h"
#include "mock_send_functions.h" #include "mock_send_functions.h"
void TestRaft_leader_becomes_leader_is_leader(CuTest * tc)
{
void *r;
r = raft_new();
raft_become_leader(r);
CuAssertTrue(tc, raft_is_leader(r));
}
/* 5.2 */
void TestRaft_leader_when_it_becomes_a_leader_sends_empty_appendentries(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t* ae;
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* candidate to leader */
raft_set_state(r,RAFT_STATE_CANDIDATE);
raft_become_leader(r);
/* receive appendentries messages for both peers */
ae = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != ae);
ae = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != ae);
}
/* 5.2 */
void TestRaft_leader_responds_to_command_msg_when_command_is_committed(CuTest * tc)
{
void *r, *sender;
msg_command_response_t *cr;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* I am the leader */
raft_set_state(r,RAFT_STATE_LEADER);
CuAssertTrue(tc, 0 == raft_get_log_count(r));
/* command message */
msg_command_t cmd;
cmd.id = 1;
cmd.data = "command";
cmd.len = strlen("command");
/* receive command */
raft_recv_command(r,1,&cmd);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
/* trigger response through commit */
raft_commit_command(r, 1);
/* leader sent response to command message */
cr = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != cr);
}
/* 5.3 */
void TestRaft_leader_sends_appendentries_with_NextIdx_when_PrevIdx_gt_NextIdx(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t* ae;
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* i'm leader */
raft_set_state(r,RAFT_STATE_LEADER);
/* receive appendentries messages */
raft_send_appendentries(r,1);
ae = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != ae);
}
/* 5.3 */
void TestRaft_leader_retries_appendentries_with_decremented_NextIdx_log_inconsistency(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t* ae;
sender = sender_new();
r = raft_new();
raft_set_external_functions(r,&funcs,sender);
raft_set_configuration(r,cfg);
/* i'm leader */
raft_set_state(r,RAFT_STATE_LEADER);
/* receive appendentries messages */
raft_send_appendentries(r,1);
ae = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != ae);
}
/*
If there exists an N such that N > commitIndex, a majority
of matchIndex[i] = N, and log[N].term == currentTerm:
set commitIndex = N (5.2, 5.4).
*/
void TestRaft_leader_append_command_to_log_increases_idxno(CuTest * tc)
{
void *r;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_command_t cmd;
cmd.id = 1;
cmd.data = "command";
cmd.len = strlen("command");
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_state(r,RAFT_STATE_LEADER);
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_recv_command(r,1,&cmd);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
}
void TestRaft_leader_doesnt_append_command_if_unique_id_is_duplicate(CuTest * tc)
{
void *r;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_command_t cmd;
cmd.id = 1;
cmd.data = "command";
cmd.len = strlen("command");
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_state(r,RAFT_STATE_LEADER);
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_recv_command(r,1,&cmd);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
raft_recv_command(r,1,&cmd);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
}
void TestRaft_leader_increase_commitno_when_majority_have_entry_and_atleast_one_newer_entry(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_appendentries_response_t aer;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
/* I'm the leader */
raft_set_state(r,RAFT_STATE_LEADER);
/* the commit index will became 5 */
raft_set_current_term(r,5);
raft_set_current_index(r,5);
raft_set_commit_index(r,4);
raft_set_external_functions(r,&funcs,sender);
raft_send_appendentries(r, 1);
raft_send_appendentries(r, 2);
/* respond that we have the appendentries */
memset(&aer,0,sizeof(msg_appendentries_response_t));
aer.term = 5;
aer.success = 1;
/* announce to leader that the majority have appended this log */
raft_recv_appendentries_response(r,1,&aer);
raft_recv_appendentries_response(r,2,&aer);
CuAssertTrue(tc, 5 == raft_get_commit_index(r));
}
void TestRaft_leader_steps_down_if_received_appendentries_is_newer_than_itself(CuTest * tc)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
msg_appendentries_t ae;
memset(&ae,0,sizeof(msg_appendentries_t));
ae.term = 5;
ae.prev_log_index = 6;
ae.prev_log_term = 5;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_state(r,RAFT_STATE_LEADER);
raft_set_current_term(r,5);
raft_set_current_index(r,5);
raft_set_external_functions(r,&funcs,sender);
raft_recv_appendentries(r,1,&ae);
CuAssertTrue(tc, 1 == raft_is_follower(r));
}
This diff is collapsed.
...@@ -10,132 +10,3 @@ ...@@ -10,132 +10,3 @@
#include "raft.h" #include "raft.h"
#include "mock_send_functions.h" #include "mock_send_functions.h"
/* If term > currentTerm, set currentTerm to term (step down if candidate or leader) */
//void TestRaft_when_recv_requestvote_step_down_if_term_is_greater(CuTest * tc)
void TestRaft_votes_are_majority_is_true(
CuTest * tc
)
{
/* 1 of 3 = lose */
CuAssertTrue(tc, 0 == raft_votes_is_majority(3,1));
/* 2 of 3 = win */
CuAssertTrue(tc, 0 == raft_votes_is_majority(3,2));
/* 2 of 5 = lose */
CuAssertTrue(tc, 0 == raft_votes_is_majority(5,2));
/* 3 of 5 = win */
CuAssertTrue(tc, 0 == raft_votes_is_majority(5,3));
/* 2 of 1?? This is an error */
CuAssertTrue(tc, 0 == raft_votes_is_majority(1,2));
}
void TestRaft_server_increase_votes_for_me_when_receive_request_vote_response(
CuTest * tc
)
{
void *r;
msg_requestvote_t rv;
msg_requestvote_response_t *rvr;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
memset(&rv,0,sizeof(msg_requestvote_response_t));
rv.term = 1;
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_current_term(r,1);
CuAssertTrue(tc, 0 == raft_get_nvotes_for_me(r));
raft_recv_requestvote(r,1,&rv);
CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
raft_vote(r,1);
CuAssertTrue(tc, 2 == raft_get_nvotes_for_me(r));
}
// Reply false if term < currentTerm (5.1)
void TestRaft_server_recv_requestvote_reply_false_if_term_less_than_current_term(
CuTest * tc
)
{
void *r;
void *sender;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_requestvote_t rv;
msg_requestvote_response_t *rvr;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
memset(&rv,0,sizeof(msg_requestvote_t));
rv.term = 2;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_current_term(r,1);
raft_set_external_functions(r,&funcs,sender);
raft_recv_requestvote(r,1,&rv);
rvr = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != rvr);
CuAssertTrue(tc, 0 == rvr->vote_granted);
}
// If votedFor is null or candidateId, and candidate's log is at
// least as up-to-date as local log, grant vote (5.2, 5.4)
void TestRaft_server_dont_grant_vote_if_we_didnt_vote_for_this_candidate(
CuTest * tc
)
{
void *r;
void *sender;
void *msg;
raft_external_functions_t funcs = {
.send = sender_send,
.log = NULL
};
msg_requestvote_t rv;
msg_requestvote_response_t *rvr;
/* 2 peers */
raft_peer_configuration_t cfg[] = {
{(-1),(void*)1},
{(-1),(void*)2},
{(-1),NULL}};
memset(&rv,0,sizeof(msg_requestvote_response_t));
rv.term = 1;
sender = sender_new();
r = raft_new();
raft_set_configuration(r,cfg);
raft_set_external_functions(r,&funcs,sender);
raft_set_current_term(r,1);
raft_vote(r,1);
raft_recv_requestvote(r,1,&rv);
rvr = sender_poll_msg(sender);
CuAssertTrue(tc, NULL != rvr);
CuAssertTrue(tc, 0 == rvr->vote_granted);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment