2 Unix SMB/CIFS implementation.
4 local testing of talloc routines.
6 Copyright (C) Andrew Tridgell 2004
8 ** NOTE! The following LGPL license applies to the talloc
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "system/time.h"
34 #include "talloc_testsuite.h"
36 static struct timeval
timeval_current(void)
39 gettimeofday(&tv
, NULL
);
43 static double timeval_elapsed(struct timeval
*tv
)
45 struct timeval tv2
= timeval_current();
46 return (tv2
.tv_sec
- tv
->tv_sec
) +
47 (tv2
.tv_usec
- tv
->tv_usec
)*1.0e-6;
50 #define torture_assert(test, expr, str) if (!(expr)) { \
51 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
52 test, __location__, #expr, str); \
56 #define torture_assert_str_equal(test, arg1, arg2, desc) \
57 if (arg1 == NULL && arg2 == NULL) { \
58 } else if (strcmp(arg1, arg2)) { \
59 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
60 test, __location__, arg1, arg2, desc); \
64 #define CHECK_SIZE(test, ptr, tsize) do { \
65 if (talloc_total_size(ptr) != (tsize)) { \
66 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
67 test, __location__, #ptr, \
68 (unsigned)talloc_total_size(ptr), \
70 talloc_report_full(ptr, stdout); \
75 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
76 if (talloc_total_blocks(ptr) != (tblocks)) { \
77 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
78 test, __location__, #ptr, \
79 (unsigned)talloc_total_blocks(ptr), \
81 talloc_report_full(ptr, stdout); \
86 #define CHECK_PARENT(test, ptr, parent) do { \
87 if (talloc_parent(ptr) != (parent)) { \
88 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
89 test, __location__, #ptr, \
92 talloc_report_full(ptr, stdout); \
93 talloc_report_full(parent, stdout); \
94 talloc_report_full(NULL, stdout); \
99 static unsigned int test_abort_count
;
102 static void test_abort_fn(const char *reason
)
104 printf("# test_abort_fn(%s)\n", reason
);
108 static void test_abort_start(void)
110 test_abort_count
= 0;
111 talloc_set_abort_fn(test_abort_fn
);
115 static void test_abort_stop(void)
117 test_abort_count
= 0;
118 talloc_set_abort_fn(NULL
);
121 static void test_log_stdout(const char *message
)
123 fprintf(stdout
, "%s", message
);
129 static bool test_ref1(void)
131 void *root
, *p1
, *p2
, *ref
, *r1
;
133 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
135 root
= talloc_named_const(NULL
, 0, "root");
136 p1
= talloc_named_const(root
, 1, "p1");
137 p2
= talloc_named_const(p1
, 1, "p2");
138 talloc_named_const(p1
, 1, "x1");
139 talloc_named_const(p1
, 2, "x2");
140 talloc_named_const(p1
, 3, "x3");
142 r1
= talloc_named_const(root
, 1, "r1");
143 ref
= talloc_reference(r1
, p2
);
144 talloc_report_full(root
, stderr
);
146 CHECK_BLOCKS("ref1", p1
, 5);
147 CHECK_BLOCKS("ref1", p2
, 1);
148 CHECK_BLOCKS("ref1", ref
, 1);
149 CHECK_BLOCKS("ref1", r1
, 2);
151 fprintf(stderr
, "Freeing p2\n");
152 talloc_unlink(r1
, p2
);
153 talloc_report_full(root
, stderr
);
155 CHECK_BLOCKS("ref1", p1
, 5);
156 CHECK_BLOCKS("ref1", p2
, 1);
157 CHECK_BLOCKS("ref1", r1
, 1);
159 fprintf(stderr
, "Freeing p1\n");
161 talloc_report_full(root
, stderr
);
163 CHECK_BLOCKS("ref1", r1
, 1);
165 fprintf(stderr
, "Freeing r1\n");
167 talloc_report_full(NULL
, stderr
);
169 fprintf(stderr
, "Testing NULL\n");
170 if (talloc_reference(root
, NULL
)) {
174 CHECK_BLOCKS("ref1", root
, 1);
176 CHECK_SIZE("ref1", root
, 0);
179 printf("success: ref1\n");
186 static bool test_ref2(void)
188 void *root
, *p1
, *p2
, *ref
, *r1
;
190 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
191 root
= talloc_named_const(NULL
, 0, "root");
192 p1
= talloc_named_const(root
, 1, "p1");
193 talloc_named_const(p1
, 1, "x1");
194 talloc_named_const(p1
, 1, "x2");
195 talloc_named_const(p1
, 1, "x3");
196 p2
= talloc_named_const(p1
, 1, "p2");
198 r1
= talloc_named_const(root
, 1, "r1");
199 ref
= talloc_reference(r1
, p2
);
200 talloc_report_full(root
, stderr
);
202 CHECK_BLOCKS("ref2", p1
, 5);
203 CHECK_BLOCKS("ref2", p2
, 1);
204 CHECK_BLOCKS("ref2", r1
, 2);
206 fprintf(stderr
, "Freeing ref\n");
207 talloc_unlink(r1
, ref
);
208 talloc_report_full(root
, stderr
);
210 CHECK_BLOCKS("ref2", p1
, 5);
211 CHECK_BLOCKS("ref2", p2
, 1);
212 CHECK_BLOCKS("ref2", r1
, 1);
214 fprintf(stderr
, "Freeing p2\n");
216 talloc_report_full(root
, stderr
);
218 CHECK_BLOCKS("ref2", p1
, 4);
219 CHECK_BLOCKS("ref2", r1
, 1);
221 fprintf(stderr
, "Freeing p1\n");
223 talloc_report_full(root
, stderr
);
225 CHECK_BLOCKS("ref2", r1
, 1);
227 fprintf(stderr
, "Freeing r1\n");
229 talloc_report_full(root
, stderr
);
231 CHECK_SIZE("ref2", root
, 0);
234 printf("success: ref2\n");
241 static bool test_ref3(void)
243 void *root
, *p1
, *p2
, *ref
, *r1
;
245 printf("test: ref3\n# PARENT REFERENCE FREE\n");
247 root
= talloc_named_const(NULL
, 0, "root");
248 p1
= talloc_named_const(root
, 1, "p1");
249 p2
= talloc_named_const(root
, 1, "p2");
250 r1
= talloc_named_const(p1
, 1, "r1");
251 ref
= talloc_reference(p2
, r1
);
252 talloc_report_full(root
, stderr
);
254 CHECK_BLOCKS("ref3", p1
, 2);
255 CHECK_BLOCKS("ref3", p2
, 2);
256 CHECK_BLOCKS("ref3", r1
, 1);
257 CHECK_BLOCKS("ref3", ref
, 1);
259 fprintf(stderr
, "Freeing p1\n");
261 talloc_report_full(root
, stderr
);
263 CHECK_BLOCKS("ref3", p2
, 2);
264 CHECK_BLOCKS("ref3", r1
, 1);
266 fprintf(stderr
, "Freeing p2\n");
268 talloc_report_full(root
, stderr
);
270 CHECK_SIZE("ref3", root
, 0);
274 printf("success: ref3\n");
281 static bool test_ref4(void)
283 void *root
, *p1
, *p2
, *ref
, *r1
;
285 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
287 root
= talloc_named_const(NULL
, 0, "root");
288 p1
= talloc_named_const(root
, 1, "p1");
289 talloc_named_const(p1
, 1, "x1");
290 talloc_named_const(p1
, 1, "x2");
291 talloc_named_const(p1
, 1, "x3");
292 p2
= talloc_named_const(p1
, 1, "p2");
294 r1
= talloc_named_const(root
, 1, "r1");
295 ref
= talloc_reference(r1
, p2
);
296 talloc_report_full(root
, stderr
);
298 CHECK_BLOCKS("ref4", p1
, 5);
299 CHECK_BLOCKS("ref4", p2
, 1);
300 CHECK_BLOCKS("ref4", ref
, 1);
301 CHECK_BLOCKS("ref4", r1
, 2);
303 fprintf(stderr
, "Freeing r1\n");
305 talloc_report_full(root
, stderr
);
307 CHECK_BLOCKS("ref4", p1
, 5);
308 CHECK_BLOCKS("ref4", p2
, 1);
310 fprintf(stderr
, "Freeing p2\n");
312 talloc_report_full(root
, stderr
);
314 CHECK_BLOCKS("ref4", p1
, 4);
316 fprintf(stderr
, "Freeing p1\n");
318 talloc_report_full(root
, stderr
);
320 CHECK_SIZE("ref4", root
, 0);
324 printf("success: ref4\n");
332 static bool test_unlink1(void)
334 void *root
, *p1
, *p2
, *ref
, *r1
;
336 printf("test: unlink\n# UNLINK\n");
338 root
= talloc_named_const(NULL
, 0, "root");
339 p1
= talloc_named_const(root
, 1, "p1");
340 talloc_named_const(p1
, 1, "x1");
341 talloc_named_const(p1
, 1, "x2");
342 talloc_named_const(p1
, 1, "x3");
343 p2
= talloc_named_const(p1
, 1, "p2");
345 r1
= talloc_named_const(p1
, 1, "r1");
346 ref
= talloc_reference(r1
, p2
);
347 talloc_report_full(root
, stderr
);
349 CHECK_BLOCKS("unlink", p1
, 7);
350 CHECK_BLOCKS("unlink", p2
, 1);
351 CHECK_BLOCKS("unlink", ref
, 1);
352 CHECK_BLOCKS("unlink", r1
, 2);
354 fprintf(stderr
, "Unreferencing r1\n");
355 talloc_unlink(r1
, p2
);
356 talloc_report_full(root
, stderr
);
358 CHECK_BLOCKS("unlink", p1
, 6);
359 CHECK_BLOCKS("unlink", p2
, 1);
360 CHECK_BLOCKS("unlink", r1
, 1);
362 fprintf(stderr
, "Freeing p1\n");
364 talloc_report_full(root
, stderr
);
366 CHECK_SIZE("unlink", root
, 0);
370 printf("success: unlink\n");
374 static int fail_destructor(void *ptr
)
380 miscellaneous tests to try to get a higher test coverage percentage
382 static bool test_misc(void)
389 printf("test: misc\n# MISCELLANEOUS\n");
391 root
= talloc_new(NULL
);
393 p1
= talloc_size(root
, 0x7fffffff);
394 torture_assert("misc", !p1
, "failed: large talloc allowed\n");
396 p1
= talloc_strdup(root
, "foo");
397 talloc_increase_ref_count(p1
);
398 talloc_increase_ref_count(p1
);
399 talloc_increase_ref_count(p1
);
400 CHECK_BLOCKS("misc", p1
, 1);
401 CHECK_BLOCKS("misc", root
, 2);
402 talloc_unlink(NULL
, p1
);
403 CHECK_BLOCKS("misc", p1
, 1);
404 CHECK_BLOCKS("misc", root
, 2);
405 talloc_unlink(NULL
, p1
);
406 CHECK_BLOCKS("misc", p1
, 1);
407 CHECK_BLOCKS("misc", root
, 2);
408 p2
= talloc_strdup(p1
, "foo");
409 torture_assert("misc", talloc_unlink(root
, p2
) == -1,
410 "failed: talloc_unlink() of non-reference context should return -1\n");
411 torture_assert("misc", talloc_unlink(p1
, p2
) == 0,
412 "failed: talloc_unlink() of parent should succeed\n");
413 talloc_unlink(NULL
, p1
);
414 CHECK_BLOCKS("misc", p1
, 1);
415 CHECK_BLOCKS("misc", root
, 2);
417 name
= talloc_set_name(p1
, "my name is %s", "foo");
418 torture_assert_str_equal("misc", talloc_get_name(p1
), "my name is foo",
419 "failed: wrong name after talloc_set_name(my name is foo)");
420 torture_assert_str_equal("misc", talloc_get_name(p1
), name
,
421 "failed: wrong name after talloc_set_name(my name is foo)");
422 CHECK_BLOCKS("misc", p1
, 2);
423 CHECK_BLOCKS("misc", root
, 3);
425 talloc_set_name_const(p1
, NULL
);
426 torture_assert_str_equal ("misc", talloc_get_name(p1
), "UNNAMED",
427 "failed: wrong name after talloc_set_name(NULL)");
428 CHECK_BLOCKS("misc", p1
, 2);
429 CHECK_BLOCKS("misc", root
, 3);
431 torture_assert("misc", talloc_free(NULL
) == -1,
432 "talloc_free(NULL) should give -1\n");
434 talloc_set_destructor(p1
, fail_destructor
);
435 torture_assert("misc", talloc_free(p1
) == -1,
436 "Failed destructor should cause talloc_free to fail\n");
437 talloc_set_destructor(p1
, NULL
);
439 talloc_report(root
, stderr
);
442 p2
= (char *)talloc_zero_size(p1
, 20);
443 torture_assert("misc", p2
[19] == 0, "Failed to give zero memory\n");
446 torture_assert("misc", talloc_strdup(root
, NULL
) == NULL
,
447 "failed: strdup on NULL should give NULL\n");
449 p2
= talloc_strndup(p1
, "foo", 2);
450 torture_assert("misc", strcmp("fo", p2
) == 0,
451 "strndup doesn't work\n");
452 p2
= talloc_asprintf_append_buffer(p2
, "o%c", 'd');
453 torture_assert("misc", strcmp("food", p2
) == 0,
454 "talloc_asprintf_append_buffer doesn't work\n");
455 CHECK_BLOCKS("misc", p2
, 1);
456 CHECK_BLOCKS("misc", p1
, 3);
458 p2
= talloc_asprintf_append_buffer(NULL
, "hello %s", "world");
459 torture_assert("misc", strcmp("hello world", p2
) == 0,
460 "talloc_asprintf_append_buffer doesn't work\n");
461 CHECK_BLOCKS("misc", p2
, 1);
462 CHECK_BLOCKS("misc", p1
, 3);
465 d
= talloc_array(p1
, double, 0x20000000);
466 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
468 d
= talloc_realloc(p1
, d
, double, 0x20000000);
469 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
472 CHECK_BLOCKS("misc", root
, 1);
474 p1
= talloc_named(root
, 100, "%d bytes", 100);
475 CHECK_BLOCKS("misc", p1
, 2);
476 CHECK_BLOCKS("misc", root
, 3);
477 talloc_unlink(root
, p1
);
479 p1
= talloc_init("%d bytes", 200);
480 p2
= talloc_asprintf(p1
, "my test '%s'", "string");
481 torture_assert_str_equal("misc", p2
, "my test 'string'",
482 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
483 CHECK_BLOCKS("misc", p1
, 3);
484 CHECK_SIZE("misc", p2
, 17);
485 CHECK_BLOCKS("misc", root
, 1);
486 talloc_unlink(NULL
, p1
);
488 p1
= talloc_named_const(root
, 10, "p1");
489 p2
= (char *)talloc_named_const(root
, 20, "p2");
490 (void)talloc_reference(p1
, p2
);
491 talloc_report_full(root
, stderr
);
492 talloc_unlink(root
, p2
);
493 talloc_report_full(root
, stderr
);
494 CHECK_BLOCKS("misc", p2
, 1);
495 CHECK_BLOCKS("misc", p1
, 2);
496 CHECK_BLOCKS("misc", root
, 3);
497 talloc_unlink(p1
, p2
);
498 talloc_unlink(root
, p1
);
500 p1
= talloc_named_const(root
, 10, "p1");
501 p2
= (char *)talloc_named_const(root
, 20, "p2");
502 (void)talloc_reference(NULL
, p2
);
503 talloc_report_full(root
, stderr
);
504 talloc_unlink(root
, p2
);
505 talloc_report_full(root
, stderr
);
506 CHECK_BLOCKS("misc", p2
, 1);
507 CHECK_BLOCKS("misc", p1
, 1);
508 CHECK_BLOCKS("misc", root
, 2);
509 talloc_unlink(NULL
, p2
);
510 talloc_unlink(root
, p1
);
512 /* Test that talloc_unlink is a no-op */
514 torture_assert("misc", talloc_unlink(root
, NULL
) == -1,
515 "failed: talloc_unlink(root, NULL) == -1\n");
517 talloc_report(root
, stderr
);
518 talloc_report(NULL
, stderr
);
520 CHECK_SIZE("misc", root
, 0);
524 CHECK_SIZE("misc", NULL
, 0);
526 talloc_enable_null_tracking_no_autofree();
527 talloc_enable_leak_report();
528 talloc_enable_leak_report_full();
530 printf("success: misc\n");
539 static bool test_realloc(void)
541 void *root
, *p1
, *p2
;
543 printf("test: realloc\n# REALLOC\n");
545 root
= talloc_new(NULL
);
547 p1
= talloc_size(root
, 10);
548 CHECK_SIZE("realloc", p1
, 10);
550 p1
= talloc_realloc_size(NULL
, p1
, 20);
551 CHECK_SIZE("realloc", p1
, 20);
555 p2
= talloc_realloc_size(p1
, NULL
, 30);
559 p2
= talloc_realloc_size(p1
, p2
, 40);
561 CHECK_SIZE("realloc", p2
, 40);
562 CHECK_SIZE("realloc", root
, 60);
563 CHECK_BLOCKS("realloc", p1
, 4);
565 p1
= talloc_realloc_size(NULL
, p1
, 20);
566 CHECK_SIZE("realloc", p1
, 60);
568 talloc_increase_ref_count(p2
);
569 torture_assert("realloc", talloc_realloc_size(NULL
, p2
, 5) == NULL
,
570 "failed: talloc_realloc() on a referenced pointer should fail\n");
571 CHECK_BLOCKS("realloc", p1
, 4);
573 talloc_realloc_size(NULL
, p2
, 0);
574 talloc_realloc_size(NULL
, p2
, 0);
575 CHECK_BLOCKS("realloc", p1
, 4);
576 talloc_realloc_size(p1
, p2
, 0);
577 CHECK_BLOCKS("realloc", p1
, 3);
579 torture_assert("realloc", talloc_realloc_size(NULL
, p1
, 0x7fffffff) == NULL
,
580 "failed: oversize talloc should fail\n");
582 talloc_realloc_size(NULL
, p1
, 0);
583 CHECK_BLOCKS("realloc", root
, 4);
584 talloc_realloc_size(root
, p1
, 0);
585 CHECK_BLOCKS("realloc", root
, 1);
587 CHECK_SIZE("realloc", root
, 0);
591 printf("success: realloc\n");
597 test realloc with a child
599 static bool test_realloc_child(void)
607 struct el2
**list
, **list2
, **list3
;
610 printf("test: REALLOC WITH CHILD\n");
612 root
= talloc_new(NULL
);
614 el1
= talloc(root
, struct el1
);
615 el1
->list
= talloc(el1
, struct el2
*);
616 el1
->list
[0] = talloc(el1
->list
, struct el2
);
617 el1
->list
[0]->name
= talloc_strdup(el1
->list
[0], "testing");
619 el1
->list2
= talloc(el1
, struct el2
*);
620 el1
->list2
[0] = talloc(el1
->list2
, struct el2
);
621 el1
->list2
[0]->name
= talloc_strdup(el1
->list2
[0], "testing2");
623 el1
->list3
= talloc(el1
, struct el2
*);
624 el1
->list3
[0] = talloc(el1
->list3
, struct el2
);
625 el1
->list3
[0]->name
= talloc_strdup(el1
->list3
[0], "testing2");
627 el2
= talloc(el1
->list
, struct el2
);
628 el2
= talloc(el1
->list2
, struct el2
);
629 el2
= talloc(el1
->list3
, struct el2
);
632 el1
->list
= talloc_realloc(el1
, el1
->list
, struct el2
*, 100);
633 el1
->list2
= talloc_realloc(el1
, el1
->list2
, struct el2
*, 200);
634 el1
->list3
= talloc_realloc(el1
, el1
->list3
, struct el2
*, 300);
638 printf("success: REALLOC WITH CHILD\n");
645 static bool test_type(void)
656 printf("test: type\n# talloc type checking\n");
658 root
= talloc_new(NULL
);
660 el1
= talloc(root
, struct el1
);
664 torture_assert("type", talloc_get_type(el1
, struct el1
) == el1
,
665 "type check failed on el1\n");
666 torture_assert("type", talloc_get_type(el1
, struct el2
) == NULL
,
667 "type check failed on el1 with el2\n");
668 talloc_set_type(el1
, struct el2
);
669 torture_assert("type", talloc_get_type(el1
, struct el2
) == (struct el2
*)el1
,
670 "type set failed on el1 with el2\n");
674 printf("success: type\n");
681 static bool test_steal(void)
683 void *root
, *p1
, *p2
;
685 printf("test: steal\n# STEAL\n");
687 root
= talloc_new(NULL
);
689 p1
= talloc_array(root
, char, 10);
690 CHECK_SIZE("steal", p1
, 10);
692 p2
= talloc_realloc(root
, NULL
, char, 20);
693 CHECK_SIZE("steal", p1
, 10);
694 CHECK_SIZE("steal", root
, 30);
696 torture_assert("steal", talloc_steal(p1
, NULL
) == NULL
,
697 "failed: stealing NULL should give NULL\n");
699 torture_assert("steal", talloc_steal(p1
, p1
) == p1
,
700 "failed: stealing to ourselves is a nop\n");
701 CHECK_BLOCKS("steal", root
, 3);
702 CHECK_SIZE("steal", root
, 30);
704 talloc_steal(NULL
, p1
);
705 talloc_steal(NULL
, p2
);
706 CHECK_BLOCKS("steal", root
, 1);
707 CHECK_SIZE("steal", root
, 0);
710 talloc_steal(root
, p2
);
711 CHECK_BLOCKS("steal", root
, 2);
712 CHECK_SIZE("steal", root
, 20);
716 CHECK_BLOCKS("steal", root
, 1);
717 CHECK_SIZE("steal", root
, 0);
721 p1
= talloc_size(NULL
, 3);
722 talloc_report_full(NULL
, stderr
);
723 CHECK_SIZE("steal", NULL
, 3);
726 printf("success: steal\n");
733 static bool test_move(void)
741 printf("test: move\n# MOVE\n");
743 root
= talloc_new(NULL
);
745 t1
= talloc(root
, struct t_move
);
746 t2
= talloc(root
, struct t_move
);
747 t1
->p
= talloc_strdup(t1
, "foo");
748 t1
->x
= talloc(t1
, int);
751 t2
->p
= talloc_move(t2
, &t1
->p
);
752 t2
->x
= talloc_move(t2
, &t1
->x
);
753 torture_assert("move", t1
->p
== NULL
&& t1
->x
== NULL
&&
754 strcmp(t2
->p
, "foo") == 0 && *t2
->x
== 42,
755 "talloc move failed");
759 printf("success: move\n");
765 test talloc_realloc_fn
767 static bool test_realloc_fn(void)
771 printf("test: realloc_fn\n# talloc_realloc_fn\n");
773 root
= talloc_new(NULL
);
775 p1
= talloc_realloc_fn(root
, NULL
, 10);
776 CHECK_BLOCKS("realloc_fn", root
, 2);
777 CHECK_SIZE("realloc_fn", root
, 10);
778 p1
= talloc_realloc_fn(root
, p1
, 20);
779 CHECK_BLOCKS("realloc_fn", root
, 2);
780 CHECK_SIZE("realloc_fn", root
, 20);
781 p1
= talloc_realloc_fn(root
, p1
, 0);
782 CHECK_BLOCKS("realloc_fn", root
, 1);
783 CHECK_SIZE("realloc_fn", root
, 0);
787 printf("success: realloc_fn\n");
792 static bool test_unref_reparent(void)
794 void *root
, *p1
, *p2
, *c1
;
796 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
798 root
= talloc_named_const(NULL
, 0, "root");
799 p1
= talloc_named_const(root
, 1, "orig parent");
800 p2
= talloc_named_const(root
, 1, "parent by reference");
802 c1
= talloc_named_const(p1
, 1, "child");
803 talloc_reference(p2
, c1
);
805 CHECK_PARENT("unref_reparent", c1
, p1
);
809 CHECK_PARENT("unref_reparent", c1
, p2
);
811 talloc_unlink(p2
, c1
);
813 CHECK_SIZE("unref_reparent", root
, 1);
818 printf("success: unref_reparent\n");
823 measure the speed of talloc versus malloc
825 static bool test_speed(void)
827 void *ctx
= talloc_new(NULL
);
829 const int loop
= 1000;
833 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
835 tv
= timeval_current();
839 for (i
=0;i
<loop
;i
++) {
840 p1
= talloc_size(ctx
, loop
% 100);
841 p2
= talloc_strdup(p1
, "foo bar");
842 p3
= talloc_size(p1
, 300);
848 } while (timeval_elapsed(&tv
) < 5.0);
850 fprintf(stderr
, "talloc: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
854 ctx
= talloc_pool(NULL
, 1024);
856 tv
= timeval_current();
860 for (i
=0;i
<loop
;i
++) {
861 p1
= talloc_size(ctx
, loop
% 100);
862 p2
= talloc_strdup(p1
, "foo bar");
863 p3
= talloc_size(p1
, 300);
869 } while (timeval_elapsed(&tv
) < 5.0);
873 fprintf(stderr
, "talloc_pool: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
875 tv
= timeval_current();
879 for (i
=0;i
<loop
;i
++) {
880 p1
= malloc(loop
% 100);
881 p2
= strdup("foo bar");
888 } while (timeval_elapsed(&tv
) < 5.0);
889 fprintf(stderr
, "malloc: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
891 printf("success: speed\n");
896 static bool test_lifeless(void)
898 void *top
= talloc_new(NULL
);
899 char *parent
, *child
;
900 void *child_owner
= talloc_new(NULL
);
902 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
904 parent
= talloc_strdup(top
, "parent");
905 child
= talloc_strdup(parent
, "child");
906 (void)talloc_reference(child
, parent
);
907 (void)talloc_reference(child_owner
, child
);
908 talloc_report_full(top
, stderr
);
909 talloc_unlink(top
, parent
);
910 talloc_unlink(top
, child
);
911 talloc_report_full(top
, stderr
);
913 talloc_free(child_owner
);
916 printf("success: lifeless\n");
920 static int loop_destructor_count
;
922 static int test_loop_destructor(char *ptr
)
924 loop_destructor_count
++;
928 static bool test_loop(void)
930 void *top
= talloc_new(NULL
);
936 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
938 parent
= talloc_strdup(top
, "parent");
939 req1
= talloc(parent
, struct req1
);
940 req1
->req2
= talloc_strdup(req1
, "req2");
941 talloc_set_destructor(req1
->req2
, test_loop_destructor
);
942 req1
->req3
= talloc_strdup(req1
, "req3");
943 (void)talloc_reference(req1
->req3
, req1
);
944 talloc_report_full(top
, stderr
);
946 talloc_report_full(top
, stderr
);
947 talloc_report_full(NULL
, stderr
);
950 torture_assert("loop", loop_destructor_count
== 1,
951 "FAILED TO FIRE LOOP DESTRUCTOR\n");
952 loop_destructor_count
= 0;
954 printf("success: loop\n");
958 static int fail_destructor_str(char *ptr
)
963 static bool test_free_parent_deny_child(void)
965 void *top
= talloc_new(NULL
);
970 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
972 level1
= talloc_strdup(top
, "level1");
973 level2
= talloc_strdup(level1
, "level2");
974 level3
= talloc_strdup(level2
, "level3");
976 talloc_set_destructor(level3
, fail_destructor_str
);
978 talloc_set_destructor(level3
, NULL
);
980 CHECK_PARENT("free_parent_deny_child", level3
, top
);
984 printf("success: free_parent_deny_child\n");
993 static int reparenting_destructor(struct new_parent
*np
)
995 talloc_set_destructor(np
, NULL
);
996 (void)talloc_move(np
->new_parent
, &np
);
1000 static bool test_free_parent_reparent_child(void)
1002 void *top
= talloc_new(NULL
);
1004 char *alternate_level1
;
1006 struct new_parent
*level3
;
1008 printf("test: free_parent_reparent_child\n# "
1009 "TALLOC FREE PARENT REPARENT CHILD\n");
1011 level1
= talloc_strdup(top
, "level1");
1012 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1013 level2
= talloc_strdup(level1
, "level2");
1014 level3
= talloc(level2
, struct new_parent
);
1015 level3
->new_parent
= alternate_level1
;
1016 memset(level3
->val
, 'x', sizeof(level3
->val
));
1018 talloc_set_destructor(level3
, reparenting_destructor
);
1019 talloc_free(level1
);
1021 CHECK_PARENT("free_parent_reparent_child",
1022 level3
, alternate_level1
);
1026 printf("success: free_parent_reparent_child\n");
1030 static bool test_free_parent_reparent_child_in_pool(void)
1032 void *top
= talloc_new(NULL
);
1034 char *alternate_level1
;
1037 struct new_parent
*level3
;
1039 printf("test: free_parent_reparent_child_in_pool\n# "
1040 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1042 pool
= talloc_pool(top
, 1024);
1043 level1
= talloc_strdup(pool
, "level1");
1044 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1045 level2
= talloc_strdup(level1
, "level2");
1046 level3
= talloc(level2
, struct new_parent
);
1047 level3
->new_parent
= alternate_level1
;
1048 memset(level3
->val
, 'x', sizeof(level3
->val
));
1050 talloc_set_destructor(level3
, reparenting_destructor
);
1051 talloc_free(level1
);
1052 talloc_set_destructor(level3
, NULL
);
1054 CHECK_PARENT("free_parent_reparent_child_in_pool",
1055 level3
, alternate_level1
);
1057 /* Even freeing alternate_level1 should leave pool alone. */
1058 talloc_free(alternate_level1
);
1061 printf("success: free_parent_reparent_child_in_pool\n");
1066 static bool test_talloc_ptrtype(void)
1068 void *top
= talloc_new(NULL
);
1072 } *s1
, *s2
, **s3
, ***s4
;
1073 const char *location1
;
1074 const char *location2
;
1075 const char *location3
;
1076 const char *location4
;
1078 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1080 s1
= talloc_ptrtype(top
, s1
);location1
= __location__
;
1082 if (talloc_get_size(s1
) != sizeof(struct struct1
)) {
1083 printf("failure: ptrtype [\n"
1084 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1085 "]\n", (unsigned long)talloc_get_size(s1
),
1086 (unsigned long)sizeof(struct struct1
));
1090 if (strcmp(location1
, talloc_get_name(s1
)) != 0) {
1091 printf("failure: ptrtype [\n"
1092 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1093 talloc_get_name(s1
), location1
);
1097 s2
= talloc_array_ptrtype(top
, s2
, 10);location2
= __location__
;
1099 if (talloc_get_size(s2
) != (sizeof(struct struct1
) * 10)) {
1100 printf("failure: ptrtype [\n"
1101 "talloc_array_ptrtype() allocated the wrong size "
1102 "%lu (should be %lu)\n]\n",
1103 (unsigned long)talloc_get_size(s2
),
1104 (unsigned long)(sizeof(struct struct1
)*10));
1108 if (strcmp(location2
, talloc_get_name(s2
)) != 0) {
1109 printf("failure: ptrtype [\n"
1110 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1111 talloc_get_name(s2
), location2
);
1115 s3
= talloc_array_ptrtype(top
, s3
, 10);location3
= __location__
;
1117 if (talloc_get_size(s3
) != (sizeof(struct struct1
*) * 10)) {
1118 printf("failure: ptrtype [\n"
1119 "talloc_array_ptrtype() allocated the wrong size "
1120 "%lu (should be %lu)\n]\n",
1121 (unsigned long)talloc_get_size(s3
),
1122 (unsigned long)(sizeof(struct struct1
*)*10));
1126 torture_assert_str_equal("ptrtype", location3
, talloc_get_name(s3
),
1127 "talloc_array_ptrtype() sets the wrong name");
1129 s4
= talloc_array_ptrtype(top
, s4
, 10);location4
= __location__
;
1131 if (talloc_get_size(s4
) != (sizeof(struct struct1
**) * 10)) {
1132 printf("failure: ptrtype [\n"
1133 "talloc_array_ptrtype() allocated the wrong size "
1134 "%lu (should be %lu)\n]\n",
1135 (unsigned long)talloc_get_size(s4
),
1136 (unsigned long)(sizeof(struct struct1
**)*10));
1140 torture_assert_str_equal("ptrtype", location4
, talloc_get_name(s4
),
1141 "talloc_array_ptrtype() sets the wrong name");
1145 printf("success: ptrtype\n");
1149 static int _test_talloc_free_in_destructor(void **ptr
)
1155 static bool test_talloc_free_in_destructor(void)
1164 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1166 level0
= talloc_new(NULL
);
1167 level1
= talloc_new(level0
);
1168 level2
= talloc_new(level1
);
1169 level3
= talloc_new(level2
);
1170 level4
= talloc_new(level3
);
1171 level5
= talloc(level4
, void *);
1174 (void)talloc_reference(level0
, level3
);
1175 (void)talloc_reference(level3
, level3
);
1176 (void)talloc_reference(level5
, level3
);
1178 talloc_set_destructor(level5
, _test_talloc_free_in_destructor
);
1180 talloc_free(level1
);
1182 talloc_free(level0
);
1184 printf("success: free_in_destructor\n");
1188 static bool test_autofree(void)
1190 #if _SAMBA_BUILD_ < 4
1191 /* autofree test would kill smbtorture */
1193 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1195 p
= talloc_autofree_context();
1198 p
= talloc_autofree_context();
1201 printf("success: autofree\n");
1206 static bool test_pool(void)
1209 void *p1
, *p2
, *p3
, *p4
;
1212 pool
= talloc_pool(NULL
, 1024);
1214 p1
= talloc_size(pool
, 80);
1215 memset(p1
, 0x11, talloc_get_size(p1
));
1216 p2
= talloc_size(pool
, 20);
1217 memset(p2
, 0x11, talloc_get_size(p2
));
1218 p3
= talloc_size(p1
, 50);
1219 memset(p3
, 0x11, talloc_get_size(p3
));
1220 p4
= talloc_size(p3
, 1000);
1221 memset(p4
, 0x11, talloc_get_size(p4
));
1223 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1224 p2_2
= talloc_realloc_size(pool
, p2
, 20+1);
1225 torture_assert("pool realloc 20+1", p2_2
== p2
, "failed: pointer changed");
1226 memset(p2
, 0x11, talloc_get_size(p2
));
1227 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1228 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1229 memset(p2
, 0x11, talloc_get_size(p2
));
1230 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1231 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1232 memset(p2
, 0x11, talloc_get_size(p2
));
1236 /* this should reclaim the memory of p4 and p3 */
1237 p2_2
= talloc_realloc_size(pool
, p2
, 400);
1238 torture_assert("pool realloc 400", p2_2
== p2
, "failed: pointer changed");
1239 memset(p2
, 0x11, talloc_get_size(p2
));
1243 /* this should reclaim the memory of p1 */
1244 p2_2
= talloc_realloc_size(pool
, p2
, 800);
1245 torture_assert("pool realloc 800", p2_2
== p1
, "failed: pointer not changed");
1247 memset(p2
, 0x11, talloc_get_size(p2
));
1249 /* this should do a malloc */
1250 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1251 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1253 memset(p2
, 0x11, talloc_get_size(p2
));
1255 /* this should reclaim the memory from the pool */
1256 p3
= talloc_size(pool
, 80);
1257 torture_assert("pool alloc 80", p3
== p1
, "failed: pointer changed");
1258 memset(p3
, 0x11, talloc_get_size(p3
));
1263 p1
= talloc_size(pool
, 80);
1264 memset(p1
, 0x11, talloc_get_size(p1
));
1265 p2
= talloc_size(pool
, 20);
1266 memset(p2
, 0x11, talloc_get_size(p2
));
1270 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1271 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1272 memset(p2
, 0x11, talloc_get_size(p2
));
1273 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1274 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1275 memset(p2
, 0x11, talloc_get_size(p2
));
1277 /* this should do a malloc */
1278 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1279 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1281 memset(p2
, 0x11, talloc_get_size(p2
));
1283 /* this should reclaim the memory from the pool */
1284 p3
= talloc_size(pool
, 800);
1285 torture_assert("pool alloc 800", p3
== p1
, "failed: pointer changed");
1286 memset(p3
, 0x11, talloc_get_size(p3
));
1288 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1295 static bool test_pool_steal(void)
1304 root
= talloc_new(NULL
);
1305 pool
= talloc_pool(root
, 1024);
1307 p1
= talloc_size(pool
, 4 * 16);
1308 torture_assert("pool allocate 4 * 16", p1
!= NULL
, "failed ");
1309 memset(p1
, 0x11, talloc_get_size(p1
));
1310 p2
= talloc_size(pool
, 4 * 16);
1311 torture_assert("pool allocate 4 * 16", p2
> p1
, "failed: !(p2 > p1) ");
1312 memset(p2
, 0x11, talloc_get_size(p2
));
1314 ofs1
= PTR_DIFF(p2
, p1
);
1315 hdr
= ofs1
- talloc_get_size(p1
);
1317 talloc_steal(root
, p1
);
1318 talloc_steal(root
, p2
);
1324 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1325 p1_2
= talloc_realloc_size(root
, p1
, 5 * 16);
1326 torture_assert("pool realloc 5 * 16", p1_2
> p2
, "failed: pointer not changed");
1327 memset(p1_2
, 0x11, talloc_get_size(p1_2
));
1328 ofs1
= PTR_DIFF(p1_2
, p2
);
1329 ofs2
= talloc_get_size(p2
) + hdr
;
1331 torture_assert("pool realloc ", ofs1
== ofs2
, "failed: pointer offset unexpected");
1333 p2_2
= talloc_realloc_size(root
, p2
, 3 * 16);
1334 torture_assert("pool realloc 5 * 16", p2_2
== p2
, "failed: pointer changed");
1335 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1336 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1342 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1343 /* now we should reclaim the full pool */
1344 p2_2
= talloc_realloc_size(root
, p2
, 8 * 16);
1345 torture_assert("pool realloc 8 * 16", p2_2
== p1
, "failed: pointer not expected");
1347 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1349 /* now we malloc and free the full pool space */
1350 p2_2
= talloc_realloc_size(root
, p2
, 2 * 1024);
1351 torture_assert("pool realloc 2 * 1024", p2_2
!= p1
, "failed: pointer not expected");
1352 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1354 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1363 static bool test_pool_nest(void)
1366 void *e
= talloc_new(NULL
);
1368 p1
= talloc_pool(NULL
, 1024);
1369 torture_assert("talloc_pool", p1
!= NULL
, "failed");
1371 p2
= talloc_pool(p1
, 500);
1372 torture_assert("talloc_pool", p2
!= NULL
, "failed");
1374 p3
= talloc_size(p2
, 10);
1376 talloc_steal(e
, p3
);
1393 static bool test_pooled_object(void)
1396 const char *s1
= "hello";
1397 const char *s2
= "world";
1398 const char *s3
= "";
1400 p
= talloc_pooled_object(NULL
, struct pooled
, 3,
1401 strlen(s1
)+strlen(s2
)+strlen(s3
)+3);
1403 if (talloc_get_size(p
) != sizeof(struct pooled
)) {
1407 p
->s1
= talloc_strdup(p
, s1
);
1410 p
->s1
= talloc_strdup(p
, s2
);
1413 p
->s1
= talloc_strdup(p
, s1
);
1414 p
->s2
= talloc_strdup(p
, s2
);
1415 p
->s3
= talloc_strdup(p
, s3
);
1421 static bool test_free_ref_null_context(void)
1426 talloc_disable_null_tracking();
1427 p1
= talloc_new(NULL
);
1428 p2
= talloc_new(NULL
);
1430 p3
= talloc_reference(p2
, p1
);
1431 torture_assert("reference", p3
== p1
, "failed: reference on null");
1433 ret
= talloc_free(p1
);
1434 torture_assert("ref free with null parent", ret
== 0, "failed: free with null parent");
1437 talloc_enable_null_tracking_no_autofree();
1438 p1
= talloc_new(NULL
);
1439 p2
= talloc_new(NULL
);
1441 p3
= talloc_reference(p2
, p1
);
1442 torture_assert("reference", p3
== p1
, "failed: reference on null");
1444 ret
= talloc_free(p1
);
1445 torture_assert("ref free with null tracked parent", ret
== 0, "failed: free with null parent");
1451 static bool test_rusty(void)
1456 talloc_enable_null_tracking();
1457 root
= talloc_new(NULL
);
1458 p1
= talloc_strdup(root
, "foo");
1459 talloc_increase_ref_count(p1
);
1460 talloc_report_full(root
, stdout
);
1462 CHECK_BLOCKS("null_context", NULL
, 2);
1466 static bool test_free_children(void)
1470 const char *name
, *name2
;
1472 talloc_enable_null_tracking();
1473 root
= talloc_new(NULL
);
1474 p1
= talloc_strdup(root
, "foo1");
1475 p2
= talloc_strdup(p1
, "foo2");
1478 talloc_set_name(p1
, "%s", "testname");
1479 talloc_free_children(p1
);
1480 /* check its still a valid talloc ptr */
1481 talloc_get_size(talloc_get_name(p1
));
1482 if (strcmp(talloc_get_name(p1
), "testname") != 0) {
1486 talloc_set_name(p1
, "%s", "testname");
1487 name
= talloc_get_name(p1
);
1488 talloc_free_children(p1
);
1489 /* check its still a valid talloc ptr */
1490 talloc_get_size(talloc_get_name(p1
));
1491 torture_assert("name", name
== talloc_get_name(p1
), "name ptr changed");
1492 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname") == 0,
1494 CHECK_BLOCKS("name1", p1
, 2);
1496 /* note that this does not free the old child name */
1497 talloc_set_name_const(p1
, "testname2");
1498 name2
= talloc_get_name(p1
);
1500 talloc_free_children(p1
);
1502 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname2") == 0,
1504 CHECK_BLOCKS("name1", p1
, 1);
1506 talloc_report_full(root
, stdout
);
1511 static bool test_memlimit(void)
1514 char *l1
, *l2
, *l3
, *l4
, *l5
, *t
;
1518 printf("test: memlimit\n# MEMORY LIMITS\n");
1520 printf("==== talloc_new(NULL)\n");
1521 root
= talloc_new(NULL
);
1523 talloc_report_full(root
, stdout
);
1525 printf("==== talloc_size(root, 2048)\n");
1526 l1
= talloc_size(root
, 2048);
1527 torture_assert("memlimit", l1
!= NULL
,
1528 "failed: alloc should not fail due to memory limit\n");
1530 talloc_report_full(root
, stdout
);
1532 printf("==== talloc_free(l1)\n");
1535 talloc_report_full(root
, stdout
);
1537 printf("==== talloc_strdup(root, level 1)\n");
1538 l1
= talloc_strdup(root
, "level 1");
1539 torture_assert("memlimit", l1
!= NULL
,
1540 "failed: alloc should not fail due to memory limit\n");
1542 talloc_report_full(root
, stdout
);
1544 printf("==== talloc_set_memlimit(l1, 2048)\n");
1545 torture_assert("memlimit", talloc_set_memlimit(l1
, 2048) == 0,
1546 "failed: setting memlimit should never fail\n");
1548 talloc_report_full(root
, stdout
);
1550 printf("==== talloc_size(root, 2048)\n");
1551 l2
= talloc_size(l1
, 2048);
1552 torture_assert("memlimit", l2
== NULL
,
1553 "failed: alloc should fail due to memory limit\n");
1555 talloc_report_full(root
, stdout
);
1557 printf("==== talloc_strdup(l1, level 2)\n");
1558 l2
= talloc_strdup(l1
, "level 2");
1559 torture_assert("memlimit", l2
!= NULL
,
1560 "failed: alloc should not fail due to memory limit\n");
1562 talloc_report_full(root
, stdout
);
1564 printf("==== talloc_free(l2)\n");
1567 talloc_report_full(root
, stdout
);
1569 printf("==== talloc_size(NULL, 2048)\n");
1570 l2
= talloc_size(NULL
, 2048);
1572 talloc_report_full(root
, stdout
);
1574 printf("==== talloc_steal(l1, l2)\n");
1575 talloc_steal(l1
, l2
);
1577 talloc_report_full(root
, stdout
);
1579 printf("==== talloc_strdup(l2, level 3)\n");
1580 l3
= talloc_strdup(l2
, "level 3");
1581 torture_assert("memlimit", l3
== NULL
,
1582 "failed: alloc should fail due to memory limit\n");
1584 talloc_report_full(root
, stdout
);
1586 printf("==== talloc_free(l2)\n");
1589 talloc_report_full(root
, stdout
);
1591 printf("==== talloc_strdup(NULL, level 2)\n");
1592 l2
= talloc_strdup(NULL
, "level 2");
1593 talloc_steal(l1
, l2
);
1595 talloc_report_full(root
, stdout
);
1597 printf("==== talloc_strdup(l2, level 3)\n");
1598 l3
= talloc_strdup(l2
, "level 3");
1599 torture_assert("memlimit", l3
!= NULL
,
1600 "failed: alloc should not fail due to memory limit\n");
1602 talloc_report_full(root
, stdout
);
1604 printf("==== talloc_set_memlimit(l3, 1024)\n");
1605 torture_assert("memlimit", talloc_set_memlimit(l3
, 1024) == 0,
1606 "failed: setting memlimit should never fail\n");
1608 talloc_report_full(root
, stdout
);
1610 printf("==== talloc_strdup(l3, level 4)\n");
1611 l4
= talloc_strdup(l3
, "level 4");
1612 torture_assert("memlimit", l4
!= NULL
,
1613 "failed: alloc should not fail due to memory limit\n");
1615 talloc_report_full(root
, stdout
);
1617 printf("==== talloc_set_memlimit(l4, 512)\n");
1618 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1619 "failed: setting memlimit should never fail\n");
1621 talloc_report_full(root
, stdout
);
1623 printf("==== talloc_strdup(l4, level 5)\n");
1624 l5
= talloc_strdup(l4
, "level 5");
1625 torture_assert("memlimit", l5
!= NULL
,
1626 "failed: alloc should not fail due to memory limit\n");
1628 talloc_report_full(root
, stdout
);
1630 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1631 t
= talloc_realloc(NULL
, l5
, char, 600);
1632 torture_assert("memlimit", t
== NULL
,
1633 "failed: alloc should fail due to memory limit\n");
1635 talloc_report_full(root
, stdout
);
1637 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1638 l5
= talloc_realloc(NULL
, l5
, char, 5);
1639 torture_assert("memlimit", l5
!= NULL
,
1640 "failed: alloc should not fail due to memory limit\n");
1642 talloc_report_full(root
, stdout
);
1644 printf("==== talloc_strdup(l3, level 4)\n");
1645 l4
= talloc_strdup(l3
, "level 4");
1646 torture_assert("memlimit", l4
!= NULL
,
1647 "failed: alloc should not fail due to memory limit\n");
1649 talloc_report_full(root
, stdout
);
1651 printf("==== talloc_set_memlimit(l4, 512)\n");
1652 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1653 "failed: setting memlimit should never fail\n");
1655 talloc_report_full(root
, stdout
);
1657 printf("==== talloc_strdup(l4, level 5)\n");
1658 l5
= talloc_strdup(l4
, "level 5");
1659 torture_assert("memlimit", l5
!= NULL
,
1660 "failed: alloc should not fail due to memory limit\n");
1662 talloc_report_full(root
, stdout
);
1664 printf("==== Make new temp context and steal l5\n");
1665 t
= talloc_new(root
);
1666 talloc_steal(t
, l5
);
1668 talloc_report_full(root
, stdout
);
1670 printf("==== talloc_size(t, 2048)\n");
1671 l1
= talloc_size(t
, 2048);
1672 torture_assert("memlimit", l1
!= NULL
,
1673 "failed: alloc should not fail due to memory limit\n");
1675 talloc_report_full(root
, stdout
);
1678 /* Test memlimits with pools. */
1679 pool
= talloc_pool(NULL
, 10*1024);
1680 torture_assert("memlimit", pool
!= NULL
,
1681 "failed: alloc should not fail due to memory limit\n");
1682 talloc_set_memlimit(pool
, 10*1024);
1683 for (i
= 0; i
< 9; i
++) {
1684 l1
= talloc_size(pool
, 1024);
1685 torture_assert("memlimit", l1
!= NULL
,
1686 "failed: alloc should not fail due to memory limit\n");
1688 /* The next alloc should fail. */
1689 l2
= talloc_size(pool
, 1024);
1690 torture_assert("memlimit", l2
== NULL
,
1691 "failed: alloc should fail due to memory limit\n");
1693 /* Moving one of the children shouldn't change the limit,
1694 as it's still inside the pool. */
1695 root
= talloc_new(NULL
);
1696 talloc_steal(root
, l1
);
1697 l2
= talloc_size(pool
, 1024);
1698 torture_assert("memlimit", l2
== NULL
,
1699 "failed: alloc should fail due to memory limit\n");
1703 printf("success: memlimit\n");
1710 #define NUM_THREADS 100
1712 /* Sync variables. */
1713 static pthread_mutex_t mtx
= PTHREAD_MUTEX_INITIALIZER
;
1714 static pthread_cond_t condvar
= PTHREAD_COND_INITIALIZER
;
1715 static void *intermediate_ptr
;
1718 static void *thread_fn(void *arg
)
1721 const char *ctx_name
= (const char *)arg
;
1722 void *sub_ctx
= NULL
;
1724 * Do stuff that creates a new talloc hierarchy in
1727 void *top_ctx
= talloc_named_const(NULL
, 0, "top");
1728 if (top_ctx
== NULL
) {
1731 sub_ctx
= talloc_named_const(top_ctx
, 100, ctx_name
);
1732 if (sub_ctx
== NULL
) {
1737 * Now transfer a pointer from our hierarchy
1738 * onto the intermediate ptr.
1740 ret
= pthread_mutex_lock(&mtx
);
1742 talloc_free(top_ctx
);
1745 /* Wait for intermediate_ptr to be free. */
1746 while (intermediate_ptr
!= NULL
) {
1747 ret
= pthread_cond_wait(&condvar
, &mtx
);
1749 talloc_free(top_ctx
);
1754 /* and move our memory onto it from our toplevel hierarchy. */
1755 intermediate_ptr
= talloc_move(NULL
, &sub_ctx
);
1757 /* Tell the main thread it's ready for pickup. */
1758 pthread_cond_broadcast(&condvar
);
1759 pthread_mutex_unlock(&mtx
);
1761 talloc_free(top_ctx
);
1766 static bool test_pthread_talloc_passing(void)
1770 char str_array
[NUM_THREADS
][20];
1771 pthread_t thread_id
;
1775 * Important ! Null tracking breaks threaded talloc.
1776 * It *must* be turned off.
1778 talloc_disable_null_tracking();
1780 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1782 /* Main thread toplevel context. */
1783 mem_ctx
= talloc_named_const(NULL
, 0, "toplevel");
1784 if (mem_ctx
== NULL
) {
1785 printf("failed to create toplevel context\n");
1790 * Spin off NUM_THREADS threads.
1791 * They will use their own toplevel contexts.
1793 for (i
= 0; i
< NUM_THREADS
; i
++) {
1794 (void)snprintf(str_array
[i
],
1798 if (str_array
[i
] == NULL
) {
1799 printf("snprintf %d failed\n", i
);
1802 ret
= pthread_create(&thread_id
,
1807 printf("failed to create thread %d (%d)\n", i
, ret
);
1812 printf("Created %d threads\n", NUM_THREADS
);
1814 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1815 for (i
= 0; i
< NUM_THREADS
; i
++) {
1816 ret
= pthread_mutex_lock(&mtx
);
1818 printf("pthread_mutex_lock %d failed (%d)\n", i
, ret
);
1819 talloc_free(mem_ctx
);
1823 /* Wait for intermediate_ptr to have our data. */
1824 while (intermediate_ptr
== NULL
) {
1825 ret
= pthread_cond_wait(&condvar
, &mtx
);
1827 printf("pthread_cond_wait %d failed (%d)\n", i
,
1829 talloc_free(mem_ctx
);
1834 /* and move it onto our toplevel hierarchy. */
1835 (void)talloc_move(mem_ctx
, &intermediate_ptr
);
1837 /* Tell the sub-threads we're ready for another. */
1838 pthread_cond_broadcast(&condvar
);
1839 pthread_mutex_unlock(&mtx
);
1842 CHECK_SIZE("pthread_talloc_passing", mem_ctx
, NUM_THREADS
* 100);
1844 /* Dump the hierarchy. */
1845 talloc_report(mem_ctx
, stdout
);
1847 talloc_free(mem_ctx
);
1848 printf("success: pthread_talloc_passing\n");
1853 static void test_reset(void)
1855 talloc_set_log_fn(test_log_stdout
);
1857 talloc_disable_null_tracking();
1858 talloc_enable_null_tracking_no_autofree();
1861 bool torture_local_talloc(struct torture_context
*tctx
)
1868 ret
&= test_pooled_object();
1870 ret
&= test_pool_nest();
1880 ret
&= test_unlink1();
1884 ret
&= test_realloc();
1886 ret
&= test_realloc_child();
1888 ret
&= test_steal();
1892 ret
&= test_unref_reparent();
1894 ret
&= test_realloc_fn();
1898 ret
&= test_lifeless();
1902 ret
&= test_free_parent_deny_child();
1904 ret
&= test_free_parent_reparent_child();
1906 ret
&= test_free_parent_reparent_child_in_pool();
1908 ret
&= test_talloc_ptrtype();
1910 ret
&= test_talloc_free_in_destructor();
1914 ret
&= test_pool_steal();
1916 ret
&= test_free_ref_null_context();
1918 ret
&= test_rusty();
1920 ret
&= test_free_children();
1922 ret
&= test_memlimit();
1925 ret
&= test_pthread_talloc_passing();
1931 ret
&= test_speed();
1934 ret
&= test_autofree();
1937 talloc_disable_null_tracking();