summaryrefslogtreecommitdiff
path: root/lib/lists_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lists_test.c')
-rw-r--r--lib/lists_test.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/lib/lists_test.c b/lib/lists_test.c
new file mode 100644
index 00000000..56cc8427
--- /dev/null
+++ b/lib/lists_test.c
@@ -0,0 +1,287 @@
+/*
+ * BIRD Library -- Linked Lists Tests
+ *
+ * (c) 2015 CZ.NIC z.s.p.o.
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "test/birdtest.h"
+#include "lib/lists.h"
+
+#define MAX_NUM 1000
+
+static node nodes[MAX_NUM];
+static list l;
+
+static void
+show_list(void)
+{
+ bt_debug("\n");
+ bt_debug("list.null is at %p and point to %p\n", &l.null, l.null);
+ bt_debug("list.head is at %p and point to %p\n", &l.head, l.head);
+ bt_debug("list.tail is at %p and point to %p\n", &l.tail, l.tail);
+
+ int i;
+ for (i = 0; i < MAX_NUM; i++)
+ {
+ bt_debug("n[%3i] is at %p\n", i, &nodes[i]);
+ bt_debug(" prev is at %p and point to %p\n", &(nodes[i].prev), nodes[i].prev);
+ bt_debug(" next is at %p and point to %p\n", &(nodes[i].next), nodes[i].next);
+ }
+}
+
+static int
+is_filled_list_well_linked(void)
+{
+ int i;
+ bt_assert(l.head == &nodes[0]);
+ bt_assert(l.tail == &nodes[MAX_NUM-1]);
+ bt_assert((void *) nodes[0].prev == (void *) &l.head);
+ bt_assert((void *) nodes[MAX_NUM-1].next == (void *) &l.null);
+
+ for (i = 0; i < MAX_NUM; i++)
+ {
+ if (i < (MAX_NUM-1))
+ bt_assert(nodes[i].next == &nodes[i+1]);
+
+ if (i > 0)
+ bt_assert(nodes[i].prev == &nodes[i-1]);
+ }
+
+ return 1;
+}
+
+static int
+is_empty_list_well_unlinked(void)
+{
+ int i;
+
+ bt_assert(l.head == NODE &l.null);
+ bt_assert(l.tail == NODE &l.head);
+ bt_assert(EMPTY_LIST(l));
+
+ for (i = 0; i < MAX_NUM; i++)
+ {
+ bt_assert(nodes[i].next == NULL);
+ bt_assert(nodes[i].prev == NULL);
+ }
+
+ return 1;
+}
+
+static void
+init_list__(list *l, struct node nodes[])
+{
+ init_list(l);
+
+ int i;
+ for (i = 0; i < MAX_NUM; i++)
+ {
+ nodes[i].next = NULL;
+ nodes[i].prev = NULL;
+ }
+}
+
+static void
+init_list_(void)
+{
+ init_list__(&l, (node *) nodes);
+}
+
+static int
+t_add_tail(void)
+{
+ int i;
+
+ init_list_();
+ for (i = 0; i < MAX_NUM; i++)
+ {
+ add_tail(&l, &nodes[i]);
+ bt_debug(".");
+ bt_assert(l.tail == &nodes[i]);
+ bt_assert(l.head == &nodes[0]);
+ bt_assert((void *) nodes[i].next == (void *) &l.null);
+ if (i > 0)
+ {
+ bt_assert(nodes[i-1].next == &nodes[i]);
+ bt_assert(nodes[i].prev == &nodes[i-1]);
+ }
+ }
+ show_list();
+ bt_assert(is_filled_list_well_linked());
+
+ return BT_SUCCESS;
+}
+
+static int
+t_add_head(void)
+{
+ int i;
+
+ init_list_();
+ for (i = MAX_NUM-1; i >= 0; i--)
+ {
+ add_head(&l, &nodes[i]);
+ bt_debug(".");
+ bt_assert(l.head == &nodes[i]);
+ bt_assert(l.tail == &nodes[MAX_NUM-1]);
+ if (i < MAX_NUM-1)
+ {
+ bt_assert(nodes[i+1].prev == &nodes[i]);
+ bt_assert(nodes[i].next == &nodes[i+1]);
+ }
+ }
+ show_list();
+ bt_assert(is_filled_list_well_linked());
+
+ return BT_SUCCESS;
+}
+
+static void
+insert_node_(node *n, node *after)
+{
+ insert_node(n, after);
+ bt_debug(".");
+}
+
+static int
+t_insert_node(void)
+{
+ int i;
+
+ init_list_();
+
+ // add first node
+ insert_node_(&nodes[0], NODE &l.head);
+
+ // add odd nodes
+ for (i = 2; i < MAX_NUM; i+=2)
+ insert_node_(&nodes[i], &nodes[i-2]);
+
+ // add even nodes
+ for (i = 1; i < MAX_NUM; i+=2)
+ insert_node_(&nodes[i], &nodes[i-1]);
+
+ bt_debug("\n");
+ bt_assert(is_filled_list_well_linked());
+
+ return BT_SUCCESS;
+}
+
+static void
+fill_list2(list *l, node nodes[])
+{
+ int i;
+ for (i = 0; i < MAX_NUM; i++)
+ add_tail(l, &nodes[i]);
+}
+
+static void
+fill_list(void)
+{
+ fill_list2(&l, (node *) nodes);
+}
+
+static int
+t_remove_node(void)
+{
+ int i;
+
+ init_list_();
+
+ /* Fill & Remove & Check */
+ fill_list();
+ for (i = 0; i < MAX_NUM; i++)
+ rem_node(&nodes[i]);
+ bt_assert(is_empty_list_well_unlinked());
+
+ /* Fill & Remove the half of nodes & Check & Remove the rest nodes & Check */
+ fill_list();
+ for (i = 0; i < MAX_NUM; i+=2)
+ rem_node(&nodes[i]);
+
+ int tail_node_index = (MAX_NUM % 2) ? MAX_NUM - 2 : MAX_NUM - 1;
+ bt_assert(l.head == &nodes[1]);
+ bt_assert(l.tail == &nodes[tail_node_index]);
+ bt_assert(nodes[tail_node_index].next == NODE &l.null);
+
+ for (i = 1; i < MAX_NUM; i+=2)
+ {
+ if (i > 1)
+ bt_assert(nodes[i].prev == &nodes[i-2]);
+ if (i < tail_node_index)
+ bt_assert(nodes[i].next == &nodes[i+2]);
+ }
+
+ for (i = 1; i < MAX_NUM; i+=2)
+ rem_node(&nodes[i]);
+ bt_assert(is_empty_list_well_unlinked());
+
+ return BT_SUCCESS;
+}
+
+static int
+t_replace_node(void)
+{
+ node head, inside, tail;
+
+ init_list_();
+ fill_list();
+
+ replace_node(&nodes[0], &head);
+ bt_assert(l.head == &head);
+ bt_assert(head.prev == NODE &l.head);
+ bt_assert(head.next == &nodes[1]);
+ bt_assert(nodes[1].prev == &head);
+
+ replace_node(&nodes[MAX_NUM/2], &inside);
+ bt_assert(nodes[MAX_NUM/2-1].next == &inside);
+ bt_assert(nodes[MAX_NUM/2+1].prev == &inside);
+ bt_assert(inside.prev == &nodes[MAX_NUM/2-1]);
+ bt_assert(inside.next == &nodes[MAX_NUM/2+1]);
+
+ replace_node(&nodes[MAX_NUM-1], &tail);
+ bt_assert(l.tail == &tail);
+ bt_assert(tail.prev == &nodes[MAX_NUM-2]);
+ bt_assert(tail.next == NODE &l.null);
+ bt_assert(nodes[MAX_NUM-2].next == &tail);
+
+ return BT_SUCCESS;
+}
+
+static int
+t_add_tail_list(void)
+{
+ node nodes2[MAX_NUM];
+ list l2;
+
+ init_list__(&l, (node *) nodes);
+ fill_list2(&l, (node *) nodes);
+
+ init_list__(&l2, (node *) nodes2);
+ fill_list2(&l2, (node *) nodes2);
+
+ add_tail_list(&l, &l2);
+
+ bt_assert(nodes[MAX_NUM-1].next == &nodes2[0]);
+ bt_assert(nodes2[0].prev == &nodes[MAX_NUM-1]);
+ bt_assert(l.tail == &nodes2[MAX_NUM-1]);
+
+ return BT_SUCCESS;
+}
+
+int
+main(int argc, char *argv[])
+{
+ bt_init(argc, argv);
+
+ bt_test_suite(t_add_tail, "Adding nodes to tail of list");
+ bt_test_suite(t_add_head, "Adding nodes to head of list");
+ bt_test_suite(t_insert_node, "Inserting nodes to list");
+ bt_test_suite(t_remove_node, "Removing nodes from list");
+ bt_test_suite(t_replace_node, "Replacing nodes in list");
+ bt_test_suite(t_add_tail_list, "At the tail of a list adding the another list");
+
+ return bt_exit_value();
+}