forked from github/server
add tests for quicklist. Fix the inevitable bug.
This commit is contained in:
parent
1cae5e2283
commit
16d86413d5
3 changed files with 128 additions and 3 deletions
|
@ -99,7 +99,7 @@ int ql_insert(quicklist ** qlp, int index, void * data) {
|
|||
ql->next = qn;
|
||||
qn->num_elements = QL_LIMIT;
|
||||
ql->num_elements -= QL_LIMIT;
|
||||
memcpy(qn->elements, ql->elements+ql->num_elements-QL_LIMIT, QL_LIMIT*sizeof(void*));
|
||||
memcpy(qn->elements, ql->elements+ql->num_elements, QL_LIMIT*sizeof(void*));
|
||||
if (index<=ql->num_elements) {
|
||||
return ql_insert(qlp, index, data);
|
||||
} else {
|
||||
|
@ -113,3 +113,35 @@ int ql_insert(quicklist ** qlp, int index, void * data) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ql_foreach(struct quicklist * ql, void (*cb)(void *))
|
||||
{
|
||||
for (;ql;ql=ql->next) {
|
||||
int i;
|
||||
for (i=0;i!=ql->num_elements;++i) {
|
||||
cb(ql->elements[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ql_advance(struct quicklist ** iterator, int * index, int stride)
|
||||
{
|
||||
quicklist * ql = *iterator;
|
||||
int i = *index;
|
||||
if (!ql || i<0 || stride<0) {
|
||||
return ERANGE;
|
||||
} else if (i + stride<ql->num_elements) {
|
||||
*index = i + stride;
|
||||
return 0;
|
||||
} else {
|
||||
*index = i - ql->num_elements + stride;
|
||||
*iterator = ql->next;
|
||||
return ql_advance(iterator, index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ql_free(struct quicklist * ql)
|
||||
{
|
||||
if (ql->next) ql_free(ql->next);
|
||||
free(ql);
|
||||
}
|
||||
|
|
|
@ -22,13 +22,15 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/* see http://en.wikipedia.org/wiki/Unrolled_linked_list */
|
||||
struct quicklist;
|
||||
typedef struct quicklist quicklist;
|
||||
void * ql_get(struct quicklist * ql, int index);
|
||||
int ql_length(const struct quicklist * ql);
|
||||
void ql_push(struct quicklist ** qlp, void * data);
|
||||
int ql_delete(struct quicklist ** qlp, int index);
|
||||
int ql_insert(struct quicklist ** qlp, int index, void * data);
|
||||
|
||||
void ql_foreach(struct quicklist * ql, void (*cb)(void *));
|
||||
int ql_advance(struct quicklist ** iterator, int * index, int stride);
|
||||
void ql_free(struct quicklist * ql);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
91
src/util/quicklist_test.c
Normal file
91
src/util/quicklist_test.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <cutest/CuTest.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "quicklist.h"
|
||||
|
||||
static const char * hello = "Hello World";
|
||||
|
||||
static void test_insert(CuTest * tc) {
|
||||
struct quicklist * ql = NULL;
|
||||
int i;
|
||||
for (i=0;i!=32;++i) {
|
||||
CuAssertIntEquals(tc, i, ql_length(ql));
|
||||
ql_insert(&ql, 0, (void*)i);
|
||||
}
|
||||
for (i=0;i!=32;++i) {
|
||||
CuAssertIntEquals(tc, 31-i, (int)ql_get(ql, i));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_advance(CuTest * tc) {
|
||||
struct quicklist * ql = NULL, *qli;
|
||||
int i, n = 31;
|
||||
for (i=0;i!=32;++i) {
|
||||
ql_insert(&ql, 0, (void*)i);
|
||||
}
|
||||
for (i=0,qli=ql;qli;ql_advance(&qli, &i, 1),n--) {
|
||||
int g = (int)ql_get(qli, i);
|
||||
CuAssertIntEquals(tc, n, g);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_push(CuTest * tc) {
|
||||
struct quicklist * ql = NULL;
|
||||
CuAssertIntEquals(tc, 0, ql_length(ql));
|
||||
ql_push(&ql, (void*)hello);
|
||||
CuAssertIntEquals(tc, 1, ql_length(ql));
|
||||
CuAssertStrEquals(tc, "Hello World", (const char *)ql_get(ql, 0));
|
||||
ql_delete(&ql, 0);
|
||||
CuAssertPtrEquals(tc, 0, ql);
|
||||
}
|
||||
|
||||
static void test_delete_edgecases(CuTest * tc) {
|
||||
struct quicklist * ql = NULL;
|
||||
ql_delete(&ql, 0);
|
||||
CuAssertPtrEquals(tc, 0, ql);
|
||||
ql_push(&ql, (void*)hello);
|
||||
ql_delete(&ql, -1);
|
||||
ql_delete(&ql, 32);
|
||||
CuAssertIntEquals(tc, 1, ql_length(ql));
|
||||
}
|
||||
|
||||
static void test_insert_many(CuTest * tc) {
|
||||
struct quicklist * ql = NULL;
|
||||
int i;
|
||||
for (i=0;i!=32;++i) {
|
||||
ql_push(&ql, (void*)i);
|
||||
}
|
||||
for (i=0;i!=32;++i) {
|
||||
CuAssertIntEquals(tc, 32-i, ql_length(ql));
|
||||
CuAssertIntEquals(tc, i, (int)ql_get(ql, 0));
|
||||
CuAssertIntEquals(tc, 31, (int)ql_get(ql, ql_length(ql)-1));
|
||||
ql_delete(&ql, 0);
|
||||
}
|
||||
CuAssertPtrEquals(tc, 0, ql);
|
||||
}
|
||||
|
||||
static void test_delete_rand(CuTest * tc) {
|
||||
struct quicklist * ql = NULL;
|
||||
int i;
|
||||
for (i=0;i!=32;++i) {
|
||||
ql_push(&ql, (void*)i);
|
||||
}
|
||||
CuAssertIntEquals(tc, 32, ql_length(ql));
|
||||
ql_delete(&ql, 0);
|
||||
CuAssertIntEquals(tc, 1, (int)ql_get(ql, 0));
|
||||
CuAssertIntEquals(tc, 31, ql_length(ql));
|
||||
ql_delete(&ql, 30);
|
||||
CuAssertIntEquals(tc, 30, ql_length(ql));
|
||||
}
|
||||
|
||||
CuSuite* get_quicklist_suite(void)
|
||||
{
|
||||
CuSuite* suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_advance);
|
||||
SUITE_ADD_TEST(suite, test_push);
|
||||
SUITE_ADD_TEST(suite, test_insert);
|
||||
SUITE_ADD_TEST(suite, test_insert_many);
|
||||
SUITE_ADD_TEST(suite, test_delete_rand);
|
||||
SUITE_ADD_TEST(suite, test_delete_edgecases);
|
||||
return suite;
|
||||
}
|
Loading…
Reference in a new issue