summaryrefslogtreecommitdiffstats
path: root/src/lib/test-llist.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/test-llist.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/lib/test-llist.c b/src/lib/test-llist.c
new file mode 100644
index 0000000..d57006c
--- /dev/null
+++ b/src/lib/test-llist.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "llist.h"
+
+
+struct dllist {
+ struct dllist *prev, *next;
+};
+
+static void test_dllist(void)
+{
+ struct dllist *head = NULL, *l4, *l3, *l2, *l1;
+ struct dllist empty = { NULL, NULL };
+
+ l4 = t_new(struct dllist, 1);
+ l3 = t_new(struct dllist, 1);
+ l2 = t_new(struct dllist, 1);
+ l1 = t_new(struct dllist, 1);
+
+ test_begin("dllist");
+ DLLIST_PREPEND(&head, l4);
+ test_assert(head == l4);
+ test_assert(l4->prev == NULL && l4->next == NULL);
+ DLLIST_PREPEND(&head, l3);
+ test_assert(head == l3);
+ test_assert(l3->prev == NULL && l3->next == l4);
+ test_assert(l4->prev == l3 && l4->next == NULL);
+ DLLIST_PREPEND(&head, l2);
+ DLLIST_PREPEND(&head, l1);
+ /* remove from middle */
+ DLLIST_REMOVE(&head, l2);
+ test_assert(l2->prev == NULL && l2->next == NULL);
+ test_assert(head == l1);
+ test_assert(l1->prev == NULL && l1->next == l3);
+ test_assert(l3->prev == l1 && l3->next == l4);
+ test_assert(l4->prev == l3 && l4->next == NULL);
+ /* remove from head */
+ DLLIST_REMOVE(&head, l1);
+ test_assert(l1->prev == NULL && l1->next == NULL);
+ test_assert(head == l3);
+ test_assert(l3->prev == NULL && l3->next == l4);
+ test_assert(l4->prev == l3 && l4->next == NULL);
+ /* remove from tail */
+ DLLIST_PREPEND(&head, l1);
+ DLLIST_REMOVE(&head, l4);
+ test_assert(l4->prev == NULL && l4->next == NULL);
+ test_assert(head == l1);
+ test_assert(l1->prev == NULL && l1->next == l3);
+ test_assert(l3->prev == l1 && l3->next == NULL);
+ /* removal of an entry not in the list shouldn't cause the list to break */
+ DLLIST_REMOVE(&head, &empty);
+ test_assert(head == l1);
+ test_assert(l1->prev == NULL && l1->next == l3);
+ test_assert(l3->prev == l1 && l3->next == NULL);
+ /* remove last two */
+ DLLIST_REMOVE(&head, l1);
+ DLLIST_REMOVE(&head, l3);
+ test_assert(l3->prev == NULL && l3->next == NULL);
+ test_assert(head == NULL);
+ test_end();
+}
+
+static void test_dllist2(void)
+{
+ struct dllist *head = NULL, *tail = NULL, *l4, *l3, *l2, *l1;
+ struct dllist empty = { NULL, NULL };
+
+ l4 = t_new(struct dllist, 1);
+ l3 = t_new(struct dllist, 1);
+ l2 = t_new(struct dllist, 1);
+ l1 = t_new(struct dllist, 1);
+
+ test_begin("dllist");
+ /* prepend to empty */
+ DLLIST2_PREPEND(&head, &tail, l3);
+ test_assert(head == l3 && tail == l3);
+ test_assert(l3->next == NULL && l3->prev == NULL);
+ /* remove last */
+ DLLIST2_REMOVE(&head, &tail, l3);
+ test_assert(head == NULL && tail == NULL);
+ test_assert(l3->next == NULL && l3->prev == NULL);
+ /* append to empty */
+ DLLIST2_APPEND(&head, &tail, l3);
+ test_assert(head == l3 && tail == l3);
+ test_assert(l3->next == NULL && l3->prev == NULL);
+ /* prepend */
+ DLLIST2_PREPEND(&head, &tail, l2);
+ test_assert(head == l2 && tail == l3);
+ test_assert(l2->prev == NULL && l2->next == l3);
+ test_assert(l3->prev == l2 && l3->next == NULL);
+ /* append */
+ DLLIST2_APPEND(&head, &tail, l4);
+ test_assert(head == l2 && tail == l4);
+ test_assert(l2->prev == NULL && l2->next == l3);
+ test_assert(l3->prev == l2 && l3->next == l4);
+ test_assert(l4->prev == l3 && l4->next == NULL);
+ DLLIST2_PREPEND(&head, &tail, l1);
+
+ /* remove from middle */
+ DLLIST2_REMOVE(&head, &tail, l2);
+ test_assert(l2->prev == NULL && l2->next == NULL);
+ test_assert(head == l1 && tail == l4);
+ test_assert(l1->prev == NULL && l1->next == l3);
+ test_assert(l3->prev == l1 && l3->next == l4);
+ test_assert(l4->prev == l3 && l4->next == NULL);
+ /* remove from head */
+ DLLIST2_REMOVE(&head, &tail, l1);
+ test_assert(l1->prev == NULL && l1->next == NULL);
+ test_assert(head == l3 && tail == l4);
+ test_assert(l3->prev == NULL && l3->next == l4);
+ test_assert(l4->prev == l3 && l4->next == NULL);
+ /* remove from tail */
+ DLLIST2_PREPEND(&head, &tail, l1);
+ DLLIST2_REMOVE(&head, &tail, l4);
+ test_assert(l4->prev == NULL && l4->next == NULL);
+ test_assert(head == l1 && tail == l3);
+ test_assert(l1->prev == NULL && l1->next == l3);
+ test_assert(l3->prev == l1 && l3->next == NULL);
+ /* removal of an entry not in the list shouldn't cause the list to break */
+ DLLIST2_REMOVE(&head, &tail, &empty);
+ test_assert(head == l1);
+ test_assert(head == l1 && tail == l3);
+ test_assert(l1->prev == NULL && l1->next == l3);
+ test_assert(l3->prev == l1 && l3->next == NULL);
+ /* remove last two */
+ DLLIST2_REMOVE(&head, &tail, l1);
+ DLLIST2_REMOVE(&head, &tail, l3);
+ test_assert(l3->prev == NULL && l3->next == NULL);
+ test_assert(head == NULL && tail == NULL);
+ test_end();
+}
+
+void test_llist(void)
+{
+ test_dllist();
+ test_dllist2();
+}