xref: /curl/tests/unit/unit1300.c (revision c296abd4)
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_element case1_list;
56   struct Curl_llist_element case2_list;
57   struct Curl_llist_element case3_list;
58   struct Curl_llist_element case4_list;
59   struct Curl_llist_element *head;
60   struct Curl_llist_element *element_next;
61   struct Curl_llist_element *element_prev;
62   struct Curl_llist_element *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(llist.size == 0, "list initial size should be zero");
77   fail_unless(llist.head == NULL, "list head should initiate to NULL");
78   fail_unless(llist.tail == NULL, "list tail should initiate to NULL");
79   fail_unless(llist.dtor == test_Curl_llist_dtor,
80                "list dtor should initiate to test_Curl_llist_dtor");
81 
82   /**
83    * testing Curl_llist_insert_next
84    * case 1:
85    * list is empty
86    * @assumptions:
87    * 1: list size will be 1
88    * 2: list head will hold the data "unusedData_case1"
89    * 3: list tail will be the same as list head
90    */
91 
92   Curl_llist_insert_next(&llist, llist.head, &unusedData_case1, &case1_list);
93 
94   fail_unless(Curl_llist_count(&llist) == 1,
95               "List size should be 1 after adding a new element");
96   /* test that the list head data holds my unusedData */
97   fail_unless(llist.head->ptr == &unusedData_case1,
98               "head ptr should be first entry");
99   /* same goes for the list tail */
100   fail_unless(llist.tail == llist.head,
101               "tail and head should be the same");
102 
103   /**
104    * testing Curl_llist_insert_next
105    * case 2:
106    * list has 1 element, adding one element after the head
107    * @assumptions:
108    * 1: the element next to head should be our newly created element
109    * 2: the list tail should be our newly created element
110    */
111 
112   Curl_llist_insert_next(&llist, llist.head,
113                          &unusedData_case3, &case3_list);
114   fail_unless(llist.head->next->ptr == &unusedData_case3,
115               "the node next to head is not getting set correctly");
116   fail_unless(llist.tail->ptr == &unusedData_case3,
117               "the list tail is not getting set correctly");
118 
119   /**
120    * testing Curl_llist_insert_next
121    * case 3:
122    * list has >1 element, adding one element after "NULL"
123    * @assumptions:
124    * 1: the element next to head should be our newly created element
125    * 2: the list tail should different from newly created element
126    */
127 
128   Curl_llist_insert_next(&llist, llist.head,
129                          &unusedData_case2, &case2_list);
130   fail_unless(llist.head->next->ptr == &unusedData_case2,
131               "the node next to head is not getting set correctly");
132   /* better safe than sorry, check that the tail isn't corrupted */
133   fail_unless(llist.tail->ptr != &unusedData_case2,
134               "the list tail is not getting set correctly");
135 
136   /* unit tests for Curl_llist_remove */
137 
138   /**
139    * case 1:
140    * list has >1 element, removing head
141    * @assumptions:
142    * 1: list size will be decremented by one
143    * 2: head will be the head->next
144    * 3: "new" head's previous will be NULL
145    */
146 
147   head = llist.head;
148   abort_unless(head, "llist.head is NULL");
149   element_next = head->next;
150   llist_size = Curl_llist_count(&llist);
151 
152   Curl_llist_remove(&llist, llist.head, NULL);
153 
154   fail_unless(Curl_llist_count(&llist) ==  (llist_size-1),
155                "llist size not decremented as expected");
156   fail_unless(llist.head == element_next,
157                "llist new head not modified properly");
158   abort_unless(llist.head, "llist.head is NULL");
159   fail_unless(llist.head->prev == NULL,
160               "new head previous not set to null");
161 
162   /**
163    * case 2:
164    * removing non head element, with list having >=2 elements
165    * @setup:
166    * 1: insert another element to the list to make element >=2
167    * @assumptions:
168    * 1: list size will be decremented by one ; tested
169    * 2: element->previous->next will be element->next
170    * 3: element->next->previous will be element->previous
171    */
172   Curl_llist_insert_next(&llist, llist.head, &unusedData_case3,
173                          &case4_list);
174   llist_size = Curl_llist_count(&llist);
175   fail_unless(llist_size == 3, "should be 3 list members");
176 
177   to_remove = llist.head->next;
178   abort_unless(to_remove, "to_remove is NULL");
179   element_next = to_remove->next;
180   element_prev = to_remove->prev;
181   Curl_llist_remove(&llist, to_remove, NULL);
182   fail_unless(element_prev->next == element_next,
183               "element previous->next is not being adjusted");
184   abort_unless(element_next, "element_next is NULL");
185   fail_unless(element_next->prev == element_prev,
186               "element next->previous is not being adjusted");
187 
188   /**
189    * case 3:
190    * removing the tail with list having >=1 element
191    * @assumptions
192    * 1: list size will be decremented by one ;tested
193    * 2: element->previous->next will be element->next ;tested
194    * 3: element->next->previous will be element->previous ;tested
195    * 4: list->tail will be tail->previous
196    */
197 
198   to_remove = llist.tail;
199   element_prev = to_remove->prev;
200   Curl_llist_remove(&llist, to_remove, NULL);
201   fail_unless(llist.tail == element_prev,
202               "llist tail is not being adjusted when removing tail");
203 
204   /**
205    * case 4:
206    * removing head with list having 1 element
207    * @assumptions:
208    * 1: list size will be decremented by one ;tested
209    * 2: list head will be null
210    * 3: list tail will be null
211    */
212 
213   to_remove = llist.head;
214   Curl_llist_remove(&llist, to_remove, NULL);
215   fail_unless(llist.head == NULL,
216               "llist head is not NULL while the llist is empty");
217   fail_unless(llist.tail == NULL,
218               "llist tail is not NULL while the llist is empty");
219 
220   /**
221    * testing Curl_llist_append
222    * case 1:
223    * list is empty
224    * @assumptions:
225    * 1: the element next to head should be our newly created element
226    * 2: the list tail should different from newly created element
227    */
228   Curl_llist_append(&llist, &unusedData_case1, &case1_list);
229   fail_unless(Curl_llist_count(&llist) == 1,
230               "List size should be 1 after appending a new element");
231   /* test that the list head data holds my unusedData */
232   fail_unless(llist.head->ptr == &unusedData_case1,
233               "head ptr should be first entry");
234   /* same goes for the list tail */
235   fail_unless(llist.tail == llist.head,
236               "tail and head should be the same");
237 
238   /**
239    * testing Curl_llist_append
240    * case 2:
241    * list is not empty
242    * @assumptions:
243    * 1: the list head-next should be the newly created element
244    * 2: the list tail should be the newly created element
245    */
246   Curl_llist_append(&llist, &unusedData_case2, &case2_list);
247   fail_unless(llist.head->next->ptr == &unusedData_case2,
248               "the node next to head is not getting set correctly");
249   fail_unless(llist.tail->ptr == &unusedData_case2,
250               "the list tail is not getting set correctly");
251 
252   /**
253    * testing Curl_llist_append
254    * case 3:
255    * list is has 2 members
256    * @assumptions:
257    * 1: the list head-next should remain the same
258    * 2: the list tail should be the newly created element
259    */
260   Curl_llist_append(&llist, &unusedData_case3, &case3_list);
261   fail_unless(llist.head->next->ptr == &unusedData_case2,
262               "the node next to head did not stay the same");
263   fail_unless(llist.tail->ptr == &unusedData_case3,
264               "the list tail is not getting set correctly");
265 
266 
267 
268   Curl_llist_destroy(&llist, NULL);
269   Curl_llist_destroy(&llist_destination, NULL);
270 }
271 UNITTEST_STOP
272