add tests for quicklist. Fix the inevitable bug.

This commit is contained in:
Enno Rehling 2011-02-23 23:22:31 -08:00
parent 1cae5e2283
commit 16d86413d5
3 changed files with 128 additions and 3 deletions

View file

@ -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);
}

View file

@ -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
View 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;
}