The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
lst_tests.c
Go to the documentation of this file.
1#include <freeradius-devel/util/acutest.h>
2#include <freeradius-devel/util/acutest_helpers.h>
3#include <freeradius-devel/util/rand.h>
4#include <freeradius-devel/util/time.h>
5#include <freeradius-devel/util/heap.h>
6
7/*
8 * This counterintuitive #include gives these separately-compiled tests
9 * access to fr_lst_t internals that lst.h doesn't reveal
10 * to those who #include it.
11 */
12#include "lst.c"
13
14typedef struct {
15 unsigned int data;
17 bool visited; /* Only used by iterator test */
18} lst_thing;
19
20#if 0
21static void lst_validate(fr_lst_t *lst);
22#endif
23
24static bool fr_lst_contains(fr_lst_t *lst, void *data)
25{
26 unsigned int size = fr_lst_num_elements(lst);
27
28 for (unsigned int i = 0; i < size; i++) if (item(lst, i + lst->idx) == data) return true;
29
30 return false;
31}
32
33static int8_t lst_cmp(void const *one, void const *two)
34{
35 lst_thing const *item1 = one, *item2 = two;
36
37 return CMP(item1->data, item2->data);
38}
39
40static void populate_values(lst_thing values[], unsigned int len)
41{
42 unsigned int i;
43 fr_fast_rand_t rand_ctx;
44
45 for (i = 0; i < len; i++) {
46 values[i].data = i;
47 values[i].idx = 0;
48 values[i].visited = false;
49 }
50
51 /* shuffle values before insertion, so the heap has to work to give them back in order */
52 rand_ctx.a = fr_rand();
53 rand_ctx.b = fr_rand();
54
55 for (i = 0; i < len; i++) {
56 unsigned int j = fr_fast_rand(&rand_ctx) % len;
57 int temp = values[i].data;
58
59 values[i].data = values[j].data;
60 values[j].data = temp;
61 }
62}
63
64#define NVALUES 20
65static void lst_test_basic(void)
66{
67 fr_lst_t *lst;
68 lst_thing values[NVALUES];
69
70 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, NVALUES);
71 TEST_CHECK(lst != NULL);
72
73 populate_values(values, NUM_ELEMENTS(values));
74
75 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++) {
76 TEST_CHECK(fr_lst_insert(lst, &values[i]) >= 0);
77 TEST_CHECK(fr_lst_entry_inserted(values[i].idx));
78 }
79
80 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++) {
82
83 TEST_CHECK(value != NULL);
85 TEST_CHECK(value->data == i);
86 TEST_MSG("iteration %u, popped %u", i, value->data);
87 }
88 talloc_free(lst);
89}
90
91#define LST_TEST_SIZE (4096)
92
93static void lst_test(int skip)
94{
95 fr_lst_t *lst;
96 int i;
97 lst_thing *values;
98 int left;
99 int ret;
100
101 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
102 TEST_CHECK(lst != NULL);
103
104 values = calloc(LST_TEST_SIZE, sizeof(lst_thing));
105
106 /*
107 * Initialise random values
108 */
110
111 TEST_CASE("insertions");
112 for (i = 0; i < LST_TEST_SIZE; i++) {
113 FR_LST_VERIFY(lst);
114 TEST_CHECK((ret = fr_lst_insert(lst, &values[i])) >= 0);
115 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
116
117 TEST_CHECK(fr_lst_contains(lst, &values[i]));
118 TEST_MSG("element %i inserted but not in LST", i);
119 }
120
121 TEST_CASE("deletions");
122 for (int entry = 0; entry < LST_TEST_SIZE; entry += skip) {
123 FR_LST_VERIFY(lst);
124 TEST_CHECK(values[entry].idx != 0);
125 TEST_MSG("element %i removed out of order", entry);
126
127 TEST_CHECK((ret = fr_lst_extract(lst, &values[entry])) >= 0);
128 TEST_MSG("element %i removal failed, returned %i", entry, ret);
129
130 TEST_CHECK(!fr_lst_contains(lst, &values[entry]));
131 TEST_MSG("element %i removed but still in LST", entry);
132
133 TEST_CHECK(values[entry].idx == 0);
134 TEST_MSG("element %i removed out of order", entry);
135 }
136
137 left = fr_lst_num_elements(lst);
138 for (i = 0; i < left; i++) {
139 FR_LST_VERIFY(lst);
140 TEST_CHECK(fr_lst_pop(lst) != NULL);
141 TEST_MSG("expected %i elements remaining in the lst", left - i);
142 TEST_MSG("failed extracting %i", i);
143 }
144
145 TEST_CHECK((ret = fr_lst_num_elements(lst)) == 0);
146 TEST_MSG("%i elements remaining", ret);
147
148 talloc_free(lst);
149 free(values);
150}
151
152static void lst_test_skip_1(void)
153{
154 lst_test(1);
155}
156
157static void lst_test_skip_2(void)
158{
159 lst_test(2);
160}
161
162static void lst_test_skip_10(void)
163{
164 lst_test(10);
165}
166
167
168static void lst_stress_realloc(void)
169{
170 fr_lst_t *lst;
171 fr_heap_t *hp;
172 lst_thing *lst_array, *hp_array;
173 fr_fast_rand_t rand_ctx;
174 int ret;
175 lst_thing *from_lst, *from_hp;
176
177 rand_ctx.a = fr_rand();
178 rand_ctx.b = fr_rand();
179
180 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
181 TEST_CHECK(lst != NULL);
182 hp = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, 0);
183
184 lst_array = calloc(2 * INITIAL_CAPACITY, sizeof(lst_thing));
185 hp_array = calloc(2 * INITIAL_CAPACITY, sizeof(lst_thing));
186
187 /*
188 * Initialise random values
189 */
190 for (unsigned int i = 0; i < 2 * INITIAL_CAPACITY; i++) {
191 lst_array[i].data = hp_array[i].data = fr_fast_rand(&rand_ctx) % 65537;
192 }
193
194 /* Add the first INITIAL_CAPACITY values to lst and to hp */
195 TEST_CASE("partial fill");
196 for (int i = 0; i < INITIAL_CAPACITY; i++) {
197 TEST_CHECK((ret = fr_lst_insert(lst, &lst_array[i])) >= 0);
198 TEST_MSG("lst insert failed, iteration %d; returned %i - %s", i, ret, fr_strerror());
199 TEST_CHECK((ret = fr_heap_insert(&hp, &hp_array[i])) >= 0);
200 TEST_MSG("heap insert failed, iteration %d; returned %i - %s", i, ret, fr_strerror());
201 }
202
203 /* Pop INITIAL_CAPACITY / 2 values from each (they should all be equal) */
204 TEST_CASE("partial pop");
205 for (unsigned int i = 0; i < INITIAL_CAPACITY / 2; i++) {
206 TEST_CHECK((from_lst = fr_lst_pop(lst)) != NULL);
207 TEST_CHECK((from_hp = fr_heap_pop(&hp)) != NULL);
208 TEST_CHECK(lst_cmp(from_lst, from_hp) == 0);
209 }
210
211 /*
212 * Add the second INITIAL_CAPACITY values to lst and to hp.
213 * This should force lst to move entries to maintain adjacency,
214 * which is what we're testing here.
215 */
216 TEST_CASE("force move with expansion");
217 for (unsigned int i = INITIAL_CAPACITY; i < 2 * INITIAL_CAPACITY; i++) {
218 TEST_CHECK((ret = fr_lst_insert(lst, &lst_array[i])) >= 0);
219 TEST_MSG("lst insert failed, iteration %u; returned %i - %s", i, ret, fr_strerror());
220 TEST_CHECK((ret = fr_heap_insert(&hp, &hp_array[i])) >= 0);
221 TEST_MSG("heap insert failed, iteration %u; returned %i - %s", i, ret, fr_strerror());
222 }
223
224 /* pop the remaining 3 * INITIAL_CAPACITY / 2 values from each (they should all be equal) */
225 TEST_CASE("complete pop");
226 for (unsigned int i = 0; i < 3 * INITIAL_CAPACITY / 2; i++) {
227 TEST_CHECK((from_lst = fr_lst_pop(lst)) != NULL);
228 TEST_CHECK((from_hp = fr_heap_pop(&hp)) != NULL);
229 TEST_CHECK(lst_cmp(from_lst, from_hp) == 0);
230 }
231
234
235 talloc_free(lst);
236 talloc_free(hp);
237 free(lst_array);
238 free(hp_array);
239}
240
241#define BURN_IN_OPS (10000000)
242
243static void lst_burn_in(void)
244{
245 fr_lst_t *lst = NULL;
246 lst_thing *array = NULL;
247 fr_fast_rand_t rand_ctx;
248 int insert_count = 0;
249
250 rand_ctx.a = fr_rand();
251 rand_ctx.b = fr_rand();
252
253 array = calloc(BURN_IN_OPS, sizeof(lst_thing));
254 for (unsigned int i = 0; i < BURN_IN_OPS; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
255
256 /* Make init small to exercise growing the pivot stack. */
257 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 32);
258
259 for (unsigned int i = 0; i < BURN_IN_OPS; i++) {
260 lst_thing *ret_thing = NULL;
261 int ret_insert = -1;
262
263 if (fr_lst_num_elements(lst) == 0) {
264 insert:
265 TEST_CHECK((ret_insert = fr_lst_insert(lst, &array[insert_count])) >= 0);
266 insert_count++;
267 } else {
268 switch (fr_fast_rand(&rand_ctx) % 3) {
269 case 0: /* insert */
270 goto insert;
271
272 case 1: /* pop */
273 ret_thing = fr_lst_pop(lst);
274 TEST_CHECK(ret_thing != NULL);
275 break;
276 case 2: /* peek */
277 ret_thing = fr_lst_peek(lst);
278 TEST_CHECK(ret_thing != NULL);
279 break;
280 }
281 }
282 }
283
284 talloc_free(lst);
285 free(array);
286}
287
288#define LST_CYCLE_SIZE (1600000)
289
290static void lst_cycle(void)
291{
292 fr_lst_t *lst;
293 int i;
294 lst_thing *values;
295 int to_remove;
296 int inserted, removed;
297 int ret;
298 fr_time_t start_insert, start_remove, start_swap, end;
299
300 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
301 TEST_CHECK(lst != NULL);
302
303 values = calloc(LST_CYCLE_SIZE, sizeof(lst_thing));
304
305 /*
306 * Initialise random values
307 */
309
310 start_insert = fr_time();
311 TEST_CASE("insertions");
312 for (i = 0; i < LST_CYCLE_SIZE; i++) {
313 TEST_CHECK((ret = fr_lst_insert(lst, &values[i])) >= 0);
314 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
315 }
317
318 TEST_CASE("pop");
319
320 /*
321 * Remove a random number of elements from the LST
322 */
323 to_remove = fr_lst_num_elements(lst) / 2;
324 start_remove = fr_time();
325 for (i = 0; i < to_remove; i++) {
326 TEST_CHECK(fr_lst_pop(lst) != NULL);
327 TEST_MSG("failed extracting %i", i);
328 TEST_MSG("expected %i elements remaining in the LST", to_remove - i);
329 }
330
331 /*
332 * Now swap the inserted and removed set creating churn
333 */
334 start_swap = fr_time();
335
336 inserted = 0;
337 removed = 0;
338
339 for (i = 0; i < LST_CYCLE_SIZE; i++) {
340 if (values[i].idx == 0) {
341 TEST_CHECK((ret = fr_lst_insert(lst, &values[i])) >= 0);
342 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
343 inserted++;
344 } else {
345 TEST_CHECK((ret = fr_lst_extract(lst, &values[i])) >= 0);
346 TEST_MSG("element %i removal failed, returned %i", i, ret);
347 removed++;
348 }
349 }
350
351 TEST_CHECK(removed == (LST_CYCLE_SIZE - to_remove));
352 TEST_MSG("expected %i", LST_CYCLE_SIZE - to_remove);
353 TEST_MSG("got %i", removed);
354
355 TEST_CHECK(inserted == to_remove);
356 TEST_MSG("expected %i", to_remove);
357 TEST_MSG("got %i", inserted);
358
359 end = fr_time();
360
361 TEST_MSG_ALWAYS("\ncycle size: %d\n", LST_CYCLE_SIZE);
362 TEST_MSG_ALWAYS("insert: %.2fs\n", fr_time_delta_unwrap(fr_time_sub(start_remove, start_insert)) / (double)NSEC);
363 TEST_MSG_ALWAYS("extract: %.2fs\n", fr_time_delta_unwrap(fr_time_sub(start_swap, start_remove)) / (double)NSEC);
364 TEST_MSG_ALWAYS("swap: %.2fs\n", fr_time_delta_unwrap(fr_time_sub(end, start_swap)) / (double)NSEC);
365
366 talloc_free(lst);
367 free(values);
368}
369
370static void lst_iter(void)
371{
372 fr_lst_t *lst;
373 fr_lst_iter_t iter;
374 lst_thing values[NVALUES], *data;
375 unsigned int total;
376
377 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
378 TEST_CHECK(lst != NULL);
379
380 populate_values(values, NUM_ELEMENTS(values));
381
382 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++) TEST_CHECK(fr_lst_insert(lst, &values[i]) == 0);
383
384 data = fr_lst_iter_init(lst, &iter);
385
386 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++, data = fr_lst_iter_next(lst, &iter)) {
387 TEST_CHECK(data != NULL);
388 TEST_CHECK(!data->visited);
389 TEST_CHECK(data->idx > 0);
390 data->visited = true;
391 }
392
393 TEST_CHECK(data == NULL);
394
395 total = 0;
397 total += item->data;
398 }}
399 TEST_CHECK(total = 190);
400
402}
403
404static CC_HINT(noinline) lst_thing *array_pop(lst_thing **array, unsigned int count)
405{
406 lst_thing *low = NULL;
407 unsigned int idx = 0;
408
409 for (unsigned int j = 0; j < count; j++) {
410 if (!array[j]) continue;
411
412 if (!low || (lst_cmp(array[j], low) < 0)) {
413 idx = j;
414 low = array[j];
415 }
416 }
417 if (low) array[idx] = NULL;
418
419 return low;
420}
421
422/** Benchmarks for LSTs vs heaps when used as queues
423 *
424 */
425static void queue_cmp(unsigned int count)
426{
427 fr_lst_t *lst;
428 fr_heap_t *hp;
429
430 lst_thing *values;
431
432 unsigned int i;
433
434 values = talloc_array(NULL, lst_thing, count);
435
436 /*
437 * Check times for LST alloc, insert, pop
438 */
439 {
440 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first = fr_time_wrap(0);
441
442 populate_values(values, count);
443
444 start_alloc = fr_time();
445 lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
446 end_alloc = fr_time();
447 TEST_CHECK(lst != NULL);
448
449 start_insert = fr_time();
450 for (i = 0; i < count; i++) TEST_CHECK(fr_lst_insert(lst, &values[i]) == 0);
451 end_insert = fr_time();
452
453 start_pop = fr_time();
454 for (i = 0; i < count; i++) {
455 TEST_CHECK(fr_lst_pop(lst) != NULL);
456 if (i == 0) end_pop_first = fr_time();
457
458 TEST_MSG("expected %u elements remaining in the lst", count - i);
459 TEST_MSG("failed extracting %u", i);
460 }
461 end_pop = fr_time();
462
463 TEST_MSG_ALWAYS("\nlst size: %u\n", count);
464 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_alloc, start_alloc)) / 1000);
465 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_insert, start_insert)) / 1000);
466 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop_first, start_pop)) / 1000);
467 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop, start_pop)) / 1000);
468
469 talloc_free(lst);
470 }
471
472 /*
473 * Check times for heap alloc, insert, pop
474 */
475 {
476 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first = fr_time_wrap(0);
477
478 populate_values(values, count);
479
480 start_alloc = fr_time();
481 hp = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, count);
482 end_alloc = fr_time();
483 TEST_CHECK(hp != NULL);
484
485 start_insert = fr_time();
486 for (i = 0; i < count; i++) fr_heap_insert(&hp, &values[i]);
487 end_insert = fr_time();
488
489 start_pop = fr_time();
490 for (i = 0; i < count; i++) {
491 TEST_CHECK(fr_heap_pop(&hp) != NULL);
492 if (i == 0) end_pop_first = fr_time();
493
494 TEST_MSG("expected %u elements remaining in the heap", count - i);
495 TEST_MSG("failed extracting %u", i);
496 }
497 end_pop = fr_time();
498
499 TEST_MSG_ALWAYS("\nheap size: %u\n", count);
500 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_alloc, start_alloc)) / 1000);
501 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_insert, start_insert)) / 1000);
502 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop_first, start_pop)) / 1000);
503 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop, start_pop)) / 1000);
504
505 talloc_free(hp);
506 }
507
508 /*
509 * Array
510 */
511 {
512 lst_thing **array;
513 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first;
514
515 populate_values(values, count);
516 end_pop_first = fr_time_wrap(0);
517
518 start_alloc = fr_time();
519 array = talloc_array(NULL, lst_thing *, count);
520 end_alloc = fr_time();
521
522 start_insert = fr_time();
523 for (i = 0; i < count; i++) array[i] = &values[i];
524 end_insert = fr_time();
525
526 start_pop = fr_time();
527 for (i = 0; i < count; i++) {
528 TEST_CHECK(array_pop(array, count) != NULL);
529 if (i == 0) end_pop_first = fr_time();
530 }
531 end_pop = fr_time();
532
533 TEST_MSG_ALWAYS("\narray size: %u\n", count);
534 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_alloc, start_alloc)) / 1000);
535 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_insert, start_insert)) / 1000);
536 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop_first, start_pop)) / 1000);
537 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop, start_pop)) / 1000);
538
539 talloc_free(array);
540 }
541
542 talloc_free(values);
543}
544
545static void queue_cmp_10(void)
546{
547 queue_cmp(10);
548}
549
550static void queue_cmp_50(void)
551{
552 queue_cmp(50);
553}
554
555static void queue_cmp_100(void)
556{
557 queue_cmp(100);
558}
559
560static void queue_cmp_1000(void)
561{
562 queue_cmp(1000);
563}
564
566 /*
567 * Basic tests
568 */
569 { "lst_test_basic", lst_test_basic },
570 { "lst_test_skip_1", lst_test_skip_1 },
571 { "lst_test_skip_2", lst_test_skip_2 },
572 { "lst_test_skip_10", lst_test_skip_10 },
573 { "lst_stress_realloc", lst_stress_realloc },
574 { "lst_burn_in", lst_burn_in },
575 { "lst_cycle", lst_cycle },
576 { "lst_iter", lst_iter },
577 { "queue_cmp_10", queue_cmp_10 },
578 { "queue_cmp_50", queue_cmp_50 },
579 { "queue_cmp_100", queue_cmp_100 },
580 { "queue_cmp_1000", queue_cmp_1000 },
581 { NULL }
582};
#define TEST_MSG_ALWAYS(...)
Definition acutest.h:222
#define TEST_CHECK(cond)
Definition acutest.h:85
#define TEST_CASE(name)
Definition acutest.h:184
#define TEST_MSG(...)
Definition acutest.h:215
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define NUM_ELEMENTS(_t)
Definition build.h:337
Test enumeration values.
Definition dict_test.h:92
#define INITIAL_CAPACITY
Definition heap.c:31
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:146
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:322
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
Definition heap.h:100
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
Definition heap.h:179
The main heap structure.
Definition heap.h:66
free(array)
Functions for a Leftmost Skeleton Tree.
void * fr_lst_iter_next(fr_lst_t *lst, fr_lst_iter_t *iter)
Get the next entry in an LST.
Definition lst.c:785
int fr_lst_extract(fr_lst_t *lst, void *data)
Remove an element from an LST.
Definition lst.c:715
void * fr_lst_iter_init(fr_lst_t *lst, fr_lst_iter_t *iter)
Iterate over entries in LST.
Definition lst.c:766
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition lst.c:122
void * fr_lst_pop(fr_lst_t *lst)
Definition lst.c:695
fr_lst_index_t idx
Starting index, initially zero.
Definition lst.c:62
int fr_lst_insert(fr_lst_t *lst, void *data)
Definition lst.c:731
unsigned int fr_lst_num_elements(fr_lst_t *lst)
Definition lst.c:750
void * fr_lst_peek(fr_lst_t *lst)
Definition lst.c:701
Definition lst.c:60
#define FR_LST_VERIFY(_lst)
Definition lst.h:119
#define fr_lst_alloc(_ctx, _cmp, _type, _field, _init)
Creates an LST that can be used with non-talloced elements.
Definition lst.h:65
static bool fr_lst_entry_inserted(fr_lst_index_t lst_id)
Check if an entry is inserted into an LST.
Definition lst.h:97
fr_lst_index_t fr_lst_iter_t
Definition lst.h:45
unsigned int fr_lst_index_t
Definition lst.h:43
#define fr_lst_foreach(_lst, _type, _data)
Iterate over the contents of an LST.
Definition lst.h:140
static void queue_cmp_100(void)
Definition lst_tests.c:555
static void queue_cmp(unsigned int count)
Benchmarks for LSTs vs heaps when used as queues.
Definition lst_tests.c:425
TEST_LIST
Definition lst_tests.c:565
static lst_thing * array_pop(lst_thing **array, unsigned int count)
Definition lst_tests.c:404
static void lst_test_skip_10(void)
Definition lst_tests.c:162
#define NVALUES
Definition lst_tests.c:64
static void lst_test(int skip)
Definition lst_tests.c:93
unsigned int data
Definition lst_tests.c:15
static int8_t lst_cmp(void const *one, void const *two)
Definition lst_tests.c:33
#define LST_TEST_SIZE
Definition lst_tests.c:91
#define BURN_IN_OPS
Definition lst_tests.c:241
fr_lst_index_t idx
Definition lst_tests.c:16
static void queue_cmp_50(void)
Definition lst_tests.c:550
static void lst_cycle(void)
Definition lst_tests.c:290
static void lst_burn_in(void)
Definition lst_tests.c:243
static void lst_test_basic(void)
Definition lst_tests.c:65
static void lst_iter(void)
Definition lst_tests.c:370
#define LST_CYCLE_SIZE
Definition lst_tests.c:288
static void queue_cmp_1000(void)
Definition lst_tests.c:560
static void lst_test_skip_2(void)
Definition lst_tests.c:157
static void queue_cmp_10(void)
Definition lst_tests.c:545
static bool fr_lst_contains(fr_lst_t *lst, void *data)
Definition lst_tests.c:24
static void lst_test_skip_1(void)
Definition lst_tests.c:152
static void lst_stress_realloc(void)
Definition lst_tests.c:168
static void populate_values(lst_thing values[], unsigned int len)
Definition lst_tests.c:40
bool visited
Definition lst_tests.c:17
talloc_free(lst)
uint32_t fr_fast_rand(fr_fast_rand_t *ctx)
Definition rand.c:279
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
uint32_t b
Definition rand.h:55
uint32_t a
Definition rand.h:55
Smaller fast random number generator.
Definition rand.h:54
return count
Definition module.c:163
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
#define fr_time_wrap(_time)
Definition time.h:145
#define NSEC
Definition time.h:379
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition time.h:229
"server local" time.
Definition time.h:69
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
static fr_slen_t data
Definition value.h:1265