/* 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(); }