Unverified Commit a634de6f authored by Ozan Tezcan's avatar Ozan Tezcan Committed by GitHub
Browse files

Add sanitizer support and fix leaks in tests (#167)

parent 75926627
......@@ -25,3 +25,19 @@ jobs:
make gcov
- name: Upload to codecov
uses: codecov/codecov-action@v2
address-sanitizer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
make tests SANITIZER=address
undefined-sanitizer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
make tests SANITIZER=undefined
......@@ -7,6 +7,9 @@
# Tests :
# mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Debug
# make && make tests_full
# SANITIZER :
# mkdir build && cd build && cmake .. -DSANITIZER=address
# make && make check
project(raft C)
cmake_minimum_required(VERSION 3.7.2)
......@@ -107,6 +110,25 @@ set(RAFT_SOURCE_FILES
src/raft_server_properties.c)
add_library(raft STATIC ${RAFT_SOURCE_FILES})
if (SANITIZER)
if ("${SANITIZER}" STREQUAL "address")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
add_link_options(-fsanitize=address)
elseif ("${SANITIZER}" STREQUAL "undefined")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
add_link_options(-fsanitize=undefined)
elseif ("${SANITIZER}" STREQUAL "thread")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
add_link_options(-fsanitize=thread)
else ()
message(FATAL_ERROR "Unknown sanitizer: ${SANITIZER}")
endif ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize-recover=all -fno-omit-frame-pointer")
message(STATUS "Using sanitizer: ${SANITIZER}")
endif ()
target_compile_options(raft PRIVATE -g -Wall -Wextra -pedantic)
target_include_directories(raft PRIVATE include)
......
......@@ -8,6 +8,28 @@ INC = -I include
GCOV_CFLAGS = -fprofile-arcs -ftest-coverage
SHELL = /bin/bash
CFLAGS += -Iinclude -fno-omit-frame-pointer -fno-common -fsigned-char -g -O2 -fPIC
ifdef SANITIZER
ifeq ($(SANITIZER),address)
MALLOC = libc
CFLAGS += -fsanitize=address -fno-sanitize-recover=all -fno-omit-frame-pointer
LDFLAGS += -fsanitize=address
else
ifeq ($(SANITIZER),undefined)
MALLOC = libc
CFLAGS += -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer
LDFLAGS += -fsanitize=undefined
else
ifeq ($(SANITIZER),thread)
CFLAGS += -fsanitize=thread -fno-sanitize-recover=all -fno-omit-frame-pointer
LDFLAGS += -fsanitize=thread
else
$(error "unknown sanitizer=${SANITIZER}")
endif
endif
endif
endif
ifeq ($(COVERAGE), 1)
CFLAGS += $(GCOV_CFLAGS)
TEST_CFLAGS = $(CFLAGS)
......
......@@ -269,6 +269,7 @@ int raft_log_poll(raft_log_t *me, raft_entry_t **etyp)
raft_entry_release(me->entries[me->front]);
me->entries[me->front] = NULL;
me->front++;
me->front = me->front % me->size;
me->count--;
......
......@@ -47,6 +47,12 @@ CuString* CuStringNew(void)
return str;
}
void CuStringFree(CuString *cu)
{
free(cu->buffer);
free(cu);
}
void CuStringResize(CuString* str, int newSize)
{
str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
......@@ -119,6 +125,12 @@ CuTest* CuTestNew(const char* name, TestFunction function)
return tc;
}
void CuTestFree(CuTest *test)
{
free(test->name);
free(test);
}
void CuTestRun(CuTest* tc)
{
#if 0 /* debugging */
......@@ -236,6 +248,14 @@ CuSuite* CuSuiteNew(void)
return testSuite;
}
void CuSuiteFree(CuSuite *testSuite)
{
for (int i = 0; i < testSuite->count; i++) {
CuTestFree(testSuite->list[i]);
}
free(testSuite);
}
void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
{
assert(testSuite->count < MAX_TEST_CASES);
......
......@@ -24,6 +24,7 @@ typedef struct
void CuStringInit(CuString* str);
CuString* CuStringNew(void);
void CuStringFree(CuString *cu);
void CuStringRead(CuString* str, const char* path);
void CuStringAppend(CuString* str, const char* text);
void CuStringAppendChar(CuString* str, char ch);
......@@ -39,16 +40,17 @@ typedef void (*TestFunction)(CuTest *);
struct CuTest
{
const char* name;
char *name;
TestFunction function;
int failed;
int ran;
const char* message;
const char *message;
jmp_buf *jumpBuf;
};
void CuTestInit(CuTest* t, const char* name, TestFunction function);
CuTest* CuTestNew(const char* name, TestFunction function);
void CuTestFree(CuTest *test);
void CuTestRun(CuTest* tc);
/* Internal versions of assert functions -- use the public versions */
......@@ -104,6 +106,7 @@ typedef struct
void CuSuiteInit(CuSuite* testSuite);
CuSuite* CuSuiteNew(void);
void CuSuiteFree(CuSuite *testSuite);
void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase);
void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2);
void CuSuiteRun(CuSuite* testSuite);
......
......@@ -3,11 +3,11 @@
static raft_entry_t *__MAKE_ENTRY(int id, raft_term_t term, const char *data)
{
raft_entry_t *ety = raft_entry_new(data ? strlen(data) : 0);
raft_entry_t *ety = raft_entry_new(data ? strlen(data) + 1 : 0);
ety->id = id;
ety->term = term;
if (data) {
memcpy(ety->data, data, strlen(data));
memcpy(ety->data, data, strlen(data) + 1);
}
return ety;
}
......@@ -36,6 +36,7 @@ static void __RAFT_APPEND_ENTRY(void *r, int id, raft_term_t term, const char *d
{
raft_entry_t *e = __MAKE_ENTRY(id, term, data);
raft_append_entry(r, e);
raft_entry_release(e);
raft_node_set_match_idx(raft_get_my_node(r), raft_get_current_idx(r));
}
......@@ -45,6 +46,7 @@ static void __RAFT_APPEND_ENTRIES_SEQ_ID(void *r, int count, int id, raft_term_t
for (i = 0; i < count; i++) {
raft_entry_t *e = __MAKE_ENTRY(id++, term, data);
raft_append_entry(r, e);
raft_entry_release(e);
}
}
......@@ -54,6 +56,7 @@ static void __RAFT_APPEND_ENTRIES_SEQ_ID_TERM(void *r, int count, int id, raft_t
for (i = 0; i < count; i++) {
raft_entry_t *e = __MAKE_ENTRY(id++, term++, data);
raft_append_entry(r, e);
raft_entry_release(e);
}
}
......
......@@ -137,7 +137,9 @@ void* sender_poll_msg_data(void* s)
{
sender_t* me = s;
msg_t* msg = llqueue_poll(me->outbox);
return NULL != msg ? msg->data : NULL;
void *data = msg ? msg->data : NULL;
free(msg);
return data;
}
void sender_set_raft(void* s, void* r)
......@@ -164,10 +166,15 @@ void sender_poll_msgs(void* s)
{
case RAFT_APPENDENTRIES_REQ:
{
raft_appendentries_req_t *ae = m->data;
raft_appendentries_resp_t response;
raft_recv_appendentries(me->raft, m->sender, m->data, &response);
__append_msg(me, &response, RAFT_APPENDENTRIES_RESP,
sizeof(response), m->sender, me->raft);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
free(ae->entries);
}
break;
case RAFT_APPENDENTRIES_RESP:
......@@ -199,5 +206,8 @@ void sender_poll_msgs(void* s)
#endif
break;
}
free(m->data);
free(m);
}
}
......@@ -59,9 +59,8 @@ static int __log_pop(
raft_index_t entry_idx
)
{
raft_entry_t* copy = malloc(sizeof(*entry));
memcpy(copy, entry, sizeof(*entry));
llqueue_offer(user_data, copy);
raft_entry_hold(entry);
llqueue_offer(user_data, entry);
return 0;
}
......@@ -82,28 +81,20 @@ raft_log_cbs_t log_funcs = {
.log_pop = __log_pop
};
void* __set_up()
{
void* queue = llqueue_new();
void *r = raft_new();
raft_set_callbacks(r, &funcs, queue);
raft_log_set_callbacks(raft_get_log(r), &log_funcs, r);
return r;
}
void TestLog_new_is_empty(CuTest * tc)
{
void *l;
l = raft_log_new();
CuAssertTrue(tc, 0 == raft_log_count(l));
raft_log_free(l);
}
void TestLog_append_is_not_empty(CuTest * tc)
{
void *l;
void *r = raft_new();
raft_entry_t *e;
l = raft_log_new();
raft_log_cbs_t funcs = {
......@@ -112,19 +103,35 @@ void TestLog_append_is_not_empty(CuTest * tc)
raft_log_set_callbacks(l, &funcs, r);
__LOG_APPEND_ENTRY(l, 1, 0, NULL);
CuAssertIntEquals(tc, 1, raft_log_count(l));
raft_log_poll(l, &e);
raft_entry_release(e);
raft_log_free(l);
raft_destroy(r);
}
void TestLog_get_at_idx(CuTest * tc)
{
void *l;
raft_entry_t *e1, *e2, *e3;
l = raft_log_new();
__LOG_APPEND_ENTRIES_SEQ_ID(l, 3, 1, 0, NULL);
CuAssertIntEquals(tc, 3, raft_log_count(l));
CuAssertIntEquals(tc, 1, raft_log_get_at_idx(l, 1)->id);
CuAssertIntEquals(tc, 2, raft_log_get_at_idx(l, 2)->id);
CuAssertIntEquals(tc, 3, raft_log_get_at_idx(l, 3)->id);
e1 = raft_log_get_at_idx(l, 1);
CuAssertIntEquals(tc, 1, e1->id);
raft_entry_release(e1);
e2 = raft_log_get_at_idx(l, 2);
CuAssertIntEquals(tc, 2, e2->id);
raft_entry_release(e2);
e3 = raft_log_get_at_idx(l, 3);
CuAssertIntEquals(tc, 3, e3->id);
raft_entry_release(e3);
raft_log_free(l);
}
void TestLog_get_at_idx_returns_null_where_out_of_bounds(CuTest * tc)
......@@ -137,11 +144,18 @@ void TestLog_get_at_idx_returns_null_where_out_of_bounds(CuTest * tc)
__LOG_APPEND_ENTRY(l, 1, 0, NULL);
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 2));
raft_entry_t *e;
raft_log_poll(l, &e);
raft_entry_release(e);
raft_log_free(l);
}
void TestLog_delete(CuTest * tc)
{
void *l;
raft_entry_t *e;
void* queue = llqueue_new();
void *r = raft_new();
......@@ -161,19 +175,39 @@ void TestLog_delete(CuTest * tc)
CuAssertIntEquals(tc, 3, raft_log_count(l));
CuAssertIntEquals(tc, 3, raft_log_get_current_idx(l));
e = raft_log_get_at_idx(l, 3);
raft_log_delete(l, 3);
CuAssertIntEquals(tc, 2, raft_log_count(l));
CuAssertIntEquals(tc, 3, ((raft_entry_t*)llqueue_poll(queue))->id);
raft_entry_release(e);
e = llqueue_poll(queue);
CuAssertIntEquals(tc, 3, e->id);
CuAssertIntEquals(tc, 2, raft_log_count(l));
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 3));
raft_entry_release(e);
e = raft_log_get_at_idx(l, 2);
raft_log_delete(l, 2);
CuAssertIntEquals(tc, 1, raft_log_count(l));
raft_entry_release(e);
e = llqueue_poll(queue);
CuAssertIntEquals(tc, 2, e->id);
CuAssertIntEquals(tc, 1, raft_log_count(l));
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 2));
raft_entry_release(e);
e = raft_log_get_at_idx(l, 1);
raft_log_delete(l, 1);
CuAssertIntEquals(tc, 0, raft_log_count(l));
raft_entry_release(e);
e = llqueue_poll(queue);
CuAssertIntEquals(tc, 1, e->id);
CuAssertIntEquals(tc, 0, raft_log_count(l));
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 1));
raft_entry_release(e);
raft_log_free(l);
llqueue_free(queue);
raft_destroy(r);
}
void TestLog_delete_onwards(CuTest * tc)
......@@ -196,11 +230,32 @@ void TestLog_delete_onwards(CuTest * tc)
CuAssertIntEquals(tc, 3, raft_log_count(l));
/* even 3 gets deleted */
raft_entry_t *e2 = raft_log_get_at_idx(l, 2);
raft_entry_t *e3 = raft_log_get_at_idx(l, 3);
raft_log_delete(l, 2);
CuAssertIntEquals(tc, 1, raft_log_count(l));
CuAssertIntEquals(tc, 1, raft_log_get_at_idx(l, 1)->id);
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 2));
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 3));
raft_entry_release(e2);
raft_entry_release(e3);
raft_entry_t *e;
while (raft_log_poll(l, &e) == 0) {
raft_entry_release(e);
}
while ((e = llqueue_poll(queue)) != NULL) {
raft_entry_release(e);
}
llqueue_free(queue);
raft_log_free(l);
raft_destroy(r);
}
void TestLog_delete_handles_log_pop_failure(CuTest * tc)
......@@ -227,6 +282,20 @@ void TestLog_delete_handles_log_pop_failure(CuTest * tc)
CuAssertIntEquals(tc, 3, raft_log_count(l));
CuAssertIntEquals(tc, 3, raft_log_count(l));
CuAssertIntEquals(tc, 3, ((raft_entry_t*) raft_log_peektail(l))->id);
raft_entry_t *e;
while (raft_log_poll(l, &e) == 0) {
raft_entry_release(e);
}
while ((e = llqueue_poll(queue)) != NULL) {
raft_entry_release(e);
}
llqueue_free(queue);
raft_log_free(l);
raft_destroy(r);
}
void TestLog_delete_fails_for_idx_zero(CuTest * tc)
......@@ -247,6 +316,20 @@ void TestLog_delete_fails_for_idx_zero(CuTest * tc)
raft_log_set_callbacks(l, &log_funcs, r);
__LOG_APPEND_ENTRIES_SEQ_ID(l, 4, 1, 0, NULL);
CuAssertIntEquals(tc, raft_log_delete(l, 0), -1);
raft_entry_t *e;
while (raft_log_poll(l, &e) == 0) {
raft_entry_release(e);
}
while ((e = llqueue_poll(queue)) != NULL) {
raft_entry_release(e);
}
raft_log_free(l);
llqueue_free(queue);
raft_destroy(r);
}
void TestLog_poll(CuTest * tc)
......@@ -288,6 +371,7 @@ void TestLog_poll(CuTest * tc)
CuAssertTrue(tc, NULL != raft_log_get_at_idx(l, 2));
CuAssertTrue(tc, NULL != raft_log_get_at_idx(l, 3));
CuAssertIntEquals(tc, 3, raft_log_get_current_idx(l));
raft_entry_release(ety);
/* remove 2nd */
ety = NULL;
......@@ -299,6 +383,7 @@ void TestLog_poll(CuTest * tc)
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 2));
CuAssertTrue(tc, NULL != raft_log_get_at_idx(l, 3));
CuAssertIntEquals(tc, 3, raft_log_get_current_idx(l));
raft_entry_release(ety);
/* remove 3rd */
ety = NULL;
......@@ -310,6 +395,11 @@ void TestLog_poll(CuTest * tc)
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 2));
CuAssertTrue(tc, NULL == raft_log_get_at_idx(l, 3));
CuAssertIntEquals(tc, 3, raft_log_get_current_idx(l));
raft_entry_release(ety);
llqueue_free(queue);
raft_log_free(l);
raft_destroy(r);
}
void TestLog_peektail(CuTest * tc)
......@@ -321,6 +411,14 @@ void TestLog_peektail(CuTest * tc)
__LOG_APPEND_ENTRIES_SEQ_ID(l, 3, 1, 0, NULL);
CuAssertIntEquals(tc, 3, raft_log_count(l));
CuAssertIntEquals(tc, 3, raft_log_peektail(l)->id);
raft_entry_t *e;
while (raft_log_poll(l, &e) == 0) {
raft_entry_release(e);
}
raft_log_free(l);
}
#if 0
......@@ -347,6 +445,8 @@ void TestLog_load_from_snapshot(CuTest * tc)
CuAssertIntEquals(tc, 0, raft_log_load_from_snapshot(l, 10, 5));
CuAssertIntEquals(tc, 10, raft_log_get_current_idx(l));
CuAssertIntEquals(tc, 0, raft_log_count(l));
raft_log_free(l);
}
void TestLog_load_from_snapshot_clears_log(CuTest * tc)
......@@ -359,14 +459,31 @@ void TestLog_load_from_snapshot_clears_log(CuTest * tc)
CuAssertIntEquals(tc, 2, raft_log_count(l));
CuAssertIntEquals(tc, 2, raft_log_get_current_idx(l));
raft_entry_t *e1 = raft_log_get_at_idx(l, 1);
raft_entry_t *e2 = raft_log_get_at_idx(l, 2);
CuAssertIntEquals(tc, 0, raft_log_load_from_snapshot(l, 10, 5));
CuAssertIntEquals(tc, 0, raft_log_count(l));
CuAssertIntEquals(tc, 10, raft_log_get_current_idx(l));
raft_entry_release(e1);
raft_entry_release(e2);
raft_entry_t *e;
while (raft_log_poll(l, &e) == 0) {
raft_entry_release(e);
}
raft_log_free(l);
}
void TestLog_front_pushes_across_boundary(CuTest * tc)
{
void* r = __set_up();
void* queue = llqueue_new();
void *r = raft_new();
raft_set_callbacks(r, &funcs, queue);
raft_log_set_callbacks(raft_get_log(r), &log_funcs, r);
void *l;
......@@ -378,9 +495,16 @@ void TestLog_front_pushes_across_boundary(CuTest * tc)
__LOG_APPEND_ENTRY(l, 1, 0, NULL);
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 1);
raft_entry_release(ety);
__LOG_APPEND_ENTRY(l, 2, 0, NULL);
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 2);
raft_entry_release(ety);
llqueue_free(queue);
raft_log_free(l);
raft_destroy(r);
}
void TestLog_front_and_back_pushed_across_boundary_with_enlargement_required(CuTest * tc)
......@@ -397,6 +521,7 @@ void TestLog_front_and_back_pushed_across_boundary_with_enlargement_required(CuT
/* poll */
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 1);
raft_entry_release(ety);
/* append */
__LOG_APPEND_ENTRY(l, 2, 0, NULL);
......@@ -404,6 +529,7 @@ void TestLog_front_and_back_pushed_across_boundary_with_enlargement_required(CuT
/* poll */
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 2);
raft_entry_release(ety);
/* append append */
__LOG_APPEND_ENTRY(l, 3, 0, NULL);
......@@ -412,6 +538,13 @@ void TestLog_front_and_back_pushed_across_boundary_with_enlargement_required(CuT
/* poll */
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 3);
raft_entry_release(ety);
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 4);
raft_entry_release(ety);
raft_log_free(l);
}
void TestLog_delete_after_polling(CuTest * tc)
......@@ -430,14 +563,19 @@ void TestLog_delete_after_polling(CuTest * tc)
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 1);
CuAssertIntEquals(tc, 0, raft_log_count(l));
raft_entry_release(ety);
/* append */
__LOG_APPEND_ENTRY(l, 2, 0, NULL);
CuAssertIntEquals(tc, 1, raft_log_count(l));
/* poll */
raft_entry_t *e = raft_log_get_at_idx(l, 2);
CuAssertIntEquals(tc, raft_log_delete(l, 1), 0);
CuAssertIntEquals(tc, 0, raft_log_count(l));
raft_entry_release(e);
raft_log_free(l);
}
void TestLog_delete_after_polling_from_double_append(CuTest * tc)
......@@ -466,14 +604,26 @@ void TestLog_delete_after_polling_from_double_append(CuTest * tc)
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 1);
CuAssertIntEquals(tc, 1, raft_log_count(l));
raft_entry_release(ety);
/* append */
__LOG_APPEND_ENTRY(l, 3, 0, NULL);
CuAssertIntEquals(tc, 2, raft_log_count(l));
/* poll */
CuAssertIntEquals(tc, raft_log_delete(l, 1), 0);
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 2);
CuAssertIntEquals(tc, 1, raft_log_count(l));
raft_entry_release(ety);
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 3);
CuAssertIntEquals(tc, 0, raft_log_count(l));
raft_entry_release(ety);
llqueue_free(queue);
raft_log_free(l);
raft_destroy(r);
}
void TestLog_get_from_idx_with_base_off_by_one(CuTest * tc)
......@@ -502,6 +652,7 @@ void TestLog_get_from_idx_with_base_off_by_one(CuTest * tc)
CuAssertIntEquals(tc, raft_log_poll(l, (void *) &ety), 0);
CuAssertIntEquals(tc, ety->id, 1);
CuAssertIntEquals(tc, 1, raft_log_count(l));
raft_entry_release(ety);
/* get off-by-one index */
long n_etys;
......@@ -514,6 +665,15 @@ void TestLog_get_from_idx_with_base_off_by_one(CuTest * tc)
CuAssertPtrNotNull(tc, e);
CuAssertIntEquals(tc, n_etys, 1);
CuAssertIntEquals(tc, e[0]->id, 2);
raft_entry_t *entry;
while (raft_log_poll(l, &entry) == 0) {
raft_entry_release(entry);
}
llqueue_free(queue);
raft_log_free(l);
raft_destroy(r);
}
int main(void)
......@@ -543,5 +703,10 @@ int main(void)
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
return suite->failCount == 0 ? 0 : 1;
int rc = suite->failCount == 0 ? 0 : 1;
CuStringFree(output);
CuSuiteFree(suite);
return rc;
}
......@@ -61,8 +61,8 @@ static const raft_log_impl_t *impl = &raft_log_internal_impl;
static void __LOGIMPL_APPEND_ENTRY(void *l, int id, raft_term_t term, const char *data)
{
raft_entry_t *e = __MAKE_ENTRY(id, term, data);
impl->append(l, e);
raft_entry_release(e);
}
static void __LOGIMPL_APPEND_ENTRIES_SEQ_ID(void *l, int count, int id, raft_term_t term, const char *data)
......@@ -71,6 +71,7 @@ static void __LOGIMPL_APPEND_ENTRIES_SEQ_ID(void *l, int count, int id, raft_ter
for (i = 0; i < count; i++) {
raft_entry_t *e = __MAKE_ENTRY(id++, term, data);
impl->append(l, e);
raft_entry_release(e);
}
}
......@@ -81,29 +82,45 @@ void TestLogImpl_new_is_empty(CuTest * tc)
l = impl->init(NULL, NULL);
CuAssertTrue(tc, 0 == impl->count(l));
CuAssertTrue(tc, 1 == impl->first_idx(l));
impl->free(l);
}
void TestLogImpl_append_is_not_empty(CuTest * tc)
{
void *l;
void *r = raft_new();
l = impl->init(r, NULL);
__LOGIMPL_APPEND_ENTRY(l, 1, 0, NULL);
CuAssertIntEquals(tc, 1, impl->count(l));
impl->free(l);
raft_destroy(r);
}
void TestLogImpl_get_at_idx(CuTest * tc)
{
void *l;
raft_entry_t *e;
l = impl->init(NULL, NULL);
__LOGIMPL_APPEND_ENTRIES_SEQ_ID(l, 3, 1, 0, NULL);
CuAssertIntEquals(tc, 3, impl->count(l));
CuAssertIntEquals(tc, 1, impl->get(l, 1)->id);
CuAssertIntEquals(tc, 2, impl->get(l, 2)->id);
CuAssertIntEquals(tc, 3, impl->get(l, 3)->id);
e = impl->get(l, 1);
CuAssertIntEquals(tc, 1, e->id);
raft_entry_release(e);
e = impl->get(l, 2);
CuAssertIntEquals(tc, 2, e->id);
raft_entry_release(e);
e = impl->get(l, 3);
CuAssertIntEquals(tc, 3, e->id);
raft_entry_release(e);
impl->free(l);
}
void TestLogImpl_get_at_idx_returns_null_where_out_of_bounds(CuTest * tc)
......@@ -116,19 +133,21 @@ void TestLogImpl_get_at_idx_returns_null_where_out_of_bounds(CuTest * tc)
__LOGIMPL_APPEND_ENTRY(l, 1, 0, NULL);
CuAssertTrue(tc, NULL == impl->get(l, 2));
impl->free(l);
}
static void event_entry_enqueue(void *arg, raft_entry_t *e, raft_index_t idx)
{
raft_entry_t* copy = malloc(sizeof(*e));
memcpy(copy, e, sizeof(*e));
llqueue_offer(arg, copy);
raft_entry_hold(e);
llqueue_offer(arg, e);
}
void TestLogImpl_pop(CuTest * tc)
{
void* queue = llqueue_new();
void *l;
raft_entry_t *ety;
void *r = raft_new();
raft_cbs_t funcs = {
......@@ -141,11 +160,16 @@ void TestLogImpl_pop(CuTest * tc)
CuAssertIntEquals(tc, 3, impl->count(l));
CuAssertIntEquals(tc, 3, impl->current_idx(l));
event_entry_enqueue(queue, impl->get(l, 3), 3);
ety = impl->get(l, 3);
event_entry_enqueue(queue, ety, 3);
impl->pop(l, 3);
CuAssertIntEquals(tc, 2, impl->count(l));
CuAssertIntEquals(tc, 3, ((raft_entry_t*)llqueue_poll(queue))->id);
raft_entry_release(ety);
ety = llqueue_poll(queue);
CuAssertIntEquals(tc, 3, ety->id);
CuAssertTrue(tc, NULL == impl->get(l, 3));
raft_entry_release(ety);
impl->pop(l, 2);
CuAssertIntEquals(tc, 1, impl->count(l));
......@@ -154,6 +178,10 @@ void TestLogImpl_pop(CuTest * tc)
impl->pop(l, 1);
CuAssertIntEquals(tc, 0, impl->count(l));
CuAssertTrue(tc, NULL == impl->get(l, 1));
llqueue_free(queue);
impl->free(l);
raft_destroy(r);
}
void TestLogImpl_pop_onwards(CuTest * tc)
......@@ -161,6 +189,7 @@ void TestLogImpl_pop_onwards(CuTest * tc)
void *r = raft_new();
void *l;
raft_entry_t *e;
l = impl->init(r, NULL);
__LOGIMPL_APPEND_ENTRIES_SEQ_ID(l, 3, 1, 0, NULL);
......@@ -169,9 +198,15 @@ void TestLogImpl_pop_onwards(CuTest * tc)
/* even 3 gets deleted */
impl->pop(l, 2);
CuAssertIntEquals(tc, 1, impl->count(l));
CuAssertIntEquals(tc, 1, impl->get(l, 1)->id);
e = impl->get(l, 1);
CuAssertIntEquals(tc, 1, e->id);
CuAssertTrue(tc, NULL == impl->get(l, 2));
CuAssertTrue(tc, NULL == impl->get(l, 3));
raft_entry_release(e);
impl->free(l);
raft_destroy(r);
}
......@@ -184,13 +219,17 @@ void TestLogImpl_pop_fails_for_idx_zero(CuTest * tc)
l = impl->init(r, NULL);
__LOGIMPL_APPEND_ENTRIES_SEQ_ID(l, 4, 1, 0, NULL);
CuAssertIntEquals(tc, impl->pop(l, 0), -1);
impl->free(l);
raft_destroy(r);
}
void TestLogImpl_poll(CuTest * tc)
{
void *l;
void *r = raft_new();
raft_entry_t *e;
void *l;
l = impl->init(r, NULL);
__LOGIMPL_APPEND_ENTRY(l, 1, 0, NULL);
......@@ -203,38 +242,45 @@ void TestLogImpl_poll(CuTest * tc)
CuAssertIntEquals(tc, 3, impl->count(l));
CuAssertIntEquals(tc, 3, impl->current_idx(l));
raft_entry_t *ety;
/* remove 1st */
ety = NULL;
CuAssertIntEquals(tc, impl->poll(l, 2), 0);
CuAssertIntEquals(tc, 2, impl->count(l));
CuAssertIntEquals(tc, 2, impl->first_idx(l));
CuAssertTrue(tc, NULL == impl->get(l, 1));
CuAssertTrue(tc, NULL != impl->get(l, 2));
CuAssertIntEquals(tc, impl->get(l, 2)->id, 2);
CuAssertTrue(tc, NULL != impl->get(l, 3));
CuAssertIntEquals(tc, impl->get(l, 3)->id, 3);
e = impl->get(l, 2);
CuAssertTrue(tc, NULL != e);
CuAssertIntEquals(tc, e->id, 2);
raft_entry_release(e);
e = impl->get(l, 3);
CuAssertTrue(tc, NULL != e);
CuAssertIntEquals(tc, e->id, 3);
CuAssertIntEquals(tc, 3, impl->current_idx(l));
raft_entry_release(e);
/* remove 2nd */
ety = NULL;
CuAssertIntEquals(tc, impl->poll(l, 3), 0);
CuAssertIntEquals(tc, 1, impl->count(l));
CuAssertTrue(tc, NULL == impl->get(l, 1));
CuAssertTrue(tc, NULL == impl->get(l, 2));
CuAssertTrue(tc, NULL != impl->get(l, 3));
CuAssertIntEquals(tc, impl->get(l, 3)->id, 3);
e = impl->get(l, 3);
CuAssertTrue(tc, NULL != e);
CuAssertIntEquals(tc, e->id, 3);
CuAssertIntEquals(tc, 3, impl->current_idx(l));
raft_entry_release(e);
/* remove 3rd */
ety = NULL;
CuAssertIntEquals(tc, impl->poll(l, 4), 0);
CuAssertIntEquals(tc, 0, impl->count(l));
CuAssertTrue(tc, NULL == impl->get(l, 1));
CuAssertTrue(tc, NULL == impl->get(l, 2));
CuAssertTrue(tc, NULL == impl->get(l, 3));
CuAssertIntEquals(tc, 3, impl->current_idx(l));
impl->free(l);
raft_destroy(r);
}
void TestLogImpl_reset_after_compaction(CuTest * tc)
......@@ -250,6 +296,8 @@ void TestLogImpl_reset_after_compaction(CuTest * tc)
/* Current index is 9 (first_idx - 1), but log is empty */
CuAssertIntEquals(tc, 9, impl->current_idx(l));
CuAssertIntEquals(tc, 0, impl->count(l));
impl->free(l);
}
void TestLogImpl_load_from_snapshot_clears_log(CuTest * tc)
......@@ -265,6 +313,8 @@ void TestLogImpl_load_from_snapshot_clears_log(CuTest * tc)
impl->reset(l, 10, 1);
CuAssertIntEquals(tc, 0, impl->count(l));
CuAssertIntEquals(tc, 9, impl->current_idx(l));
impl->free(l);
}
void TestLogImpl_pop_after_polling(CuTest * tc)
......@@ -294,12 +344,16 @@ void TestLogImpl_pop_after_polling(CuTest * tc)
CuAssertIntEquals(tc, impl->pop(l, 1), 0);
CuAssertIntEquals(tc, 0, impl->count(l));
CuAssertIntEquals(tc, 1, impl->current_idx(l));
impl->free(l);
}
void TestLogImpl_pop_after_polling_from_double_append(CuTest * tc)
{
void *r = raft_new();
void *l;
void *r = raft_new();
raft_entry_t *e;
l = impl->init(r, NULL);
......@@ -309,8 +363,10 @@ void TestLogImpl_pop_after_polling_from_double_append(CuTest * tc)
/* poll */
CuAssertIntEquals(tc, impl->poll(l, 2), 0);
CuAssertIntEquals(tc, impl->get(l, 2)->id, 2);
e = impl->get(l, 2);
CuAssertIntEquals(tc, e->id, 2);
CuAssertIntEquals(tc, 1, impl->count(l));
raft_entry_release(e);
/* append */
__LOGIMPL_APPEND_ENTRY(l, 3, 0, NULL);
......@@ -319,6 +375,9 @@ void TestLogImpl_pop_after_polling_from_double_append(CuTest * tc)
/* pop */
CuAssertIntEquals(tc, impl->pop(l, 1), 0);
CuAssertIntEquals(tc, 0, impl->count(l));
impl->free(l);
raft_destroy(r);
}
void TestLogImpl_get_from_idx_with_base_off_by_one(CuTest * tc)
......@@ -338,12 +397,16 @@ void TestLogImpl_get_from_idx_with_base_off_by_one(CuTest * tc)
CuAssertIntEquals(tc, 1, impl->count(l));
/* get off-by-one index */
raft_entry_t *e[1];
raft_entry_t *e[1] = {NULL};
CuAssertIntEquals(tc, impl->get_batch(l, 1, 1, e), 0);
/* now get the correct index */
CuAssertIntEquals(tc, impl->get_batch(l, 2, 1, e), 1);
CuAssertIntEquals(tc, e[0]->id, 2);
raft_entry_release(e[0]);
impl->free(l);
raft_destroy(r);
}
int main(void)
......@@ -369,5 +432,10 @@ int main(void)
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
return suite->failCount == 0 ? 0 : 1;
int rc = suite->failCount == 0 ? 0 : 1;
CuStringFree(output);
CuSuiteFree(suite);
return rc;
}
......@@ -15,6 +15,7 @@ void TestRaft_node_set_nextIdx(CuTest * tc)
raft_node_t *p = raft_node_new((void *) 1, 1, 1);
raft_node_set_next_idx(p, 3);
CuAssertTrue(tc, 3 == raft_node_get_next_idx(p));
raft_node_free(p);
}
......@@ -29,5 +30,10 @@ int main(void)
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
return suite->failCount == 0 ? 0 : 1;
int rc = suite->failCount == 0 ? 0 : 1;
CuStringFree(output);
CuSuiteFree(suite);
return rc;
}
......@@ -88,5 +88,10 @@ int main(void)
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
return suite->failCount == 0 ? 0 : 1;
int rc = suite->failCount == 0 ? 0 : 1;
CuStringFree(output);
CuSuiteFree(suite);
return rc;
}
......@@ -103,6 +103,8 @@ void TestRaft_server_voted_for_records_who_we_voted_for(CuTest * tc)
raft_add_node(r, NULL, 2, 0);
raft_vote(r, raft_get_node(r, 2));
CuAssertTrue(tc, 2 == raft_get_voted_for(r));
raft_destroy(r);
}
void TestRaft_server_get_my_node(CuTest * tc)
......@@ -111,6 +113,8 @@ void TestRaft_server_get_my_node(CuTest * tc)
raft_node_t* me = raft_add_node(r, NULL, 1, 1);
raft_add_node(r, NULL, 2, 0);
CuAssertTrue(tc, me == raft_get_my_node(r));
raft_destroy(r);
}
void TestRaft_server_idx_starts_at_1(CuTest * tc)
......@@ -122,12 +126,16 @@ void TestRaft_server_idx_starts_at_1(CuTest * tc)
__RAFT_APPEND_ENTRY(r, 1, 1, "aaa");
CuAssertTrue(tc, 1 == raft_get_current_idx(r));
raft_destroy(r);
}
void TestRaft_server_currentterm_defaults_to_0(CuTest * tc)
{
void *r = raft_new();
CuAssertTrue(tc, 0 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_server_set_currentterm_sets_term(CuTest * tc)
......@@ -136,6 +144,8 @@ void TestRaft_server_set_currentterm_sets_term(CuTest * tc)
raft_set_callbacks(r, &generic_funcs, NULL);
raft_set_current_term(r, 5);
CuAssertTrue(tc, 5 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_server_voting_results_in_voting(CuTest * tc)
......@@ -149,6 +159,8 @@ void TestRaft_server_voting_results_in_voting(CuTest * tc)
CuAssertTrue(tc, 1 == raft_get_voted_for(r));
raft_vote(r, raft_get_node(r, 9));
CuAssertTrue(tc, 9 == raft_get_voted_for(r));
raft_destroy(r);
}
void TestRaft_server_add_node_makes_non_voting_node_voting(CuTest * tc)
......@@ -160,6 +172,8 @@ void TestRaft_server_add_node_makes_non_voting_node_voting(CuTest * tc)
raft_add_node(r, NULL, 9, 0);
CuAssertTrue(tc, raft_node_is_voting(n1));
CuAssertIntEquals(tc, 1, raft_get_num_nodes(r));
raft_destroy(r);
}
void TestRaft_server_add_node_with_already_existing_id_is_not_allowed(CuTest * tc)
......@@ -170,6 +184,8 @@ void TestRaft_server_add_node_with_already_existing_id_is_not_allowed(CuTest * t
CuAssertTrue(tc, NULL == raft_add_node(r, NULL, 9, 0));
CuAssertTrue(tc, NULL == raft_add_node(r, NULL, 11, 0));
raft_destroy(r);
}
void TestRaft_server_add_non_voting_node_with_already_existing_id_is_not_allowed(CuTest * tc)
......@@ -180,6 +196,8 @@ void TestRaft_server_add_non_voting_node_with_already_existing_id_is_not_allowed
CuAssertTrue(tc, NULL == raft_add_non_voting_node(r, NULL, 9, 0));
CuAssertTrue(tc, NULL == raft_add_non_voting_node(r, NULL, 11, 0));
raft_destroy(r);
}
void TestRaft_server_add_non_voting_node_with_already_existing_voting_id_is_not_allowed(CuTest * tc)
......@@ -190,6 +208,8 @@ void TestRaft_server_add_non_voting_node_with_already_existing_voting_id_is_not_
CuAssertTrue(tc, NULL == raft_add_non_voting_node(r, NULL, 9, 0));
CuAssertTrue(tc, NULL == raft_add_non_voting_node(r, NULL, 11, 0));
raft_destroy(r);
}
void TestRaft_server_remove_node(CuTest * tc)
......@@ -203,6 +223,8 @@ void TestRaft_server_remove_node(CuTest * tc)
CuAssertTrue(tc, NULL != raft_get_node(r, 9));
raft_remove_node(r, n2);
CuAssertTrue(tc, NULL == raft_get_node(r, 9));
raft_destroy(r);
}
void TestRaft_election_start_does_not_increment_term(CuTest * tc)
......@@ -213,6 +235,8 @@ void TestRaft_election_start_does_not_increment_term(CuTest * tc)
raft_set_current_term(r, 1);
raft_election_start(r, 0);
CuAssertTrue(tc, 1 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_election_become_candidate_increments_term(CuTest * tc)
......@@ -223,6 +247,8 @@ void TestRaft_election_become_candidate_increments_term(CuTest * tc)
raft_set_current_term(r, 1);
raft_become_candidate(r);
CuAssertTrue(tc, 2 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_set_state(CuTest * tc)
......@@ -243,12 +269,16 @@ void TestRaft_set_state(CuTest * tc)
raft_set_state(r, RAFT_STATE_FOLLOWER);
CuAssertTrue(tc, RAFT_STATE_FOLLOWER == raft_get_state(r));
CuAssertStrEquals(tc, "follower", raft_get_state_str(r));
raft_destroy(r);
}
void TestRaft_server_starts_as_follower(CuTest * tc)
{
void *r = raft_new();
CuAssertTrue(tc, RAFT_STATE_FOLLOWER == raft_get_state(r));
raft_destroy(r);
}
void TestRaft_server_starts_with_election_timeout_of_1000ms(CuTest * tc)
......@@ -259,6 +289,8 @@ void TestRaft_server_starts_with_election_timeout_of_1000ms(CuTest * tc)
raft_config(r, 0, RAFT_CONFIG_ELECTION_TIMEOUT, &election_timeout);
CuAssertTrue(tc, 1000 == election_timeout);
raft_destroy(r);
}
void TestRaft_server_starts_with_request_timeout_of_200ms(CuTest * tc)
......@@ -269,6 +301,8 @@ void TestRaft_server_starts_with_request_timeout_of_200ms(CuTest * tc)
raft_config(r, 0, RAFT_CONFIG_REQUEST_TIMEOUT, &request_timeout);
CuAssertTrue(tc, 200 == request_timeout);
raft_destroy(r);
}
void TestRaft_server_entry_append_increases_logidx(CuTest* tc)
......@@ -279,7 +313,10 @@ void TestRaft_server_entry_append_increases_logidx(CuTest* tc)
raft_entry_t *ety = __MAKE_ENTRY(1, 1, "aaa");
CuAssertTrue(tc, 0 == raft_get_current_idx(r));
raft_append_entry(r, ety);
raft_entry_release(ety);
CuAssertTrue(tc, 1 == raft_get_current_idx(r));
raft_destroy(r);
}
// this eems like a total duplicte of previous test case
......@@ -291,7 +328,10 @@ void TestRaft_server_append_entry_means_entry_gets_current_term(CuTest* tc)
raft_entry_t *ety = __MAKE_ENTRY(1, 1, "aaa");
CuAssertTrue(tc, 0 == raft_get_current_idx(r));
raft_append_entry(r, ety);
raft_entry_release(ety);
CuAssertTrue(tc, 1 == raft_get_current_idx(r));
raft_destroy(r);
}
void TestRaft_server_append_entry_is_retrievable(CuTest * tc)
......@@ -305,8 +345,11 @@ void TestRaft_server_append_entry_is_retrievable(CuTest * tc)
__RAFT_APPEND_ENTRY(r, 100, 1, "aaa");
raft_entry_t* kept = raft_get_entry_from_idx(r, 1);
CuAssertIntEquals(tc, 3, kept->data_len);
CuAssertIntEquals(tc, 4, kept->data_len);
CuAssertStrEquals(tc, "aaa", kept->data);
raft_entry_release(kept);
raft_destroy(r);
}
static int __raft_logentry_offer(
......@@ -364,6 +407,9 @@ void TestRaft_server_entry_is_retrieveable_using_idx(CuTest* tc)
CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 2)));
CuAssertTrue(tc, !strncmp(ety_appended->data, str2, 3));
raft_entry_release(ety_appended);
raft_destroy(r);
}
void TestRaft_server_wont_apply_entry_if_we_dont_have_entry_to_apply(CuTest* tc)
......@@ -375,6 +421,8 @@ void TestRaft_server_wont_apply_entry_if_we_dont_have_entry_to_apply(CuTest* tc)
raft_apply_entry(r);
CuAssertTrue(tc, 0 == raft_get_last_applied_idx(r));
CuAssertTrue(tc, 0 == raft_get_commit_idx(r));
raft_destroy(r);
}
void TestRaft_server_wont_apply_entry_if_there_isnt_a_majority(CuTest* tc)
......@@ -397,6 +445,8 @@ void TestRaft_server_wont_apply_entry_if_there_isnt_a_majority(CuTest* tc)
/* Not allowed to be applied because we haven't confirmed a majority yet */
CuAssertTrue(tc, 0 == raft_get_last_applied_idx(r));
CuAssertTrue(tc, 0 == raft_get_commit_idx(r));
raft_destroy(r);
}
/* If commitidx > lastApplied: increment lastApplied, apply log[lastApplied]
......@@ -427,6 +477,8 @@ void TestRaft_server_increment_lastApplied_when_lastApplied_lt_commitidx(
/* let time lapse */
raft_periodic_internal(r, 1);
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_user_applylog_error_propogates_to_periodic(
......@@ -454,6 +506,8 @@ void TestRaft_user_applylog_error_propogates_to_periodic(
/* let time lapse */
CuAssertIntEquals(tc, RAFT_ERR_SHUTDOWN, raft_periodic_internal(r, 1));
CuAssertIntEquals(tc, 0, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_server_apply_entry_increments_last_applied_idx(CuTest* tc)
......@@ -472,6 +526,8 @@ void TestRaft_server_apply_entry_increments_last_applied_idx(CuTest* tc)
raft_set_commit_idx(r, 1);
raft_apply_entry(r);
CuAssertTrue(tc, 1 == raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_server_periodic_elapses_election_timeout(CuTest * tc)
......@@ -486,6 +542,8 @@ void TestRaft_server_periodic_elapses_election_timeout(CuTest * tc)
raft_periodic_internal(r, 100);
CuAssertTrue(tc, 100 == raft_get_timeout_elapsed(r));
raft_destroy(r);
}
void TestRaft_server_election_timeout_does_not_promote_us_to_leader_if_there_is_are_more_than_1_nodes(CuTest * tc)
......@@ -506,6 +564,8 @@ void TestRaft_server_election_timeout_does_not_promote_us_to_leader_if_there_is_
raft_periodic_internal(r, 1001);
CuAssertTrue(tc, 0 == raft_is_leader(r));
raft_destroy(r);
}
void TestRaft_server_election_timeout_does_not_promote_us_to_leader_if_we_are_not_voting_node(CuTest * tc)
......@@ -519,6 +579,8 @@ void TestRaft_server_election_timeout_does_not_promote_us_to_leader_if_we_are_no
CuAssertTrue(tc, 0 == raft_is_leader(r));
CuAssertTrue(tc, 0 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_server_election_timeout_does_not_start_election_if_there_are_no_voting_nodes(CuTest * tc)
......@@ -532,6 +594,8 @@ void TestRaft_server_election_timeout_does_not_start_election_if_there_are_no_vo
raft_periodic_internal(r, 1001);
CuAssertTrue(tc, 0 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_server_election_timeout_does_promote_us_to_leader_if_there_is_only_1_node(CuTest * tc)
......@@ -546,6 +610,8 @@ void TestRaft_server_election_timeout_does_promote_us_to_leader_if_there_is_only
CuAssertTrue(tc, 1 == raft_is_leader(r));
CuAssertTrue(tc, old_term + 1 == raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_server_election_timeout_does_promote_us_to_leader_if_there_is_only_1_voting_node(CuTest * tc)
......@@ -565,6 +631,8 @@ void TestRaft_server_election_timeout_does_promote_us_to_leader_if_there_is_only
raft_periodic_internal(r, 1001);
CuAssertTrue(tc, 1 == raft_is_leader(r));
raft_destroy(r);
}
void TestRaft_server_recv_entry_auto_commits_if_we_are_the_only_node(CuTest * tc)
......@@ -581,8 +649,11 @@ void TestRaft_server_recv_entry_auto_commits_if_we_are_the_only_node(CuTest * tc
/* receive entry */
raft_entry_resp_t cr;
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertTrue(tc, 2 == raft_get_log_count(r));
CuAssertTrue(tc, 2 == raft_get_commit_idx(r));
raft_destroy(r);
}
void TestRaft_server_recv_entry_fails_if_there_is_already_a_voting_change(CuTest * tc)
......@@ -601,12 +672,16 @@ void TestRaft_server_recv_entry_fails_if_there_is_already_a_voting_change(CuTest
/* receive entry */
raft_entry_resp_t cr;
CuAssertTrue(tc, 0 == raft_recv_entry(r, ety, &cr));
raft_entry_release(ety);
CuAssertTrue(tc, 2 == raft_get_log_count(r));
raft_entry_t *ety2 = __MAKE_ENTRY(2, 1, "entry");
ety2->type = RAFT_LOGTYPE_ADD_NODE;
CuAssertTrue(tc, RAFT_ERR_ONE_VOTING_CHANGE_ONLY == raft_recv_entry(r, ety2, &cr));
raft_entry_release(ety2);
CuAssertTrue(tc, 1 == raft_get_commit_idx(r));
raft_destroy(r);
}
void TestRaft_server_cfg_sets_num_nodes(CuTest * tc)
......@@ -616,6 +691,8 @@ void TestRaft_server_cfg_sets_num_nodes(CuTest * tc)
raft_add_node(r, NULL, 2, 0);
CuAssertTrue(tc, 2 == raft_get_num_nodes(r));
raft_destroy(r);
}
void TestRaft_server_cant_get_node_we_dont_have(CuTest * tc)
......@@ -628,6 +705,8 @@ void TestRaft_server_cant_get_node_we_dont_have(CuTest * tc)
CuAssertTrue(tc, NULL != raft_get_node(r, 1));
CuAssertTrue(tc, NULL != raft_get_node(r, 2));
CuAssertTrue(tc, NULL == raft_get_node(r, 3));
raft_destroy(r);
}
/* If term > currentTerm, set currentTerm to term (step down if candidate or
......@@ -675,6 +754,8 @@ void TestRaft_server_recv_requestvote_response_dont_increase_votes_for_me_when_n
int e = raft_recv_requestvote_response(r, raft_get_node(r, 2), &rvr);
CuAssertIntEquals(tc, 0, e);
CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
raft_destroy(r);
}
void TestRaft_server_recv_requestvote_response_dont_increase_votes_for_me_when_term_is_not_equal(
......@@ -699,6 +780,8 @@ void TestRaft_server_recv_requestvote_response_dont_increase_votes_for_me_when_t
rvr.vote_granted = 1;
raft_recv_requestvote_response(r, raft_get_node(r, 2), &rvr);
CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
raft_destroy(r);
}
void TestRaft_server_recv_requestvote_response_increase_votes_for_me(
......@@ -732,6 +815,8 @@ void TestRaft_server_recv_requestvote_response_increase_votes_for_me(
int e = raft_recv_requestvote_response(r, raft_get_node(r, 2), &rvr);
CuAssertIntEquals(tc, 0, e);
CuAssertTrue(tc, 2 == raft_get_nvotes_for_me(r));
raft_destroy(r);
}
void TestRaft_server_recv_requestvote_response_must_be_candidate_to_receive(
......@@ -759,6 +844,8 @@ void TestRaft_server_recv_requestvote_response_must_be_candidate_to_receive(
rvr.vote_granted = 1;
raft_recv_requestvote_response(r, raft_get_node(r, 2), &rvr);
CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
raft_destroy(r);
}
/* Reply false if term < currentTerm (§5.1) */
......@@ -786,6 +873,8 @@ void TestRaft_server_recv_requestvote_reply_false_if_term_less_than_current_term
int e = raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertIntEquals(tc, 0, e);
CuAssertIntEquals(tc, 0, rvr.vote_granted);
raft_destroy(r);
}
void TestRaft_leader_recv_requestvote_does_not_step_down(
......@@ -815,6 +904,8 @@ void TestRaft_leader_recv_requestvote_does_not_step_down(
rv.term = 1;
raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertIntEquals(tc, 1, raft_get_leader_id(r));
raft_destroy(r);
}
/* Reply true if term >= currentTerm (§5.1) */
......@@ -843,6 +934,8 @@ void TestRaft_server_recv_requestvote_reply_true_if_term_greater_than_or_equal_t
raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertTrue(tc, 1 == rvr.vote_granted);
raft_destroy(r);
}
void TestRaft_server_recv_requestvote_reset_timeout(
......@@ -872,6 +965,8 @@ void TestRaft_server_recv_requestvote_reset_timeout(
raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertTrue(tc, 1 == rvr.vote_granted);
CuAssertIntEquals(tc, 0, raft_get_timeout_elapsed(r));
raft_destroy(r);
}
void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than_current_term(
......@@ -903,6 +998,8 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
CuAssertIntEquals(tc, 1, raft_is_follower(r));
CuAssertIntEquals(tc, 2, raft_get_current_term(r));
CuAssertIntEquals(tc, 2, raft_get_voted_for(r));
raft_destroy(r);
}
void TestRaft_server_recv_requestvote_depends_on_candidate_id(
......@@ -934,6 +1031,8 @@ void TestRaft_server_recv_requestvote_depends_on_candidate_id(
CuAssertIntEquals(tc, 1, raft_is_follower(r));
CuAssertIntEquals(tc, 2, raft_get_current_term(r));
CuAssertIntEquals(tc, 3, raft_get_voted_for(r));
raft_destroy(r);
}
/* If votedFor is null or candidateId, and candidate's log is at
......@@ -970,6 +1069,8 @@ void TestRaft_server_recv_requestvote_dont_grant_vote_if_we_didnt_vote_for_this_
raft_vote_for_nodeid(r, 0);
raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertTrue(tc, 0 == rvr.vote_granted);
raft_destroy(r);
}
/* If requestvote is received within the minimum election timeout of
......@@ -1011,6 +1112,8 @@ void TestRaft_server_recv_requestvote_ignore_if_master_is_fresh(CuTest * tc)
raft_periodic_internal(r, 1001);
raft_recv_requestvote(r, raft_get_node(r, 3), &rv, &rvr);
CuAssertTrue(tc, 1 == rvr.vote_granted);
raft_destroy(r);
}
void TestRaft_server_recv_prevote_ignore_if_candidate(CuTest * tc)
......@@ -1034,6 +1137,8 @@ void TestRaft_server_recv_prevote_ignore_if_candidate(CuTest * tc)
CuAssertTrue(tc, raft_is_candidate(r));
CuAssertTrue(tc, raft_get_nvotes_for_me(r) == 1);
raft_destroy(r);
}
void TestRaft_server_recv_reqvote_ignore_if_not_candidate(CuTest * tc)
......@@ -1056,6 +1161,8 @@ void TestRaft_server_recv_reqvote_ignore_if_not_candidate(CuTest * tc)
CuAssertTrue(tc, raft_is_precandidate(r));
CuAssertTrue(tc, raft_get_nvotes_for_me(r) == 1);
raft_destroy(r);
}
void TestRaft_server_recv_reqvote_always_update_term(CuTest * tc)
......@@ -1078,6 +1185,8 @@ void TestRaft_server_recv_reqvote_always_update_term(CuTest * tc)
CuAssertTrue(tc, raft_is_follower(r));
CuAssertTrue(tc, raft_get_current_term(r) == 3);
raft_destroy(r);
}
void TestRaft_follower_becomes_follower_is_follower(CuTest * tc)
......@@ -1086,6 +1195,8 @@ void TestRaft_follower_becomes_follower_is_follower(CuTest * tc)
raft_add_node(r, NULL, 1, 1);
raft_become_follower(r);
CuAssertTrue(tc, raft_is_follower(r));
raft_destroy(r);
}
void TestRaft_follower_becomes_follower_does_not_clear_voted_for(CuTest * tc)
......@@ -1103,6 +1214,8 @@ void TestRaft_follower_becomes_follower_does_not_clear_voted_for(CuTest * tc)
CuAssertIntEquals(tc, 1, raft_get_voted_for(r));
raft_become_follower(r);
CuAssertIntEquals(tc, 1, raft_get_voted_for(r));
raft_destroy(r);
}
/* 5.1 */
......@@ -1134,6 +1247,8 @@ void TestRaft_follower_recv_appendentries_reply_false_if_term_less_than_currentt
CuAssertTrue(tc, 0 == aer.success);
/* rejected appendentries doesn't change the current leader. */
CuAssertTrue(tc, -1 == raft_get_leader_id(r));
raft_destroy(r);
}
void TestRaft_follower_recv_snapshot_reply_false_if_term_less_than_currentterm(
......@@ -1166,6 +1281,8 @@ void TestRaft_follower_recv_snapshot_reply_false_if_term_less_than_currentterm(
/* rejected snapshot req doesn't change the current leader. */
CuAssertTrue(tc, raft_get_leader_id(r) == RAFT_NODE_ID_NONE);
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_does_not_need_node(CuTest * tc)
......@@ -1184,6 +1301,8 @@ void TestRaft_follower_recv_appendentries_does_not_need_node(CuTest * tc)
raft_appendentries_resp_t aer;
raft_recv_appendentries(r, NULL, &ae, &aer);
CuAssertTrue(tc, 1 == aer.success);
raft_destroy(r);
}
/* TODO: check if test case is needed */
......@@ -1222,6 +1341,8 @@ void TestRaft_follower_recv_appendentries_updates_currentterm_if_term_gt_current
CuAssertTrue(tc, 2 == raft_get_current_term(r));
/* and leader has been updated */
CuAssertIntEquals(tc, 2, raft_get_leader_id(r));
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_does_not_log_if_no_entries_are_specified(
......@@ -1255,6 +1376,8 @@ void TestRaft_follower_recv_appendentries_does_not_log_if_no_entries_are_specifi
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_increases_log(CuTest * tc)
......@@ -1291,10 +1414,18 @@ void TestRaft_follower_recv_appendentries_increases_log(CuTest * tc)
ae.n_entries = 1;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
CuAssertTrue(tc, 1 == aer.success);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
raft_entry_t* log = raft_get_entry_from_idx(r, 1);
CuAssertTrue(tc, 2 == log->term);
raft_entry_release(log);
raft_destroy(r);
}
/* 5.3 */
......@@ -1333,8 +1464,15 @@ void TestRaft_follower_recv_appendentries_reply_false_if_doesnt_have_log_at_prev
/* trigger reply */
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* reply is false */
CuAssertTrue(tc, 0 == aer.success);
raft_destroy(r);
}
static raft_entry_t* __create_mock_entries_for_conflict_tests(
......@@ -1355,6 +1493,7 @@ static raft_entry_t* __create_mock_entries_for_conflict_tests(
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, str2, 3));
raft_entry_release(ety_appended);
/* this log will be overwritten by a later appendentries */
char *str3 = strs[2];
......@@ -1387,6 +1526,7 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
char* strs[] = {"111", "222", "333"};
raft_entry_t *ety_appended = __create_mock_entries_for_conflict_tests(tc, r, strs);
raft_entry_release(ety_appended);
/* pass a appendentry that is newer */
memset(&ae, 0, sizeof(raft_appendentries_req_t));
......@@ -1403,12 +1543,22 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 1 == aer.success);
CuAssertTrue(tc, 2 == raft_get_log_count(r));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* str1 is still there */
CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 1)));
CuAssertTrue(tc, !strncmp(ety_appended->data, strs[0], 3));
raft_entry_release(ety_appended);
/* str4 has overwritten the last 2 entries */
CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 2)));
CuAssertTrue(tc, !strncmp(ety_appended->data, str4, 3));
raft_entry_release(ety_appended);
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_entries_via_prev_log_idx_at_idx_0(
......@@ -1431,6 +1581,7 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
char* strs[] = {"111", "222", "333"};
raft_entry_t *ety_appended = __create_mock_entries_for_conflict_tests(tc, r, strs);
raft_entry_release(ety_appended);
/* pass a appendentry that is newer */
......@@ -1447,9 +1598,18 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 1 == aer.success);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* str1 is gone */
CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 1)));
CuAssertTrue(tc, !strncmp(ety_appended->data, str4, 3));
raft_entry_release(ety_appended);
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_entries_greater_than_prev_log_idx(
......@@ -1471,10 +1631,9 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
raft_set_current_term(r, 1);
char* strs[] = {"111", "222", "333"};
raft_entry_t *ety_appended;
__create_mock_entries_for_conflict_tests(tc, r, strs);
raft_entry_t *ety_appended = __create_mock_entries_for_conflict_tests(tc, r, strs);
CuAssertIntEquals(tc, 3, raft_get_log_count(r));
raft_entry_release(ety_appended);
memset(&ae, 0, sizeof(raft_appendentries_req_t));
ae.term = 2;
......@@ -1485,10 +1644,18 @@ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_en
ae.n_entries = 1;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(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, strs[0], 3));
raft_entry_release(ety_appended);
raft_destroy(r);
}
// TODO: add TestRaft_follower_recv_appendentries_delete_entries_if_term_is_different
......@@ -1521,6 +1688,13 @@ void TestRaft_follower_recv_appendentries_add_new_entries_not_already_in_log(
CuAssertTrue(tc, 1 == aer.success);
CuAssertTrue(tc, 2 == raft_get_log_count(r));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_does_not_add_dupe_entries_already_in_log(
......@@ -1549,12 +1723,18 @@ void TestRaft_follower_recv_appendentries_does_not_add_dupe_entries_already_in_l
ae.n_entries = 1;
memset(&aer, 0, sizeof(aer));
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
memset(&aer, 0, sizeof(aer));
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
/* still successful even when no raft_append_entry() happened! */
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, 1, raft_get_log_count(r));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* lets get the server to append 2 now! */
ae.entries = __MAKE_ENTRY_ARRAY_SEQ_ID(2, 1, 1, "aaa");
ae.n_entries = 2;
......@@ -1562,6 +1742,13 @@ void TestRaft_follower_recv_appendentries_does_not_add_dupe_entries_already_in_l
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
raft_destroy(r);
}
typedef enum {
......@@ -1642,6 +1829,7 @@ void TestRaft_follower_recv_appendentries_partial_failures(
error.idx = 2;
memset(&aer, 0, sizeof(aer));
int err = raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertIntEquals(tc, RAFT_ERR_NOMEM, err);
CuAssertIntEquals(tc, 1, aer.success);
CuAssertIntEquals(tc, 1, aer.current_idx);
......@@ -1649,6 +1837,7 @@ void TestRaft_follower_recv_appendentries_partial_failures(
raft_entry_t *tmp = raft_get_entry_from_idx(r, 2);
CuAssertTrue(tc, NULL != tmp);
CuAssertIntEquals(tc, 1, tmp->term);
raft_entry_release(tmp);
/* Ask log_offer to fail at entry 3. */
error.type = __RAFT_LOG_OFFER_ERR;
......@@ -1662,6 +1851,7 @@ void TestRaft_follower_recv_appendentries_partial_failures(
tmp = raft_get_entry_from_idx(r, 2);
CuAssertTrue(tc, NULL != tmp);
CuAssertIntEquals(tc, 2, tmp->term);
raft_entry_release(tmp);
/* No more errors. */
memset(&error, 0, sizeof(error));
......@@ -1671,6 +1861,13 @@ void TestRaft_follower_recv_appendentries_partial_failures(
CuAssertIntEquals(tc, 1, aer.success);
CuAssertIntEquals(tc, 3, aer.current_idx);
CuAssertIntEquals(tc, 3, raft_get_current_idx(r));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
raft_destroy(r);
}
/* If leaderCommit > commitidx, set commitidx =
......@@ -1697,10 +1894,10 @@ void TestRaft_follower_recv_appendentries_set_commitidx_to_prevLogIdx(
ae.prev_log_term = 0;
/* include entries */
raft_entry_req_t e[4] = {
{ .id = 1, .term = 1 },
{ .id = 2, .term = 1 },
{ .id = 3, .term = 1 },
{ .id = 4, .term = 1 }
{ .id = 1, .term = 1, .refs = 1 },
{ .id = 2, .term = 1, .refs = 1 },
{ .id = 3, .term = 1, .refs = 1 },
{ .id = 4, .term = 1, .refs = 1}
};
raft_entry_req_t *e_array[4] = {
&e[0], &e[1], &e[2], &e[3]
......@@ -1721,6 +1918,8 @@ void TestRaft_follower_recv_appendentries_set_commitidx_to_prevLogIdx(
CuAssertTrue(tc, 1 == aer.success);
/* set to 4 because commitIDX is lower */
CuAssertIntEquals(tc, 4, raft_get_commit_idx(r));
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_set_commitidx_to_LeaderCommit(
......@@ -1745,10 +1944,10 @@ void TestRaft_follower_recv_appendentries_set_commitidx_to_LeaderCommit(
ae.prev_log_term = 0;
/* include entries */
raft_entry_req_t e[4] = {
{ .id = 1, .term = 1 },
{ .id = 2, .term = 1 },
{ .id = 3, .term = 1 },
{ .id = 4, .term = 1 }
{ .id = 1, .term = 1, .refs = 1 },
{ .id = 2, .term = 1, .refs = 1 },
{ .id = 3, .term = 1, .refs = 1 },
{ .id = 4, .term = 1, .refs = 1 }
};
raft_entry_req_t *e_array[4] = {
&e[0], &e[1], &e[2], &e[3]
......@@ -1770,6 +1969,8 @@ void TestRaft_follower_recv_appendentries_set_commitidx_to_LeaderCommit(
CuAssertTrue(tc, 1 == aer.success);
/* set to 3 because leaderCommit is lower */
CuAssertIntEquals(tc, 3, raft_get_commit_idx(r));
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_failure_includes_current_idx(
......@@ -1808,6 +2009,8 @@ void TestRaft_follower_recv_appendentries_failure_includes_current_idx(
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 0 == aer.success);
CuAssertIntEquals(tc, 2, aer.current_idx);
raft_destroy(r);
}
void TestRaft_follower_becomes_precandidate_when_election_timeout_occurs(
......@@ -1832,6 +2035,8 @@ void TestRaft_follower_becomes_precandidate_when_election_timeout_occurs(
/* is a candidate now */
CuAssertTrue(tc, 1 == raft_is_precandidate(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -1878,6 +2083,8 @@ void TestRaft_follower_dont_grant_vote_if_candidate_has_a_less_complete_log(
rv.last_log_term = 3;
raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertIntEquals(tc, 1, rvr.vote_granted);
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_heartbeat_does_not_overwrite_logs(
......@@ -1905,6 +2112,11 @@ void TestRaft_follower_recv_appendentries_heartbeat_does_not_overwrite_logs(
ae.n_entries = 1;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* The server sends a follow up AE
* NOTE: the server has received a response from the last AE so
* prev_log_idx has been incremented */
......@@ -1917,6 +2129,11 @@ void TestRaft_follower_recv_appendentries_heartbeat_does_not_overwrite_logs(
ae.n_entries = 4;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* receive a heartbeat
* NOTE: the leader hasn't received the response to the last AE so it can
* only assume prev_Log_idx is still 1 */
......@@ -1929,6 +2146,8 @@ void TestRaft_follower_recv_appendentries_heartbeat_does_not_overwrite_logs(
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, 5, raft_get_current_idx(r));
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_does_not_deleted_commited_entries(
......@@ -1956,6 +2175,11 @@ void TestRaft_follower_recv_appendentries_does_not_deleted_commited_entries(
ae.n_entries = 1;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* Follow up AE. Node responded with success */
memset(&ae, 0, sizeof(raft_appendentries_req_t));
ae.term = 1;
......@@ -1967,6 +2191,11 @@ void TestRaft_follower_recv_appendentries_does_not_deleted_commited_entries(
ae.leader_commit = 4;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
/* The server sends a follow up AE */
memset(&ae, 0, sizeof(raft_appendentries_req_t));
ae.term = 1;
......@@ -1978,6 +2207,11 @@ void TestRaft_follower_recv_appendentries_does_not_deleted_commited_entries(
ae.leader_commit = 4;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, 6, raft_get_current_idx(r));
CuAssertIntEquals(tc, 4, raft_get_commit_idx(r));
......@@ -1995,8 +2229,15 @@ void TestRaft_follower_recv_appendentries_does_not_deleted_commited_entries(
ae.leader_commit = 4;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, 6, raft_get_current_idx(r));
raft_destroy(r);
}
void TestRaft_candidate_becomes_candidate_is_candidate(CuTest * tc)
......@@ -2010,6 +2251,8 @@ void TestRaft_candidate_becomes_candidate_is_candidate(CuTest * tc)
raft_add_node(r, NULL, 1, 1);
raft_become_candidate(r);
CuAssertTrue(tc, raft_is_candidate(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2026,6 +2269,8 @@ void TestRaft_follower_becoming_candidate_increments_current_term(CuTest * tc)
CuAssertTrue(tc, 0 == raft_get_current_term(r));
raft_become_candidate(r);
CuAssertTrue(tc, 1 == raft_get_current_term(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2043,6 +2288,8 @@ void TestRaft_follower_becoming_candidate_votes_for_self(CuTest * tc)
raft_become_candidate(r);
CuAssertTrue(tc, raft_get_nodeid(r) == raft_get_voted_for(r));
CuAssertTrue(tc, 1 == raft_get_nvotes_for_me(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2066,6 +2313,8 @@ void TestRaft_follower_becoming_candidate_resets_election_timeout(CuTest * tc)
raft_become_candidate(r);
/* time is selected randomly */
CuAssertTrue(tc, raft_get_timeout_elapsed(r) < 1000);
raft_destroy(r);
}
void TestRaft_follower_recv_appendentries_resets_election_timeout(
......@@ -2091,6 +2340,8 @@ void TestRaft_follower_recv_appendentries_resets_election_timeout(
ae.term = 1;
raft_recv_appendentries(r, raft_get_node(r, 1), &ae, &aer);
CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2121,10 +2372,15 @@ void TestRaft_follower_becoming_candidate_requests_votes_from_other_servers(
CuAssertTrue(tc, NULL != rv);
CuAssertTrue(tc, 2 != rv->term);
CuAssertTrue(tc, 3 == rv->term);
raft_free(rv);
/* TODO: there should be more items */
rv = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != rv);
CuAssertTrue(tc, 3 == rv->term);
raft_free(rv);
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2171,6 +2427,8 @@ void TestRaft_candidate_election_timeout_and_no_leader_results_in_new_election(
/* receiving this vote gives the server majority */
raft_recv_requestvote_response(r, raft_get_node(r, 2), &vr1);
CuAssertIntEquals(tc, RAFT_STATE_LEADER, raft_get_state(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2213,6 +2471,8 @@ void TestRaft_candidate_receives_majority_of_votes_becomes_leader(CuTest * tc)
* now has majority (ie. 3/5 votes) */
raft_recv_requestvote_response(r, raft_get_node(r, 3), &vr);
CuAssertTrue(tc, 1 == raft_is_leader(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2239,6 +2499,8 @@ void TestRaft_candidate_will_not_respond_to_voterequest_if_it_has_already_voted(
/* we've vote already, so won't respond with a vote granted... */
CuAssertTrue(tc, 0 == rvr.vote_granted);
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2264,12 +2526,15 @@ void TestRaft_candidate_requestvote_includes_logidx(CuTest * tc)
__RAFT_APPEND_ENTRY(r, 102, 3, "aaa");
raft_send_requestvote(r, raft_get_node(r, 2));
raft_requestvote_req_t * rv = sender_poll_msg_data(sender);
raft_requestvote_req_t *rv = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != rv);
CuAssertIntEquals(tc, 3, rv->last_log_idx);
CuAssertIntEquals(tc, 5, rv->term);
CuAssertIntEquals(tc, 3, rv->last_log_term);
CuAssertIntEquals(tc, 1, rv->candidate_id);
free(rv);
raft_destroy(r);
}
void TestRaft_candidate_recv_requestvote_response_becomes_follower_if_current_term_is_less_than_term(
......@@ -2301,6 +2566,8 @@ void TestRaft_candidate_recv_requestvote_response_becomes_follower_if_current_te
CuAssertTrue(tc, 1 == raft_is_follower(r));
CuAssertTrue(tc, 2 == raft_get_current_term(r));
CuAssertTrue(tc, -1 == raft_get_voted_for(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2336,6 +2603,8 @@ void TestRaft_candidate_recv_appendentries_frm_leader_results_in_follower(
CuAssertTrue(tc, 2 == raft_get_leader_id(r));
CuAssertTrue(tc, 1 == raft_get_current_term(r));
CuAssertTrue(tc, -1 == raft_get_voted_for(r));
raft_destroy(r);
}
/* Candidate 5.2 */
......@@ -2381,6 +2650,8 @@ void TestRaft_candidate_recv_appendentries_from_same_term_results_in_step_down(
* Node self votes for Other2
*/
CuAssertIntEquals(tc, 1, raft_get_voted_for(r));
raft_destroy(r);
}
void TestRaft_candidate_recv_appendentries_from_higher_term_results_in_step_down(
......@@ -2411,6 +2682,8 @@ void TestRaft_candidate_recv_appendentries_from_higher_term_results_in_step_down
raft_recv_appendentries(r, raft_get_node(r, 2), &append_req2, &append_resp);
CuAssertIntEquals(tc, 1, raft_is_follower(r));
CuAssertIntEquals(tc, 4, raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_candidate_recv_snapshot_from_higher_term_results_in_step_down(
......@@ -2442,6 +2715,8 @@ void TestRaft_candidate_recv_snapshot_from_higher_term_results_in_step_down(
raft_recv_snapshot(r, raft_get_node(r, 2), &snapshot_req2, &snapshot_resp);
CuAssertIntEquals(tc, 1, raft_is_follower(r));
CuAssertIntEquals(tc, 6, raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_leader_becomes_leader_is_leader(CuTest * tc)
......@@ -2452,6 +2727,8 @@ void TestRaft_leader_becomes_leader_is_leader(CuTest * tc)
CuAssertTrue(tc, raft_is_leader(r));
CuAssertTrue(tc, raft_get_leader_node(r) == n);
raft_destroy(r);
}
void TestRaft_leader_becomes_leader_does_not_clear_voted_for(CuTest * tc)
......@@ -2468,6 +2745,8 @@ void TestRaft_leader_becomes_leader_does_not_clear_voted_for(CuTest * tc)
CuAssertTrue(tc, 1 == raft_get_voted_for(r));
raft_become_leader(r);
CuAssertTrue(tc, 1 == raft_get_voted_for(r));
raft_destroy(r);
}
void TestRaft_leader_when_becomes_leader_all_nodes_have_nextidx_equal_to_lastlog_idx_plus_1(
......@@ -2495,6 +2774,8 @@ void TestRaft_leader_when_becomes_leader_all_nodes_have_nextidx_equal_to_lastlog
CuAssertTrue(tc, raft_get_current_idx(r) + 1 ==
raft_node_get_next_idx(p));
}
raft_destroy(r);
}
/* 5.2 */
......@@ -2518,10 +2799,23 @@ void TestRaft_leader_when_it_becomes_a_leader_sends_empty_appendentries(
raft_become_leader(r);
/* receive appendentries messages for both nodes */
raft_appendentries_req_t * ae = sender_poll_msg_data(sender);
raft_appendentries_req_t *ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
/* 5.2
......@@ -2549,10 +2843,18 @@ void TestRaft_leader_responds_to_entry_msg_when_entry_is_committed(CuTest * tc)
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
/* trigger response through commit */
raft_apply_entry(r);
raft_destroy(r);
}
static void read_request_dummy_cb(void *arg, int safe)
{
}
void TestRaft_non_leader_recv_entry_msg_fails(CuTest * tc)
......@@ -2570,11 +2872,14 @@ void TestRaft_non_leader_recv_entry_msg_fails(CuTest * tc)
/* receive entry */
int e = raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertTrue(tc, RAFT_ERR_NOT_LEADER == e);
/* receive read request */
e = raft_recv_read_request(r, NULL, NULL);
e = raft_recv_read_request(r, read_request_dummy_cb, NULL);
CuAssertTrue(tc, RAFT_ERR_NOT_LEADER == e);
raft_destroy(r);
}
/* 5.3 */
......@@ -2602,6 +2907,13 @@ void TestRaft_leader_sends_appendentries_with_NextIdx_when_PrevIdx_gt_NextIdx(
raft_send_appendentries(r, p);
raft_appendentries_req_t * ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
void TestRaft_leader_sends_appendentries_with_leader_commit(
......@@ -2622,10 +2934,7 @@ void TestRaft_leader_sends_appendentries_with_leader_commit(
raft_set_state(r, RAFT_STATE_LEADER);
raft_set_current_term(r, 1);
int i;
for (i=0; i<10; i++)
{
for (int i = 0; i < 10; i++) {
__RAFT_APPEND_ENTRY(r, 1, 1, "aaa");
}
......@@ -2636,6 +2945,13 @@ void TestRaft_leader_sends_appendentries_with_leader_commit(
raft_appendentries_req_t * ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
CuAssertTrue(tc, ae->leader_commit == 10);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
void TestRaft_leader_sends_appendentries_with_prevLogIdx(
......@@ -2662,6 +2978,12 @@ void TestRaft_leader_sends_appendentries_with_prevLogIdx(
CuAssertTrue(tc, NULL != ae);
CuAssertIntEquals(tc, 0, ae->prev_log_idx);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_node_t* n = raft_get_node(r, 2);
/* add 1 entry */
......@@ -2676,6 +2998,12 @@ void TestRaft_leader_sends_appendentries_with_prevLogIdx(
CuAssertIntEquals(tc, 100, ae->entries[0]->id);
CuAssertIntEquals(tc, 2, ae->entries[0]->term);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
/* set next_idx */
/* receive appendentries messages */
raft_node_set_next_idx(n, 2);
......@@ -2683,6 +3011,14 @@ void TestRaft_leader_sends_appendentries_with_prevLogIdx(
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
CuAssertTrue(tc, ae->prev_log_idx == 1);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
void TestRaft_leader_sends_appendentries_when_node_has_next_idx_of_0(
......@@ -2705,7 +3041,12 @@ void TestRaft_leader_sends_appendentries_when_node_has_next_idx_of_0(
/* receive appendentries messages */
raft_send_appendentries(r, raft_get_node(r, 2));
raft_appendentries_req_t * ae = sender_poll_msg_data(sender);
raft_appendentries_req_t *ae = sender_poll_msg_data(sender);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
/* add an entry */
/* receive appendentries messages */
......@@ -2716,6 +3057,14 @@ void TestRaft_leader_sends_appendentries_when_node_has_next_idx_of_0(
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
CuAssertTrue(tc, ae->prev_log_idx == 0);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
void TestRaft_leader_updates_next_idx_on_send_ae(CuTest *tc)
......@@ -2738,7 +3087,12 @@ void TestRaft_leader_updates_next_idx_on_send_ae(CuTest *tc)
/* receive appendentries messages */
raft_node_t* n = raft_get_node(r, 2);
raft_send_appendentries(r, n);
raft_appendentries_req_t * ae = sender_poll_msg_data(sender);
raft_appendentries_req_t *ae = sender_poll_msg_data(sender);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_node_set_next_idx(n, 1);
__RAFT_APPEND_ENTRY(r, 100, 1, "aaa");
......@@ -2748,6 +3102,11 @@ void TestRaft_leader_updates_next_idx_on_send_ae(CuTest *tc)
CuAssertIntEquals(tc, 0,ae->prev_log_idx);
CuAssertIntEquals(tc, 1, ae->n_entries);
CuAssertIntEquals(tc, 2, raft_node_get_next_idx(n));
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_node_set_next_idx(n, 1);
__RAFT_APPEND_ENTRY(r, 101, 1, "bbb");
......@@ -2757,6 +3116,13 @@ void TestRaft_leader_updates_next_idx_on_send_ae(CuTest *tc)
CuAssertIntEquals(tc, 0,ae->prev_log_idx);
CuAssertIntEquals(tc, 2, ae->n_entries);
CuAssertIntEquals(tc, 3, raft_node_get_next_idx(n));
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
/* 5.3 */
......@@ -2779,8 +3145,16 @@ void TestRaft_leader_retries_appendentries_with_decremented_NextIdx_log_inconsis
/* receive appendentries messages */
raft_send_appendentries(r, raft_get_node(r, 2));
raft_appendentries_req_t * ae = sender_poll_msg_data(sender);
raft_appendentries_req_t *ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
/*
......@@ -2804,7 +3178,10 @@ void TestRaft_leader_append_entry_to_log_increases_idxno(CuTest * tc)
CuAssertTrue(tc, 0 == raft_get_log_count(r));
raft_recv_entry(r, ety, NULL);
raft_entry_release(ety);
CuAssertTrue(tc, 1 == raft_get_log_count(r));
raft_destroy(r);
}
#if 0
......@@ -2905,6 +3282,8 @@ void TestRaft_leader_recv_appendentries_response_increase_commit_idx_when_majori
CuAssertIntEquals(tc, 2, raft_get_commit_idx(r));
raft_periodic_internal(r, 1);
CuAssertIntEquals(tc, 2, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_set_has_sufficient_logs_for_node(
......@@ -2953,6 +3332,8 @@ void TestRaft_leader_recv_appendentries_response_set_has_sufficient_logs_for_nod
raft_recv_appendentries_response(r, node, &aer);
CuAssertIntEquals(tc, 1, has_sufficient_logs_flag);
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_fail_set_has_sufficient_logs_for_node_if_not_addition_committed(
......@@ -2996,6 +3377,8 @@ void TestRaft_leader_recv_appendentries_response_fail_set_has_sufficient_logs_fo
raft_node_set_voting(node, 0);
raft_recv_appendentries_response(r, node, &aer);
CuAssertIntEquals(tc, 0, has_sufficient_logs_flag);
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_increase_commit_idx_using_voting_nodes_majority(
......@@ -3043,6 +3426,8 @@ void TestRaft_leader_recv_appendentries_response_increase_commit_idx_using_votin
/* leader will now have majority followers who have appended this log */
raft_periodic_internal(r, 1);
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_duplicate_does_not_decrement_match_idx(
......@@ -3095,6 +3480,8 @@ void TestRaft_leader_recv_appendentries_response_duplicate_does_not_decrement_ma
aer.current_idx = 1;
raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer);
CuAssertIntEquals(tc, 2, raft_node_get_match_idx(raft_get_node(r, 2)));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_do_not_increase_commit_idx_because_of_old_terms_with_majority(
......@@ -3176,6 +3563,8 @@ void TestRaft_leader_recv_appendentries_response_do_not_increase_commit_idx_beca
CuAssertIntEquals(tc, 3, raft_get_commit_idx(r));
raft_periodic_internal(r, 1);
CuAssertIntEquals(tc, 3, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_jumps_to_lower_next_idx(
......@@ -3214,6 +3603,12 @@ void TestRaft_leader_recv_appendentries_response_jumps_to_lower_next_idx(
CuAssertIntEquals(tc, 4, ae->prev_log_term);
CuAssertIntEquals(tc, 4, ae->prev_log_idx);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
/* receive mock success responses */
memset(&aer, 0, sizeof(raft_appendentries_resp_t));
aer.term = 4;
......@@ -3230,6 +3625,12 @@ void TestRaft_leader_recv_appendentries_response_jumps_to_lower_next_idx(
/* since current_idx is 1, and we are up 5, if it reset next_idx correctly, we should have 4 entries */
CuAssertIntEquals(tc, 4, ae->n_entries);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
/* receive mock success responses */
memset(&aer, 0, sizeof(raft_appendentries_resp_t));
aer.term = 4;
......@@ -3238,6 +3639,8 @@ void TestRaft_leader_recv_appendentries_response_jumps_to_lower_next_idx(
CuAssertIntEquals(tc, 0, raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer));
// it's 6 and not 2 because the raft_send_appendentries() that is sent at end of recv_response send the rest
CuAssertIntEquals(tc, 6, raft_node_get_next_idx(node));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_retry_only_if_leader(CuTest * tc)
......@@ -3267,8 +3670,22 @@ void TestRaft_leader_recv_appendentries_response_retry_only_if_leader(CuTest * t
raft_send_appendentries(r, raft_get_node(r, 2));
raft_send_appendentries(r, raft_get_node(r, 3));
CuAssertTrue(tc, NULL != sender_poll_msg_data(sender));
CuAssertTrue(tc, NULL != sender_poll_msg_data(sender));
raft_appendentries_req_t *ae;
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_become_follower(r);
......@@ -3280,6 +3697,8 @@ void TestRaft_leader_recv_appendentries_response_retry_only_if_leader(CuTest * t
aer.current_idx = 1;
CuAssertTrue(tc, 0 == raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer));
CuAssertTrue(tc, NULL == sender_poll_msg_data(sender));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_without_node(CuTest *tc)
......@@ -3305,6 +3724,8 @@ void TestRaft_leader_recv_appendentries_response_without_node(CuTest *tc)
CuAssertIntEquals(tc, 0, raft_recv_appendentries_response(r, NULL, &aer));
/* Verify response was ignored and term is not 5000. */
CuAssertIntEquals(tc, 1, raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_leader_recv_snapshot_response_without_node(CuTest *tc)
......@@ -3333,6 +3754,8 @@ void TestRaft_leader_recv_snapshot_response_without_node(CuTest *tc)
CuAssertIntEquals(tc, 0, raft_recv_snapshot_response(r, NULL, &resp));
/* Verify response was ignored and term is not 5000. */
CuAssertIntEquals(tc, 1, raft_get_current_term(r));
raft_destroy(r);
}
void TestRaft_leader_recv_entry_resets_election_timeout(
......@@ -3351,7 +3774,10 @@ void TestRaft_leader_recv_entry_resets_election_timeout(
/* receive entry */
raft_entry_resp_t cr;
raft_recv_entry(r, mety, &cr);
raft_entry_release(mety);
CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r));
raft_destroy(r);
}
void TestRaft_leader_recv_entry_is_committed_returns_0_if_not_committed(CuTest * tc)
......@@ -3377,10 +3803,13 @@ void TestRaft_leader_recv_entry_is_committed_returns_0_if_not_committed(CuTest *
/* receive entry */
raft_entry_resp_t cr;
raft_recv_entry(r, mety, &cr);
raft_entry_release(mety);
CuAssertTrue(tc, 0 == raft_msg_entry_response_committed(r, &cr));
raft_set_commit_idx(r, 1);
CuAssertTrue(tc, 1 == raft_msg_entry_response_committed(r, &cr));
raft_destroy(r);
}
void TestRaft_leader_recv_entry_is_committed_returns_neg_1_if_invalidated(CuTest * tc)
......@@ -3406,6 +3835,8 @@ void TestRaft_leader_recv_entry_is_committed_returns_neg_1_if_invalidated(CuTest
/* receive entry */
raft_entry_resp_t cr;
raft_recv_entry(r, mety, &cr);
raft_entry_release(mety);
CuAssertTrue(tc, 0 == raft_msg_entry_response_committed(r, &cr));
CuAssertTrue(tc, cr.term == 1);
CuAssertTrue(tc, cr.idx == 1);
......@@ -3427,6 +3858,13 @@ void TestRaft_leader_recv_entry_is_committed_returns_neg_1_if_invalidated(CuTest
CuAssertTrue(tc, 1 == raft_get_current_idx(r));
CuAssertTrue(tc, 1 == raft_get_commit_idx(r));
CuAssertTrue(tc, -1 == raft_msg_entry_response_committed(r, &cr));
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
raft_destroy(r);
}
void TestRaft_leader_recv_entry_fails_if_prevlogidx_less_than_commit(CuTest * tc)
......@@ -3452,6 +3890,7 @@ void TestRaft_leader_recv_entry_fails_if_prevlogidx_less_than_commit(CuTest * tc
/* receive entry */
raft_entry_resp_t cr;
raft_recv_entry(r, mety, &cr);
raft_entry_release(mety);
CuAssertTrue(tc, 0 == raft_msg_entry_response_committed(r, &cr));
CuAssertTrue(tc, cr.term == 2);
CuAssertTrue(tc, cr.idx == 1);
......@@ -3472,6 +3911,13 @@ void TestRaft_leader_recv_entry_fails_if_prevlogidx_less_than_commit(CuTest * tc
ae.n_entries = 1;
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertIntEquals(tc, 0, aer.success);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
raft_destroy(r);
}
int backpressure(raft_server_t* raft, void* udata, raft_node_t* node)
......@@ -3510,11 +3956,14 @@ void TestRaft_leader_recv_entry_does_not_send_new_appendentries_to_slow_nodes(Cu
/* receive entry */
raft_entry_resp_t cr;
raft_recv_entry(r, mety, &cr);
raft_entry_release(mety);
/* check if the slow node got sent this appendentries */
raft_appendentries_req_t * ae;
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL == ae);
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_failure_does_not_set_node_nextid_to_0(
......@@ -3555,6 +4004,8 @@ void TestRaft_leader_recv_appendentries_response_failure_does_not_set_node_nexti
CuAssertIntEquals(tc, 2, raft_node_get_next_idx(p));
raft_recv_appendentries_response(r, p, &aer);
CuAssertIntEquals(tc, 2, raft_node_get_next_idx(p));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_increment_idx_of_node(
......@@ -3587,6 +4038,8 @@ void TestRaft_leader_recv_appendentries_response_increment_idx_of_node(
aer.current_idx = 0;
raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer);
CuAssertIntEquals(tc, 1, raft_node_get_next_idx(p));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_drop_message_if_term_is_old(
......@@ -3612,12 +4065,15 @@ void TestRaft_leader_recv_appendentries_response_drop_message_if_term_is_old(
CuAssertTrue(tc, 1 == raft_node_get_next_idx(p));
/* receive OLD mock success responses */
raft_appendentries_resp_t aer;
aer.term = 1;
aer.success = 1;
aer.current_idx = 1;
raft_appendentries_resp_t aer = {
.term = 1,
.success = 1,
.current_idx = 1
};
raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer);
CuAssertTrue(tc, 1 == raft_node_get_next_idx(p));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_steps_down_if_term_is_newer(
......@@ -3642,13 +4098,16 @@ void TestRaft_leader_recv_appendentries_response_steps_down_if_term_is_newer(
CuAssertTrue(tc, 1 == raft_node_get_next_idx(p));
/* receive NEW mock failed responses */
raft_appendentries_resp_t aer;
aer.term = 3;
aer.success = 0;
aer.current_idx = 2;
raft_appendentries_resp_t aer = {
.term = 3,
.success = 0,
.current_idx = 2
};
raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer);
CuAssertTrue(tc, 1 == raft_is_follower(r));
CuAssertTrue(tc, -1 == raft_get_leader_id(r));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_steps_down_if_newer(
......@@ -3684,6 +4143,8 @@ void TestRaft_leader_recv_appendentries_steps_down_if_newer(
* consider node 2 the leader. */
CuAssertTrue(tc, 1 == raft_is_follower(r));
CuAssertTrue(tc, 2 == raft_get_leader_id(r));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_steps_down_if_newer_term(
......@@ -3712,6 +4173,8 @@ void TestRaft_leader_recv_appendentries_steps_down_if_newer_term(
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 1 == raft_is_follower(r));
raft_destroy(r);
}
void TestRaft_leader_sends_empty_appendentries_every_request_timeout(
......@@ -3740,16 +4203,31 @@ void TestRaft_leader_sends_empty_appendentries_every_request_timeout(
raft_appendentries_req_t * ae;
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL == ae);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
/* force request timeout */
raft_periodic_internal(r, 501);
ae = sender_poll_msg_data(sender);
CuAssertTrue(tc, NULL != ae);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
/* TODO: If a server receives a request with a stale term number, it rejects the request. */
......@@ -3803,6 +4281,8 @@ void TestRaft_leader_recv_requestvote_responds_without_granting(CuTest * tc)
raft_recv_requestvote(r, raft_get_node(r, 3), &rv, &rvr);
CuAssertTrue(tc, 0 == rvr.vote_granted);
raft_destroy(r);
}
#if 0
......@@ -3892,6 +4372,8 @@ void TestRaft_leader_recv_entry_add_nonvoting_node_remove_and_revert(CuTest *tc)
CuAssertIntEquals(tc, 0, raft_delete_entry_from_idx(r, etyr.idx));
CuAssertIntEquals(tc, 1, raft_node_is_active(raft_get_node(r, 3)));
CuAssertIntEquals(tc, 0, raft_node_is_voting(raft_get_node(r, 3)));
raft_destroy(r);
}
void TestRaft_leader_recv_appendentries_response_set_has_sufficient_logs_after_voting_committed(
......@@ -3924,10 +4406,12 @@ void TestRaft_leader_recv_appendentries_response_set_has_sufficient_logs_after_v
ety->type = RAFT_LOGTYPE_ADD_NONVOTING_NODE;
raft_entry_resp_t etyr;
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, &etyr));
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "3");
ety->type = RAFT_LOGTYPE_ADD_NONVOTING_NODE;
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, &etyr));
raft_entry_release(ety);
raft_appendentries_resp_t aer = {
.term = 1, .success = 1, .current_idx = 2
......@@ -3941,6 +4425,7 @@ void TestRaft_leader_recv_appendentries_response_set_has_sufficient_logs_after_v
ety = __MAKE_ENTRY(3, 1, "3");
ety->type = RAFT_LOGTYPE_ADD_NODE;
raft_recv_entry(r, ety, &etyr);
raft_entry_release(ety);
/* we now get a response from node 2, but it's still behind */
raft_node_set_addition_committed(raft_get_node(r, 2), 1);
......@@ -3960,6 +4445,8 @@ void TestRaft_leader_recv_appendentries_response_set_has_sufficient_logs_after_v
CuAssertIntEquals(tc, 1, has_sufficient_logs_flag);
raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer);
CuAssertIntEquals(tc, 2, has_sufficient_logs_flag);
raft_destroy(r);
}
struct read_request_arg {
......@@ -4042,6 +4529,8 @@ void TestRaft_read_action_callback(
raft_periodic_internal(r, 1);
CuAssertIntEquals(tc, 1, ra.calls);
CuAssertIntEquals(tc, 0, ra.last_cb_safe);
raft_destroy(r);
}
void single_node_commits_noop_cb(void* arg, int can_read)
......@@ -4065,6 +4554,8 @@ void TestRaft_single_node_commits_noop(CuTest * tc)
CuAssertIntEquals(tc, 1, raft_get_commit_idx(r));
CuAssertStrEquals(tc, "success", str);
raft_destroy(r);
}
/*
......@@ -4105,6 +4596,8 @@ void TestRaft_server_recv_requestvote_with_transfer_node(CuTest * tc)
rv.prevote = 0;
raft_recv_requestvote(r, raft_get_node(r, 2), &rv, &rvr);
CuAssertTrue(tc, 1 == rvr.vote_granted);
raft_destroy(r);
}
/*
......@@ -4125,6 +4618,8 @@ void TestRaft_targeted_node_becomes_candidate_when_before_real_timeout_occurs(Cu
raft_timeout_now(r);
CuAssertTrue(tc, 1 == raft_is_candidate(r));
raft_destroy(r);
}
void quorum_msg_id_correctness_cb(void* arg, int can_read)
......@@ -4181,6 +4676,8 @@ void TestRaft_quorum_msg_id_correctness(CuTest * tc)
raft_node_set_match_msgid(raft_get_node(r, 3), 2);
raft_periodic_internal(r, 200);
CuAssertIntEquals(tc, 1, val);
raft_destroy(r);
}
int timeoutnow_sent = 0;
......@@ -4225,6 +4722,8 @@ void TestRaft_callback_timeoutnow_at_set_if_up_to_date(CuTest *tc)
ret = raft_transfer_leader(r, 2, 0);
CuAssertIntEquals(tc, 0, ret);
CuAssertTrue(tc, 1 == timeoutnow_sent);
raft_destroy(r);
}
void TestRaft_callback_timeoutnow_at_send_appendentries_response_if_up_to_date(CuTest *tc)
......@@ -4265,6 +4764,8 @@ void TestRaft_callback_timeoutnow_at_send_appendentries_response_if_up_to_date(C
/* Verify we won't send timeout now message twice. */
raft_recv_appendentries_response(r, raft_get_node(r, 2), &aer);
CuAssertTrue(tc, 1 == timeoutnow_sent);
raft_destroy(r);
}
void TestRaft_leader_steps_down_if_there_is_no_quorum(CuTest * tc)
......@@ -4317,6 +4818,8 @@ void TestRaft_leader_steps_down_if_there_is_no_quorum(CuTest * tc)
// No ack along quorum_timeout, leader will step down.
raft_periodic_internal(r, quorum_timeout + 1);
CuAssertTrue(tc, !raft_is_leader(r));
raft_destroy(r);
}
void TestRaft_vote_for_unknown_node(CuTest * tc)
......@@ -4413,6 +4916,11 @@ void TestRaft_unknown_node_can_become_leader(CuTest * tc)
CuAssertIntEquals(tc, raft_get_leader_id(r), req_append.leader_id);
CuAssertTrue(tc, resp.success == 1);
for (raft_index_t i = 0; i < req_append.n_entries; i++) {
raft_entry_release(req_append.entries[i]);
}
raft_free(req_append.entries);
// Send another req with incremented leader_commit to commit the addition
raft_appendentries_req_t req_commit = {
.term = 1,
......@@ -4457,6 +4965,11 @@ void TestRaft_unknown_node_can_become_leader(CuTest * tc)
CuAssertIntEquals(tc, raft_get_leader_id(r), req_append.leader_id);
CuAssertTrue(tc, resp.success == 1);
for (raft_index_t i = 0; i < req_add_node.n_entries; i++) {
raft_entry_release(req_add_node.entries[i]);
}
raft_free(req_add_node.entries);
raft_periodic_internal(r, 1000);
CuAssertIntEquals(tc, raft_get_leader_id(r), req_append.leader_id);
CuAssertTrue(tc, resp.success == 1);
......@@ -4489,6 +5002,7 @@ void TestRaft_removed_node_starts_election(CuTest * tc)
entry->type = RAFT_LOGTYPE_REMOVE_NODE;
raft_recv_entry(r, entry, &entry_resp);
raft_entry_release(entry);
CuAssertTrue(r, raft_is_leader(r));
CuAssertTrue(r, !raft_node_is_active(n1));
CuAssertTrue(r, raft_node_is_active(n2));
......@@ -4546,11 +5060,14 @@ void TestRaft_verify_append_entries_fields_are_set(CuTest * tc)
raft_append_entry(r, ety);
raft_append_entry(r, ety);
raft_append_entry(r, ety);
raft_entry_release(ety);
raft_set_current_term(r, 300);
raft_set_commit_idx(r, 4);
raft_node_set_next_idx(raft_get_node(r, 2), 2);
raft_send_appendentries_all(r);
raft_destroy(r);
}
void cb_notify_transfer_event(raft_server_t *raft, void *udata, raft_leader_transfer_e state)
......@@ -4590,6 +5107,8 @@ void Test_reset_transfer_leader(CuTest *tc)
CuAssertIntEquals(tc, 0, ret);
raft_periodic_internal(r, 2);
CuAssertIntEquals(tc, RAFT_LEADER_TRANSFER_TIMEOUT, state);
raft_destroy(r);
}
void Test_transfer_leader_success(CuTest *tc)
......@@ -4616,6 +5135,8 @@ void Test_transfer_leader_success(CuTest *tc)
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, RAFT_LEADER_TRANSFER_EXPECTED_LEADER, state);
raft_destroy(r);
}
void Test_transfer_leader_unexpected(CuTest *tc)
......@@ -4644,6 +5165,8 @@ void Test_transfer_leader_unexpected(CuTest *tc)
raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer);
CuAssertTrue(tc, 1 == aer.success);
CuAssertIntEquals(tc, RAFT_LEADER_TRANSFER_UNEXPECTED_LEADER, state);
raft_destroy(r);
}
void Test_transfer_leader_not_leader(CuTest *tc)
......@@ -4656,6 +5179,8 @@ void Test_transfer_leader_not_leader(CuTest *tc)
int ret = raft_transfer_leader(r, 3, 0);
CuAssertIntEquals(tc, RAFT_ERR_NOT_LEADER, ret);
raft_destroy(r);
}
void Test_transfer_automatic(CuTest *tc)
......@@ -4683,6 +5208,8 @@ void Test_transfer_automatic(CuTest *tc)
CuAssertIntEquals(tc, 0, ret);
CuAssertIntEquals(tc, 3, raft_get_transfer_leader(r));
raft_destroy(r);
}
void TestRaft_config(CuTest *tc)
......@@ -4722,6 +5249,8 @@ void TestRaft_config(CuTest *tc)
CuAssertIntEquals(tc, 0, raft_config(r, 1, RAFT_CONFIG_DISABLE_APPLY, 1));
CuAssertIntEquals(tc, 0, raft_config(r, 0, RAFT_CONFIG_DISABLE_APPLY, &tmp));
CuAssertIntEquals(tc, 1, val);
raft_destroy(r);
}
static int cb_send_ae(raft_server_t *raft, void *udata, raft_node_t *node,
......@@ -4777,6 +5306,8 @@ void TestRaft_limit_appendentries_size(CuTest *tc)
* 10 entries. */
raft_send_appendentries_all(r);
CuAssertIntEquals(tc, 20, appendentries_msg_count);
raft_destroy(r);
}
static int cb_sendmsg(raft_server_t *raft, void *udata, raft_node_t *node,
......@@ -4808,7 +5339,7 @@ void TestRaft_flush_sends_msg(CuTest *tc)
raft_set_current_term(r, 1);
raft_become_leader(r);
raft_recv_read_request(r, NULL, NULL);
raft_recv_read_request(r, read_request_dummy_cb, NULL);
/* Verify that we send appendentries if the next msgid of a node equals
* to the last read request's msgid. */
......@@ -4818,6 +5349,8 @@ void TestRaft_flush_sends_msg(CuTest *tc)
int msg_send = appendentries_msg_count;
raft_flush(r, 0);
CuAssertIntEquals(tc, msg_send + 1, appendentries_msg_count);
raft_destroy(r);
}
void TestRaft_recv_appendentries_does_not_change_next_idx(CuTest *tc)
......@@ -4860,6 +5393,8 @@ void TestRaft_recv_appendentries_does_not_change_next_idx(CuTest *tc)
CuAssertIntEquals(tc, 201, raft_node_get_next_idx(node));
CuAssertIntEquals(tc, 21, raft_node_get_next_msgid(node));
raft_destroy(r);
}
#define OPERATION_DURATION 10000 /* milliseconds */
......@@ -4916,6 +5451,8 @@ void TestRaft_apply_entry_timeout(CuTest *tc)
raft_exec_operations(r);
CuAssertIntEquals(tc, 0, raft_pending_operations(r));
CuAssertIntEquals(tc, 21, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void read_request(void *arg, int can_read)
......@@ -4965,6 +5502,8 @@ void TestRaft_apply_read_request_timeout(CuTest *tc)
raft_exec_operations(r);
CuAssertIntEquals(tc, 0, raft_pending_operations(r));
CuAssertIntEquals(tc, 0, remaining);
raft_destroy(r);
}
......@@ -5004,6 +5543,8 @@ void TestRaft_test_metadata_on_restart(CuTest *tc)
CuAssertIntEquals(tc, 0, raft_restore_metadata(r, test_term, test_vote));
CuAssertIntEquals(tc, 1, raft_get_current_term(r));
CuAssertIntEquals(tc, 10, raft_get_voted_for(r));
raft_destroy(r);
}
void TestRaft_rebuild_config_after_restart(CuTest *tc)
......@@ -5024,22 +5565,28 @@ void TestRaft_rebuild_config_after_restart(CuTest *tc)
raft_entry_req_t *ety = __MAKE_ENTRY(1, 1, "1");
ety->type = RAFT_LOGTYPE_ADD_NODE;
CuAssertTrue(tc, 0 == raft_recv_entry(r, ety, NULL));
raft_entry_release(ety);
raft_periodic_internal(r, 2000);
raft_entry_t *ety2 = __MAKE_ENTRY(2, 1, "2");
ety2->type = RAFT_LOGTYPE_ADD_NODE;
CuAssertTrue(tc, 0 == raft_recv_entry(r, ety2, NULL));
raft_entry_release(ety2);
raft_entry_t *ety3 = __MAKE_ENTRY(3, 1, "3");
ety3->type = RAFT_LOGTYPE_ADD_NONVOTING_NODE;
CuAssertTrue(tc, 0 == raft_recv_entry(r, ety3, NULL));
raft_entry_release(ety3);
/* Cluster has three nodes in the configuration now. A bit hacky but let's
* create another server and use first server's log implementation for the
* new server. We are just simulating the restart scenario. Normally, new
* server would read log entries from the disk. */
raft_server_t *r2 = raft_new();
raft_log_free(r2->log);
r2->log = raft_get_log(r);
r->log = NULL;
raft_set_callbacks(r2, &funcs, NULL);
raft_add_non_voting_node(r2, NULL, 1, 1);
......@@ -5057,6 +5604,9 @@ void TestRaft_rebuild_config_after_restart(CuTest *tc)
CuAssertIntEquals(tc, raft_node_is_active(n1), raft_node_is_active(n2));
CuAssertIntEquals(tc, raft_node_is_voting(n1), raft_node_is_voting(n2));
}
raft_destroy(r);
raft_destroy(r2);
}
void TestRaft_delete_configuration_change_entries(CuTest *tc)
......@@ -5084,6 +5634,7 @@ void TestRaft_delete_configuration_change_entries(CuTest *tc)
raft_entry_t *ety = __MAKE_ENTRY(1, 1, "3");
ety->type = RAFT_LOGTYPE_ADD_NONVOTING_NODE;
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, NULL));
raft_entry_release(ety);
/* If there idx is out of bounds, delete should return immediately. */
CuAssertIntEquals(tc, 0, raft_delete_entry_from_idx(r, 3));
......@@ -5092,6 +5643,7 @@ void TestRaft_delete_configuration_change_entries(CuTest *tc)
ety = __MAKE_ENTRY(1, 1, "3");
ety->type = RAFT_LOGTYPE_REMOVE_NODE;
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, NULL));
raft_entry_release(ety);
/* Another configuration change entry should be rejected. */
ety = __MAKE_ENTRY(1, 1, "4");
......@@ -5112,6 +5664,9 @@ void TestRaft_delete_configuration_change_entries(CuTest *tc)
/* Configuration change entry should be accepted now. */
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, NULL));
raft_entry_release(ety);
raft_destroy(r);
}
static int fail_sequence = 0;
......@@ -5151,6 +5706,8 @@ void TestRaft_propagate_persist_metadata_failure(CuTest *tc)
fail_sequence = 0;
e = raft_begin_load_snapshot(r, 2, 10);
CuAssertIntEquals(tc, e, -1);
raft_destroy(r);
}
void TestRaft_reject_config_change_before_log_replay(CuTest *tc)
......@@ -5168,11 +5725,15 @@ void TestRaft_reject_config_change_before_log_replay(CuTest *tc)
raft_entry_req_t *ety = __MAKE_ENTRY(1, 1, "1");
ety->type = RAFT_LOGTYPE_ADD_NODE;
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, NULL));
raft_entry_release(ety);
raft_periodic_internal(r, 2000);
/* To simulate restart, restore log with the first node's data.*/
raft_server_t *r2 = raft_new();
raft_log_free(r2->log);
r2->log = raft_get_log(r);
r->log = NULL;
raft_set_callbacks(r2, &funcs, NULL);
raft_add_non_voting_node(r2, NULL, 1, 1);
......@@ -5200,6 +5761,10 @@ void TestRaft_reject_config_change_before_log_replay(CuTest *tc)
CuAssertIntEquals(tc, 0, raft_recv_entry(r2, ety, NULL));
CuAssertIntEquals(tc, RAFT_ERR_ONE_VOTING_CHANGE_ONLY,
raft_recv_entry(r2, ety, NULL));
raft_entry_release(ety);
raft_destroy(r);
raft_destroy(r2);
}
int main(void)
......@@ -5364,5 +5929,10 @@ int main(void)
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
return suite->failCount == 0 ? 0 : 1;
int rc = suite->failCount == 0 ? 0 : 1;
CuStringFree(output);
CuSuiteFree(suite);
return rc;
}
......@@ -226,14 +226,19 @@ void TestRaft_leader_begin_snapshot_fails_if_no_logs_to_compact(CuTest * tc)
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
CuAssertIntEquals(tc, -1, raft_begin_snapshot(r));
raft_set_commit_idx(r, 1);
CuAssertIntEquals(tc, 0, raft_begin_snapshot(r));
raft_destroy(r);
}
void TestRaft_leader_will_not_apply_entry_if_snapshot_is_in_progress(CuTest * tc)
......@@ -260,6 +265,7 @@ void TestRaft_leader_will_not_apply_entry_if_snapshot_is_in_progress(CuTest * tc
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 1);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
......@@ -268,6 +274,8 @@ void TestRaft_leader_will_not_apply_entry_if_snapshot_is_in_progress(CuTest * tc
raft_set_commit_idx(r, 2);
CuAssertIntEquals(tc, -1, raft_apply_entry(r));
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_leader_snapshot_end_fails_if_snapshot_not_in_progress(CuTest * tc)
......@@ -286,6 +294,8 @@ void TestRaft_leader_snapshot_end_fails_if_snapshot_not_in_progress(CuTest * tc)
raft_set_state(r, RAFT_STATE_LEADER);
CuAssertIntEquals(tc, 0, raft_get_log_count(r));
CuAssertIntEquals(tc, -1, raft_end_snapshot(r));
raft_destroy(r);
}
void TestRaft_leader_snapshot_begin_fails_if_less_than_2_logs_to_compact(CuTest * tc)
......@@ -311,9 +321,12 @@ void TestRaft_leader_snapshot_begin_fails_if_less_than_2_logs_to_compact(CuTest
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 1);
CuAssertIntEquals(tc, 1, raft_get_log_count(r));
CuAssertIntEquals(tc, -1, raft_begin_snapshot(r));
raft_destroy(r);
}
void TestRaft_leader_snapshot_end_succeeds_if_log_compacted(CuTest * tc)
......@@ -341,12 +354,18 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted(CuTest * tc)
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(3, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 2);
CuAssertIntEquals(tc, 3, raft_get_log_count(r));
CuAssertIntEquals(tc, 2, raft_get_num_snapshottable_logs(r));
CuAssertIntEquals(tc, 1, raft_get_last_log_term(r));
......@@ -365,6 +384,7 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted(CuTest * tc)
/* snapshot doesn't work if only one entry to snapshot, so add another one */
ety = __MAKE_ENTRY(4, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 4);
CuAssertIntEquals(tc, 0, raft_periodic_internal(r, 1000));
......@@ -379,6 +399,8 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted(CuTest * tc)
CuAssertIntEquals(tc, 4, raft_get_commit_idx(r));
CuAssertIntEquals(tc, 4, raft_get_last_applied_idx(r));
CuAssertIntEquals(tc, 1, raft_get_last_log_term(r));
raft_destroy(r);
}
void TestRaft_leader_snapshot_end_succeeds_if_log_compacted2(CuTest * tc)
......@@ -406,10 +428,16 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted2(CuTest * tc)
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(3, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 2);
CuAssertIntEquals(tc, 3, raft_get_log_count(r));
CuAssertIntEquals(tc, 2, raft_get_num_snapshottable_logs(r));
......@@ -421,6 +449,8 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted2(CuTest * tc)
CuAssertIntEquals(tc, 2, raft_get_commit_idx(r));
CuAssertIntEquals(tc, 2, raft_get_last_applied_idx(r));
CuAssertIntEquals(tc, 0, raft_periodic_internal(r, 1000));
raft_destroy(r);
}
void TestRaft_joinee_needs_to_get_snapshot(CuTest * tc)
......@@ -446,8 +476,12 @@ void TestRaft_joinee_needs_to_get_snapshot(CuTest * tc)
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 1);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
CuAssertIntEquals(tc, 1, raft_get_num_snapshottable_logs(r));
......@@ -456,6 +490,8 @@ void TestRaft_joinee_needs_to_get_snapshot(CuTest * tc)
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
CuAssertIntEquals(tc, -1, raft_apply_entry(r));
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
raft_destroy(r);
}
void TestRaft_follower_load_from_snapshot(CuTest * tc)
......@@ -472,9 +508,6 @@ void TestRaft_follower_load_from_snapshot(CuTest * tc)
raft_set_state(r, RAFT_STATE_FOLLOWER);
CuAssertIntEquals(tc, 0, raft_get_log_count(r));
/* entry message */
raft_entry_req_t *ety = __MAKE_ENTRY(1, 1, "entry");
CuAssertIntEquals(tc, 0, raft_get_log_count(r));
CuAssertIntEquals(tc, 0, raft_begin_load_snapshot(r, 5, 5));
CuAssertIntEquals(tc, 0, raft_end_load_snapshot(r));
......@@ -486,13 +519,19 @@ void TestRaft_follower_load_from_snapshot(CuTest * tc)
CuAssertIntEquals(tc, 0, raft_periodic_internal(r, 1000));
/* current idx means snapshot was unnecessary */
ety = __MAKE_ENTRY(2, 1, "entry");
raft_entry_t *ety = __MAKE_ENTRY(2, 1, "entry");
raft_append_entry(r, ety);
raft_entry_release(ety);
ety = __MAKE_ENTRY(3, 1, "entry");
raft_append_entry(r, ety);
raft_entry_release(ety);
raft_set_commit_idx(r, 7);
CuAssertIntEquals(tc, RAFT_ERR_MISUSE, raft_begin_load_snapshot(r, 6, 5));
CuAssertIntEquals(tc, 7, raft_get_commit_idx(r));
raft_destroy(r);
}
void TestRaft_follower_load_from_snapshot_fails_if_term_is_0(CuTest * tc)
......@@ -509,6 +548,8 @@ void TestRaft_follower_load_from_snapshot_fails_if_term_is_0(CuTest * tc)
raft_set_state(r, RAFT_STATE_FOLLOWER);
CuAssertIntEquals(tc, 0, raft_get_log_count(r));
CuAssertIntEquals(tc, RAFT_ERR_MISUSE, raft_begin_load_snapshot(r, 0, 5));
raft_destroy(r);
}
void TestRaft_follower_load_from_snapshot_fails_if_already_loaded(CuTest * tc)
......@@ -534,6 +575,8 @@ void TestRaft_follower_load_from_snapshot_fails_if_already_loaded(CuTest * tc)
CuAssertIntEquals(tc, 5, raft_get_last_applied_idx(r));
CuAssertIntEquals(tc, RAFT_ERR_SNAPSHOT_ALREADY_LOADED, raft_begin_load_snapshot(r, 5, 5));
raft_destroy(r);
}
void TestRaft_follower_load_from_snapshot_does_not_break_cluster_safety(CuTest * tc)
......@@ -558,6 +601,8 @@ void TestRaft_follower_load_from_snapshot_does_not_break_cluster_safety(CuTest *
__RAFT_APPEND_ENTRY(r, 3, 1, "entry");
CuAssertIntEquals(tc, RAFT_ERR_MISUSE, raft_begin_load_snapshot(r, 2, 2));
raft_destroy(r);
}
void TestRaft_follower_load_from_snapshot_fails_if_log_is_newer(CuTest * tc)
......@@ -577,6 +622,8 @@ void TestRaft_follower_load_from_snapshot_fails_if_log_is_newer(CuTest * tc)
raft_set_last_applied_idx(r, 5);
CuAssertIntEquals(tc, RAFT_ERR_MISUSE, raft_begin_load_snapshot(r, 2, 2));
raft_destroy(r);
}
void TestRaft_leader_sends_snapshot_when_node_next_index_was_compacted(CuTest* tc)
......@@ -637,6 +684,8 @@ void TestRaft_leader_sends_snapshot_when_node_next_index_was_compacted(CuTest* t
CuAssertIntEquals(tc, 3, ae.term);
CuAssertIntEquals(tc, 3, ae.prev_log_idx);
CuAssertIntEquals(tc, 2, ae.prev_log_term);
raft_destroy(r);
}
void TestRaft_recv_entry_fails_if_snapshot_in_progress(CuTest* tc)
......@@ -662,8 +711,11 @@ void TestRaft_recv_entry_fails_if_snapshot_in_progress(CuTest* tc)
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
raft_set_commit_idx(r, 1);
......@@ -672,6 +724,9 @@ void TestRaft_recv_entry_fails_if_snapshot_in_progress(CuTest* tc)
ety = __MAKE_ENTRY(3, 1, "entry");
ety->type = RAFT_LOGTYPE_ADD_NODE;
CuAssertIntEquals(tc, RAFT_ERR_SNAPSHOT_IN_PROGRESS, raft_recv_entry(r, ety, &cr));
raft_entry_release(ety);
raft_destroy(r);
}
void TestRaft_recv_entry_succeeds_if_snapshot_nonblocking_apply_is_set(CuTest* tc)
......@@ -697,8 +752,11 @@ void TestRaft_recv_entry_succeeds_if_snapshot_nonblocking_apply_is_set(CuTest* t
/* receive entry */
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
raft_set_commit_idx(r, 1);
......@@ -709,6 +767,9 @@ void TestRaft_recv_entry_succeeds_if_snapshot_nonblocking_apply_is_set(CuTest* t
ety = __MAKE_ENTRY(3, 1, "entry");
ety->type = RAFT_LOGTYPE_ADD_NODE;
CuAssertIntEquals(tc, 0, raft_recv_entry(r, ety, &cr));
raft_entry_release(ety);
raft_destroy(r);
}
......@@ -740,6 +801,13 @@ void TestRaft_follower_recv_appendentries_is_successful_when_previous_log_idx_eq
ae.n_entries = 1;
CuAssertIntEquals(tc, 0, raft_recv_appendentries(r, raft_get_node(r, 2), &ae, &aer));
CuAssertIntEquals(tc, 1, aer.success);
for (raft_index_t i = 0; i < ae.n_entries; i++) {
raft_entry_release(ae.entries[i]);
}
raft_free(ae.entries);
raft_destroy(r);
}
void TestRaft_leader_sends_appendentries_with_correct_prev_log_idx_when_snapshotted(
......@@ -775,6 +843,14 @@ void TestRaft_leader_sends_appendentries_with_correct_prev_log_idx_when_snapshot
CuAssertTrue(tc, NULL != ae);
CuAssertIntEquals(tc, 2, ae->prev_log_term);
CuAssertIntEquals(tc, 4, ae->prev_log_idx);
for (raft_index_t i = 0; i < ae->n_entries; i++) {
raft_entry_release(ae->entries[i]);
}
raft_free(ae->entries);
raft_free(ae);
raft_destroy(r);
}
void TestRaft_cancel_snapshot_restores_state(CuTest* tc)
......@@ -798,9 +874,11 @@ void TestRaft_cancel_snapshot_restores_state(CuTest* tc)
/* single entry */
raft_entry_req_t *ety = __MAKE_ENTRY(1, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(2, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
raft_set_commit_idx(r, 2);
CuAssertIntEquals(tc, 0, raft_begin_snapshot(r));
......@@ -809,8 +887,12 @@ void TestRaft_cancel_snapshot_restores_state(CuTest* tc)
/* more entries */
ety = __MAKE_ENTRY(3, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
ety = __MAKE_ENTRY(4, 1, "entry");
raft_recv_entry(r, ety, &cr);
raft_entry_release(ety);
CuAssertIntEquals(tc, 2, raft_get_log_count(r));
CuAssertIntEquals(tc, 2, raft_get_snapshot_last_idx(r));
......@@ -823,6 +905,8 @@ void TestRaft_cancel_snapshot_restores_state(CuTest* tc)
/* snapshot no longer in progress, index must not have changed */
CuAssertIntEquals(tc, 0, raft_snapshot_is_in_progress(r));
CuAssertIntEquals(tc, 2, raft_get_snapshot_last_idx(r));
raft_destroy(r);
}
void TestRaft_leader_sends_snapshot_if_log_was_compacted(CuTest* tc)
......@@ -875,13 +959,16 @@ void TestRaft_leader_sends_snapshot_if_log_was_compacted(CuTest* tc)
raft_node_set_match_idx(node, 1);
raft_node_set_next_idx(node, 2);
raft_appendentries_resp_t aer;
aer.term = 1;
aer.success = 0;
aer.current_idx = 1;
raft_appendentries_resp_t aer = {
.term = 1,
.success = 0,
.current_idx = 1
};
raft_recv_appendentries_response(r, node, &aer);
CuAssertIntEquals(tc, 1, send_snapshot_count);
raft_destroy(r);
}
void TestRaft_clear_snapshot_on_leader_change(CuTest * tc)
......@@ -922,6 +1009,8 @@ void TestRaft_clear_snapshot_on_leader_change(CuTest * tc)
raft_recv_snapshot(r, NULL, &msg, &resp);
CuAssertIntEquals(tc, 1, data.clear);
CuAssertIntEquals(tc, 2, data.store_chunk);
raft_destroy(r);
}
void TestRaft_reject_wrong_offset(CuTest * tc)
......@@ -962,6 +1051,8 @@ void TestRaft_reject_wrong_offset(CuTest * tc)
CuAssertIntEquals(tc, 0, resp.success);
CuAssertIntEquals(tc, 50, resp.offset);
raft_destroy(r);
}
void TestRaft_set_last_chunk_on_duplicate(CuTest * tc)
......@@ -1014,6 +1105,8 @@ void TestRaft_set_last_chunk_on_duplicate(CuTest * tc)
CuAssertIntEquals(tc, 1, resp.success);
CuAssertIntEquals(tc, 1, resp.last_chunk);
raft_destroy(r);
}
void TestRaft_set_last_chunk_if_log_is_more_advanced(CuTest * tc)
......@@ -1059,6 +1152,8 @@ void TestRaft_set_last_chunk_if_log_is_more_advanced(CuTest * tc)
CuAssertIntEquals(tc, 0, data.load);
CuAssertIntEquals(tc, 1, resp.success);
CuAssertIntEquals(tc, 1, resp.last_chunk);
raft_destroy(r);
}
void TestRaft_report_fail_on_load_snapshot_error(CuTest * tc)
......@@ -1147,6 +1242,8 @@ void TestRaft_report_fail_on_load_snapshot_error(CuTest * tc)
CuAssertIntEquals(tc, 1, resp.success);
CuAssertIntEquals(tc, 80, resp.offset);
CuAssertIntEquals(tc, 1, resp.last_chunk);
raft_destroy(r);
}
void TestRaft_restore_after_restart(CuTest * tc)
......@@ -1159,11 +1256,15 @@ void TestRaft_restore_after_restart(CuTest * tc)
CuAssertIntEquals(tc, RAFT_ERR_MISUSE, raft_restore_snapshot(r, -1, 3));
CuAssertIntEquals(tc, RAFT_ERR_MISUSE, raft_restore_snapshot(r, 11, 5));
raft_destroy(r);
r = raft_new();
raft_add_node(r, NULL, 1, 1);
/* Restore should work on start-up */
CuAssertIntEquals(tc, 0, raft_restore_snapshot(r, 11, 5));
raft_destroy(r);
}
int main(void)
......@@ -1201,5 +1302,10 @@ int main(void)
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
return suite->failCount == 0 ? 0 : 1;
int rc = suite->failCount == 0 ? 0 : 1;
CuStringFree(output);
CuSuiteFree(suite);
return rc;
}
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