The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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
29typedef struct {
30 char const *id;
33
34static 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
122static 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");
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
165static 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
179
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_RET(_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_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 void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition dlist.h:638
fr_dlist_t * next
Definition dlist.h:43
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
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 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
#define fr_dlist_foreach_safe(_list_head, _type, _iter)
Iterate over the contents of a list allowing for removals.
Definition dlist.h:108
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
Head of a doubly linked list.
Definition dlist.h:51
Entry in a doubly linked list.
Definition dlist.h:41
TEST_LIST
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)
static void test_dlist_entry_move(void)
return count
Definition module.c:163
static fr_slen_t head
Definition xlat.h:422