Home | History | Annotate | Line # | Download | only in testsuite
      1 #include <stdbool.h>
      2 #include <stdlib.h>
      3 #include <stdio.h>
      4 
      5 #include "doubly-linked-list.h"
      6 
      7 #ifndef EXIT_SUCCESS
      8 #define EXIT_SUCCESS 0
      9 #endif
     10 
     11 #ifndef EXIT_FAILURE
     12 #define EXIT_FAILURE 1
     13 #endif
     14 
     15 /* Implementation */
     16 
     17 typedef int T;
     18 
     19 typedef struct ListNodeType
     20 {
     21   T value;
     22   struct ListNodeType *next;
     23   struct ListNodeType *prev;
     24 } ListNodeType;
     25 
     26 ListNodeType * l_new_node (T value)
     27 {
     28   ListNodeType *n = malloc (sizeof (ListNodeType));
     29   n->next = NULL;
     30   n->prev = NULL;
     31   n->value = value;
     32   return n;
     33 }
     34 
     35 typedef struct LinkedListWrapperType
     36 {
     37   ListNodeType *first;
     38   ListNodeType *last;
     39   size_t size;
     40 } LinkedListWrapperType;
     41 
     42 int compare_nodes (const ListNodeType *n1, const ListNodeType *n2)
     43 {
     44   if (n1->value == n2->value)
     45     return 0;
     46   else if (n1->value < n2->value)
     47     return -1;
     48   else
     49     return 1;
     50 }
     51 
     52 LINKED_LIST_MUTATIVE_OPS_PROTOTYPE (LinkedListWrapperType, ListNodeType, static);
     53 LINKED_LIST_MERGE_SORT_PROTOTYPE (LinkedListWrapperType, ListNodeType, static);
     54 
     55 LINKED_LIST_MUTATIVE_OPS_DECL (LinkedListWrapperType, ListNodeType, static)
     56 LINKED_LIST_MERGE_SORT_DECL (LinkedListWrapperType, ListNodeType, static)
     57 
     58 ListNodeType * find_last_node (ListNodeType *head)
     59 {
     60   if (head == NULL)
     61     return NULL;
     62 
     63   ListNodeType *n = head;
     64   while (n->next != NULL)
     65     n = n->next;
     66 
     67   return n;
     68 }
     69 
     70 void l_print (ListNodeType *node)
     71 {
     72   for (ListNodeType *l = node; l != NULL; l = l->next)
     73     printf ("%d ", l->value);
     74   printf ("\n");
     75 }
     76 
     77 void l_reverse_print (ListNodeType *last_node)
     78 {
     79   for (ListNodeType *l = last_node; l != NULL; l = l->prev)
     80     printf ("%d ", l->value);
     81   printf ("\n");
     82 }
     83 
     84 struct test_data_t
     85 {
     86   T const *content;
     87   size_t size;
     88 };
     89 
     90 bool run_test (const struct test_data_t *expect,
     91 	       LinkedListWrapperType *current,
     92 	       bool reversed)
     93 {
     94   ListNodeType *node = (reversed) ? current->last : current->first;
     95   bool passed = true;
     96   for (int i=0; i<expect->size && node != NULL; ++i)
     97     {
     98       if (reversed)
     99 	{
    100 	  if (expect->content[expect->size - 1 - i] != node->value)
    101 	    {
    102 	      printf ("FAIL: mismatching expected (%d) VS current (%d).\n",
    103 		      expect->content[expect->size - 1 - i], node->value);
    104 	      passed = false;
    105 	    }
    106 	  if (node->prev == NULL && current->first != node)
    107 	    {
    108 	      printf ("FAIL: first is not matching the first node.\n");
    109 	      passed = false;
    110 	    }
    111 	}
    112       else
    113 	{
    114 	  if (expect->content[i] != node->value)
    115 	    {
    116 	      printf ("FAIL: mismatching expected (%d) VS current (%d).\n",
    117 		      expect->content[i], node->value);
    118 	      passed = false;
    119 	    }
    120 	  if (node->next == NULL && current->last != node)
    121 	    {
    122 	      printf ("FAIL: last_ is not matching the last node.\n");
    123 	      passed = false;
    124 	    }
    125 	}
    126 
    127       if (!passed)
    128 	return false;
    129 
    130       if (reversed)
    131 	node = node->prev;
    132       else
    133 	node = node->next;
    134     }
    135 
    136   if (node != NULL)
    137     {
    138       printf ("FAIL: the list is longer than expected.\n");
    139       passed = false;
    140     }
    141   if (expect->size != current->size)
    142     {
    143       printf ("FAIL: size (%ld) is not matching the real size of the list (%ld).\n",
    144 	      current->size, expect->size);
    145       passed = false;
    146     }
    147 
    148   return passed;
    149 }
    150 
    151 bool check(const char *op,
    152 	  const struct test_data_t *expect,
    153 	  LinkedListWrapperType *wrapper)
    154 {
    155   bool success = true;
    156   bool res;
    157 
    158 #define DUMP_LIST 0
    159 
    160   if (DUMP_LIST)
    161     l_print (wrapper->first);
    162 
    163   res = run_test (expect, wrapper, false);
    164   printf ("%s: test-linked-list::%s: check forward conformity\n",
    165 	  res ? "PASS": "FAIL", op);
    166   success &= res;
    167 
    168   if (DUMP_LIST)
    169     l_reverse_print (wrapper->last);
    170 
    171   res = run_test (expect, wrapper, true);
    172   printf ("%s: test-linked-list::%s: check backward conformity\n",
    173 	  res ? "PASS": "FAIL", op);
    174   success &= res;
    175 
    176   if (DUMP_LIST)
    177     printf("\n");
    178 
    179   return success;
    180 }
    181 
    182 const int EXPECT_0 [] = { 10, 4, 3, 1, 9, 2 };
    183 const int EXPECT_1 [] = { 1, 2, 3, 4, 9, 10 };
    184 const int EXPECT_2 [] = { 11, 1, 2, 3, 4, 9, 10 };
    185 const int EXPECT_3 [] = { 11, 1, 2, 3, 4, 9, 8, 10 };
    186 const int EXPECT_4 [] = { 11, 2, 3, 4, 9, 8, 10 };
    187 const int EXPECT_5 [] = { 10, 2, 3, 4, 9, 8, 11 };
    188 const int EXPECT_6 [] = { 10, 3, 2, 4, 9, 8, 11 };
    189 const int EXPECT_7 [] = { 10, 9, 2, 4, 3, 8, 11 };
    190 const int EXPECT_8 [] = { 2, 3, 4, 8, 9, 10, 11 };
    191 const int EXPECT_9 [] = { 3, 4, 8, 9, 10, 11 };
    192 const int EXPECT_10 [] = { 3, 4, 8, 9, 10 };
    193 const struct test_data_t test_data[] = {
    194   { .content = EXPECT_0, .size = sizeof(EXPECT_0) / sizeof(EXPECT_0[0]) },
    195   { .content = EXPECT_1, .size = sizeof(EXPECT_1) / sizeof(EXPECT_1[0]) },
    196   { .content = EXPECT_2, .size = sizeof(EXPECT_2) / sizeof(EXPECT_2[0]) },
    197   { .content = EXPECT_3, .size = sizeof(EXPECT_3) / sizeof(EXPECT_3[0]) },
    198   { .content = EXPECT_4, .size = sizeof(EXPECT_4) / sizeof(EXPECT_4[0]) },
    199   { .content = EXPECT_5, .size = sizeof(EXPECT_5) / sizeof(EXPECT_5[0]) },
    200   { .content = EXPECT_6, .size = sizeof(EXPECT_6) / sizeof(EXPECT_6[0]) },
    201   { .content = EXPECT_7, .size = sizeof(EXPECT_7) / sizeof(EXPECT_7[0]) },
    202   { .content = EXPECT_8, .size = sizeof(EXPECT_8) / sizeof(EXPECT_8[0]) },
    203   { .content = EXPECT_9, .size = sizeof(EXPECT_9) / sizeof(EXPECT_9[0]) },
    204   { .content = EXPECT_10, .size = sizeof(EXPECT_10) / sizeof(EXPECT_10[0]) },
    205 };
    206 
    207 int main (void)
    208 {
    209   int failures = 0;
    210 
    211   LinkedListWrapperType wrapper = {
    212     .first = NULL,
    213     .last = NULL,
    214     .size = 0,
    215   };
    216 
    217   /* Append nodes.  */
    218   LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (10));
    219   LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (4));
    220   LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (3));
    221   LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (1));
    222   LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (9));
    223   LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (2));
    224 
    225   failures += ! check ("append", &test_data[0], &wrapper);
    226 
    227   /* Sort nodes (without updating wrapper).  */
    228   wrapper.first =
    229     LINKED_LIST_MERGE_SORT_(ListNodeType) (wrapper.first, compare_nodes);
    230   wrapper.last = find_last_node (wrapper.first);
    231 
    232   failures += ! check ("sort", &test_data[1], &wrapper);
    233 
    234   /* Save a reference to this node for later.  */
    235   ListNodeType *n_to_remove = wrapper.first;
    236 
    237   /* Prepend node.  */
    238   LINKED_LIST_PREPEND(ListNodeType) (&wrapper, l_new_node (11));
    239   failures += ! check ("prepend", &test_data[2], &wrapper);
    240 
    241   /* Insert node.  */
    242   LINKED_LIST_INSERT_BEFORE(ListNodeType) (&wrapper, l_new_node (8), wrapper.last);
    243   failures += ! check ("insert_before", &test_data[3], &wrapper);
    244 
    245   /* Remove a node.  */
    246   LINKED_LIST_REMOVE(ListNodeType) (&wrapper, n_to_remove);
    247   failures += ! check ("remove", &test_data[4], &wrapper);
    248 
    249   /* Swap first and last.  */
    250   LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first, wrapper.last);
    251   failures += ! check ("swap first and last", &test_data[5], &wrapper);
    252 
    253   /* Swap adjacent nodes.  */
    254   LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next,
    255 				  wrapper.first->next->next);
    256   failures += ! check ("swap adjacent nodes", &test_data[6], &wrapper);
    257 
    258   /* Swap non-adjacent nodes, but neither first nor last.  */
    259   LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next,
    260 				  wrapper.first->next->next->next->next);
    261   failures += ! check ("swap non-adjacent nodes", &test_data[7], &wrapper);
    262 
    263   /* Sort nodes.  */
    264   LINKED_LIST_MERGE_SORT(ListNodeType) (&wrapper, compare_nodes);
    265   failures += ! check ("sort", &test_data[8], &wrapper);
    266 
    267   /* Pop front.  */
    268   LINKED_LIST_POP_FRONT(ListNodeType) (&wrapper);
    269   failures += ! check ("pop_front", &test_data[9], &wrapper);
    270 
    271   /* Pop back.  */
    272   LINKED_LIST_POP_BACK(ListNodeType) (&wrapper);
    273   failures += ! check ("pop_back", &test_data[10], &wrapper);
    274 
    275   exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
    276 }
    277