9#include <freeradius-devel/util/timer.h>
10#include <freeradius-devel/util/slab.h>
32 .interval.value = 1 *
NSEC
56 test_slab_list_t *test_slab_list;
63 test_slab_list = test_slab_list_alloc(NULL, NULL, &
def_slab_config, NULL, NULL, NULL,
true,
false);
66 test_elements[0] = test_slab_reserve(test_slab_list);
75 if (test_elements[0]) test_elements[0]->
name =
talloc_strdup(test_elements[0],
"Hello there");
76 if (test_elements[0]) test_slab_element_set_destructor(test_elements[0],
test_element_free, &test_uctx);
78 test_elements[1] = test_slab_reserve(test_slab_list);
80 TEST_CHECK(test_elements[1] != test_elements[0]);
85 test_elements[2] = test_slab_reserve(test_slab_list);
87 if (test_elements[2]) test_elements[2]->
name =
talloc_strdup(test_elements[2],
"Hello there testing");
88 if (test_elements[2]) test_slab_element_set_destructor(test_elements[2],
test_element_free, &test_uctx2);
92 test_elements[3] = test_slab_reserve(test_slab_list);
98 test_elements[4] = test_slab_reserve(test_slab_list);
104 if (test_elements[0]) test_slab_release(test_elements[0]);
109 if (test_elements[1]) test_slab_release(test_elements[1]);
113 if (test_elements[2]) test_slab_release(test_elements[2]);
126 test_slab_list_t *test_slab_list;
134 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL, NULL, NULL,
true,
false);
137 test_elements[0] = test_slab_reserve(test_slab_list);
142 test_elements[1] = test_slab_reserve(test_slab_list);
143 test_elements[2] = test_slab_reserve(test_slab_list);
144 test_elements[3] = test_slab_reserve(test_slab_list);
150 test_elements[4] = test_slab_reserve(test_slab_list);
163 test_slab_list_t *test_slab_list;
167 test_slab_list = test_slab_list_alloc(NULL, NULL, &
def_slab_config, NULL, NULL, NULL,
true,
false);
170 test_elements[0] = test_slab_reserve(test_slab_list);
177 if (test_elements[0]) test_elements[0]->
name =
talloc_strdup(test_elements[0],
"Hello there");
178 if (test_elements[0]) test_slab_element_set_destructor(test_elements[0],
test_element_free, &test_uctx);
180 test_elements[1] = test_slab_reserve(test_slab_list);
182 TEST_CHECK(test_elements[1] != test_elements[0]);
184 test_elements[2] = test_slab_reserve(test_slab_list);
187 test_elements[3] = test_slab_reserve(test_slab_list);
190 if (test_elements[0]) test_slab_release(test_elements[0]);
198 test_elements[4] = test_slab_reserve(test_slab_list);
200 TEST_CHECK(test_elements[4] == test_elements[0]);
210 if (test_elements[4]) test_elements[4]->
name =
talloc_strdup(test_elements[4],
"Different length string");
211 if (test_elements[4]) test_slab_release(test_elements[4]);
222 test_slab_list_t *test_slab_list;
226 test_slab_list = test_slab_list_alloc(NULL, NULL, &
def_slab_config, NULL, NULL, NULL,
false,
false);
229 test_elements[0] = test_slab_reserve(test_slab_list);
236 if (test_elements[0]) test_elements[0]->
name =
talloc_strdup(test_elements[0],
"Hello there");
237 if (test_elements[0]) test_slab_element_set_destructor(test_elements[0],
test_element_free, &test_uctx);
239 test_elements[1] = test_slab_reserve(test_slab_list);
241 TEST_CHECK(test_elements[1] != test_elements[0]);
243 if (test_elements[0]) test_slab_release(test_elements[0]);
251 test_elements[2] = test_slab_reserve(test_slab_list);
253 TEST_CHECK(test_elements[2] == test_elements[0]);
254 if (test_elements[0] && test_elements[2])
TEST_CHECK(test_elements[2]->
name == test_elements[0]->
name);
261 if (test_elements[2]) test_elements[2]->
name =
talloc_strdup(test_elements[2],
"Different length string");
262 if (test_elements[2]) test_slab_release(test_elements[2]);
274 test_slab_list_t *test_slab_list;
281 test_slab_list = test_slab_list_alloc(NULL, NULL, &
def_slab_config, NULL, NULL, NULL,
true,
false);
284 test_elements[0] = test_slab_reserve(test_slab_list);
287 if (test_elements[0]) test_slab_release(test_elements[0]);
289 test_elements[1] = test_slab_reserve(test_slab_list);
291 TEST_CHECK(test_elements[0] != test_elements[1]);
298 test_slab_list = test_slab_list_alloc(NULL, NULL, &
def_slab_config, NULL, NULL, NULL,
true,
true);
301 test_elements[0] = test_slab_reserve(test_slab_list);
304 if (test_elements[0]) test_slab_release(test_elements[0]);
306 test_elements[1] = test_slab_reserve(test_slab_list);
308 TEST_CHECK(test_elements[0] == test_elements[1]);
318 test_slab_list_t *test_slab_list;
324 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL, NULL, NULL,
true,
false);
327 test_element = test_slab_reserve(test_slab_list);
332 if (test_element) test_element->
name =
talloc_strdup(test_element,
"Hello there");
333 if (test_element) test_slab_element_set_destructor(test_element,
test_element_free, &test_uctx);
356 test_slab_list_t *test_slab_list;
362 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config,
test_element_alloc, NULL, &test_conf,
false,
false);
365 test_elements[0] = test_slab_reserve(test_slab_list);
367 TEST_CHECK(test_elements[0] && (test_elements[0]->num == 10));
372 if (test_elements[0]) {
373 test_elements[0]->
num = 5;
374 test_slab_release(test_elements[0]);
380 test_elements[1] = test_slab_reserve(test_slab_list);
382 TEST_CHECK(test_elements[1] == test_elements[0]);
383 if (test_elements[1])
TEST_CHECK(test_elements[1]->num == 5);
393 test_slab_list_t *test_slab_list;
399 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL,
test_element_alloc, &test_conf,
false,
false);
402 test_elements[0] = test_slab_reserve(test_slab_list);
404 TEST_CHECK(test_elements[0] && (test_elements[0]->num == 10));
409 if (test_elements[0]) {
410 test_elements[0]->
num = 5;
411 test_slab_release(test_elements[0]);
417 test_elements[1] = test_slab_reserve(test_slab_list);
419 TEST_CHECK(test_elements[1] == test_elements[0]);
420 if (test_elements[1])
TEST_CHECK(test_elements[1]->num == 10);
466 test_slab_list_t *test_slab_list;
475 test_elements[0] = test_slab_reserve(test_slab_list);
477 TEST_CHECK(test_elements[0] && (test_elements[0]->num == 20));
482 if (test_elements[0]) {
483 test_elements[0]->
num = 5;
484 test_slab_release(test_elements[0]);
490 test_elements[1] = test_slab_reserve(test_slab_list);
492 TEST_CHECK(test_elements[1] == test_elements[0]);
493 if (test_elements[1])
TEST_CHECK(test_elements[1]->num == 20);
514 test_slab_list_t *test_slab_list;
528 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config,
530 &
count,
false,
false);
533 TEST_CASE(
"Neither callback runs before the first reserve");
537 TEST_CASE(
"The first reserve makes one element and initialises it once");
538 first = test_slab_reserve(test_slab_list);
544 TEST_CASE(
"Reserve, release, reserve does not initialise the element again");
546 for (i = 0; i < 5; i++) {
547 test_slab_release(element);
549 element = test_slab_reserve(test_slab_list);
552 TEST_MSG(
"cycle %u was handed a different element", i);
556 TEST_MSG(
"the alloc callback ran once per reserve rather than once per "
557 "element, so released elements are being rebuilt instead of reused");
576 test_slab_list_t *test_slab_list;
585 test_slab_list = test_slab_list_alloc(NULL,
el, &slab_config, NULL, NULL, NULL,
true,
false);
591 for (i = 0; i < 6; i++) {
592 test_elements[i] = test_slab_reserve(test_slab_list);
601 for (i = 0; i < 4; i++) {
602 test_slab_release(test_elements[i]);
629 test_slab_list_t *test_slab_list;
639 test_slab_list = test_slab_list_alloc(NULL,
el, &slab_config, NULL, NULL, NULL,
true,
false);
645 for (i = 0; i < 20; i++) {
646 test_elements[i] = test_slab_reserve(test_slab_list);
655 for (i = 0; i < 20; i++) {
656 test_slab_release(test_elements[i]);
693 test_slab_list_t *test_slab_list;
703 test_slab_list = test_slab_list_alloc(NULL,
el, &slab_config, NULL, NULL, NULL,
true,
false);
709 for (i = 0; i < 20; i++) {
710 test_elements[i] = test_slab_reserve(test_slab_list);
719 for (i = 0; i < 20; i++) {
720 test_slab_release(test_elements[i]);
786 test_slab_list_t *test_slab_list;
796 test_slab_list = test_slab_list_alloc(NULL,
el, &slab_config, NULL, NULL, NULL,
true,
false);
802 for (i = 0; i < 20; i++) {
803 test_elements[i] = test_slab_reserve(test_slab_list);
812 for (i = 0; i < 20; i++) {
813 test_slab_release(test_elements[i]);
832 for (i = 0; i < 20; i++) {
833 test_elements[i] = test_slab_reserve(test_slab_list);
847 test_slab_list_t *test_slab_list;
854 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL, NULL, NULL,
true,
false);
857 for (i = 0; i < 4; i++) {
858 test_elements[i] = test_slab_reserve(test_slab_list);
864 if (test_elements[0]) test_elements[0]->
name =
talloc_strdup(test_elements[0],
"first");
865 if (test_elements[0]) test_slab_element_set_destructor(test_elements[0],
test_element_free, &test_uctx);
870 if (test_elements[0])
talloc_free(test_elements[0]);
874 if (test_elements[1])
talloc_free(test_elements[1]);
877 if (test_elements[2])
talloc_free(test_elements[2]);
880 if (test_elements[3])
talloc_free(test_elements[3]);
894 test_slab_list_t *test_slab_list;
903 test_slab_list = test_slab_list_alloc(NULL, NULL, &
def_slab_config, NULL, NULL, NULL,
true,
false);
906 for (i = 0; i < 4; i++) {
907 test_elements[i] = test_slab_reserve(test_slab_list);
913 if (test_elements[0]) test_elements[0]->
name =
talloc_strdup(test_elements[0],
"bulk teardown");
914 if (test_elements[0]) test_slab_element_set_destructor(test_elements[0],
test_element_free, &test_uctx);
933 test_slab_list_t *test_slab_list;
939 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL, NULL, NULL,
true,
false);
942 test_elements[0] = test_slab_reserve(test_slab_list);
943 test_elements[1] = test_slab_reserve(test_slab_list);
944 test_elements[2] = test_slab_reserve(test_slab_list);
945 test_elements[3] = test_slab_reserve(test_slab_list);
948 test_uctx1.
count = 0;
949 test_uctx2.
count = 0;
950 if (test_elements[0]) test_elements[0]->
name =
talloc_strdup(test_elements[0],
"release me");
951 if (test_elements[0]) test_slab_element_set_destructor(test_elements[0],
test_element_free, &test_uctx1);
952 if (test_elements[1]) test_elements[1]->
name =
talloc_strdup(test_elements[1],
"free me");
953 if (test_elements[1]) test_slab_element_set_destructor(test_elements[1],
test_element_free, &test_uctx2);
958 if (test_elements[0]) test_slab_release(test_elements[0]);
962 if (test_elements[1])
talloc_free(test_elements[1]);
969 if (test_elements[2]) test_slab_release(test_elements[2]);
972 if (test_elements[3]) test_slab_release(test_elements[3]);
982 test_slab_list_t *test_slab_list;
988 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL, NULL, NULL,
true,
false);
994 test_elements[0] = test_slab_reserve(test_slab_list);
995 test_elements[1] = test_slab_reserve(test_slab_list);
1005 if (test_elements[0])
talloc_free(test_elements[0]);
1012 test_elements[2] = test_slab_reserve(test_slab_list);
1021 test_slab_list_t *test_slab_list;
1028 test_slab_list = test_slab_list_alloc(NULL, NULL, &slab_config, NULL, NULL, NULL,
false,
false);
1031 test_elements[0] = test_slab_reserve(test_slab_list);
1033 test_elements[1] = test_slab_reserve(test_slab_list);
1043 if (test_elements[0]) {
1045 TEST_CHECK((
void *)test_elements[0]->
name > (
void *)test_elements[0]);
1046 if (test_elements[1] && (test_elements[1] > test_elements[0])) {
1047 TEST_CHECK((
void *)test_elements[0]->
name < (
void *)test_elements[1]);
1048 TEST_MSG(
"element 0: %p, name %p, element 1: %p",
1049 test_elements[0], test_elements[0]->
name, test_elements[1]);
#define TEST_ASSERT(cond)
Common initialisation for acutest binaries.
#define TEST_CHECK_RET(_got, _exp)
void fr_event_service(fr_event_list_t *el)
Service any outstanding timer or file descriptor events.
int fr_event_corral(fr_event_list_t *el, fr_time_t now, bool wait)
Gather outstanding timer and file descriptor events.
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
Stores all information relating to an event list.
static fr_event_list_t * events
#define FR_SLAB_FUNCS(_name, _type)
Define type specific wrapper functions for slabs and slab elements.
#define FR_SLAB_TYPES(_name, _type)
Define type specific wrapper structs for slabs and slab elements.
unsigned int min_elements
Minimum number of elements to keep allocated.
unsigned int max_elements
Maximum number of elements to allocate using slabs.
bool at_max_fail
Should requests for additional elements fail when the number in use has reached max_elements.
unsigned int elements_per_slab
Number of elements to allocate per slab.
unsigned int num_children
How many child allocations are expected off each element.
size_t child_pool_size
Size of pool space to be allocated to each element.
bool allow_direct_free
Allow in-use elements to be freed with talloc_free.
Tuneable parameters for slabs.
static fr_time_t test_time(void)
static void test_clearup_3(void)
Test that repeated clearing frees more slabs.
int alloc
Calls to the alloc callback.
static void test_reserve(void)
Test that a reserve callback correctly initialises slab elements.
static fr_time_t test_time_base
static void test_init_reserve(void)
Test that reserve callback runs after init callback.
static fr_slab_config_t def_slab_config
static void test_reserve_mru(void)
Test that setting reserve_mru to true works.
static int test_element_count_alloc(test_element_t *elem, void *uctx)
static void test_clearup_2(void)
Test that slab clearing does not go beyond the minimum.
static void test_reuse_noreset(void)
Test that freeing an element makes it available for reuse with the element not reset between uses.
static void test_child_alloc(void)
static int test_element_reserve(test_element_t *elem, void *uctx)
static void test_clearup_1(void)
Test of clearing unused slabs.
static void test_free(void)
Test that freeing an element results in the destructor being called, and that all accounting is corre...
static void test_alloc(void)
Test basic allocation and reservation of elements.
static void test_reuse_reset(void)
Test that freeing an element makes it available for reuse with the element reset between uses.
static int test_element_free(test_element_t *elem, void *uctx)
static void test_free_and_reserve(void)
Test that reserving after talloc_free of an element still works.
static void test_free_mixed(void)
Test mixed release and talloc_free of elements from the same slab.
int reserve
Calls to the reserve callback.
static void test_alloc_reserve_count(void)
Count the callbacks across a reserve, release, reserve cycle.
static void test_init(void)
Test that a callback correctly initialises slab elements on first use.
static void test_bulk_teardown(void)
Test that talloc free of the slab list with in-use elements does not assert.
static void test_alloc_fail(void)
Test allocation beyond max fails correctly.
static int test_element_alloc(test_element_t *elem, void *uctx)
static void test_realloc(void)
Test that reserving after clearup results in new slab allocation.
static void test_free_multiple(void)
Test that talloc freeing multiple in-use elements correctly updates accounting.
static int test_element_count_reserve(UNUSED test_element_t *elem, void *uctx)
How many times each callback has run.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
#define talloc_strdup(_ctx, _str)
static fr_time_t fr_time_add_time_delta(fr_time_t a, fr_time_delta_t b)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_wrap(_time)
void fr_timer_list_set_time_func(fr_timer_list_t *tl, fr_event_time_source_t func)
Override event list time source.
static fr_event_list_t * el