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();