xref: /curl/tests/unit/unit1300.c (revision 77839133)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 #include "curlcheck.h"
25 
26 #include "llist.h"
27 
28 static struct Curl_llist llist;
29 
30 static struct Curl_llist llist_destination;
31 
test_Curl_llist_dtor(void * key,void * value)32 static void test_Curl_llist_dtor(void *key, void *value)
33 {
34   /* used by the llist API, does nothing here */
35   (void)key;
36   (void)value;
37 }
38 
unit_setup(void)39 static CURLcode unit_setup(void)
40 {
41   Curl_llist_init(&llist, test_Curl_llist_dtor);
42   Curl_llist_init(&llist_destination, test_Curl_llist_dtor);
43   return CURLE_OK;
44 }
45 
unit_stop(void)46 static void unit_stop(void)
47 {
48 }
49 
50 UNITTEST_START
51 {
52   int unusedData_case1 = 1;
53   int unusedData_case2 = 2;
54   int unusedData_case3 = 3;
55   struct Curl_llist_node case1_list;
56   struct Curl_llist_node case2_list;
57   struct Curl_llist_node case3_list;
58   struct Curl_llist_node case4_list;
59   struct Curl_llist_node *head;
60   struct Curl_llist_node *element_next;
61   struct Curl_llist_node *element_prev;
62   struct Curl_llist_node *to_remove;
63   size_t llist_size = Curl_llist_count(&llist);
64 
65   /**
66    * testing llist_init
67    * case 1:
68    * list initiation
69    * @assumptions:
70    * 1: list size will be 0
71    * 2: list head will be NULL
72    * 3: list tail will be NULL
73    * 4: list dtor will be NULL
74   */
75 
76   fail_unless(Curl_llist_count(&llist) == 0,
77               "list initial size should be zero");
78   fail_unless(Curl_llist_head(&llist) == NULL,
79               "list head should initiate to NULL");
80   fail_unless(Curl_llist_tail(&llist) == NULL,
81               "list tail should initiate to NULL");
82 
83   /**
84    * testing Curl_llist_insert_next
85    * case 1:
86    * list is empty
87    * @assumptions:
88    * 1: list size will be 1
89    * 2: list head will hold the data "unusedData_case1"
90    * 3: list tail will be the same as list head
91    */
92 
93   Curl_llist_insert_next(&llist, Curl_llist_head(&llist), &unusedData_case1,
94                          &case1_list);
95 
96   fail_unless(Curl_llist_count(&llist) == 1,
97               "List size should be 1 after adding a new element");
98   /* test that the list head data holds my unusedData */
99   fail_unless(Curl_node_elem(Curl_llist_head(&llist)) == &unusedData_case1,
100               "head ptr should be first entry");
101   /* same goes for the list tail */
102   fail_unless(Curl_llist_tail(&llist) == Curl_llist_head(&llist),
103               "tail and head should be the same");
104 
105   /**
106    * testing Curl_llist_insert_next
107    * case 2:
108    * list has 1 element, adding one element after the head
109    * @assumptions:
110    * 1: the element next to head should be our newly created element
111    * 2: the list tail should be our newly created element
112    */
113 
114   Curl_llist_insert_next(&llist, Curl_llist_head(&llist),
115                          &unusedData_case3, &case3_list);
116   fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
117               &unusedData_case3,
118               "the node next to head is not getting set correctly");
119   fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) == &unusedData_case3,
120               "the list tail is not getting set correctly");
121 
122   /**
123    * testing Curl_llist_insert_next
124    * case 3:
125    * list has >1 element, adding one element after "NULL"
126    * @assumptions:
127    * 1: the element next to head should be our newly created element
128    * 2: the list tail should different from newly created element
129    */
130 
131   Curl_llist_insert_next(&llist, Curl_llist_head(&llist),
132                          &unusedData_case2, &case2_list);
133   fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
134               &unusedData_case2,
135               "the node next to head is not getting set correctly");
136   /* better safe than sorry, check that the tail isn't corrupted */
137   fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) != &unusedData_case2,
138               "the list tail is not getting set correctly");
139 
140   /* unit tests for Curl_node_remove */
141 
142   /**
143    * case 1:
144    * list has >1 element, removing head
145    * @assumptions:
146    * 1: list size will be decremented by one
147    * 2: head will be the head->next
148    * 3: "new" head's previous will be NULL
149    */
150 
151   head = Curl_llist_head(&llist);
152   abort_unless(head, "llist.head is NULL");
153   element_next = Curl_node_next(head);
154   llist_size = Curl_llist_count(&llist);
155 
156   Curl_node_remove(Curl_llist_head(&llist));
157 
158   fail_unless(Curl_llist_count(&llist) ==  (llist_size-1),
159               "llist size not decremented as expected");
160   fail_unless(Curl_llist_head(&llist) == element_next,
161               "llist new head not modified properly");
162   abort_unless(Curl_llist_head(&llist), "llist.head is NULL");
163   fail_unless(Curl_node_prev(Curl_llist_head(&llist)) == NULL,
164               "new head previous not set to null");
165 
166   /**
167    * case 2:
168    * removing non head element, with list having >=2 elements
169    * @setup:
170    * 1: insert another element to the list to make element >=2
171    * @assumptions:
172    * 1: list size will be decremented by one ; tested
173    * 2: element->previous->next will be element->next
174    * 3: element->next->previous will be element->previous
175    */
176   Curl_llist_insert_next(&llist, Curl_llist_head(&llist), &unusedData_case3,
177                          &case4_list);
178   llist_size = Curl_llist_count(&llist);
179   fail_unless(llist_size == 3, "should be 3 list members");
180 
181   to_remove = Curl_node_next(Curl_llist_head(&llist));
182   abort_unless(to_remove, "to_remove is NULL");
183   element_next = Curl_node_next(to_remove);
184   element_prev = Curl_node_prev(to_remove);
185   Curl_node_uremove(to_remove, NULL);
186   fail_unless(Curl_node_next(element_prev) == element_next,
187               "element previous->next is not being adjusted");
188   abort_unless(element_next, "element_next is NULL");
189   fail_unless(Curl_node_prev(element_next) == element_prev,
190               "element next->previous is not being adjusted");
191 
192   /**
193    * case 3:
194    * removing the tail with list having >=1 element
195    * @assumptions
196    * 1: list size will be decremented by one ;tested
197    * 2: element->previous->next will be element->next ;tested
198    * 3: element->next->previous will be element->previous ;tested
199    * 4: list->tail will be tail->previous
200    */
201 
202   to_remove = Curl_llist_tail(&llist);
203   element_prev = Curl_node_prev(to_remove);
204   Curl_node_remove(to_remove);
205   fail_unless(Curl_llist_tail(&llist) == element_prev,
206               "llist tail is not being adjusted when removing tail");
207 
208   /**
209    * case 4:
210    * removing head with list having 1 element
211    * @assumptions:
212    * 1: list size will be decremented by one ;tested
213    * 2: list head will be null
214    * 3: list tail will be null
215    */
216 
217   to_remove = Curl_llist_head(&llist);
218   Curl_node_remove(to_remove);
219   fail_unless(Curl_llist_head(&llist) == NULL,
220               "llist head is not NULL while the llist is empty");
221   fail_unless(Curl_llist_tail(&llist) == NULL,
222               "llist tail is not NULL while the llist is empty");
223 
224   /**
225    * testing Curl_llist_append
226    * case 1:
227    * list is empty
228    * @assumptions:
229    * 1: the element next to head should be our newly created element
230    * 2: the list tail should different from newly created element
231    */
232   Curl_llist_append(&llist, &unusedData_case1, &case1_list);
233   fail_unless(Curl_llist_count(&llist) == 1,
234               "List size should be 1 after appending a new element");
235   /* test that the list head data holds my unusedData */
236   fail_unless(Curl_node_elem(Curl_llist_head(&llist)) == &unusedData_case1,
237               "head ptr should be first entry");
238   /* same goes for the list tail */
239   fail_unless(Curl_llist_tail(&llist) == Curl_llist_head(&llist),
240               "tail and head should be the same");
241 
242   /**
243    * testing Curl_llist_append
244    * case 2:
245    * list is not empty
246    * @assumptions:
247    * 1: the list head-next should be the newly created element
248    * 2: the list tail should be the newly created element
249    */
250   Curl_llist_append(&llist, &unusedData_case2, &case2_list);
251   fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
252               &unusedData_case2,
253               "the node next to head is not getting set correctly");
254   fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) == &unusedData_case2,
255               "the list tail is not getting set correctly");
256 
257   /**
258    * testing Curl_llist_append
259    * case 3:
260    * list is has 2 members
261    * @assumptions:
262    * 1: the list head-next should remain the same
263    * 2: the list tail should be the newly created element
264    */
265   Curl_llist_append(&llist, &unusedData_case3, &case3_list);
266   fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
267               &unusedData_case2,
268               "the node next to head did not stay the same");
269   fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) == &unusedData_case3,
270               "the list tail is not getting set correctly");
271 
272   Curl_llist_destroy(&llist, NULL);
273   Curl_llist_destroy(&llist_destination, NULL);
274 }
275 UNITTEST_STOP
276