--- /dev/null
+#include <freeradius-devel/util/acutest.h>
+
+#include "dcursor.c"
+
+/*
+ * A repeat of the tests in dcursor_tests.c, but using
+ * type specific dcursors
+ */
+
+FR_DLIST_TYPES(test_list);
+
+typedef struct {
+ char const *name;
+ FR_DLIST_ENTRY(test_list) entry;
+} test_item_t;
+
+FR_DLIST_FUNCS(test_list, test_item_t, entry);
+
+FR_DCURSOR_DLIST_TYPES(test_dcursor, test_list, test_item_t);
+
+FR_DCURSOR_FUNCS(test_dcursor, test_list, test_item_t);
+
+static test_item_t *test_iter(FR_DLIST_HEAD(test_list) *list, test_item_t *current, UNUSED void *uctx)
+{
+ return test_list_next(list, current);
+}
+
+static void test_init_null_item(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ item_p = test_dcursor_iter_init(&cursor, &list, test_iter, NULL, &cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK((cursor.dcursor.dlist) == &list.head);
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor));
+ TEST_CHECK(cursor.dcursor.iter_uctx == &cursor);
+}
+
+static void test_init_1i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+
+ item_p = test_dcursor_init(&cursor, &list);
+ TEST_CHECK(item_p == &item1);
+ TEST_CHECK((cursor.dcursor.dlist) == &list.head);
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+}
+
+static void test_init_2i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ item_p = test_dcursor_init(&cursor, &list);
+ TEST_CHECK(item_p == &item1);
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+}
+
+static void test_next(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+ TEST_CHECK(test_dcursor_current(&cursor) == &item2);
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+}
+
+static void test_next_wrap(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+}
+
+static void test_dcursor_head_tail_null(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_head(&cursor));
+ TEST_CHECK(!test_dcursor_tail(&cursor));
+}
+
+static void test_dcursor_test_head(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+}
+
+static void test_dcursor_head_reset(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == NULL);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item1);
+}
+
+static void test_dcursor_iter_head_reset(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ item_p = test_dcursor_iter_init(&cursor, &list, test_iter, NULL, &cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == NULL);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item1);
+}
+
+static void test_dcursor_head_after_next(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+}
+
+static void test_dcursor_test_tail(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item3);
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item3);
+}
+
+static void test_dcursor_head_after_tail(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_tail(&cursor);
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+}
+
+static void test_dcursor_wrap_after_tail(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_tail(&cursor);
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+}
+
+static void test_dcursor_append_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t *item_p;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item1);
+}
+
+static void test_dcursor_append_empty_3(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, &item1);
+ test_dcursor_append(&cursor, &item2);
+ test_dcursor_append(&cursor, &item3);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item3);
+}
+
+static void test_dcursor_prepend_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t *item_p;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_prepend(&cursor, &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item1);
+}
+
+static void test_dcursor_prepend_empty_3(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_prepend(&cursor, &item1);
+ test_dcursor_prepend(&cursor, &item2);
+ test_dcursor_prepend(&cursor, &item3);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item3);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item1);
+}
+
+static void test_dcursor_insert_into_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t *item_p;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_insert(&cursor, &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item1);
+}
+
+static void test_dcursor_insert_into_empty_3(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_insert(&cursor, &item1);
+ test_dcursor_insert(&cursor, &item2);
+ test_dcursor_insert(&cursor, &item3);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next(&cursor) == &item3);
+}
+
+static void test_dcursor_replace_in_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t *item_p;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+ TEST_CHECK(!test_dcursor_replace(&cursor, &item1));
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(!item_p);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item1);
+}
+
+static void test_dcursor_prepend_1i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_prepend(&cursor, &item2);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item2);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item1);
+}
+
+static void test_dcursor_append_1i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, &item2);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item2);
+}
+
+static void test_dcursor_insert_1i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, &item2);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item2);
+}
+
+static void test_dcursor_replace_1i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+
+ test_dcursor_init(&cursor, &list);
+ item_p = test_dcursor_replace(&cursor, &item2);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item2);
+}
+
+static void test_dcursor_prepend_2i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_prepend(&cursor, &item3);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item2);
+}
+
+static void test_dcursor_append_2i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, &item3);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item3);
+}
+
+static void test_dcursor_insert_2i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_insert(&cursor, &item3);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item3);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item2);
+}
+
+static void test_dcursor_replace_2i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+ item_p = test_dcursor_replace(&cursor, &item3);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item2);
+}
+
+static void test_dcursor_prepend_3i_mid(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_prepend(&cursor, &item4);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item3);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item3);
+}
+
+static void test_dcursor_append_3i_mid(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_append(&cursor, &item4);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item3);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item4);
+}
+
+static void test_dcursor_insert_3i_mid(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_insert(&cursor, &item4);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item4);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item3);
+}
+
+static void test_dcursor_replace_3i_mid(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ item_p = test_dcursor_replace(&cursor, &item4);
+ TEST_CHECK(item_p == &item2);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item3);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item3);
+}
+
+static void test_dcursor_prepend_3i_end(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_next(&cursor);
+ test_dcursor_prepend(&cursor, &item4);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item3);
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(!item_p);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item3);
+}
+
+static void test_dcursor_append_3i_end(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_next(&cursor);
+ test_dcursor_append(&cursor, &item4);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item3);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item4);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item4);
+}
+
+static void test_dcursor_insert_3i_end(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_next(&cursor);
+ test_dcursor_insert(&cursor, &item4);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item3);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item4);
+
+ item_p = test_dcursor_next(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item4);
+}
+
+static void test_dcursor_replace_3i_end(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t item4 = { "item4", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+ test_dcursor_next(&cursor);
+ item_p = test_dcursor_replace(&cursor, &item4);
+ TEST_CHECK(item_p == &item3);
+
+ item_p = test_dcursor_current(&cursor);
+ TEST_CHECK(item_p == &item4);
+
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_head(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ item_p = test_dcursor_tail(&cursor);
+ TEST_CHECK(item_p == &item4);
+}
+
+static void test_dcursor_remove_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+
+ test_dcursor_init(&cursor, &list);
+
+ TEST_CHECK(!test_dcursor_remove(&cursor));
+}
+
+static void test_dcursor_remove_1i(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+
+ test_dcursor_init(&cursor, &list);
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next(&cursor));
+ TEST_CHECK(!test_dcursor_tail(&cursor));
+ TEST_CHECK(!test_dcursor_head(&cursor));
+}
+
+static void test_dcursor_remove_2i(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+
+ test_dcursor_init(&cursor, &list);
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item1);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == &item2);
+ TEST_CHECK(!test_dcursor_next(&cursor));
+ TEST_CHECK(test_dcursor_tail(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_head(&cursor) == &item2);
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item2);
+
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next(&cursor));
+ TEST_CHECK(!test_dcursor_tail(&cursor));
+ TEST_CHECK(!test_dcursor_head(&cursor));
+}
+
+static void test_dcursor_remove_3i_start(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item1);
+ TEST_CHECK(test_dcursor_current(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_next_peek(&cursor) == &item3);
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item2);
+ TEST_CHECK(test_dcursor_current(&cursor) == &item3);
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_tail(&cursor));
+ TEST_CHECK(!test_dcursor_head(&cursor));
+}
+
+static void test_dcursor_remove_3i_mid(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_next(&cursor);
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item2);
+ TEST_CHECK(test_dcursor_current(&cursor) == &item3);
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item3);
+
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(!item_p);
+
+ TEST_CHECK(test_dcursor_tail(&cursor) == &item1);
+ TEST_CHECK(test_dcursor_head(&cursor) == &item1);
+}
+
+static void test_dcursor_remove_3i_end(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item_p;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_tail(&cursor);
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(item_p == &item3);
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ item_p = test_dcursor_remove(&cursor);
+ TEST_CHECK(!item_p);
+
+ TEST_CHECK(!test_dcursor_current(&cursor));
+ TEST_CHECK(!test_dcursor_next_peek(&cursor));
+
+ TEST_CHECK(test_dcursor_tail(&cursor) == &item2);
+ TEST_CHECK(test_dcursor_head(&cursor) == &item1);
+}
+
+static void test_dcursor_merge_start_a_b(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1a = { "item1a", { { NULL, NULL } } };
+ test_item_t item2a = { "item2a", { { NULL, NULL } } };
+ test_item_t item3a = { "item3a", { { NULL, NULL } } };
+
+ test_item_t item1b = { "item1b", { { NULL, NULL } } };
+ test_item_t item2b = { "item2b", { { NULL, NULL } } };
+ test_item_t item3b = { "item3b", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1a);
+ test_list_insert_tail(&list_a, &item2a);
+ test_list_insert_tail(&list_a, &item3a);
+
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item1b);
+ test_list_insert_tail(&list_b, &item2b);
+ test_list_insert_tail(&list_b, &item3b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_current(&cursor_a) == &item1a);
+ TEST_MSG("Expected %s", item1a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item1b);
+ TEST_MSG("Expected %s", item1b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2b);
+ TEST_MSG("Expected %s", item2b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3b);
+ TEST_MSG("Expected %s", item3b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2a);
+ TEST_MSG("Expected %s", item2a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3a);
+ TEST_MSG("Expected %s", item3a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(!test_dcursor_next(&cursor_a));
+
+ TEST_CHECK(!test_dcursor_current(&cursor_b));
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor_b));
+}
+
+static void test_dcursor_merge_mid_a(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1a = { "item1a", { { NULL, NULL } } };
+ test_item_t item2a = { "item2a", { { NULL, NULL } } };
+ test_item_t item3a = { "item3a", { { NULL, NULL } } };
+
+ test_item_t item1b = { "item1b", { { NULL, NULL } } };
+ test_item_t item2b = { "item2b", { { NULL, NULL } } };
+ test_item_t item3b = { "item3b", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1a);
+ test_list_insert_tail(&list_a, &item2a);
+ test_list_insert_tail(&list_a, &item3a);
+
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item1b);
+ test_list_insert_tail(&list_b, &item2b);
+ test_list_insert_tail(&list_b, &item3b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_next(&cursor_a);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_current(&cursor_a) == &item2a);
+ TEST_MSG("Expected %s", item2a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item1b);
+ TEST_MSG("Expected %s", item1b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2b);
+ TEST_MSG("Expected %s", item2b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3b);
+ TEST_MSG("Expected %s", item3b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ /*
+ * Final item should be from cursor a
+ */
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3a);
+ TEST_MSG("Expected %s", item3a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(!test_dcursor_next(&cursor_a));
+
+ TEST_CHECK(!test_dcursor_current(&cursor_b));
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor_b));
+}
+
+static void test_dcursor_merge_end_a(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1a = { "item1a", { { NULL, NULL } } };
+ test_item_t item2a = { "item2a", { { NULL, NULL } } };
+ test_item_t item3a = { "item3a", { { NULL, NULL } } };
+
+ test_item_t item1b = { "item1b", { { NULL, NULL } } };
+ test_item_t item2b = { "item2b", { { NULL, NULL } } };
+ test_item_t item3b = { "item3b", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1a);
+ test_list_insert_tail(&list_a, &item2a);
+ test_list_insert_tail(&list_a, &item3a);
+
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item1b);
+ test_list_insert_tail(&list_b, &item2b);
+ test_list_insert_tail(&list_b, &item3b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_tail(&cursor_a);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_current(&cursor_a) == &item3a);
+ TEST_MSG("Expected %s", item3a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item1b);
+ TEST_MSG("Expected %s", item1b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2b);
+ TEST_MSG("Expected %s", item2b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3b);
+ TEST_MSG("Expected %s", item3b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor_a));
+ TEST_CHECK(!test_dcursor_current(&cursor_b));
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor_b));
+}
+
+static void test_dcursor_merge_mid_b(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1a = { "item1a", { { NULL, NULL } } };
+ test_item_t item2a = { "item2a", { { NULL, NULL } } };
+ test_item_t item3a = { "item3a", { { NULL, NULL } } };
+
+ test_item_t item1b = { "item1b", { { NULL, NULL } } };
+ test_item_t item2b = { "item2b", { { NULL, NULL } } };
+ test_item_t item3b = { "item3b", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1a);
+ test_list_insert_tail(&list_a, &item2a);
+ test_list_insert_tail(&list_a, &item3a);
+
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item1b);
+ test_list_insert_tail(&list_b, &item2b);
+ test_list_insert_tail(&list_b, &item3b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_next(&cursor_b);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_current(&cursor_a) == &item1a);
+ TEST_MSG("Expected %s", item1a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2b);
+ TEST_MSG("Expected %s", item2b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3b);
+ TEST_MSG("Expected %s", item3b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2a);
+ TEST_MSG("Expected %s", item2a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3a);
+ TEST_MSG("Expected %s", item3a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(!test_dcursor_next(&cursor_a));
+
+ TEST_CHECK(!test_dcursor_current(&cursor_b));
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor_b));
+}
+
+static void test_dcursor_merge_end_b(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1a = { "item1a", { { NULL, NULL } } };
+ test_item_t item2a = { "item2a", { { NULL, NULL } } };
+ test_item_t item3a = { "item3a", { { NULL, NULL } } };
+
+ test_item_t item1b = { "item1b", { { NULL, NULL } } };
+ test_item_t item2b = { "item2b", { { NULL, NULL } } };
+ test_item_t item3b = { "item3b", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1a);
+ test_list_insert_tail(&list_a, &item2a);
+ test_list_insert_tail(&list_a, &item3a);
+
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item1b);
+ test_list_insert_tail(&list_b, &item2b);
+ test_list_insert_tail(&list_b, &item3b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_next(&cursor_b);
+ test_dcursor_next(&cursor_b);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_current(&cursor_a) == &item1a);
+ TEST_MSG("Expected %s", item1a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3b);
+ TEST_MSG("Expected %s", item3b.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2a);
+ TEST_MSG("Expected %s", item2a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3a);
+ TEST_MSG("Expected %s", item3a.name);
+ TEST_MSG("Got %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(!test_dcursor_next(&cursor_a));
+
+ TEST_CHECK(!test_dcursor_current(&cursor_b));
+ TEST_CHECK(test_dcursor_head(&cursor_b) == &item1b);
+}
+
+static void test_dcursor_merge_with_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1b = { "item1b", { { NULL, NULL } } };
+ test_item_t item2b = { "item2b", { { NULL, NULL } } };
+ test_item_t item3b = { "item3b", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item1b);
+ test_list_insert_tail(&list_b, &item2b);
+ test_list_insert_tail(&list_b, &item3b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_head(&cursor_a) == &item1b);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2b);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3b);
+
+ TEST_CHECK(!test_dcursor_current(&cursor_b));
+ TEST_CHECK(!test_dcursor_list_next_peek(&cursor_b));
+}
+
+static void test_dcursor_merge_empty(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1a = { "item1a", { { NULL, NULL } } };
+ test_item_t item2a = { "item2a", { { NULL, NULL } } };
+ test_item_t item3a = { "item3a", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1a);
+ test_list_insert_tail(&list_a, &item2a);
+ test_list_insert_tail(&list_a, &item3a);
+ test_list_init(&list_b);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+ test_dcursor_merge(&cursor_a, &cursor_b);
+
+ TEST_CHECK(test_dcursor_head(&cursor_a) == &item1a);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item2a);
+ TEST_CHECK(test_dcursor_next(&cursor_a) == &item3a);
+}
+
+static void test_dcursor_copy_test(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor_a, &list);
+ test_dcursor_copy(&cursor_b, &cursor_a);
+
+ TEST_CHECK(test_dcursor_head(&cursor_b) == &item1);
+ TEST_CHECK(test_dcursor_next(&cursor_b) == &item2);
+ TEST_CHECK(test_dcursor_next(&cursor_b) == &item3);
+}
+
+static void test_dcursor_free_by_list(void)
+{
+ test_item_t *item1, *item2, *item3;
+ FR_DLIST_HEAD(test_list) list;
+ FR_DCURSOR(test_dcursor) cursor;
+
+ test_list_init(&list);
+
+ item1 = talloc_zero(NULL, test_item_t);
+ item2 = talloc_zero(NULL, test_item_t);
+ item3 = talloc_zero(NULL, test_item_t);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, item1);
+ test_dcursor_append(&cursor, item2);
+ test_dcursor_append(&cursor, item3);
+
+ test_dcursor_head(&cursor);
+ test_dcursor_free_list(&cursor);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == NULL);
+ TEST_CHECK(!test_dcursor_tail(&cursor));
+ TEST_CHECK(!test_dcursor_head(&cursor));
+}
+
+static void test_dcursor_free_by_item(void)
+{
+ test_item_t *item1, *item2, *item3;
+ FR_DLIST_HEAD(test_list) list;
+ FR_DCURSOR(test_dcursor) cursor;
+
+ test_list_init(&list);
+
+ item1 = talloc_zero(NULL, test_item_t);
+ item2 = talloc_zero(NULL, test_item_t);
+ item3 = talloc_zero(NULL, test_item_t);
+
+ test_dcursor_init(&cursor, &list);
+ test_dcursor_append(&cursor, item1);
+ test_dcursor_append(&cursor, item2);
+ test_dcursor_append(&cursor, item3);
+
+ test_dcursor_head(&cursor);
+ test_dcursor_free_item(&cursor);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == item2);
+ TEST_CHECK(test_dcursor_tail(&cursor) == item3);
+ TEST_CHECK(test_dcursor_head(&cursor) == item2);
+
+ test_dcursor_free_item(&cursor);
+ test_dcursor_free_item(&cursor);
+
+ TEST_CHECK(test_dcursor_current(&cursor) == NULL);
+ TEST_CHECK(!test_dcursor_tail(&cursor));
+ TEST_CHECK(!test_dcursor_head(&cursor));
+}
+
+typedef struct {
+ int pos;
+ char val;
+} item_filter;
+
+static test_item_t *iter_name_check(FR_DLIST_HEAD(test_list) *list, test_item_t *current, void *uctx)
+{
+ item_filter *f = uctx;
+
+ while ((current = test_list_next(list, current))) {
+ if (current->name[f->pos] == f->val) break;
+ }
+
+ return current;
+}
+
+static void test_intersect_differing_lists(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list_a, list_b;
+
+ test_list_init(&list_a);
+ test_list_insert_tail(&list_a, &item1);
+ test_list_init(&list_b);
+ test_list_insert_tail(&list_b, &item2);
+
+ test_dcursor_init(&cursor_a, &list_a);
+ test_dcursor_init(&cursor_b, &list_b);
+
+ TEST_CHECK(test_dcursor_intersect_head(&cursor_a, &cursor_b) == NULL);
+}
+
+static void test_intersect_no_iterators(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "item1", { { NULL, NULL } } };
+ test_item_t item2 = { "item2", { { NULL, NULL } } };
+ test_item_t item3 = { "item3", { { NULL, NULL } } };
+ test_item_t *item4 = NULL;
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+
+ test_dcursor_init(&cursor_a, &list);
+ test_dcursor_init(&cursor_b, &list);
+
+ item4 = test_dcursor_intersect_head(&cursor_a, &cursor_b);
+ TEST_CHECK(item4 == &item1);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item2);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item3);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == NULL);
+}
+
+static void test_intersect_iterator_a(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "actor", { { NULL, NULL } } };
+ test_item_t item2 = { "alter", { { NULL, NULL } } };
+ test_item_t item3 = { "extra", { { NULL, NULL } } };
+ test_item_t item4 = { "after", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+ item_filter filter_a = { 0, 'a' };
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+
+ test_dcursor_iter_init(&cursor_a, &list, iter_name_check, NULL, &filter_a);
+ test_dcursor_init(&cursor_b, &list);
+
+ TEST_CHECK(test_dcursor_intersect_head(&cursor_a, &cursor_b) == &item1);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item2);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item4);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == NULL);
+}
+
+static void test_intersect_iterator_b(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "blink", { { NULL, NULL } } };
+ test_item_t item2 = { "alter", { { NULL, NULL } } };
+ test_item_t item3 = { "basic", { { NULL, NULL } } };
+ test_item_t item4 = { "bland", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+ item_filter filter_b = { 0, 'b'};
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+
+ test_dcursor_init(&cursor_a, &list);
+ test_dcursor_iter_init(&cursor_b, &list, iter_name_check, NULL, &filter_b);
+
+ TEST_CHECK(test_dcursor_intersect_head(&cursor_a, &cursor_b) == &item1);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item3);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item4);
+}
+
+static void test_intersect_iterator_ab(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "baits", { { NULL, NULL } } };
+ test_item_t item2 = { "alter", { { NULL, NULL } } };
+ test_item_t item3 = { "basic", { { NULL, NULL } } };
+ test_item_t item4 = { "cavil", { { NULL, NULL } } };
+ test_item_t item5 = { "bland", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+ item_filter filter_a = { 1, 'a' };
+ item_filter filter_b = { 0, 'b' };
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+ test_list_insert_tail(&list, &item5);
+
+ test_dcursor_iter_init(&cursor_a, &list, iter_name_check, NULL, &filter_a);
+ test_dcursor_iter_init(&cursor_b, &list, iter_name_check, NULL, &filter_b);
+
+ TEST_CHECK(test_dcursor_intersect_head(&cursor_a, &cursor_b) == &item1);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == &item3);
+ TEST_MSG("Expected %s", item3.name);
+ TEST_MSG("Current %s", test_dcursor_current(&cursor_a)->name);
+ TEST_CHECK(test_dcursor_intersect_next(&cursor_a, &cursor_b) == NULL);
+}
+
+static void test_intersect_iterator_disjoint(void)
+{
+ FR_DCURSOR(test_dcursor) cursor_a, cursor_b;
+
+ test_item_t item1 = { "baits", { { NULL, NULL } } };
+ test_item_t item2 = { "alter", { { NULL, NULL } } };
+ test_item_t item3 = { "basic", { { NULL, NULL } } };
+ test_item_t item4 = { "cavil", { { NULL, NULL } } };
+ test_item_t item5 = { "bland", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+ item_filter filter_a = { 0, 'a' };
+ item_filter filter_b = { 0, 'b' };
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+ test_list_insert_tail(&list, &item5);
+
+ test_dcursor_iter_init(&cursor_a, &list, iter_name_check, NULL, &filter_a);
+ test_dcursor_iter_init(&cursor_b, &list, iter_name_check, NULL, &filter_b);
+
+ TEST_CHECK(test_dcursor_intersect_head(&cursor_a, &cursor_b) == NULL);
+}
+
+static bool eval_eq(test_item_t const *item, void const *uctx)
+{
+ char const *s = uctx;
+ return strcmp(item->name, s) == 0;
+}
+
+static void test_filter_head_next(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+
+ test_item_t item1 = { "yes", { { NULL, NULL } } };
+ test_item_t item2 = { "no", { { NULL, NULL } } };
+ test_item_t item3 = { "yes", { { NULL, NULL } } };
+ test_item_t item4 = { "no", { { NULL, NULL } } };
+ test_item_t item5 = { "yes", { { NULL, NULL } } };
+ test_item_t item6 = { "no", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+ test_list_insert_tail(&list, &item5);
+ test_list_insert_tail(&list, &item6);
+
+ test_dcursor_init(&cursor, &list);
+
+ TEST_CHECK(test_dcursor_filter_head(&cursor, eval_eq, "yes") == &item1);
+ TEST_CHECK(test_dcursor_filter_next(&cursor, eval_eq, "yes") == &item3);
+ TEST_CHECK(test_dcursor_filter_next(&cursor, eval_eq, "yes") == &item5);
+ TEST_CHECK(test_dcursor_filter_next(&cursor, eval_eq, "yes") == NULL);
+}
+
+static void test_filter_current(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+
+ test_item_t item1 = { "yes", { { NULL, NULL } } };
+ test_item_t item2 = { "no", { { NULL, NULL } } };
+ test_item_t item3 = { "yes", { { NULL, NULL } } };
+ test_item_t item4 = { "no", { { NULL, NULL } } };
+ test_item_t item5 = { "yes", { { NULL, NULL } } };
+ test_item_t item6 = { "no", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+ test_list_insert_tail(&list, &item5);
+ test_list_insert_tail(&list, &item6);
+
+ test_dcursor_init(&cursor, &list);
+
+ TEST_CHECK(test_dcursor_filter_current(&cursor, eval_eq, "yes") == &item1);
+ test_dcursor_next(&cursor);
+ TEST_CHECK(test_dcursor_filter_current(&cursor, eval_eq, "yes") == &item3);
+ test_dcursor_next(&cursor);
+ TEST_CHECK(test_dcursor_filter_current(&cursor, eval_eq, "yes") == &item5);
+ test_dcursor_next(&cursor);
+ TEST_CHECK(test_dcursor_filter_current(&cursor, eval_eq, "yes") == NULL);
+}
+
+static void test_filter_no_match(void)
+{
+ FR_DCURSOR(test_dcursor) cursor;
+
+ test_item_t item1 = { "yes", { { NULL, NULL } } };
+ test_item_t item2 = { "no", { { NULL, NULL } } };
+ test_item_t item3 = { "yes", { { NULL, NULL } } };
+ test_item_t item4 = { "no", { { NULL, NULL } } };
+ test_item_t item5 = { "yes", { { NULL, NULL } } };
+ test_item_t item6 = { "no", { { NULL, NULL } } };
+ FR_DLIST_HEAD(test_list) list;
+
+ test_list_init(&list);
+ test_list_insert_tail(&list, &item1);
+ test_list_insert_tail(&list, &item2);
+ test_list_insert_tail(&list, &item3);
+ test_list_insert_tail(&list, &item4);
+ test_list_insert_tail(&list, &item5);
+ test_list_insert_tail(&list, &item6);
+
+ test_dcursor_init(&cursor, &list);
+
+ TEST_CHECK(test_dcursor_filter_current(&cursor, eval_eq, "maybe") == NULL);
+}
+
+TEST_LIST = {
+ /*
+ * Initialisation
+ */
+ { "init_null", test_init_null_item },
+ { "init_one", test_init_1i_start },
+ { "init_two", test_init_2i_start },
+
+ /*
+ * Normal iteration
+ */
+ { "next", test_next },
+ { "next_wrap", test_next_wrap },
+
+ /*
+ * Jump to head/tail
+ */
+ { "head_tail_null", test_dcursor_head_tail_null },
+ { "head", test_dcursor_test_head },
+ { "head_resest", test_dcursor_head_reset },
+ { "head_iter_reset", test_dcursor_iter_head_reset },
+ { "head_after_next", test_dcursor_head_after_next },
+ { "tail", test_dcursor_test_tail },
+ { "head_after_tail", test_dcursor_head_after_tail },
+ { "wrap_after_tail", test_dcursor_wrap_after_tail },
+
+ /*
+ * Insert with empty list
+ */
+ { "append_empty", test_dcursor_append_empty },
+ { "append_empty_3", test_dcursor_append_empty_3 },
+ { "prepend_empty", test_dcursor_prepend_empty },
+ { "prepend_empty_3", test_dcursor_prepend_empty_3 },
+ { "insert_empty", test_dcursor_insert_into_empty },
+ { "insert_empty_3", test_dcursor_insert_into_empty_3 },
+ { "replace_empty", test_dcursor_replace_in_empty },
+
+ /*
+ * Insert with one item list
+ */
+ { "prepend_1i_start", test_dcursor_prepend_1i_start },
+ { "append_1i_start", test_dcursor_append_1i_start },
+ { "insert_1i_start", test_dcursor_insert_1i_start },
+ { "replace_li_start", test_dcursor_replace_1i_start },
+
+ /*
+ * Insert with two item list
+ */
+ { "prepend_2i_start", test_dcursor_prepend_2i_start },
+ { "append_2i_start", test_dcursor_append_2i_start },
+ { "insert_2i_start", test_dcursor_insert_2i_start },
+ { "replace_2i_start", test_dcursor_replace_2i_start },
+
+ /*
+ * Insert with three item list (with cursor on item2)
+ */
+ { "prepend_3i_mid", test_dcursor_prepend_3i_mid },
+ { "append_3i_mid", test_dcursor_append_3i_mid },
+ { "insert_3i_mid", test_dcursor_insert_3i_mid },
+ { "replace_3i_mid", test_dcursor_replace_3i_mid },
+
+ /*
+ * Insert with three item list (with cursor on item3)
+ */
+ { "prepend_3i_end", test_dcursor_prepend_3i_end },
+ { "append_3i_end", test_dcursor_append_3i_end },
+ { "insert_3i_end", test_dcursor_insert_3i_end },
+ { "replace_3i_end", test_dcursor_replace_3i_end },
+
+ /*
+ * Remove
+ */
+ { "remove_empty", test_dcursor_remove_empty },
+ { "remove_1i", test_dcursor_remove_1i },
+ { "remove_2i", test_dcursor_remove_2i },
+ { "remove_3i_start", test_dcursor_remove_3i_start },
+ { "remove_3i_mid", test_dcursor_remove_3i_mid },
+ { "remove_3i_end", test_dcursor_remove_3i_end },
+
+ /*
+ * Merge
+ */
+ { "merge_start_a_b", test_dcursor_merge_start_a_b },
+ { "merge_mid_a", test_dcursor_merge_mid_a },
+ { "merge_end_a", test_dcursor_merge_end_a },
+ { "merge_mid_b", test_dcursor_merge_mid_b },
+ { "merge_end_b", test_dcursor_merge_end_b },
+ { "merge_with_empty", test_dcursor_merge_with_empty },
+ { "merge_empty", test_dcursor_merge_empty },
+
+ /*
+ * Copy
+ */
+ { "copy", test_dcursor_copy_test },
+
+ /*
+ * Free
+ */
+ { "free_list", test_dcursor_free_by_list },
+ { "free_item", test_dcursor_free_by_item },
+
+ /*
+ * Intersect
+ */
+ { "differing_lists", test_intersect_differing_lists },
+ { "no_iterators", test_intersect_no_iterators },
+ { "iterator_a", test_intersect_iterator_a },
+ { "iterator_b", test_intersect_iterator_b },
+ { "iterator_ab", test_intersect_iterator_ab },
+ { "iterator_disjoint", test_intersect_iterator_disjoint },
+
+ /*
+ * Filter
+ */
+ { "head_next", test_filter_head_next },
+ { "current", test_filter_current },
+ { "no_match", test_filter_no_match },
+
+ { NULL }
+};