xref: /third_party/curl/tests/unit/unit1300.c (revision 13498266)
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
28static struct Curl_llist llist;
29
30static struct Curl_llist llist_destination;
31
32static 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
39static 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
46static void unit_stop(void)
47{
48}
49
50UNITTEST_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  Curl_llist_destroy(&llist, NULL);
221  Curl_llist_destroy(&llist_destination, NULL);
222}
223UNITTEST_STOP
224