Line data Source code
1 : /***************************************************************************//**
2 :
3 : @file listtest.c
4 :
5 : @author Stephen Brennan
6 :
7 : @date Friday, 6 March 2015
8 :
9 : @brief Libstephen: Generic list tests.
10 :
11 : @copyright Copyright (c) 2013-2015, Stephen Brennan. Released under the
12 : Revised BSD License. See the LICENSE.txt file for details.
13 :
14 : *******************************************************************************/
15 :
16 : #include <string.h>
17 :
18 : #include "libstephen/base.h"
19 : #include "libstephen/list.h"
20 : #include "libstephen/ll.h"
21 : #include "libstephen/al.h"
22 : #include "libstephen/ut.h"
23 : #include "tests.h"
24 :
25 : /*******************************************************************************
26 :
27 : Test Setup
28 :
29 : *******************************************************************************/
30 :
31 : smb_list (*get_list)(void);
32 :
33 : /*******************************************************************************
34 :
35 : Tests
36 :
37 : *******************************************************************************/
38 :
39 2 : int test_append()
40 : {
41 2 : smb_status status = SMB_SUCCESS;
42 : DATA d;
43 2 : smb_list list = get_list();
44 :
45 402 : for (d.data_llint = 0; d.data_llint < 200; d.data_llint++) {
46 : // Put a small, 200 item load on it. This tests appending on
47 : // empty and general appending.
48 400 : list.append(&list, d);
49 400 : TEST_ASSERT(list.length(&list) == d.data_llint + 1);
50 :
51 : // Test that the data is correct.
52 40600 : for (int i = 0; i < list.length(&list); i++) {
53 40200 : TEST_ASSERT(list.get(&list, i, &status).data_llint == i);
54 40200 : TEST_ASSERT(status == SMB_SUCCESS);
55 : }
56 : }
57 :
58 2 : list.delete(&list);
59 2 : return 0;
60 : }
61 :
62 2 : int test_prepend()
63 : {
64 2 : smb_status status = SMB_SUCCESS;
65 : DATA d;
66 2 : smb_list list = get_list();
67 :
68 : // Test prepend about 200 times...
69 402 : for (d.data_llint = 0; d.data_llint < 200; d.data_llint++) {
70 400 : list.prepend(&list, d);
71 400 : TEST_ASSERT(list.length(&list) == d.data_llint + 1);
72 :
73 40600 : for (int i = 0; i < list.length(&list); i++) {
74 40200 : TEST_ASSERT(list.get(&list, i, &status).data_llint == d.data_llint - i);
75 40200 : TEST_ASSERT(status == SMB_SUCCESS);
76 : }
77 : }
78 :
79 2 : list.delete(&list);
80 2 : return 0;
81 : }
82 :
83 2 : int test_set()
84 : {
85 2 : smb_status status = SMB_SUCCESS;
86 : DATA d;
87 2 : smb_list list = get_list();
88 2 : const int length = 30;
89 :
90 : // Create the data
91 62 : for (d.data_llint = 0 ; d.data_llint < length; d.data_llint++) {
92 60 : list.append(&list, d);
93 : }
94 :
95 : // Verify the data
96 62 : for (d.data_llint = 0 ; d.data_llint < length; d.data_llint++) {
97 60 : TEST_ASSERT(list.get(&list, d.data_llint, &status).data_llint == d.data_llint);
98 60 : TEST_ASSERT(status == SMB_SUCCESS);
99 : }
100 :
101 : // Test that the length is correct
102 2 : TEST_ASSERT(list.length(&list) == length);
103 :
104 : // Test set
105 62 : for (int i = 0; i < list.length(&list); i++) {
106 60 : d.data_llint = length - i;
107 60 : list.set(&list, i, d, &status);
108 60 : TEST_ASSERT(status == SMB_SUCCESS);
109 60 : TEST_ASSERT(list.get(&list, i, &status).data_llint == d.data_llint);
110 60 : TEST_ASSERT(status == SMB_SUCCESS);
111 : }
112 :
113 : // Test that the length is still correct
114 2 : TEST_ASSERT(list.length(&list) == length);
115 :
116 2 : list.set(&list, list.length(&list), d, &status);
117 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
118 :
119 2 : status = SMB_SUCCESS;
120 2 : list.get(&list, list.length(&list), &status);
121 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
122 :
123 2 : list.delete(&list);
124 2 : return 0;
125 : }
126 :
127 2 : int test_remove()
128 : {
129 2 : smb_status status = SMB_SUCCESS;
130 : DATA d;
131 2 : smb_list list = get_list();
132 2 : const int length = 20;
133 :
134 : // Create the data
135 42 : for (d.data_llint = 0 ; d.data_llint < length; d.data_llint++) {
136 40 : list.append(&list, d);
137 : }
138 :
139 : // Verify the data
140 42 : for (d.data_llint = 0 ; d.data_llint < length; d.data_llint++) {
141 40 : TEST_ASSERT(list.get(&list, d.data_llint, &status).data_llint == d.data_llint);
142 40 : TEST_ASSERT(status == SMB_SUCCESS);
143 : }
144 :
145 : // Remove first element
146 2 : list.remove(&list, 0, &status);
147 2 : TEST_ASSERT(status == SMB_SUCCESS);
148 2 : TEST_ASSERT(list.length(&list) == length - 1);
149 2 : TEST_ASSERT(list.get(&list, 0, &status).data_llint == 1);
150 2 : TEST_ASSERT(status == SMB_SUCCESS);
151 :
152 : // Remove middle element
153 2 : list.remove(&list, 10, &status); // list[10] == 11 before
154 2 : TEST_ASSERT(status == SMB_SUCCESS);
155 2 : TEST_ASSERT(list.length(&list) == length - 2);
156 2 : TEST_ASSERT(list.get(&list, 10, &status).data_llint == 12);
157 2 : TEST_ASSERT(status == SMB_SUCCESS);
158 :
159 : // Remove last element
160 2 : list.remove(&list, list.length(&list) - 1, &status);
161 2 : TEST_ASSERT(status == SMB_SUCCESS);
162 2 : TEST_ASSERT(list.length(&list) == length - 3);
163 :
164 : // Remove invalid element
165 2 : list.remove(&list, list.length(&list), &status);
166 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
167 2 : status = SMB_SUCCESS;
168 2 : list.remove(&list, -1, &status);
169 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
170 2 : status = SMB_SUCCESS;
171 :
172 : // Test all elements values
173 2 : int value = 1;
174 36 : for (int i = 0; i < length - 3; i++) {
175 34 : if (i == 10) value++;
176 34 : TEST_ASSERT(list.get(&list, i, &status).data_llint == value);
177 34 : TEST_ASSERT(status == SMB_SUCCESS);
178 34 : value++;
179 : }
180 :
181 2 : list.delete(&list);
182 2 : return 0;
183 : }
184 :
185 2 : int test_insert()
186 : {
187 2 : smb_status status = SMB_SUCCESS;
188 : DATA d;
189 2 : smb_list list = get_list();
190 2 : const int length = 20;
191 :
192 : // Create the data
193 42 : for (d.data_llint = 0 ; d.data_llint < length; d.data_llint++) {
194 40 : list.append(&list, d);
195 : }
196 :
197 : // Verify the data
198 42 : for (d.data_llint = 0 ; d.data_llint < length; d.data_llint++) {
199 40 : TEST_ASSERT(list.get(&list, d.data_llint, &status).data_llint == d.data_llint);
200 40 : TEST_ASSERT(status == SMB_SUCCESS);
201 : }
202 :
203 : // Here are the insertions for the test:
204 2 : d.data_llint = 100;
205 2 : list.insert(&list, 0, d);
206 2 : TEST_ASSERT(list.length(&list) == length + 1);
207 :
208 2 : d.data_llint = 101;
209 2 : list.insert(&list, 10, d);
210 2 : TEST_ASSERT(list.length(&list) == length + 2);
211 :
212 2 : d.data_llint = 102;
213 2 : list.insert(&list, list.length(&list), d);
214 2 : TEST_ASSERT(list.length(&list) == length + 3);
215 :
216 :
217 2 : d.data_llint = 101;
218 2 : list.insert(&list, -1, d);
219 2 : TEST_ASSERT(list.length(&list) == length + 4);
220 :
221 2 : d.data_llint = 102;
222 2 : list.insert(&list, list.length(&list) + 1, d);
223 2 : TEST_ASSERT(list.length(&list) == length + 5);
224 :
225 2 : int value = 0;
226 :
227 52 : for (int i = 0; i < list.length(&list); i++) {
228 50 : if (i == 0) {
229 2 : TEST_ASSERT(list.get(&list, i, &status).data_llint == 101);
230 2 : TEST_ASSERT(status == SMB_SUCCESS);
231 48 : } else if (i == 1) {
232 2 : TEST_ASSERT(list.get(&list, i, &status).data_llint == 100);
233 2 : TEST_ASSERT(status == SMB_SUCCESS);
234 46 : } else if (i == 11) {
235 2 : TEST_ASSERT(list.get(&list, i, &status).data_llint == 101);
236 2 : TEST_ASSERT(status == SMB_SUCCESS);
237 44 : } else if (i == list.length(&list) - 2) {
238 2 : TEST_ASSERT(list.get(&list, i, &status).data_llint == 102);
239 2 : TEST_ASSERT(status == SMB_SUCCESS);
240 42 : } else if (i == list.length(&list) - 1) {
241 2 : TEST_ASSERT(list.get(&list, i, &status).data_llint == 102);
242 2 : TEST_ASSERT(status == SMB_SUCCESS);
243 : } else {
244 40 : TEST_ASSERT(list.get(&list, i, &status).data_llint == value);
245 40 : TEST_ASSERT(status == SMB_SUCCESS);
246 40 : value++;
247 : }
248 : }
249 :
250 2 : list.delete(&list);
251 2 : return 0;
252 : }
253 :
254 2 : int test_front(void)
255 : {
256 2 : smb_list list = get_list();
257 2 : smb_status status = SMB_SUCCESS;
258 : DATA d;
259 2 : const int length = 5;
260 :
261 : // Push test data to get 0, 1, 2, 3, 4
262 12 : for (d.data_llint = length-1; d.data_llint >= 0; d.data_llint--) {
263 10 : list.push_front(&list, d);
264 : }
265 :
266 : // Test that peek works correctly with data.
267 2 : TEST_ASSERT(list.peek_front(&list, &status).data_llint == 0);
268 2 : TEST_ASSERT(status == SMB_SUCCESS);
269 :
270 : // Check that pop works correctly.
271 12 : for (d.data_llint = 0; d.data_llint < length; d.data_llint++) {
272 10 : TEST_ASSERT(list.pop_front(&list, &status).data_llint == d.data_llint);
273 10 : TEST_ASSERT(status == SMB_SUCCESS);
274 : }
275 :
276 : // Check that peek and pop will fail correctly.
277 2 : list.peek_front(&list, &status);
278 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
279 2 : status = SMB_SUCCESS;
280 2 : list.pop_front(&list, &status);
281 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
282 :
283 : // Cleanup
284 2 : list.delete(&list);
285 2 : return 0;
286 : }
287 :
288 2 : int test_back(void)
289 : {
290 2 : smb_list list = get_list();
291 2 : smb_status status = SMB_SUCCESS;
292 : DATA d;
293 2 : const int length = 5;
294 :
295 : // Push test data to get 0, 1, 2, 3, 4
296 12 : for (d.data_llint = 0; d.data_llint < length; d.data_llint++) {
297 10 : list.push_back(&list, d);
298 : }
299 :
300 : // Test that peek works correctly with data.
301 2 : TEST_ASSERT(list.peek_back(&list, &status).data_llint == 4);
302 2 : TEST_ASSERT(status == SMB_SUCCESS);
303 :
304 : // Check that pop works correctly.
305 12 : for (d.data_llint = length-1; d.data_llint >= 0; d.data_llint--) {
306 10 : TEST_ASSERT(list.pop_back(&list, &status).data_llint == d.data_llint);
307 10 : TEST_ASSERT(status == SMB_SUCCESS);
308 : }
309 :
310 : // Check that peek and pop will fail correctly.
311 2 : list.peek_back(&list, &status);
312 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
313 2 : status = SMB_SUCCESS;
314 2 : list.pop_back(&list, &status);
315 2 : TEST_ASSERT(status == SMB_INDEX_ERROR);
316 :
317 : // Cleanup
318 2 : list.delete(&list);
319 2 : return 0;
320 : }
321 :
322 2 : int test_index_of(void)
323 : {
324 2 : smb_list list = get_list();
325 2 : smb_status status = SMB_SUCCESS;
326 : DATA d, d2;
327 2 : char *t1 = "I'm a string";
328 : char *t2;
329 2 : int strsize = strlen(t1) + 1;
330 2 : const int length = 20;
331 :
332 : // Make a copy of the test string so pointer comparison won't work.
333 2 : t2 = (char*)smb_new(char, strsize);
334 2 : strncpy(t2, t1, strsize);
335 2 : d.data_ptr = t1;
336 :
337 : // Check that the string won't be found in an empty list.
338 2 : TEST_ASSERT(list.index_of(&list, d, &data_compare_string) == -1);
339 :
340 : // Now add the copy to the list.
341 2 : d2.data_ptr = t2;
342 2 : list.append(&list, d2);
343 :
344 : // Now assert that the string will be found in the list.
345 2 : TEST_ASSERT(list.index_of(&list, d, &data_compare_string) == 0);
346 :
347 2 : smb_free(t2);
348 2 : list.pop_back(&list, &status);
349 :
350 : // Push test data to get 0, 1, 2, 3, 4, ..., 20
351 42 : for (d.data_llint = 0; d.data_llint < length; d.data_llint++) {
352 40 : list.push_back(&list, d);
353 : }
354 :
355 : // Check that it finds the data.
356 42 : for (d.data_llint = 0; d.data_llint < length; d.data_llint++) {
357 40 : TEST_ASSERT(list.index_of(&list, d, NULL) == d.data_llint);
358 : }
359 :
360 2 : list.delete(&list);
361 2 : return 0;
362 : }
363 :
364 : /*******************************************************************************
365 :
366 : Test Runner
367 :
368 : *******************************************************************************/
369 :
370 : /**
371 : @brief Run the tests in this file with a specified description.
372 :
373 : This allows you to set the setup and tear down functions to different values
374 : and run the tests again with a different name.
375 :
376 : @param desc The description for this run through.
377 : */
378 2 : void run_list_tests(char *desc)
379 : {
380 2 : smb_ut_group *group = su_create_test_group(desc);
381 :
382 2 : smb_ut_test *append = su_create_test("append", test_append);
383 2 : su_add_test(group, append);
384 :
385 2 : smb_ut_test *prepend = su_create_test("prepend", test_prepend);
386 2 : su_add_test(group, prepend);
387 :
388 2 : smb_ut_test *set = su_create_test("set", test_set);
389 2 : su_add_test(group, set);
390 :
391 2 : smb_ut_test *remove = su_create_test("remove", test_remove);
392 2 : su_add_test(group, remove);
393 :
394 2 : smb_ut_test *insert = su_create_test("insert", test_insert);
395 2 : su_add_test(group, insert);
396 :
397 2 : smb_ut_test *front = su_create_test("front", test_front);
398 2 : su_add_test(group, front);
399 :
400 2 : smb_ut_test *back = su_create_test("back", test_back);
401 2 : su_add_test(group, back);
402 :
403 2 : smb_ut_test *index_of = su_create_test("index_of", test_index_of);
404 2 : su_add_test(group, index_of);
405 :
406 2 : su_run_group(group);
407 2 : su_delete_group(group);
408 2 : }
409 :
410 : /**
411 : @brief Run the tests on lists.
412 : */
413 1 : void list_test(void)
414 : {
415 1 : get_list = &ll_create_list;
416 1 : run_list_tests("list_ll");
417 :
418 1 : get_list = &al_create_list;
419 1 : run_list_tests("list_al");
420 1 : }
|