1 /**
2  * @file     check_element.c
3  * @brief    Unit testing for SCEW lists
4  * @author   Aleix Conchillo Flaque <aconchillo@gmail.com>
5  * @date     Fri Aug 03, 2007 17:11
6  *
7  * @if copyright
8  *
9  * Copyright (C) 2007-2009 Aleix Conchillo Flaque
10  *
11  * SCEW is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * SCEW is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24  * 02110-1301, USA.
25  *
26  * @endif
27  */
28 
29 #include "test.h"
30 
31 #include <scew/list.h>
32 
33 #include <check.h>
34 
35 
36 /* Private */
37 
38 typedef struct
39 {
40   int value;
41 } item_t;
42 
43 enum { N_ELEMENTS_ = 10 };
44 
45 static item_t data_[N_ELEMENTS_];
46 
47 
48 /* Unit tests */
49 
50 /* Allocation */
51 
START_TEST(test_alloc)52 START_TEST (test_alloc)
53 {
54   item_t data = { 3 };
55 
56   scew_list *list = scew_list_create (&data);
57 
58   CHECK_PTR (list, "Unable to create list");
59 
60   CHECK_BOOL (scew_list_data (list) == &data, SCEW_TRUE,
61               "Invalid data pointer");
62 
63   scew_list_free (list);
64 }
65 END_TEST
66 
67 
68 /* Accessors */
69 
START_TEST(test_accessors)70 START_TEST (test_accessors)
71 {
72   /* Add items to list */
73   scew_list *list = NULL;
74   scew_list *last = NULL;
75   unsigned int i = 0;
76   for (i = 0; i < N_ELEMENTS_; ++i)
77     {
78       last = scew_list_append (last, &data_[i]);
79 
80       CHECK_PTR (last, "Unable to append item %d", i);
81       CHECK_BOOL (scew_list_data (last) == &data_[i], SCEW_TRUE,
82                   "Invalid data pointer (item %d)", i);
83 
84       item_t *tmp = scew_list_data (last);
85       CHECK_S_INT (tmp->value, i, "Invalid data value (item %d)", i);
86 
87       if (list == NULL)
88         {
89           list = last;
90           CHECK_NULL_PTR (scew_list_previous (list),
91                           "First item should have no previous");
92         }
93     }
94 
95   CHECK_U_INT (scew_list_size (list), N_ELEMENTS_, "Number of items mismatch");
96 
97   scew_list_free (list);
98 }
99 END_TEST
100 
101 
102 /* Append */
103 
START_TEST(test_append)104 START_TEST (test_append)
105 {
106   /* Append items to list */
107   scew_list *list = NULL;
108   unsigned int i = 0;
109   for (i = 0; i < N_ELEMENTS_; ++i)
110     {
111       scew_list *item = scew_list_append (list, &data_[i]);
112       if (list == NULL)
113         {
114           list = item;
115         }
116       CHECK_PTR (item, "Unable to append item %d", i);
117       CHECK_BOOL (scew_list_data (item) == &data_[i], SCEW_TRUE,
118                   "Invalid data pointer (item %d)", i);
119 
120       item_t *tmp = scew_list_data (item);
121       CHECK_S_INT (tmp->value, i, "Invalid data value (item %d)", i);
122     }
123 
124   CHECK_U_INT (scew_list_size (list), N_ELEMENTS_, "Number of items mismatch");
125 
126   scew_list_free (list);
127 }
128 END_TEST
129 
130 
131 /* Prepend */
132 
START_TEST(test_prepend)133 START_TEST (test_prepend)
134 {
135   /* Prepend items to list */
136   scew_list *list = NULL;
137   unsigned int i = 0;
138   for (i = 0; i < N_ELEMENTS_; ++i)
139     {
140       list = scew_list_prepend (list, &data_[i]);
141 
142       CHECK_PTR (list, "Unable to prepend item %d", i);
143       CHECK_BOOL (scew_list_data (list) == &data_[i], SCEW_TRUE,
144                   "Invalid data pointer (item %d)", i);
145 
146       item_t *tmp = scew_list_data (list);
147       CHECK_S_INT (tmp->value, i, "Invalid data value (item %d)", i);
148     }
149 
150   CHECK_U_INT (scew_list_size (list), N_ELEMENTS_, "Number of items mismatch");
151 
152   scew_list_free (list);
153 }
154 END_TEST
155 
156 
157 /* Delete */
158 
START_TEST(test_delete)159 START_TEST (test_delete)
160 {
161   /* Append items to list */
162   scew_list *list = NULL;
163   unsigned int i = 0;
164   for (i = 0; i < N_ELEMENTS_; ++i)
165     {
166       scew_list *item = scew_list_append (list, &data_[i]);
167       if (list == NULL)
168         {
169           list = item;
170         }
171     }
172 
173   /* Delete items 2 and 6 */
174   list = scew_list_delete (list, &data_[2]);
175   list = scew_list_delete (list, &data_[6]);
176 
177   CHECK_U_INT (scew_list_size (list), N_ELEMENTS_ - 2,
178              "Number of items mismatch");
179 
180   /* Delete item 1 */
181   scew_list *item = scew_list_next (list);
182   list = scew_list_delete_item (list, item);
183 
184   CHECK_U_INT (scew_list_size (list), N_ELEMENTS_ - 3,
185              "Number of items mismatch");
186 
187   /* Check for all remaining items */
188   enum { N_REMOVED = 3 };
189   unsigned int const REMOVED[N_REMOVED] = { 1, 2, 6 };
190   item = list;
191   while (item != NULL)
192     {
193       item_t *tmp = scew_list_data (item);
194       unsigned int j = 0;
195       for (j = 0; j < N_REMOVED; ++j)
196         {
197           CHECK_BOOL (tmp->value != REMOVED[j], SCEW_TRUE,
198                       "Item %d should have been previously removed",
199                       tmp->value);
200         }
201       item = scew_list_next (item);
202     }
203 
204   scew_list_free (list);
205 }
206 END_TEST
207 
208 
209 /* Traverse */
210 
START_TEST(test_traverse)211 START_TEST (test_traverse)
212 {
213   /* Append items to list */
214   scew_list *item = NULL;
215   scew_list *list = NULL;
216   unsigned int i = 0;
217   for (i = 0; i < N_ELEMENTS_; ++i)
218     {
219       item = scew_list_append (list, &data_[i]);
220       if (list == NULL)
221         {
222           list = item;
223         }
224     }
225 
226   CHECK_BOOL (list == scew_list_first (list), SCEW_TRUE,
227               "First list item should be itself");
228 
229   CHECK_BOOL (item == scew_list_last (list), SCEW_TRUE,
230               "Last list item should be last item added");
231 
232   CHECK_NULL_PTR (scew_list_previous (list),
233               "First previous item should be NULL");
234 
235   CHECK_NULL_PTR (scew_list_next (item),
236               "Last next item should be NULL");
237 
238   item = list;
239   while (item != NULL)
240     {
241       scew_list *old_item = item;
242 
243       item = scew_list_next (item);
244 
245       if (item != NULL)
246         {
247           CHECK_BOOL (old_item == scew_list_previous (item), SCEW_TRUE,
248                       "Wrong previous item");
249         }
250     }
251 }
252 END_TEST
253 
254 
255 /* Traverse (foreach) */
256 
257 static unsigned int foreach_calls_ = 0; /* keep track of number of calls */
258 
259 static void
foreach_check_(scew_list * item,void * user_data)260 foreach_check_ (scew_list *item, void *user_data)
261 {
262   item_t *fe_data = (item_t *) user_data;
263 
264   item_t *tmp = scew_list_data (item);
265 
266   CHECK_BOOL (tmp == &fe_data[foreach_calls_], SCEW_TRUE,
267               "Data pointer does not match in foreach call");
268 
269   CHECK_S_INT (tmp->value, foreach_calls_,
270                "Invalid data value in foreach call (item %d)", foreach_calls_);
271 
272   ++foreach_calls_;
273 }
274 
START_TEST(test_traverse_foreach)275 START_TEST (test_traverse_foreach)
276 {
277   /* Append items to list */
278   scew_list *list = NULL;
279   unsigned int i = 0;
280   for (i = 0; i < N_ELEMENTS_; ++i)
281     {
282       scew_list *item = scew_list_append (list, &data_[i]);
283       if (list == NULL)
284         {
285           list = item;
286         }
287     }
288 
289   foreach_calls_ = 0;
290 
291   scew_list_foreach (list, foreach_check_, data_);
292 
293   CHECK_U_INT (foreach_calls_, N_ELEMENTS_,
294                "Number of foreach calls mismatch");
295 }
296 END_TEST
297 
298 
299 /* Search */
300 
301 static scew_bool
search_cmp_(void const * a,void const * b)302 search_cmp_ (void const *a, void const *b)
303 {
304   return (((item_t *) a)->value == ((item_t *) b)->value);
305 }
306 
START_TEST(test_search)307 START_TEST (test_search)
308 {
309   /* Append items to list */
310   scew_list *item_5 = NULL;
311   scew_list *list = NULL;
312   unsigned int i = 0;
313   for (i = 0; i < N_ELEMENTS_; ++i)
314     {
315       scew_list *item = scew_list_append (list, &data_[i]);
316       if (i == 5)
317         {
318           item_5 = item;
319         }
320       if (list == NULL)
321         {
322           list = item;
323         }
324     }
325 
326   CHECK_BOOL (item_5 == scew_list_find (list, &data_[5]), SCEW_TRUE,
327               "Item 5 search failed");
328 
329   item_t value_5 = { 5 };
330   CHECK_BOOL (item_5 == scew_list_find_custom (list, &value_5, search_cmp_),
331               SCEW_TRUE, "Item 5 custom search failed");
332 
333   /* Sequential indexing */
334   scew_list *item = list;
335   for (i = 0; i < N_ELEMENTS_; ++i)
336     {
337       CHECK_BOOL (item == scew_list_index (list, i), SCEW_TRUE,
338                   "Sequential index item mismatch");
339       item = scew_list_next (item);
340     }
341 
342   CHECK_NULL_PTR (scew_list_index (list, N_ELEMENTS_),
343                   "Sequential index out of range");
344 }
345 END_TEST
346 
347 
348 /* Suite */
349 
350 static Suite*
list_suite(void)351 list_suite (void)
352 {
353   Suite *s = suite_create ("SCEW lists");
354 
355   /* Setup items */
356   unsigned int i = 0;
357   for (i = 0; i < N_ELEMENTS_; ++i)
358     {
359       data_[i].value = i;
360     }
361 
362   /* Core test case */
363   TCase *tc_core = tcase_create ("Core");
364   tcase_add_test (tc_core, test_alloc);
365   tcase_add_test (tc_core, test_accessors);
366   tcase_add_test (tc_core, test_append);
367   tcase_add_test (tc_core, test_prepend);
368   tcase_add_test (tc_core, test_delete);
369   tcase_add_test (tc_core, test_traverse);
370   tcase_add_test (tc_core, test_traverse_foreach);
371   tcase_add_test (tc_core, test_search);
372   suite_add_tcase (s, tc_core);
373 
374   return s;
375 }
376 
377 void
run_tests(SRunner * sr)378 run_tests (SRunner *sr)
379 {
380   srunner_add_suite (sr, list_suite ());
381 }
382