The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
dlist_tests.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** Tests for the dlist API
18  *
19  * @file src/lib/util/dlist_tests.c
20  *
21  * @copyright 2021 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
22  */
23 
24 #include <freeradius-devel/util/acutest.h>
25 #include <freeradius-devel/util/acutest_helpers.h>
26 
27 #include "dlist.h"
28 
29 typedef struct {
30  char const *id;
33 
34 static void test_dlist_move(void)
35 {
36  fr_dlist_head_t a_list, b_list;
37 
38  dlist_test_item_t a1 = { .id = "a1" };
39  dlist_test_item_t a2 = { .id = "a2" };
40  dlist_test_item_t b1 = { .id = "b1" };
41  dlist_test_item_t b2 = { .id = "b2" };
43 
44  TEST_CASE("Two items - Merge");
45  fr_dlist_init(&a_list, dlist_test_item_t, entry);
46  fr_dlist_init(&b_list, dlist_test_item_t, entry);
47 
48  fr_dlist_insert_tail(&a_list, &a1);
49  fr_dlist_insert_tail(&a_list, &a2);
50 
51  fr_dlist_insert_tail(&b_list, &b1);
52  fr_dlist_insert_tail(&b_list, &b2);
53 
54  fr_dlist_move(&a_list, &b_list);
55 
58 
59  TEST_CASE("Two items - Linking is correct running forwards");
60  p = fr_dlist_head(&a_list);
61  TEST_CHECK_STRCMP(p->id, "a1");
62  p = fr_dlist_next(&a_list, p);
63  TEST_CHECK_STRCMP(p->id, "a2");
64  p = fr_dlist_next(&a_list, p);
65  TEST_CHECK_STRCMP(p->id, "b1");
66  p = fr_dlist_next(&a_list, p);
67  TEST_CHECK_STRCMP(p->id, "b2");
68 
69  p = fr_dlist_next(&a_list, p);
70  TEST_CHECK(p == NULL);
71 
72  TEST_CASE("Two items - Linking is correct running backwards");
73  p = fr_dlist_tail(&a_list);
74  TEST_CHECK_STRCMP(p->id, "b2");
75  p = fr_dlist_prev(&a_list, p);
76  TEST_CHECK_STRCMP(p->id, "b1");
77  p = fr_dlist_prev(&a_list, p);
78  TEST_CHECK_STRCMP(p->id, "a2");
79  p = fr_dlist_prev(&a_list, p);
80  TEST_CHECK_STRCMP(p->id, "a1");
81 
82  p = fr_dlist_prev(&a_list, p);
83  TEST_CHECK(p == NULL);
84 
85  TEST_CASE("Two items - Old list is really empty");
86  TEST_CHECK(fr_dlist_head(&b_list) == NULL);
87  TEST_CHECK(fr_dlist_tail(&b_list) == NULL);
88 
89  TEST_CASE("One item - Merge");
90  fr_dlist_init(&a_list, dlist_test_item_t, entry);
91  fr_dlist_init(&b_list, dlist_test_item_t, entry);
92 
93  fr_dlist_insert_tail(&a_list, &a1);
94  fr_dlist_insert_tail(&b_list, &b1);
95 
96  fr_dlist_move(&a_list, &b_list);
99 
100  TEST_CASE("One item - Linking is correct running forwards");
101  p = fr_dlist_head(&a_list);
102  TEST_CHECK_STRCMP(p->id, "a1");
103  p = fr_dlist_next(&a_list, p);
104  TEST_CHECK_STRCMP(p->id, "b1");
105  p = fr_dlist_next(&a_list, p);
106  TEST_CHECK(p == NULL);
107 
108  TEST_CASE("One item - Linking is correct running backwards");
109  p = fr_dlist_tail(&a_list);
110  TEST_CHECK_STRCMP(p->id, "b1");
111  p = fr_dlist_prev(&a_list, p);
112  TEST_CHECK_STRCMP(p->id, "a1");
113  p = fr_dlist_prev(&a_list, p);
114  TEST_CHECK(p == NULL);
115 
116  TEST_CASE("One item - Old list is really empty");
117  TEST_CHECK(fr_dlist_head(&b_list) == NULL);
118  TEST_CHECK(fr_dlist_tail(&b_list) == NULL);
119 
120 }
121 
122 static void test_dlist_entry_move(void)
123 {
124  dlist_test_item_t a1 = { .id = "a1" };
125  dlist_test_item_t a2 = { .id = "a2" };
126  dlist_test_item_t a3 = { .id = "a3" };
127  dlist_test_item_t b1 = { .id = "b1" };
128  dlist_test_item_t b2 = { .id = "b2" };
129  dlist_test_item_t b3 = { .id = "b3" };
130 
131  a1.entry.next = &a2.entry;
132  a1.entry.prev = &a3.entry;
133  a2.entry.next = &a3.entry;
134  a2.entry.prev = &a1.entry;
135  a3.entry.next = &a1.entry;
136  a3.entry.prev = &a2.entry;
137 
138  b1.entry.next = &b2.entry;
139  b1.entry.prev = &b3.entry;
140  b2.entry.next = &b3.entry;
141  b2.entry.prev = &b1.entry;
142  b3.entry.next = &b1.entry;
143  b3.entry.prev = &b2.entry;
144 
145  TEST_CASE("Three items - Merge");
146  fr_dlist_entry_move(&a1.entry, &b1.entry);
147 
148  TEST_CASE("Three items - Linking is correct running forwards");
149  TEST_CHECK(a1.entry.next == &a2.entry);
150  TEST_CHECK(a2.entry.next == &a3.entry);
151  TEST_CHECK(a3.entry.next == &b1.entry);
152  TEST_CHECK(b1.entry.next == &b2.entry);
153  TEST_CHECK(b2.entry.next == &b3.entry);
154  TEST_CHECK(b3.entry.next == &a1.entry);
155 
156  TEST_CASE("Three items - Linking is correct running backwards");
157  TEST_CHECK(a1.entry.prev == &b3.entry);
158  TEST_CHECK(b3.entry.prev == &b2.entry);
159  TEST_CHECK(b2.entry.prev == &b1.entry);
160  TEST_CHECK(b1.entry.prev == &a3.entry);
161  TEST_CHECK(a3.entry.prev == &a2.entry);
162  TEST_CHECK(a2.entry.prev == &a1.entry);
163 }
164 
165 static void test_dlist_foreach_safe(void)
166 {
167  dlist_test_item_t a1 = { .id = "a1" };
168  dlist_test_item_t a2 = { .id = "a2" };
169  dlist_test_item_t a3 = { .id = "a3" };
170 
172  unsigned int count = 0;
173 
175 
176  fr_dlist_insert_tail(&head, &a1);
177  fr_dlist_insert_tail(&head, &a2);
178  fr_dlist_insert_tail(&head, &a3);
179 
181  fr_dlist_remove(&head, i);
182  count++;
183  }}
184 
185  TEST_CHECK_RET((int)count, (int)3);
186 }
187 
189  /*
190  * Allocation and management
191  */
192  { "fr_dlist_move", test_dlist_move },
193  { "fr_dlist_entry_move", test_dlist_entry_move },
194  { "fr_dlist_foreach_safe", test_dlist_foreach_safe },
195 
196  { NULL }
197 };
#define TEST_CHECK(cond)
Definition: acutest.h:85
#define TEST_CASE(name)
Definition: acutest.h:184
#define TEST_CHECK_LEN(_got, _exp)
#define TEST_CHECK_STRCMP(_got, _exp)
Doubly linked list implementation.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition: dlist.h:260
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition: dlist.h:555
fr_dlist_t * next
Definition: dlist.h:43
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
Definition: dlist.h:939
static void * fr_dlist_tail(fr_dlist_head_t const *list_head)
Return the TAIL item of a list or NULL if the list is empty.
Definition: dlist.h:531
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
Definition: dlist.h:486
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition: dlist.h:378
static int fr_dlist_move(fr_dlist_head_t *list_dst, fr_dlist_head_t *list_src)
Merge two lists, inserting the source at the tail of the destination.
Definition: dlist.h:763
static void fr_dlist_entry_move(fr_dlist_t *dst, fr_dlist_t *src)
Link in a sublist before the current entry.
Definition: dlist.h:206
fr_dlist_t * prev
Definition: dlist.h:42
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition: dlist.h:638
static void * fr_dlist_prev(fr_dlist_head_t const *list_head, void const *ptr)
Get the previous item in a list.
Definition: dlist.h:588
#define fr_dlist_foreach_safe(_list_head, _type, _iter)
Iterate over the contents of a list allowing for removals.
Definition: dlist.h:108
Head of a doubly linked list.
Definition: dlist.h:51
Entry in a doubly linked list.
Definition: dlist.h:41
TEST_LIST
Definition: dlist_tests.c:188
TEST_CHECK_RET((int) count,(int) 3)
static void test_dlist_move(void)
Definition: dlist_tests.c:34
char const * id
Definition: dlist_tests.c:30
fr_dlist_t entry
Definition: dlist_tests.c:31
static void test_dlist_foreach_safe(void)
Definition: dlist_tests.c:165
static void test_dlist_entry_move(void)
Definition: dlist_tests.c:122
return count
Definition: module.c:175
static fr_slen_t head
Definition: xlat.h:408