Commit 9caa7c5a authored by willem's avatar willem
Browse files

New tests

parent 03aa7488
...@@ -14,27 +14,6 @@ typedef struct { ...@@ -14,27 +14,6 @@ typedef struct {
void* udata_address; void* udata_address;
} raft_peer_configuration_t; } raft_peer_configuration_t;
#if 0
typedef struct {
/* -1 uses implementation default */
int election_timeout;
/* -1 uses implementation default */
int request_timeout;
/* Terminated by udata_address being NULL */
raft_peer_configuration_t *peers;
} raft_configuration_t;
#endif
/* messages */
#if 0
enum {
MSG_RequestVote,
MSG_RequestVoteResponse,
MSG_AppendEntries,
MSG_AppendEntriesResponse
};
#endif
typedef struct { typedef struct {
/* term candidate's term */ /* term candidate's term */
int term; int term;
...@@ -49,12 +28,22 @@ typedef struct { ...@@ -49,12 +28,22 @@ typedef struct {
int last_log_term; int last_log_term;
} msg_requestvote_t; } msg_requestvote_t;
/**
* every server must send commands in this format */
typedef struct { typedef struct {
unsigned int id; unsigned int id;
unsigned char* data; unsigned char* data;
unsigned int len; unsigned int len;
} msg_command_t; } msg_command_t;
typedef struct {
unsigned int term;
unsigned int id;
unsigned char* data;
unsigned int len;
} raft_command_t;
typedef struct { typedef struct {
unsigned int id; unsigned int id;
int was_committed; int was_committed;
...@@ -74,7 +63,7 @@ typedef struct { ...@@ -74,7 +63,7 @@ typedef struct {
int prev_log_index; int prev_log_index;
int prev_log_term; int prev_log_term;
int n_entries; int n_entries;
void* entries; msg_command_t* entries;
int leader_commit; int leader_commit;
} msg_appendentries_t; } msg_appendentries_t;
...@@ -124,7 +113,6 @@ typedef struct { ...@@ -124,7 +113,6 @@ typedef struct {
func_applylog_f applylog; func_applylog_f applylog;
} raft_external_functions_t; } raft_external_functions_t;
typedef struct { typedef struct {
int pass; int pass;
// recv_appendentries_f recv_appendentries, // recv_appendentries_f recv_appendentries,
...@@ -195,7 +183,7 @@ int raft_send_requestvote(raft_server_t* me, int peer); ...@@ -195,7 +183,7 @@ int raft_send_requestvote(raft_server_t* me, int peer);
void raft_send_appendentries(raft_server_t* me, int peer); void raft_send_appendentries(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_, raft_command_t* c);
void raft_commit_command(raft_server_t* me, int logIndex); void raft_commit_command(raft_server_t* me, int logIndex);
......
...@@ -109,7 +109,6 @@ static long __peer_compare( ...@@ -109,7 +109,6 @@ static long __peer_compare(
return obj - other; return obj - other;
} }
raft_server_t* raft_new() raft_server_t* raft_new()
{ {
raft_server_private_t* me; raft_server_private_t* me;
...@@ -123,6 +122,7 @@ raft_server_t* raft_new() ...@@ -123,6 +122,7 @@ raft_server_t* raft_new()
raft_set_state((void*)me,RAFT_STATE_FOLLOWER); raft_set_state((void*)me,RAFT_STATE_FOLLOWER);
raft_set_request_timeout((void*)me, 500); raft_set_request_timeout((void*)me, 500);
raft_set_election_timeout((void*)me, 1000); raft_set_election_timeout((void*)me, 1000);
// me->log_map = hashmap_new(__log_hash, __log_compare, 100);
// me->peers = hashmap_new(__peer_hash, __peer_compare, 100); // me->peers = hashmap_new(__peer_hash, __peer_compare, 100);
return (void*)me; return (void*)me;
} }
...@@ -255,22 +255,47 @@ int raft_recv_appendentries(raft_server_t* me_, const int peer, msg_appendentrie ...@@ -255,22 +255,47 @@ int raft_recv_appendentries(raft_server_t* me_, const int peer, msg_appendentrie
ae->prev_log_index < raft_get_current_index(me_)) ae->prev_log_index < raft_get_current_index(me_))
{ {
r.success = 0; r.success = 0;
goto done;
} }
else
if (raft_is_candidate(me_))
{ {
if (raft_is_candidate(me_)) raft_become_follower(me_);
{ }
raft_become_follower(me_);
} if (raft_get_current_term(me_) < ae->term)
{
raft_set_current_term(me_, ae->term);
}
int i;
for (i=0; i<ae->n_entries; i++)
{
msg_command_t* cmd;
raft_command_t* c;
cmd = &ae->entries[i];
c = malloc(sizeof(raft_command_t));
c->term = raft_get_current_term(me_);
c->len = cmd->len;
c->id = cmd->id;
c->data = malloc(cmd->len);
memcpy(c->data,cmd->data,cmd->len);
if (raft_get_current_term(me_) < ae->term) if (0 == raft_append_command(me_, c))
{ {
raft_set_current_term(me_, ae->term); /* failure, we couldn't append it for some reason */
r.success = 0;
goto done;
} }
r.success = 1;
} }
r.success = 1;
done:
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_appendentries_response_t)); sizeof(msg_appendentries_response_t));
...@@ -278,6 +303,13 @@ int raft_recv_appendentries(raft_server_t* me_, const int peer, msg_appendentrie ...@@ -278,6 +303,13 @@ int raft_recv_appendentries(raft_server_t* me_, const int peer, msg_appendentrie
return 0; return 0;
} }
raft_command_t* raft_get_command_from_index(raft_server_t* me_, int idx)
{
raft_server_private_t* me = (void*)me_;
return NULL;
}
int raft_recv_appendentries_response(raft_server_t* me_, int peer, msg_appendentries_response_t* ae) int raft_recv_appendentries_response(raft_server_t* me_, int peer, msg_appendentries_response_t* ae)
{ {
return 0; return 0;
...@@ -319,7 +351,6 @@ int raft_votes_is_majority(const int npeers, const int nvotes) ...@@ -319,7 +351,6 @@ int raft_votes_is_majority(const int npeers, const int nvotes)
return 0; 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;
} }
...@@ -417,9 +448,12 @@ int raft_recv_command(raft_server_t* me_, int peer, msg_command_t* cmd) ...@@ -417,9 +448,12 @@ int raft_recv_command(raft_server_t* me_, int peer, msg_command_t* cmd)
return 0; return 0;
} }
/**
* @return number of items within log */
int raft_get_log_count(raft_server_t* me_) int raft_get_log_count(raft_server_t* me_)
{ {
return 0; raft_server_private_t* me = (void*)me_;
return arrayqueue_count(me->log);
} }
int raft_get_voted_for(raft_server_t* me_) int raft_get_voted_for(raft_server_t* me_)
...@@ -485,17 +519,17 @@ int raft_send_requestvote(raft_server_t* me_, int peer) ...@@ -485,17 +519,17 @@ int raft_send_requestvote(raft_server_t* me_, int peer)
return 0; return 0;
} }
int raft_append_command(raft_server_t* me_, unsigned char* data, int len) /**
* Appends command using the current term.
* Note: we make the assumption that current term is up-to-date
* @return 0 if unsuccessful */
int raft_append_command(raft_server_t* me_, raft_command_t* c)
{ {
raft_server_private_t* me = (void*)me_; raft_server_private_t* me = (void*)me_;
char* d; arrayqueue_offer(me->log, c);
d = malloc(len);
memcpy(d,data,len);
arrayqueue_offer(me->log,d);
me->current_index += 1; me->current_index += 1;
return 0; return 1;
} }
void raft_set_commit_index(raft_server_t* me_, int commit_idx) void raft_set_commit_index(raft_server_t* me_, int commit_idx)
......
...@@ -117,14 +117,89 @@ void TestRaft_server_starts_with_request_timeout_of_500ms(CuTest * tc) ...@@ -117,14 +117,89 @@ void TestRaft_server_starts_with_request_timeout_of_500ms(CuTest * tc)
CuAssertTrue(tc, 500 == raft_get_request_timeout(r)); CuAssertTrue(tc, 500 == raft_get_request_timeout(r));
} }
void TestRaft_server_increases_logindex_when_command_appended(CuTest* tc) void TestRaft_server_command_append_increases_logindex(CuTest* tc)
{ {
void *r; void *r;
raft_command_t cmd;
char *str = "aaa";
cmd.data = str;
cmd.len = 3;
cmd.id = 0;
cmd.term = 1;
r = raft_new();
CuAssertTrue(tc, 0 == raft_get_current_index(r));
raft_append_command(r,&cmd);
CuAssertTrue(tc, 1 == raft_get_current_index(r));
}
void TestRaft_server_append_command_means_command_gets_current_term(CuTest* tc)
{
void *r;
raft_command_t cmd;
char *str = "aaa";
cmd.data = str;
cmd.len = 3;
cmd.id = 0;
cmd.term = 1;
r = raft_new();
CuAssertTrue(tc, 0 == raft_get_current_index(r));
raft_append_command(r,&cmd);
CuAssertTrue(tc, 1 == raft_get_current_index(r));
}
void TestRaft_server_append_command_not_sucessful_if_command_with_id_already_appended(CuTest* tc)
{
void *r;
raft_command_t cmd;
char *str = "aaa";
cmd.data = str;
cmd.len = 3;
cmd.id = 0;
cmd.term = 1;
r = raft_new(); r = raft_new();
CuAssertTrue(tc, 0 == raft_get_current_index(r)); CuAssertTrue(tc, 0 == raft_get_current_index(r));
raft_append_command(r,"aaa", 3); raft_append_command(r,&cmd);
raft_append_command(r,&cmd);
CuAssertTrue(tc, 1 == raft_get_current_index(r)); CuAssertTrue(tc, 1 == raft_get_current_index(r));
/* different ID so we can be successful */
cmd.id = 1;
raft_append_command(r,&cmd);
CuAssertTrue(tc, 2 == raft_get_current_index(r));
}
void TestRaft_server_command_is_retrieveable_using_index(CuTest* tc)
{
void *r;
raft_command_t cmd;
raft_command_t *cmd_appended;
char *str = "aaa";
char *str2 = "bbb";
cmd.term = 1;
r = raft_new();
cmd.id = 0;
cmd.data = str;
cmd.len = 3;
raft_append_command(r,&cmd);
/* different ID so we can be successful */
cmd.id = 1;
cmd.data = str2;
cmd.len = 3;
raft_append_command(r,&cmd);
//CuAssertTrue(tc, (cmd_appended = raft_get_command_from_index(r,1)));
//CuAssertTrue(tc, !strncmp(cmd_appended->data,str2,3));
} }
// If commitIndex > lastApplied: increment lastApplied, apply // If commitIndex > lastApplied: increment lastApplied, apply
...@@ -407,6 +482,62 @@ void TestRaft_follower_recv_appendentries_updates_currentterm_if_term_gt_current ...@@ -407,6 +482,62 @@ void TestRaft_follower_recv_appendentries_updates_currentterm_if_term_gt_current
CuAssertTrue(tc, 2 == raft_get_current_term(r)); CuAssertTrue(tc, 2 == raft_get_current_term(r));
} }
void TestRaft_follower_doesnt_log_after_appendentry_if_no_entries_are_specified(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_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));
}
/* 5.3 */ /* 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 TestRaft_follower_recv_appendentries_reply_false_if_doesnt_have_log_at_prev_log_index_which_matches_prev_log_term(CuTest * tc)
{ {
...@@ -471,8 +602,15 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en ...@@ -471,8 +602,15 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
ae.prev_log_index = 0; ae.prev_log_index = 0;
ae.prev_log_term = 0; ae.prev_log_term = 0;
raft_command_t cmd;
char *str = "111";
/* increase log size */ /* increase log size */
raft_append_command(r, "111", 3); cmd.data = str;
cmd.len = 3;
cmd.id = 0;
cmd.term = 1;
raft_append_command(r, &cmd);
CuAssertTrue(tc, 1 == raft_get_log_count(r)); CuAssertTrue(tc, 1 == raft_get_log_count(r));
/* pass a appendentry that is newer */ /* pass a appendentry that is newer */
...@@ -591,34 +729,6 @@ void TestRaft_follower_recv_appendentries_set_commitindex_to_LeaderCommit(CuTest ...@@ -591,34 +729,6 @@ void TestRaft_follower_recv_appendentries_set_commitindex_to_LeaderCommit(CuTest
CuAssertTrue(tc, 3 == raft_get_commit_index(r)); 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 TestRaft_follower_rejects_appendentries_if_idx_and_term_dont_match_preceding_ones(CuTest * tc)
{ {
void *r; void *r;
......
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