25#include <freeradius-devel/util/talloc.h>
43 TEST_CASE(
"talloc allocates child of context");
50 TEST_CASE(
"talloc_size allocates arbitrary size");
51 s = talloc_size(ctx, 100);
71 TEST_CASE(
"talloc_zero initializes to zero");
72 p = talloc_zero(ctx,
int);
76 TEST_CASE(
"talloc_zero_size initializes to zero");
77 buf = talloc_zero_size(ctx, 64);
79 for (i = 0; i < 64; i++) {
97 TEST_CASE(
"talloc_array allocates typed array");
98 arr = talloc_array(ctx,
int, 10);
100 TEST_CHECK(talloc_get_size(arr) == 10 *
sizeof(
int));
101 for (i = 0; i < 10; i++) arr[i] = (
int)i;
102 for (i = 0; i < 10; i++)
TEST_CHECK(arr[i] == (
int)i);
104 TEST_CASE(
"talloc_zero_array initializes to zero");
105 arr = talloc_zero_array(ctx,
int, 5);
107 for (i = 0; i < 5; i++)
TEST_CHECK(arr[i] == 0);
109 TEST_CASE(
"talloc_realloc grows array preserving content");
110 arr = talloc_array(ctx,
int, 4);
111 for (i = 0; i < 4; i++) arr[i] = (
int)(i + 100);
112 arr = talloc_realloc(ctx, arr,
int, 8);
114 for (i = 0; i < 4; i++)
TEST_CHECK(arr[i] == (
int)(i + 100));
115 TEST_CHECK(talloc_get_size(arr) == 8 *
sizeof(
int));
117 TEST_CASE(
"talloc_realloc shrinks array");
118 arr = talloc_realloc(ctx, arr,
int, 2);
122 TEST_CHECK(talloc_get_size(arr) == 2 *
sizeof(
int));
133 int *child1, *child2;
135 TEST_CASE(
"talloc_free(NULL) returns -1");
138 TEST_CASE(
"talloc_free recursively frees children");
140 child1 = talloc(ctx,
int);
142 child2 = talloc(child1,
int);
158 TEST_CASE(
"talloc_set_name_const / talloc_get_name roundtrip");
159 p = talloc_size(ctx, 10);
160 talloc_set_name_const(p,
"my_chunk");
161 TEST_CHECK(strcmp(talloc_get_name(p),
"my_chunk") == 0);
163 TEST_CASE(
"talloc_check_name succeeds on match");
164 TEST_CHECK(talloc_check_name(p,
"my_chunk") == p);
166 TEST_CASE(
"talloc_check_name returns NULL on mismatch");
167 TEST_CHECK(talloc_check_name(p,
"wrong_name") == NULL);
169 TEST_CASE(
"talloc_named_const sets name at creation");
170 p = talloc_named_const(ctx, 20,
"named_chunk");
172 TEST_CHECK(strcmp(talloc_get_name(p),
"named_chunk") == 0);
187 TEST_CASE(
"talloc_parent returns correct parent");
188 child = talloc(ctx,
int);
191 TEST_CASE(
"talloc_parent_name returns parent's name");
192 TEST_CHECK(strcmp(talloc_parent_name(child),
"test_parent") == 0);
194 TEST_CASE(
"talloc_parent of top-level returns NULL context");
200 void *
parent = talloc_parent(ctx);
212 TALLOC_CTX *ctx1, *ctx2;
219 TEST_CASE(
"talloc_steal moves child to new parent");
220 p = talloc(ctx1,
int);
223 ret = talloc_steal(ctx2, p);
228 TEST_CASE(
"talloc_steal NULL returns NULL");
231 TEST_CASE(
"talloc_steal to NULL reparents to null context");
232 p = talloc(ctx1,
int);
233 ret = talloc_steal(NULL, p);
246 TALLOC_CTX *ctx1, *ctx2;
252 TEST_CASE(
"talloc_move transfers ownership and NULLs source");
253 p = talloc(ctx1,
int);
255 moved = talloc_move(ctx2, &p);
270 TALLOC_CTX *ctx1, *ctx2;
277 TEST_CASE(
"talloc_reference creates a reference");
279 ref = talloc_reference(ctx2, str);
283 TEST_CASE(
"talloc_unlink removes the reference");
287 TEST_CASE(
"Multiple references increment count");
288 talloc_reference(ctx2, str);
289 talloc_reference(ctx2, str);
318 p = talloc(ctx,
int);
324 TEST_CASE(
"Destructor returning -1 prevents free");
331 p = talloc(ctx,
int);
349 TEST_CASE(
"talloc_strdup duplicates string");
355 TEST_CASE(
"talloc_strndup limits length");
360 TEST_CASE(
"talloc_strdup of NULL returns NULL");
377 TEST_CASE(
"talloc_asprintf formats string");
382 TEST_CASE(
"talloc_asprintf_append appends at string end");
384 s = talloc_asprintf_append(s,
" %s",
"world");
388 TEST_CASE(
"talloc_asprintf_append_buffer appends at buffer end");
390 s = talloc_asprintf_append_buffer(s,
"def");
405 TEST_CASE(
"talloc_pool creates a pool context");
406 pool = talloc_pool(NULL, 1024);
409 TEST_CASE(
"Allocations from pool succeed");
410 a = talloc(pool,
int);
411 b = talloc(pool,
int);
412 c = talloc(pool,
int);
416 *a = 1; *b = 2; *c = 3;
421 TEST_CASE(
"Pool children have pool as parent");
438 TEST_CASE(
"talloc_free_children frees all children");
440 p = talloc(ctx,
int);
442 p = talloc(ctx,
int);
444 p = talloc(ctx,
int);
449 talloc_free_children(ctx);
452 TEST_CASE(
"Context is still usable after free_children");
453 p = talloc(ctx,
int);
467 size_t total_size, total_blocks;
471 TEST_CASE(
"Empty context has size 0 and 1 block");
475 TEST_CASE(
"Allocations increase totals");
476 talloc_size(ctx, 100);
477 talloc_size(ctx, 200);
478 total_size = talloc_total_size(ctx);
479 total_blocks = talloc_total_blocks(ctx);
483 TEST_CASE(
"Nested children counted in totals");
485 void *child = talloc_size(ctx, 50);
486 talloc_size(child, 25);
504 TEST_CASE(
"talloc_get_size returns requested size");
505 p = talloc_size(ctx, 42);
508 TEST_CASE(
"talloc_get_size of NULL returns 0");
511 TEST_CASE(
"talloc_get_size after realloc returns new size");
512 p = talloc_realloc_size(ctx, p, 100);
523 TALLOC_CTX *root, *mid;
527 root = talloc_named_const(NULL, 0,
"root_ctx");
528 mid = talloc_named_const(root, 0,
"mid_ctx");
529 leaf = talloc(mid,
int);
531 TEST_CASE(
"Find existing parent by name");
532 found = talloc_find_parent_byname(leaf,
"root_ctx");
535 found = talloc_find_parent_byname(leaf,
"mid_ctx");
538 TEST_CASE(
"Return NULL for non-existent parent name");
539 found = talloc_find_parent_byname(leaf,
"nonexistent");
550 TALLOC_CTX *root, *mid;
554 mid = talloc(root,
char);
555 leaf = talloc(mid,
int);
561 TEST_CHECK(talloc_is_parent(leaf, root) == 1);
566 TEST_CHECK(talloc_is_parent(leaf, other) == 0);
578 TALLOC_CTX *old_parent, *new_parent;
585 TEST_CASE(
"talloc_reparent moves from old to new parent");
586 p = talloc(old_parent,
int);
588 ret = talloc_reparent(old_parent, new_parent, p);
593 TEST_CASE(
"talloc_reparent NULL returns NULL");
594 ret = talloc_reparent(old_parent, new_parent, NULL);
607 uint8_t src[] = {0x01, 0x02, 0x03, 0x04};
612 TEST_CASE(
"talloc_memdup duplicates bytes");
613 dup = talloc_memdup(ctx, src,
sizeof(src));
615 TEST_CHECK(memcmp(dup, src,
sizeof(src)) == 0);
616 TEST_CHECK(talloc_get_size(dup) ==
sizeof(src));
634 TEST_CASE(
"Deep hierarchy (100 levels) works");
635 for (i = 0; i < 100; i++) {
636 current = talloc_size(current, 16);
640 TEST_CASE(
"Total blocks counts all levels");
643 TEST_CASE(
"Free cleans up entire hierarchy");
657 TEST_CASE(
"talloc_strndup_append appends limited length");
659 s = talloc_strndup_append(s,
" world!!", 6);
663 TEST_CASE(
"talloc_strndup_append_buffer appends at buffer end");
665 s = talloc_strndup_append_buffer(s,
"defgh", 3);
683 TEST_CASE(
"increase_ref_count succeeds");
685 ret = talloc_increase_ref_count(str);
690 ret = talloc_increase_ref_count(str);
704 ret = talloc_total_blocks(ctx);
738 TEST_CASE(
"Duplicate NULL returns NULL");
782 TEST_CHECK(strcmp(str,
"hello world 42") == 0);
802 TEST_CASE(
"Duplicate string with embedded NUL");
809 TEST_CASE(
"Duplicate zero-length string");
832 TEST_CHECK(strcmp(result,
"hello world") == 0);
834 TEST_CASE(
"Append to NULL creates new string");
852 TEST_CASE(
"Realloc NULL allocates new buffer");
856 TEST_CHECK(talloc_array_length(result) == 11);
858 TEST_CASE(
"Realloc existing buffer to smaller size");
876 uint8_t data4a[] = {1, 2, 3, 4};
877 uint8_t data4b[] = {1, 2, 4, 4};
894 TEST_CASE(
"Same length, different content");
956 TEST_CASE(
"Concatenate two talloc strings");
962 TEST_CHECK(strcmp(result,
"hello world") == 0);
966 TEST_CASE(
"NULL first arg returns NULL");
974 TEST_CASE(
"NULL second arg returns NULL");
988 void **array, **result;
993 array = talloc_array(ctx,
void *, 3);
994 array[0] = (
void *)1;
995 array[1] = (
void *)2;
996 array[2] = (
void *)3;
1006 TEST_CHECK(talloc_array_length(result) == 3);
1008 TEST_CASE(
"NULL terminate NULL returns NULL");
1011 TEST_CASE(
"NULL strip NULL returns NULL");
1032 TALLOC_CTX *ctx, *fire;
1037 TEST_CASE(
"Destructor fires when fire_ctx is freed");
1039 fire = talloc(ctx,
int);
1046 TEST_CASE(
"Manual disarm via talloc_destructor_disarm");
1048 fire = talloc(ctx,
int);
1055 TEST_CASE(
"NULL fire_ctx returns NULL");
1067 TALLOC_CTX *
parent, *child;
1070 TEST_CASE(
"Child freed when parent freed");
1085 TEST_CASE(
"Header size is positive and reasonable");
1091 TEST_CASE(
"Repeated calls return same value");
1120 TEST_CASE(
"Allocate children in order");
1123 v1 = talloc(c1,
int);
1129 v2 = talloc(c2,
int);
1135 v3 = talloc(c3,
int);
1139 TEST_CASE(
"Children freed in FILO order");
1162 arr = talloc_array(ctx,
uint8_t, 4);
1164 memset(arr, 0xff, 4);
1166 TEST_CASE(
"Realloc larger zeros new portion");
1171 for (i = 0; i < 4; i++) {
1176 for (i = 4; i < 16; i++) {
1188 TALLOC_CTX *ctx, *ref_ctx;
1195 TEST_CASE(
"Decrease ref count with no references frees memory");
1204 TEST_CASE(
"With a reference, unlinks instead of freeing");
1206 talloc_reference(ref_ctx, str);
1219 TALLOC_CTX *ctx, *array;
1221 size_t page_size = (
size_t)getpagesize();
1225 TEST_CASE(
"Aligned array returns non-NULL");
1230 TEST_CASE(
"Start address is page-aligned");
1231 TEST_CHECK(((uintptr_t)start % page_size) == 0);
#define TEST_ASSERT(cond)
void ** talloc_array_null_terminate(void **array)
Add a NULL pointer to an array of pointers.
TALLOC_CHILD_CTX * talloc_child_ctx_alloc(TALLOC_CHILD_CTX *parent)
Allocate a TALLOC_CHILD_CTX from a parent.
fr_talloc_destructor_t * talloc_destructor_add(TALLOC_CTX *fire_ctx, TALLOC_CTX *disarm_ctx, fr_talloc_free_func_t func, void const *uctx)
Add an additional destructor to a talloc chunk.
ssize_t talloc_hdr_size(void)
Calculate the size of the talloc chunk header.
TALLOC_CHILD_CTX * talloc_child_ctx_init(TALLOC_CTX *ctx)
Allocate and initialize a TALLOC_CHILD_CTX.
int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
Compares two talloced uint8_t arrays with memcmp.
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
TALLOC_CTX * talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
Return a page aligned talloc memory array.
int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
Link two different parent and child contexts, so the child is freed before the parent.
uint8_t * talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
Call talloc_memdup, setting the type on the new chunk correctly.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
char * talloc_typed_strndup(TALLOC_CTX *ctx, char const *p, size_t len)
Call talloc_strndup, setting the type on the new chunk correctly.
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
void ** talloc_array_null_strip(void **array)
Remove a NULL termination pointer from an array of pointers.
char * talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
Append a bstr to a bstr.
void talloc_destructor_disarm(fr_talloc_destructor_t *d)
Disarm a destructor and free all memory allocated in the trigger ctxs.
int talloc_memcmp_bstr(char const *a, char const *b)
Compares two talloced char arrays with memcmp.
#define talloc_strndup(_ctx, _str, _len)
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
#define talloc_strdup(_ctx, _str)
#define talloc_realloc_zero(_ctx, _ptr, _type, _count)
Structure to record a destructor operation on a specific talloc chunk.
static int native_destructor_count
static void test_talloc_bstrndup(void)
static void test_talloc_steal(void)
static void test_talloc_buffer_append_buffer(void)
static void test_talloc_free_children(void)
static int _track_free_order(int *ptr)
static void test_talloc_get_size(void)
static int test_fr_destructor_func(UNUSED void *fire_ctx, void *uctx)
static int native_destructor(int *ptr)
static void test_talloc_decrease_ref_count(void)
static void test_talloc_hdr_size(void)
static void test_talloc_zero(void)
static void test_talloc_typed_memdup(void)
static void test_talloc_is_parent(void)
static int child_free_idx
static void test_talloc_move(void)
static void test_talloc_parent(void)
static void test_talloc_typed_strndup(void)
static void const * fr_destructor_uctx
static void test_talloc_destructor_add(void)
static void test_talloc_bstr_append(void)
static void test_talloc_reparent(void)
static void test_talloc_deep_hierarchy(void)
static void test_talloc_asprintf(void)
static void test_talloc_reference(void)
static void test_talloc_typed_asprintf(void)
static void test_talloc_naming(void)
static void test_talloc_memcmp_array(void)
static void test_talloc_find_parent_byname(void)
static void test_talloc_typed_strdup(void)
static void test_talloc_basic(void)
static void test_talloc_link_ctx(void)
static void test_talloc_child_ctx(void)
static void test_talloc_aligned_array(void)
static void test_talloc_free(void)
static void test_talloc_array(void)
static void test_talloc_strdup(void)
static void test_talloc_set_destructor(void)
static void test_talloc_array_null_terminate(void)
static void test_talloc_increase_ref_count(void)
static void test_talloc_strndup_append(void)
static void test_talloc_bstr_realloc(void)
static int fr_destructor_called
static void test_talloc_realloc_zero(void)
static void test_talloc_memcmp_bstr(void)
static void test_talloc_pool(void)
static int child_free_order[4]
static void test_talloc_memdup(void)
static void test_talloc_total_size(void)