209 lines
4.4 KiB
C
209 lines
4.4 KiB
C
|
#include "test/jemalloc_test.h"
|
||
|
|
||
|
/* Number of ring entries, in [2..26]. */
|
||
|
#define NENTRIES 9
|
||
|
|
||
|
typedef struct list_s list_t;
|
||
|
typedef ql_head(list_t) list_head_t;
|
||
|
|
||
|
struct list_s {
|
||
|
ql_elm(list_t) link;
|
||
|
char id;
|
||
|
};
|
||
|
|
||
|
static void
|
||
|
test_empty_list(list_head_t *head)
|
||
|
{
|
||
|
list_t *t;
|
||
|
unsigned i;
|
||
|
|
||
|
assert_ptr_null(ql_first(head), "Unexpected element for empty list");
|
||
|
assert_ptr_null(ql_last(head, link),
|
||
|
"Unexpected element for empty list");
|
||
|
|
||
|
i = 0;
|
||
|
ql_foreach(t, head, link) {
|
||
|
i++;
|
||
|
}
|
||
|
assert_u_eq(i, 0, "Unexpected element for empty list");
|
||
|
|
||
|
i = 0;
|
||
|
ql_reverse_foreach(t, head, link) {
|
||
|
i++;
|
||
|
}
|
||
|
assert_u_eq(i, 0, "Unexpected element for empty list");
|
||
|
}
|
||
|
|
||
|
TEST_BEGIN(test_ql_empty)
|
||
|
{
|
||
|
list_head_t head;
|
||
|
|
||
|
ql_new(&head);
|
||
|
test_empty_list(&head);
|
||
|
}
|
||
|
TEST_END
|
||
|
|
||
|
static void
|
||
|
init_entries(list_t *entries, unsigned nentries)
|
||
|
{
|
||
|
unsigned i;
|
||
|
|
||
|
for (i = 0; i < nentries; i++) {
|
||
|
entries[i].id = 'a' + i;
|
||
|
ql_elm_new(&entries[i], link);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_entries_list(list_head_t *head, list_t *entries, unsigned nentries)
|
||
|
{
|
||
|
list_t *t;
|
||
|
unsigned i;
|
||
|
|
||
|
assert_c_eq(ql_first(head)->id, entries[0].id, "Element id mismatch");
|
||
|
assert_c_eq(ql_last(head, link)->id, entries[nentries-1].id,
|
||
|
"Element id mismatch");
|
||
|
|
||
|
i = 0;
|
||
|
ql_foreach(t, head, link) {
|
||
|
assert_c_eq(t->id, entries[i].id, "Element id mismatch");
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
i = 0;
|
||
|
ql_reverse_foreach(t, head, link) {
|
||
|
assert_c_eq(t->id, entries[nentries-i-1].id,
|
||
|
"Element id mismatch");
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < nentries-1; i++) {
|
||
|
t = ql_next(head, &entries[i], link);
|
||
|
assert_c_eq(t->id, entries[i+1].id, "Element id mismatch");
|
||
|
}
|
||
|
assert_ptr_null(ql_next(head, &entries[nentries-1], link),
|
||
|
"Unexpected element");
|
||
|
|
||
|
assert_ptr_null(ql_prev(head, &entries[0], link), "Unexpected element");
|
||
|
for (i = 1; i < nentries; i++) {
|
||
|
t = ql_prev(head, &entries[i], link);
|
||
|
assert_c_eq(t->id, entries[i-1].id, "Element id mismatch");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TEST_BEGIN(test_ql_tail_insert)
|
||
|
{
|
||
|
list_head_t head;
|
||
|
list_t entries[NENTRIES];
|
||
|
unsigned i;
|
||
|
|
||
|
ql_new(&head);
|
||
|
init_entries(entries, sizeof(entries)/sizeof(list_t));
|
||
|
for (i = 0; i < NENTRIES; i++)
|
||
|
ql_tail_insert(&head, &entries[i], link);
|
||
|
|
||
|
test_entries_list(&head, entries, NENTRIES);
|
||
|
}
|
||
|
TEST_END
|
||
|
|
||
|
TEST_BEGIN(test_ql_tail_remove)
|
||
|
{
|
||
|
list_head_t head;
|
||
|
list_t entries[NENTRIES];
|
||
|
unsigned i;
|
||
|
|
||
|
ql_new(&head);
|
||
|
init_entries(entries, sizeof(entries)/sizeof(list_t));
|
||
|
for (i = 0; i < NENTRIES; i++)
|
||
|
ql_tail_insert(&head, &entries[i], link);
|
||
|
|
||
|
for (i = 0; i < NENTRIES; i++) {
|
||
|
test_entries_list(&head, entries, NENTRIES-i);
|
||
|
ql_tail_remove(&head, list_t, link);
|
||
|
}
|
||
|
test_empty_list(&head);
|
||
|
}
|
||
|
TEST_END
|
||
|
|
||
|
TEST_BEGIN(test_ql_head_insert)
|
||
|
{
|
||
|
list_head_t head;
|
||
|
list_t entries[NENTRIES];
|
||
|
unsigned i;
|
||
|
|
||
|
ql_new(&head);
|
||
|
init_entries(entries, sizeof(entries)/sizeof(list_t));
|
||
|
for (i = 0; i < NENTRIES; i++)
|
||
|
ql_head_insert(&head, &entries[NENTRIES-i-1], link);
|
||
|
|
||
|
test_entries_list(&head, entries, NENTRIES);
|
||
|
}
|
||
|
TEST_END
|
||
|
|
||
|
TEST_BEGIN(test_ql_head_remove)
|
||
|
{
|
||
|
list_head_t head;
|
||
|
list_t entries[NENTRIES];
|
||
|
unsigned i;
|
||
|
|
||
|
ql_new(&head);
|
||
|
init_entries(entries, sizeof(entries)/sizeof(list_t));
|
||
|
for (i = 0; i < NENTRIES; i++)
|
||
|
ql_head_insert(&head, &entries[NENTRIES-i-1], link);
|
||
|
|
||
|
for (i = 0; i < NENTRIES; i++) {
|
||
|
test_entries_list(&head, &entries[i], NENTRIES-i);
|
||
|
ql_head_remove(&head, list_t, link);
|
||
|
}
|
||
|
test_empty_list(&head);
|
||
|
}
|
||
|
TEST_END
|
||
|
|
||
|
TEST_BEGIN(test_ql_insert)
|
||
|
{
|
||
|
list_head_t head;
|
||
|
list_t entries[8];
|
||
|
list_t *a, *b, *c, *d, *e, *f, *g, *h;
|
||
|
|
||
|
ql_new(&head);
|
||
|
init_entries(entries, sizeof(entries)/sizeof(list_t));
|
||
|
a = &entries[0];
|
||
|
b = &entries[1];
|
||
|
c = &entries[2];
|
||
|
d = &entries[3];
|
||
|
e = &entries[4];
|
||
|
f = &entries[5];
|
||
|
g = &entries[6];
|
||
|
h = &entries[7];
|
||
|
|
||
|
/*
|
||
|
* ql_remove(), ql_before_insert(), and ql_after_insert() are used
|
||
|
* internally by other macros that are already tested, so there's no
|
||
|
* need to test them completely. However, insertion/deletion from the
|
||
|
* middle of lists is not otherwise tested; do so here.
|
||
|
*/
|
||
|
ql_tail_insert(&head, f, link);
|
||
|
ql_before_insert(&head, f, b, link);
|
||
|
ql_before_insert(&head, f, c, link);
|
||
|
ql_after_insert(f, h, link);
|
||
|
ql_after_insert(f, g, link);
|
||
|
ql_before_insert(&head, b, a, link);
|
||
|
ql_after_insert(c, d, link);
|
||
|
ql_before_insert(&head, f, e, link);
|
||
|
|
||
|
test_entries_list(&head, entries, sizeof(entries)/sizeof(list_t));
|
||
|
}
|
||
|
TEST_END
|
||
|
|
||
|
int
|
||
|
main(void)
|
||
|
{
|
||
|
return (test(
|
||
|
test_ql_empty,
|
||
|
test_ql_tail_insert,
|
||
|
test_ql_tail_remove,
|
||
|
test_ql_head_insert,
|
||
|
test_ql_head_remove,
|
||
|
test_ql_insert));
|
||
|
}
|