The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
fifo_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 FIFO queue
18 *
19 * @file src/lib/util/test/fifo_tests.c
20 *
21 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
22 */
23#include "acutest.h"
24#include "acutest_helpers.h"
25
26#include <freeradius-devel/util/fifo.h>
27
28#define FIFO_TEST_SIZE 128
29
30static void test_fifo_create(void)
31{
32 fr_fifo_t *fi;
33
34 TEST_CASE("Create a basic fifo");
35 fi = fr_fifo_create(NULL, FIFO_TEST_SIZE, NULL);
36 TEST_ASSERT(fi != NULL);
38
39 talloc_free(fi);
40}
41
42static void test_fifo_create_invalid(void)
43{
44 fr_fifo_t *fi;
45
46 TEST_CASE("max < 2 should fail");
47 fi = fr_fifo_create(NULL, 1, NULL);
48 TEST_CHECK(fi == NULL);
49
50 TEST_CASE("max = 0 should fail");
51 fi = fr_fifo_create(NULL, 0, NULL);
52 TEST_CHECK(fi == NULL);
53
54 TEST_CASE("max too large should fail");
55 fi = fr_fifo_create(NULL, (1024 * 1024) + 1, NULL);
56 TEST_CHECK(fi == NULL);
57}
58
59static void test_fifo_push_pop(void)
60{
61 fr_fifo_t *fi;
62 int values[FIFO_TEST_SIZE];
63 int *p;
64 int i, ret;
65
66 fi = fr_fifo_create(NULL, FIFO_TEST_SIZE, NULL);
67 TEST_ASSERT(fi != NULL);
68
69 TEST_CASE("Push elements");
70 for (i = 0; i < FIFO_TEST_SIZE; i++) {
71 values[i] = i;
72 ret = fr_fifo_push(fi, &values[i]);
73 TEST_CHECK(ret == 0);
74 TEST_MSG("push %d failed, returned %d", i, ret);
75 }
76
78
79 TEST_CASE("Pop elements in FIFO order");
80 for (i = 0; i < FIFO_TEST_SIZE; i++) {
81 p = fr_fifo_pop(fi);
82 TEST_ASSERT(p != NULL);
83
84 TEST_CHECK(*p == i);
85 TEST_MSG("expected %d, got %d", i, *p);
86 }
87
89
90 TEST_CASE("Pop from empty fifo returns NULL");
91 p = fr_fifo_pop(fi);
92 TEST_CHECK(p == NULL);
93
94 talloc_free(fi);
95}
96
97static void test_fifo_peek(void)
98{
99 fr_fifo_t *fi;
100 int a = 10, b = 20;
101 int *p;
102
103 fi = fr_fifo_create(NULL, FIFO_TEST_SIZE, NULL);
104 TEST_ASSERT(fi != NULL);
105
106 TEST_CASE("Peek on empty fifo returns NULL");
107 p = fr_fifo_peek(fi);
108 TEST_CHECK(p == NULL);
109
110 TEST_CASE("Peek returns head without removing it");
111 fr_fifo_push(fi, &a);
112 fr_fifo_push(fi, &b);
113
114 p = fr_fifo_peek(fi);
115 TEST_ASSERT(p != NULL);
116 TEST_CHECK(*p == 10);
118
119 p = fr_fifo_peek(fi);
120 TEST_ASSERT(p != NULL);
121 TEST_CHECK(*p == 10);
123
124 talloc_free(fi);
125}
126
127static void test_fifo_full(void)
128{
129 fr_fifo_t *fi;
130 int values[FIFO_TEST_SIZE + 1];
131 int i, ret;
132
133 fi = fr_fifo_create(NULL, FIFO_TEST_SIZE, NULL);
134 TEST_ASSERT(fi != NULL);
135
136 TEST_CASE("Fill fifo to capacity");
137 for (i = 0; i < FIFO_TEST_SIZE; i++) {
138 values[i] = i;
139 ret = fr_fifo_push(fi, &values[i]);
140 TEST_CHECK(ret == 0);
141 }
142
143 TEST_CASE("Push to full fifo fails");
145 ret = fr_fifo_push(fi, &values[FIFO_TEST_SIZE]);
146 TEST_CHECK(ret < 0);
147
149
150 talloc_free(fi);
151}
152
153static void test_fifo_wraparound(void)
154{
155 fr_fifo_t *fi;
156 int values[FIFO_TEST_SIZE * 2];
157 int *p;
158 int i, ret;
159
160 fi = fr_fifo_create(NULL, FIFO_TEST_SIZE, NULL);
161 TEST_ASSERT(fi != NULL);
162
163 TEST_CASE("Fill, drain, and refill to test circular buffer wraparound");
164 for (int cycle = 0; cycle < 3; cycle++) {
165 int base = cycle * FIFO_TEST_SIZE;
166
167 for (i = 0; i < FIFO_TEST_SIZE; i++) {
168 values[i] = base + i;
169 ret = fr_fifo_push(fi, &values[i]);
170 TEST_CHECK(ret == 0);
171 TEST_MSG("cycle %d, push %d failed", cycle, i);
172 }
173
175
176 for (i = 0; i < FIFO_TEST_SIZE; i++) {
177 p = fr_fifo_pop(fi);
178 TEST_ASSERT(p != NULL);
179
180 TEST_CHECK(*p == base + i);
181 TEST_MSG("cycle %d, expected %d, got %d", cycle, base + i, *p);
182 }
183
185 }
186
187 talloc_free(fi);
188}
189
190static void test_fifo_partial_drain(void)
191{
192 fr_fifo_t *fi;
193 int values[FIFO_TEST_SIZE];
194 int *p;
195 int i;
196
197 fi = fr_fifo_create(NULL, FIFO_TEST_SIZE, NULL);
198 TEST_ASSERT(fi != NULL);
199
200 TEST_CASE("Push half, pop half, push half again");
201 for (i = 0; i < FIFO_TEST_SIZE / 2; i++) {
202 values[i] = i;
203 fr_fifo_push(fi, &values[i]);
204 }
206
207 for (i = 0; i < FIFO_TEST_SIZE / 4; i++) {
208 p = fr_fifo_pop(fi);
209 TEST_ASSERT(p != NULL);
210
211 TEST_CHECK(*p == i);
212 }
214
215 for (i = FIFO_TEST_SIZE / 2; i < FIFO_TEST_SIZE; i++) {
216 values[i] = i;
217 TEST_CHECK(fr_fifo_push(fi, &values[i]) == 0);
218 }
219
220 TEST_CASE("Verify remaining elements are in correct order");
221 for (i = FIFO_TEST_SIZE / 4; i < FIFO_TEST_SIZE; i++) {
222 p = fr_fifo_pop(fi);
223 TEST_ASSERT(p != NULL);
224
225 TEST_CHECK(*p == i);
226 TEST_MSG("expected %d, got %d", i, *p);
227 }
229
230 talloc_free(fi);
231}
232
233static unsigned int free_count;
234
235static void test_free_callback(void *data)
236{
237 (void)data;
238 free_count++;
239}
240
241static void test_fifo_free_callback(void)
242{
243 fr_fifo_t *fi;
244 int values[8];
245 int i;
246
247 free_count = 0;
248
249 fi = fr_fifo_create(NULL, 16, test_free_callback);
250 TEST_ASSERT(fi != NULL);
251
252 TEST_CASE("Free callback is called for remaining elements on destroy");
253 for (i = 0; i < 8; i++) {
254 values[i] = i;
255 fr_fifo_push(fi, &values[i]);
256 }
257
258 talloc_free(fi);
259
261 TEST_MSG("expected 8 free callbacks, got %u", free_count);
262}
263
264static void test_fifo_null_args(void)
265{
266 TEST_CASE("NULL fifo operations don't crash");
267 TEST_CHECK(fr_fifo_pop(NULL) == NULL);
268 TEST_CHECK(fr_fifo_peek(NULL) == NULL);
270}
271
273 { "fifo_create", test_fifo_create },
274 { "fifo_create_invalid", test_fifo_create_invalid },
275 { "fifo_push_pop", test_fifo_push_pop },
276 { "fifo_peek", test_fifo_peek },
277 { "fifo_full", test_fifo_full },
278 { "fifo_wraparound", test_fifo_wraparound },
279 { "fifo_partial_drain", test_fifo_partial_drain },
280 { "fifo_free_callback", test_fifo_free_callback },
281 { "fifo_null_args", test_fifo_null_args },
283};
#define TEST_CHECK(cond)
Definition acutest.h:87
#define TEST_CASE(name)
Definition acutest.h:186
#define TEST_ASSERT(cond)
Definition acutest.h:110
#define TEST_TERMINATOR
Definition acutest.h:64
#define TEST_MSG(...)
Definition acutest.h:217
void * fr_fifo_peek(fr_fifo_t *fi)
Examine the next element that would be popped.
Definition fifo.c:158
unsigned int fr_fifo_num_elements(fr_fifo_t *fi)
Return the number of elements in the fifo queue.
Definition fifo.c:170
int fr_fifo_push(fr_fifo_t *fi, void *data)
Push data onto the fifo.
Definition fifo.c:111
void * fr_fifo_pop(fr_fifo_t *fi)
Pop data off of the fifo.
Definition fifo.c:135
#define fr_fifo_create(_ctx, _max_entries, _node_free)
Creates a fifo.
Definition fifo.h:66
static void test_fifo_full(void)
Definition fifo_tests.c:127
TEST_LIST
Definition fifo_tests.c:272
#define FIFO_TEST_SIZE
Definition fifo_tests.c:28
static void test_free_callback(void *data)
Definition fifo_tests.c:235
static void test_fifo_create_invalid(void)
Definition fifo_tests.c:42
static void test_fifo_peek(void)
Definition fifo_tests.c:97
static unsigned int free_count
Definition fifo_tests.c:233
static void test_fifo_free_callback(void)
Definition fifo_tests.c:241
static void test_fifo_partial_drain(void)
Definition fifo_tests.c:190
static void test_fifo_null_args(void)
Definition fifo_tests.c:264
static void test_fifo_push_pop(void)
Definition fifo_tests.c:59
static void test_fifo_create(void)
Definition fifo_tests.c:30
static void test_fifo_wraparound(void)
Definition fifo_tests.c:153
talloc_free(hp)
static fr_slen_t data
Definition value.h:1340