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"
43 #include "talloc_testsuite.h"
45 static struct timeval private_timeval_current(void)
48 gettimeofday(&tv, NULL);
52 static double private_timeval_elapsed(struct timeval *tv)
54 struct timeval tv2 = private_timeval_current();
55 return (tv2.tv_sec - tv->tv_sec) +
56 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
59 #define torture_assert(test, expr, str) if (!(expr)) { \
60 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
61 test, __location__, #expr, str); \
65 #define torture_assert_str_equal(test, arg1, arg2, desc) \
66 if (arg1 == NULL && arg2 == NULL) { \
67 } else if (strcmp(arg1, arg2)) { \
68 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
69 test, __location__, arg1, arg2, desc); \
73 #define CHECK_SIZE(test, ptr, tsize) do { \
74 if (talloc_total_size(ptr) != (tsize)) { \
75 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
76 test, __location__, #ptr, \
77 (unsigned)talloc_total_size(ptr), \
79 talloc_report_full(ptr, stdout); \
84 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
85 if (talloc_total_blocks(ptr) != (tblocks)) { \
86 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
87 test, __location__, #ptr, \
88 (unsigned)talloc_total_blocks(ptr), \
90 talloc_report_full(ptr, stdout); \
95 #define CHECK_PARENT(test, ptr, parent) do { \
96 if (talloc_parent(ptr) != (parent)) { \
97 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
98 test, __location__, #ptr, \
101 talloc_report_full(ptr, stdout); \
102 talloc_report_full(parent, stdout); \
103 talloc_report_full(NULL, stdout); \
108 static unsigned int test_abort_count;
111 static void test_abort_fn(const char *reason)
113 printf("# test_abort_fn(%s)\n", reason);
117 static void test_abort_start(void)
119 test_abort_count = 0;
120 talloc_set_abort_fn(test_abort_fn);
124 static void test_abort_stop(void)
126 test_abort_count = 0;
127 talloc_set_abort_fn(NULL);
130 static void test_log_stdout(const char *message)
132 fprintf(stdout, "%s", message);
138 static bool test_ref1(void)
140 void *root, *p1, *p2, *ref, *r1;
142 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
144 root = talloc_named_const(NULL, 0, "root");
145 p1 = talloc_named_const(root, 1, "p1");
146 p2 = talloc_named_const(p1, 1, "p2");
147 talloc_named_const(p1, 1, "x1");
148 talloc_named_const(p1, 2, "x2");
149 talloc_named_const(p1, 3, "x3");
151 r1 = talloc_named_const(root, 1, "r1");
152 ref = talloc_reference(r1, p2);
153 talloc_report_full(root, stderr);
155 CHECK_BLOCKS("ref1", p1, 5);
156 CHECK_BLOCKS("ref1", p2, 1);
157 CHECK_BLOCKS("ref1", ref, 1);
158 CHECK_BLOCKS("ref1", r1, 2);
160 fprintf(stderr, "Freeing p2\n");
161 talloc_unlink(r1, p2);
162 talloc_report_full(root, stderr);
164 CHECK_BLOCKS("ref1", p1, 5);
165 CHECK_BLOCKS("ref1", p2, 1);
166 CHECK_BLOCKS("ref1", r1, 1);
168 fprintf(stderr, "Freeing p1\n");
170 talloc_report_full(root, stderr);
172 CHECK_BLOCKS("ref1", r1, 1);
174 fprintf(stderr, "Freeing r1\n");
176 talloc_report_full(NULL, stderr);
178 fprintf(stderr, "Testing NULL\n");
179 if (talloc_reference(root, NULL)) {
183 CHECK_BLOCKS("ref1", root, 1);
185 CHECK_SIZE("ref1", root, 0);
188 printf("success: ref1\n");
195 static bool test_ref2(void)
197 void *root, *p1, *p2, *ref, *r1;
199 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
200 root = talloc_named_const(NULL, 0, "root");
201 p1 = talloc_named_const(root, 1, "p1");
202 talloc_named_const(p1, 1, "x1");
203 talloc_named_const(p1, 1, "x2");
204 talloc_named_const(p1, 1, "x3");
205 p2 = talloc_named_const(p1, 1, "p2");
207 r1 = talloc_named_const(root, 1, "r1");
208 ref = talloc_reference(r1, p2);
209 talloc_report_full(root, stderr);
211 CHECK_BLOCKS("ref2", p1, 5);
212 CHECK_BLOCKS("ref2", p2, 1);
213 CHECK_BLOCKS("ref2", r1, 2);
215 fprintf(stderr, "Freeing ref\n");
216 talloc_unlink(r1, ref);
217 talloc_report_full(root, stderr);
219 CHECK_BLOCKS("ref2", p1, 5);
220 CHECK_BLOCKS("ref2", p2, 1);
221 CHECK_BLOCKS("ref2", r1, 1);
223 fprintf(stderr, "Freeing p2\n");
225 talloc_report_full(root, stderr);
227 CHECK_BLOCKS("ref2", p1, 4);
228 CHECK_BLOCKS("ref2", r1, 1);
230 fprintf(stderr, "Freeing p1\n");
232 talloc_report_full(root, stderr);
234 CHECK_BLOCKS("ref2", r1, 1);
236 fprintf(stderr, "Freeing r1\n");
238 talloc_report_full(root, stderr);
240 CHECK_SIZE("ref2", root, 0);
243 printf("success: ref2\n");
250 static bool test_ref3(void)
252 void *root, *p1, *p2, *ref, *r1;
254 printf("test: ref3\n# PARENT REFERENCE FREE\n");
256 root = talloc_named_const(NULL, 0, "root");
257 p1 = talloc_named_const(root, 1, "p1");
258 p2 = talloc_named_const(root, 1, "p2");
259 r1 = talloc_named_const(p1, 1, "r1");
260 ref = talloc_reference(p2, r1);
261 talloc_report_full(root, stderr);
263 CHECK_BLOCKS("ref3", p1, 2);
264 CHECK_BLOCKS("ref3", p2, 2);
265 CHECK_BLOCKS("ref3", r1, 1);
266 CHECK_BLOCKS("ref3", ref, 1);
268 fprintf(stderr, "Freeing p1\n");
270 talloc_report_full(root, stderr);
272 CHECK_BLOCKS("ref3", p2, 2);
273 CHECK_BLOCKS("ref3", r1, 1);
275 fprintf(stderr, "Freeing p2\n");
277 talloc_report_full(root, stderr);
279 CHECK_SIZE("ref3", root, 0);
283 printf("success: ref3\n");
290 static bool test_ref4(void)
292 void *root, *p1, *p2, *ref, *r1;
294 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
296 root = talloc_named_const(NULL, 0, "root");
297 p1 = talloc_named_const(root, 1, "p1");
298 talloc_named_const(p1, 1, "x1");
299 talloc_named_const(p1, 1, "x2");
300 talloc_named_const(p1, 1, "x3");
301 p2 = talloc_named_const(p1, 1, "p2");
303 r1 = talloc_named_const(root, 1, "r1");
304 ref = talloc_reference(r1, p2);
305 talloc_report_full(root, stderr);
307 CHECK_BLOCKS("ref4", p1, 5);
308 CHECK_BLOCKS("ref4", p2, 1);
309 CHECK_BLOCKS("ref4", ref, 1);
310 CHECK_BLOCKS("ref4", r1, 2);
312 fprintf(stderr, "Freeing r1\n");
314 talloc_report_full(root, stderr);
316 CHECK_BLOCKS("ref4", p1, 5);
317 CHECK_BLOCKS("ref4", p2, 1);
319 fprintf(stderr, "Freeing p2\n");
321 talloc_report_full(root, stderr);
323 CHECK_BLOCKS("ref4", p1, 4);
325 fprintf(stderr, "Freeing p1\n");
327 talloc_report_full(root, stderr);
329 CHECK_SIZE("ref4", root, 0);
333 printf("success: ref4\n");
341 static bool test_unlink1(void)
343 void *root, *p1, *p2, *ref, *r1;
345 printf("test: unlink\n# UNLINK\n");
347 root = talloc_named_const(NULL, 0, "root");
348 p1 = talloc_named_const(root, 1, "p1");
349 talloc_named_const(p1, 1, "x1");
350 talloc_named_const(p1, 1, "x2");
351 talloc_named_const(p1, 1, "x3");
352 p2 = talloc_named_const(p1, 1, "p2");
354 r1 = talloc_named_const(p1, 1, "r1");
355 ref = talloc_reference(r1, p2);
356 talloc_report_full(root, stderr);
358 CHECK_BLOCKS("unlink", p1, 7);
359 CHECK_BLOCKS("unlink", p2, 1);
360 CHECK_BLOCKS("unlink", ref, 1);
361 CHECK_BLOCKS("unlink", r1, 2);
363 fprintf(stderr, "Unreferencing r1\n");
364 talloc_unlink(r1, p2);
365 talloc_report_full(root, stderr);
367 CHECK_BLOCKS("unlink", p1, 6);
368 CHECK_BLOCKS("unlink", p2, 1);
369 CHECK_BLOCKS("unlink", r1, 1);
371 fprintf(stderr, "Freeing p1\n");
373 talloc_report_full(root, stderr);
375 CHECK_SIZE("unlink", root, 0);
379 printf("success: unlink\n");
383 static int fail_destructor(void *ptr)
389 miscellaneous tests to try to get a higher test coverage percentage
391 static bool test_misc(void)
398 printf("test: misc\n# MISCELLANEOUS\n");
400 root = talloc_new(NULL);
402 p1 = talloc_size(root, 0x7fffffff);
403 torture_assert("misc", !p1, "failed: large talloc allowed\n");
405 p1 = talloc_strdup(root, "foo");
406 talloc_increase_ref_count(p1);
407 talloc_increase_ref_count(p1);
408 talloc_increase_ref_count(p1);
409 CHECK_BLOCKS("misc", p1, 1);
410 CHECK_BLOCKS("misc", root, 2);
411 talloc_unlink(NULL, p1);
412 CHECK_BLOCKS("misc", p1, 1);
413 CHECK_BLOCKS("misc", root, 2);
414 talloc_unlink(NULL, p1);
415 CHECK_BLOCKS("misc", p1, 1);
416 CHECK_BLOCKS("misc", root, 2);
417 p2 = talloc_strdup(p1, "foo");
418 torture_assert("misc", talloc_unlink(root, p2) == -1,
419 "failed: talloc_unlink() of non-reference context should return -1\n");
420 torture_assert("misc", talloc_unlink(p1, p2) == 0,
421 "failed: talloc_unlink() of parent should succeed\n");
422 talloc_unlink(NULL, p1);
423 CHECK_BLOCKS("misc", p1, 1);
424 CHECK_BLOCKS("misc", root, 2);
426 name = talloc_set_name(p1, "my name is %s", "foo");
427 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
428 "failed: wrong name after talloc_set_name(my name is foo)");
429 torture_assert_str_equal("misc", talloc_get_name(p1), name,
430 "failed: wrong name after talloc_set_name(my name is foo)");
431 CHECK_BLOCKS("misc", p1, 2);
432 CHECK_BLOCKS("misc", root, 3);
434 talloc_set_name_const(p1, NULL);
435 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
436 "failed: wrong name after talloc_set_name(NULL)");
437 CHECK_BLOCKS("misc", p1, 2);
438 CHECK_BLOCKS("misc", root, 3);
440 torture_assert("misc", talloc_free(NULL) == -1,
441 "talloc_free(NULL) should give -1\n");
443 talloc_set_destructor(p1, fail_destructor);
444 torture_assert("misc", talloc_free(p1) == -1,
445 "Failed destructor should cause talloc_free to fail\n");
446 talloc_set_destructor(p1, NULL);
448 talloc_report(root, stderr);
451 p2 = (char *)talloc_zero_size(p1, 20);
452 torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
455 torture_assert("misc", talloc_strdup(root, NULL) == NULL,
456 "failed: strdup on NULL should give NULL\n");
458 p2 = talloc_strndup(p1, "foo", 2);
459 torture_assert("misc", strcmp("fo", p2) == 0,
460 "strndup doesn't work\n");
461 p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
462 torture_assert("misc", strcmp("food", p2) == 0,
463 "talloc_asprintf_append_buffer doesn't work\n");
464 CHECK_BLOCKS("misc", p2, 1);
465 CHECK_BLOCKS("misc", p1, 3);
467 p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
468 torture_assert("misc", strcmp("hello world", p2) == 0,
469 "talloc_asprintf_append_buffer doesn't work\n");
470 CHECK_BLOCKS("misc", p2, 1);
471 CHECK_BLOCKS("misc", p1, 3);
474 d = talloc_array(p1, double, 0x20000000);
475 torture_assert("misc", !d, "failed: integer overflow not detected\n");
477 d = talloc_realloc(p1, d, double, 0x20000000);
478 torture_assert("misc", !d, "failed: integer overflow not detected\n");
481 CHECK_BLOCKS("misc", root, 1);
483 p1 = talloc_named(root, 100, "%d bytes", 100);
484 CHECK_BLOCKS("misc", p1, 2);
485 CHECK_BLOCKS("misc", root, 3);
486 talloc_unlink(root, p1);
488 p1 = talloc_init("%d bytes", 200);
489 p2 = talloc_asprintf(p1, "my test '%s'", "string");
490 torture_assert_str_equal("misc", p2, "my test 'string'",
491 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
492 CHECK_BLOCKS("misc", p1, 3);
493 CHECK_SIZE("misc", p2, 17);
494 CHECK_BLOCKS("misc", root, 1);
495 talloc_unlink(NULL, p1);
497 p1 = talloc_named_const(root, 10, "p1");
498 p2 = (char *)talloc_named_const(root, 20, "p2");
499 (void)talloc_reference(p1, p2);
500 talloc_report_full(root, stderr);
501 talloc_unlink(root, p2);
502 talloc_report_full(root, stderr);
503 CHECK_BLOCKS("misc", p2, 1);
504 CHECK_BLOCKS("misc", p1, 2);
505 CHECK_BLOCKS("misc", root, 3);
506 talloc_unlink(p1, p2);
507 talloc_unlink(root, p1);
509 p1 = talloc_named_const(root, 10, "p1");
510 p2 = (char *)talloc_named_const(root, 20, "p2");
511 (void)talloc_reference(NULL, p2);
512 talloc_report_full(root, stderr);
513 talloc_unlink(root, p2);
514 talloc_report_full(root, stderr);
515 CHECK_BLOCKS("misc", p2, 1);
516 CHECK_BLOCKS("misc", p1, 1);
517 CHECK_BLOCKS("misc", root, 2);
518 talloc_unlink(NULL, p2);
519 talloc_unlink(root, p1);
521 /* Test that talloc_unlink is a no-op */
523 torture_assert("misc", talloc_unlink(root, NULL) == -1,
524 "failed: talloc_unlink(root, NULL) == -1\n");
526 talloc_report(root, stderr);
527 talloc_report(NULL, stderr);
529 CHECK_SIZE("misc", root, 0);
533 CHECK_SIZE("misc", NULL, 0);
535 talloc_enable_null_tracking_no_autofree();
536 talloc_enable_leak_report();
537 talloc_enable_leak_report_full();
539 printf("success: misc\n");
548 static bool test_realloc(void)
550 void *root, *p1, *p2;
552 printf("test: realloc\n# REALLOC\n");
554 root = talloc_new(NULL);
556 p1 = talloc_size(root, 10);
557 CHECK_SIZE("realloc", p1, 10);
559 p1 = talloc_realloc_size(NULL, p1, 20);
560 CHECK_SIZE("realloc", p1, 20);
564 p2 = talloc_realloc_size(p1, NULL, 30);
568 p2 = talloc_realloc_size(p1, p2, 40);
570 CHECK_SIZE("realloc", p2, 40);
571 CHECK_SIZE("realloc", root, 60);
572 CHECK_BLOCKS("realloc", p1, 4);
574 p1 = talloc_realloc_size(NULL, p1, 20);
575 CHECK_SIZE("realloc", p1, 60);
577 talloc_increase_ref_count(p2);
578 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
579 "failed: talloc_realloc() on a referenced pointer should fail\n");
580 CHECK_BLOCKS("realloc", p1, 4);
582 talloc_realloc_size(NULL, p2, 0);
583 talloc_realloc_size(NULL, p2, 0);
584 CHECK_BLOCKS("realloc", p1, 4);
585 talloc_realloc_size(p1, p2, 0);
586 CHECK_BLOCKS("realloc", p1, 3);
588 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
589 "failed: oversize talloc should fail\n");
591 talloc_realloc_size(NULL, p1, 0);
592 CHECK_BLOCKS("realloc", root, 4);
593 talloc_realloc_size(root, p1, 0);
594 CHECK_BLOCKS("realloc", root, 1);
596 CHECK_SIZE("realloc", root, 0);
600 printf("success: realloc\n");
606 test realloc with a child
608 static bool test_realloc_child(void)
616 struct el2 **list, **list2, **list3;
619 printf("test: REALLOC WITH CHILD\n");
621 root = talloc_new(NULL);
623 el1 = talloc(root, struct el1);
624 el1->list = talloc(el1, struct el2 *);
625 el1->list[0] = talloc(el1->list, struct el2);
626 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
628 el1->list2 = talloc(el1, struct el2 *);
629 el1->list2[0] = talloc(el1->list2, struct el2);
630 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
632 el1->list3 = talloc(el1, struct el2 *);
633 el1->list3[0] = talloc(el1->list3, struct el2);
634 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
636 el2 = talloc(el1->list, struct el2);
637 el2 = talloc(el1->list2, struct el2);
638 el2 = talloc(el1->list3, struct el2);
641 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
642 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
643 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
647 printf("success: REALLOC WITH CHILD\n");
654 static bool test_type(void)
665 printf("test: type\n# talloc type checking\n");
667 root = talloc_new(NULL);
669 el1 = talloc(root, struct el1);
673 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
674 "type check failed on el1\n");
675 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
676 "type check failed on el1 with el2\n");
677 talloc_set_type(el1, struct el2);
678 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
679 "type set failed on el1 with el2\n");
683 printf("success: type\n");
690 static bool test_steal(void)
692 void *root, *p1, *p2;
694 printf("test: steal\n# STEAL\n");
696 root = talloc_new(NULL);
698 p1 = talloc_array(root, char, 10);
699 CHECK_SIZE("steal", p1, 10);
701 p2 = talloc_realloc(root, NULL, char, 20);
702 CHECK_SIZE("steal", p1, 10);
703 CHECK_SIZE("steal", root, 30);
705 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
706 "failed: stealing NULL should give NULL\n");
708 torture_assert("steal", talloc_steal(p1, p1) == p1,
709 "failed: stealing to ourselves is a nop\n");
710 CHECK_BLOCKS("steal", root, 3);
711 CHECK_SIZE("steal", root, 30);
713 talloc_steal(NULL, p1);
714 talloc_steal(NULL, p2);
715 CHECK_BLOCKS("steal", root, 1);
716 CHECK_SIZE("steal", root, 0);
719 talloc_steal(root, p2);
720 CHECK_BLOCKS("steal", root, 2);
721 CHECK_SIZE("steal", root, 20);
725 CHECK_BLOCKS("steal", root, 1);
726 CHECK_SIZE("steal", root, 0);
730 p1 = talloc_size(NULL, 3);
731 talloc_report_full(NULL, stderr);
732 CHECK_SIZE("steal", NULL, 3);
735 printf("success: steal\n");
742 static bool test_move(void)
750 printf("test: move\n# MOVE\n");
752 root = talloc_new(NULL);
754 t1 = talloc(root, struct t_move);
755 t2 = talloc(root, struct t_move);
756 t1->p = talloc_strdup(t1, "foo");
757 t1->x = talloc(t1, int);
760 t2->p = talloc_move(t2, &t1->p);
761 t2->x = talloc_move(t2, &t1->x);
762 torture_assert("move", t1->p == NULL && t1->x == NULL &&
763 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
764 "talloc move failed");
768 printf("success: move\n");
774 test talloc_realloc_fn
776 static bool test_realloc_fn(void)
780 printf("test: realloc_fn\n# talloc_realloc_fn\n");
782 root = talloc_new(NULL);
784 p1 = talloc_realloc_fn(root, NULL, 10);
785 CHECK_BLOCKS("realloc_fn", root, 2);
786 CHECK_SIZE("realloc_fn", root, 10);
787 p1 = talloc_realloc_fn(root, p1, 20);
788 CHECK_BLOCKS("realloc_fn", root, 2);
789 CHECK_SIZE("realloc_fn", root, 20);
790 p1 = talloc_realloc_fn(root, p1, 0);
791 CHECK_BLOCKS("realloc_fn", root, 1);
792 CHECK_SIZE("realloc_fn", root, 0);
796 printf("success: realloc_fn\n");
801 static bool test_unref_reparent(void)
803 void *root, *p1, *p2, *c1;
805 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
807 root = talloc_named_const(NULL, 0, "root");
808 p1 = talloc_named_const(root, 1, "orig parent");
809 p2 = talloc_named_const(root, 1, "parent by reference");
811 c1 = talloc_named_const(p1, 1, "child");
812 talloc_reference(p2, c1);
814 CHECK_PARENT("unref_reparent", c1, p1);
818 CHECK_PARENT("unref_reparent", c1, p2);
820 talloc_unlink(p2, c1);
822 CHECK_SIZE("unref_reparent", root, 1);
827 printf("success: unref_reparent\n");
832 measure the speed of talloc versus malloc
834 static bool test_speed(void)
836 void *ctx = talloc_new(NULL);
838 const int loop = 1000;
842 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
844 tv = private_timeval_current();
848 for (i=0;i<loop;i++) {
849 p1 = talloc_size(ctx, loop % 100);
850 p2 = talloc_strdup(p1, "foo bar");
851 p3 = talloc_size(p1, 300);
857 } while (private_timeval_elapsed(&tv) < 5.0);
859 fprintf(stderr, "talloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
863 ctx = talloc_pool(NULL, 1024);
865 tv = private_timeval_current();
869 for (i=0;i<loop;i++) {
870 p1 = talloc_size(ctx, loop % 100);
871 p2 = talloc_strdup(p1, "foo bar");
872 p3 = talloc_size(p1, 300);
878 } while (private_timeval_elapsed(&tv) < 5.0);
882 fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
884 tv = private_timeval_current();
888 for (i=0;i<loop;i++) {
889 p1 = malloc(loop % 100);
890 p2 = strdup("foo bar");
897 } while (private_timeval_elapsed(&tv) < 5.0);
898 fprintf(stderr, "malloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
900 printf("success: speed\n");
905 static bool test_lifeless(void)
907 void *top = talloc_new(NULL);
908 char *parent, *child;
909 void *child_owner = talloc_new(NULL);
911 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
913 parent = talloc_strdup(top, "parent");
914 child = talloc_strdup(parent, "child");
915 (void)talloc_reference(child, parent);
916 (void)talloc_reference(child_owner, child);
917 talloc_report_full(top, stderr);
918 talloc_unlink(top, parent);
919 talloc_unlink(top, child);
920 talloc_report_full(top, stderr);
922 talloc_free(child_owner);
925 printf("success: lifeless\n");
929 static int loop_destructor_count;
931 static int test_loop_destructor(char *ptr)
933 loop_destructor_count++;
937 static bool test_loop(void)
939 void *top = talloc_new(NULL);
945 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
947 parent = talloc_strdup(top, "parent");
948 req1 = talloc(parent, struct req1);
949 req1->req2 = talloc_strdup(req1, "req2");
950 talloc_set_destructor(req1->req2, test_loop_destructor);
951 req1->req3 = talloc_strdup(req1, "req3");
952 (void)talloc_reference(req1->req3, req1);
953 talloc_report_full(top, stderr);
955 talloc_report_full(top, stderr);
956 talloc_report_full(NULL, stderr);
959 torture_assert("loop", loop_destructor_count == 1,
960 "FAILED TO FIRE LOOP DESTRUCTOR\n");
961 loop_destructor_count = 0;
963 printf("success: loop\n");
967 static int fail_destructor_str(char *ptr)
972 static bool test_free_parent_deny_child(void)
974 void *top = talloc_new(NULL);
979 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
981 level1 = talloc_strdup(top, "level1");
982 level2 = talloc_strdup(level1, "level2");
983 level3 = talloc_strdup(level2, "level3");
985 talloc_set_destructor(level3, fail_destructor_str);
987 talloc_set_destructor(level3, NULL);
989 CHECK_PARENT("free_parent_deny_child", level3, top);
993 printf("success: free_parent_deny_child\n");
1002 static int reparenting_destructor(struct new_parent *np)
1004 talloc_set_destructor(np, NULL);
1005 (void)talloc_move(np->new_parent, &np);
1009 static bool test_free_parent_reparent_child(void)
1011 void *top = talloc_new(NULL);
1013 char *alternate_level1;
1015 struct new_parent *level3;
1017 printf("test: free_parent_reparent_child\n# "
1018 "TALLOC FREE PARENT REPARENT CHILD\n");
1020 level1 = talloc_strdup(top, "level1");
1021 alternate_level1 = talloc_strdup(top, "alternate_level1");
1022 level2 = talloc_strdup(level1, "level2");
1023 level3 = talloc(level2, struct new_parent);
1024 level3->new_parent = alternate_level1;
1025 memset(level3->val, 'x', sizeof(level3->val));
1027 talloc_set_destructor(level3, reparenting_destructor);
1028 talloc_free(level1);
1030 CHECK_PARENT("free_parent_reparent_child",
1031 level3, alternate_level1);
1035 printf("success: free_parent_reparent_child\n");
1039 static bool test_free_parent_reparent_child_in_pool(void)
1041 void *top = talloc_new(NULL);
1043 char *alternate_level1;
1046 struct new_parent *level3;
1048 printf("test: free_parent_reparent_child_in_pool\n# "
1049 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1051 pool = talloc_pool(top, 1024);
1052 level1 = talloc_strdup(pool, "level1");
1053 alternate_level1 = talloc_strdup(top, "alternate_level1");
1054 level2 = talloc_strdup(level1, "level2");
1055 level3 = talloc(level2, struct new_parent);
1056 level3->new_parent = alternate_level1;
1057 memset(level3->val, 'x', sizeof(level3->val));
1059 talloc_set_destructor(level3, reparenting_destructor);
1060 talloc_free(level1);
1061 talloc_set_destructor(level3, NULL);
1063 CHECK_PARENT("free_parent_reparent_child_in_pool",
1064 level3, alternate_level1);
1066 /* Even freeing alternate_level1 should leave pool alone. */
1067 talloc_free(alternate_level1);
1070 printf("success: free_parent_reparent_child_in_pool\n");
1075 static bool test_talloc_ptrtype(void)
1077 void *top = talloc_new(NULL);
1081 } *s1, *s2, **s3, ***s4;
1082 const char *location1;
1083 const char *location2;
1084 const char *location3;
1085 const char *location4;
1087 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1089 s1 = talloc_ptrtype(top, s1);location1 = __location__;
1091 if (talloc_get_size(s1) != sizeof(struct struct1)) {
1092 printf("failure: ptrtype [\n"
1093 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1094 "]\n", (unsigned long)talloc_get_size(s1),
1095 (unsigned long)sizeof(struct struct1));
1099 if (strcmp(location1, talloc_get_name(s1)) != 0) {
1100 printf("failure: ptrtype [\n"
1101 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1102 talloc_get_name(s1), location1);
1106 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1108 if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1109 printf("failure: ptrtype [\n"
1110 "talloc_array_ptrtype() allocated the wrong size "
1111 "%lu (should be %lu)\n]\n",
1112 (unsigned long)talloc_get_size(s2),
1113 (unsigned long)(sizeof(struct struct1)*10));
1117 if (strcmp(location2, talloc_get_name(s2)) != 0) {
1118 printf("failure: ptrtype [\n"
1119 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1120 talloc_get_name(s2), location2);
1124 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1126 if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1127 printf("failure: ptrtype [\n"
1128 "talloc_array_ptrtype() allocated the wrong size "
1129 "%lu (should be %lu)\n]\n",
1130 (unsigned long)talloc_get_size(s3),
1131 (unsigned long)(sizeof(struct struct1 *)*10));
1135 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1136 "talloc_array_ptrtype() sets the wrong name");
1138 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1140 if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1141 printf("failure: ptrtype [\n"
1142 "talloc_array_ptrtype() allocated the wrong size "
1143 "%lu (should be %lu)\n]\n",
1144 (unsigned long)talloc_get_size(s4),
1145 (unsigned long)(sizeof(struct struct1 **)*10));
1149 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1150 "talloc_array_ptrtype() sets the wrong name");
1154 printf("success: ptrtype\n");
1158 static int _test_talloc_free_in_destructor(void **ptr)
1164 static bool test_talloc_free_in_destructor(void)
1173 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1175 level0 = talloc_new(NULL);
1176 level1 = talloc_new(level0);
1177 level2 = talloc_new(level1);
1178 level3 = talloc_new(level2);
1179 level4 = talloc_new(level3);
1180 level5 = talloc(level4, void *);
1183 (void)talloc_reference(level0, level3);
1184 (void)talloc_reference(level3, level3);
1185 (void)talloc_reference(level5, level3);
1187 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1189 talloc_free(level1);
1191 talloc_free(level0);
1193 printf("success: free_in_destructor\n");
1197 static bool test_autofree(void)
1199 #if _SAMBA_BUILD_ < 4
1200 /* autofree test would kill smbtorture */
1202 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1204 p = talloc_autofree_context();
1207 p = talloc_autofree_context();
1210 printf("success: autofree\n");
1215 static bool test_pool(void)
1218 void *p1, *p2, *p3, *p4;
1221 pool = talloc_pool(NULL, 1024);
1223 p1 = talloc_size(pool, 80);
1224 memset(p1, 0x11, talloc_get_size(p1));
1225 p2 = talloc_size(pool, 20);
1226 memset(p2, 0x11, talloc_get_size(p2));
1227 p3 = talloc_size(p1, 50);
1228 memset(p3, 0x11, talloc_get_size(p3));
1229 p4 = talloc_size(p3, 1000);
1230 memset(p4, 0x11, talloc_get_size(p4));
1232 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1233 p2_2 = talloc_realloc_size(pool, p2, 20+1);
1234 torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1235 memset(p2, 0x11, talloc_get_size(p2));
1236 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1237 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1238 memset(p2, 0x11, talloc_get_size(p2));
1239 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1240 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1241 memset(p2, 0x11, talloc_get_size(p2));
1245 /* this should reclaim the memory of p4 and p3 */
1246 p2_2 = talloc_realloc_size(pool, p2, 400);
1247 torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1248 memset(p2, 0x11, talloc_get_size(p2));
1252 /* this should reclaim the memory of p1 */
1253 p2_2 = talloc_realloc_size(pool, p2, 800);
1254 torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1256 memset(p2, 0x11, talloc_get_size(p2));
1258 /* this should do a malloc */
1259 p2_2 = talloc_realloc_size(pool, p2, 1800);
1260 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1262 memset(p2, 0x11, talloc_get_size(p2));
1264 /* this should reclaim the memory from the pool */
1265 p3 = talloc_size(pool, 80);
1266 torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1267 memset(p3, 0x11, talloc_get_size(p3));
1272 p1 = talloc_size(pool, 80);
1273 memset(p1, 0x11, talloc_get_size(p1));
1274 p2 = talloc_size(pool, 20);
1275 memset(p2, 0x11, talloc_get_size(p2));
1279 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1280 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1281 memset(p2, 0x11, talloc_get_size(p2));
1282 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1283 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1284 memset(p2, 0x11, talloc_get_size(p2));
1286 /* this should do a malloc */
1287 p2_2 = talloc_realloc_size(pool, p2, 1800);
1288 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1290 memset(p2, 0x11, talloc_get_size(p2));
1292 /* this should reclaim the memory from the pool */
1293 p3 = talloc_size(pool, 800);
1294 torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1295 memset(p3, 0x11, talloc_get_size(p3));
1297 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1304 static bool test_pool_steal(void)
1313 root = talloc_new(NULL);
1314 pool = talloc_pool(root, 1024);
1316 p1 = talloc_size(pool, 4 * 16);
1317 torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1318 memset(p1, 0x11, talloc_get_size(p1));
1319 p2 = talloc_size(pool, 4 * 16);
1320 torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1321 memset(p2, 0x11, talloc_get_size(p2));
1323 ofs1 = PTR_DIFF(p2, p1);
1324 hdr = ofs1 - talloc_get_size(p1);
1326 talloc_steal(root, p1);
1327 talloc_steal(root, p2);
1333 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1334 p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1335 torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1336 memset(p1_2, 0x11, talloc_get_size(p1_2));
1337 ofs1 = PTR_DIFF(p1_2, p2);
1338 ofs2 = talloc_get_size(p2) + hdr;
1340 torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1342 p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1343 torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1344 memset(p2_2, 0x11, talloc_get_size(p2_2));
1345 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1351 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1352 /* now we should reclaim the full pool */
1353 p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1354 torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1356 memset(p2_2, 0x11, talloc_get_size(p2_2));
1358 /* now we malloc and free the full pool space */
1359 p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1360 torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1361 memset(p2_2, 0x11, talloc_get_size(p2_2));
1363 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1372 static bool test_pool_nest(void)
1375 void *e = talloc_new(NULL);
1377 p1 = talloc_pool(NULL, 1024);
1378 torture_assert("talloc_pool", p1 != NULL, "failed");
1380 p2 = talloc_pool(p1, 500);
1381 torture_assert("talloc_pool", p2 != NULL, "failed");
1383 p3 = talloc_size(p2, 10);
1385 talloc_steal(e, p3);
1402 static bool test_pooled_object(void)
1405 const char *s1 = "hello";
1406 const char *s2 = "world";
1407 const char *s3 = "";
1409 p = talloc_pooled_object(NULL, struct pooled, 3,
1410 strlen(s1)+strlen(s2)+strlen(s3)+3);
1412 if (talloc_get_size(p) != sizeof(struct pooled)) {
1416 p->s1 = talloc_strdup(p, s1);
1419 p->s1 = talloc_strdup(p, s2);
1422 p->s1 = talloc_strdup(p, s1);
1423 p->s2 = talloc_strdup(p, s2);
1424 p->s3 = talloc_strdup(p, s3);
1430 static bool test_free_ref_null_context(void)
1435 talloc_disable_null_tracking();
1436 p1 = talloc_new(NULL);
1437 p2 = talloc_new(NULL);
1439 p3 = talloc_reference(p2, p1);
1440 torture_assert("reference", p3 == p1, "failed: reference on null");
1442 ret = talloc_free(p1);
1443 torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1446 talloc_enable_null_tracking_no_autofree();
1447 p1 = talloc_new(NULL);
1448 p2 = talloc_new(NULL);
1450 p3 = talloc_reference(p2, p1);
1451 torture_assert("reference", p3 == p1, "failed: reference on null");
1453 ret = talloc_free(p1);
1454 torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1460 static bool test_rusty(void)
1465 talloc_enable_null_tracking();
1466 root = talloc_new(NULL);
1467 p1 = talloc_strdup(root, "foo");
1468 talloc_increase_ref_count(p1);
1469 talloc_report_full(root, stdout);
1471 CHECK_BLOCKS("null_context", NULL, 2);
1475 static bool test_free_children(void)
1479 const char *name, *name2;
1481 talloc_enable_null_tracking();
1482 root = talloc_new(NULL);
1483 p1 = talloc_strdup(root, "foo1");
1484 p2 = talloc_strdup(p1, "foo2");
1487 talloc_set_name(p1, "%s", "testname");
1488 talloc_free_children(p1);
1489 /* check its still a valid talloc ptr */
1490 talloc_get_size(talloc_get_name(p1));
1491 if (strcmp(talloc_get_name(p1), "testname") != 0) {
1495 talloc_set_name(p1, "%s", "testname");
1496 name = talloc_get_name(p1);
1497 talloc_free_children(p1);
1498 /* check its still a valid talloc ptr */
1499 talloc_get_size(talloc_get_name(p1));
1500 torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
1501 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
1503 CHECK_BLOCKS("name1", p1, 2);
1505 /* note that this does not free the old child name */
1506 talloc_set_name_const(p1, "testname2");
1507 name2 = talloc_get_name(p1);
1509 talloc_free_children(p1);
1511 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1513 CHECK_BLOCKS("name1", p1, 1);
1515 talloc_report_full(root, stdout);
1520 static bool test_memlimit(void)
1523 char *l1, *l2, *l3, *l4, *l5, *t;
1527 printf("test: memlimit\n# MEMORY LIMITS\n");
1529 printf("==== talloc_new(NULL)\n");
1530 root = talloc_new(NULL);
1532 talloc_report_full(root, stdout);
1534 printf("==== talloc_size(root, 2048)\n");
1535 l1 = talloc_size(root, 2048);
1536 torture_assert("memlimit", l1 != NULL,
1537 "failed: alloc should not fail due to memory limit\n");
1539 talloc_report_full(root, stdout);
1541 printf("==== talloc_free(l1)\n");
1544 talloc_report_full(root, stdout);
1546 printf("==== talloc_strdup(root, level 1)\n");
1547 l1 = talloc_strdup(root, "level 1");
1548 torture_assert("memlimit", l1 != NULL,
1549 "failed: alloc should not fail due to memory limit\n");
1551 talloc_report_full(root, stdout);
1553 printf("==== talloc_set_memlimit(l1, 2048)\n");
1554 torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
1555 "failed: setting memlimit should never fail\n");
1557 talloc_report_full(root, stdout);
1559 printf("==== talloc_size(root, 2048)\n");
1560 l2 = talloc_size(l1, 2048);
1561 torture_assert("memlimit", l2 == NULL,
1562 "failed: alloc should fail due to memory limit\n");
1564 talloc_report_full(root, stdout);
1566 printf("==== talloc_strdup(l1, level 2)\n");
1567 l2 = talloc_strdup(l1, "level 2");
1568 torture_assert("memlimit", l2 != NULL,
1569 "failed: alloc should not fail due to memory limit\n");
1571 talloc_report_full(root, stdout);
1573 printf("==== talloc_free(l2)\n");
1576 talloc_report_full(root, stdout);
1578 printf("==== talloc_size(NULL, 2048)\n");
1579 l2 = talloc_size(NULL, 2048);
1581 talloc_report_full(root, stdout);
1583 printf("==== talloc_steal(l1, l2)\n");
1584 talloc_steal(l1, l2);
1586 talloc_report_full(root, stdout);
1588 printf("==== talloc_strdup(l2, level 3)\n");
1589 l3 = talloc_strdup(l2, "level 3");
1590 torture_assert("memlimit", l3 == NULL,
1591 "failed: alloc should fail due to memory limit\n");
1593 talloc_report_full(root, stdout);
1595 printf("==== talloc_free(l2)\n");
1598 talloc_report_full(root, stdout);
1600 printf("==== talloc_strdup(NULL, level 2)\n");
1601 l2 = talloc_strdup(NULL, "level 2");
1602 talloc_steal(l1, l2);
1604 talloc_report_full(root, stdout);
1606 printf("==== talloc_strdup(l2, level 3)\n");
1607 l3 = talloc_strdup(l2, "level 3");
1608 torture_assert("memlimit", l3 != NULL,
1609 "failed: alloc should not fail due to memory limit\n");
1611 talloc_report_full(root, stdout);
1613 printf("==== talloc_set_memlimit(l3, 1024)\n");
1614 torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
1615 "failed: setting memlimit should never fail\n");
1617 talloc_report_full(root, stdout);
1619 printf("==== talloc_strdup(l3, level 4)\n");
1620 l4 = talloc_strdup(l3, "level 4");
1621 torture_assert("memlimit", l4 != NULL,
1622 "failed: alloc should not fail due to memory limit\n");
1624 talloc_report_full(root, stdout);
1626 printf("==== talloc_set_memlimit(l4, 512)\n");
1627 torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1628 "failed: setting memlimit should never fail\n");
1630 talloc_report_full(root, stdout);
1632 printf("==== talloc_strdup(l4, level 5)\n");
1633 l5 = talloc_strdup(l4, "level 5");
1634 torture_assert("memlimit", l5 != NULL,
1635 "failed: alloc should not fail due to memory limit\n");
1637 talloc_report_full(root, stdout);
1639 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1640 t = talloc_realloc(NULL, l5, char, 600);
1641 torture_assert("memlimit", t == NULL,
1642 "failed: alloc should fail due to memory limit\n");
1644 talloc_report_full(root, stdout);
1646 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1647 l5 = talloc_realloc(NULL, l5, char, 5);
1648 torture_assert("memlimit", l5 != NULL,
1649 "failed: alloc should not fail due to memory limit\n");
1651 talloc_report_full(root, stdout);
1653 printf("==== talloc_strdup(l3, level 4)\n");
1654 l4 = talloc_strdup(l3, "level 4");
1655 torture_assert("memlimit", l4 != NULL,
1656 "failed: alloc should not fail due to memory limit\n");
1658 talloc_report_full(root, stdout);
1660 printf("==== talloc_set_memlimit(l4, 512)\n");
1661 torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1662 "failed: setting memlimit should never fail\n");
1664 talloc_report_full(root, stdout);
1666 printf("==== talloc_strdup(l4, level 5)\n");
1667 l5 = talloc_strdup(l4, "level 5");
1668 torture_assert("memlimit", l5 != NULL,
1669 "failed: alloc should not fail due to memory limit\n");
1671 talloc_report_full(root, stdout);
1673 printf("==== Make new temp context and steal l5\n");
1674 t = talloc_new(root);
1675 talloc_steal(t, l5);
1677 talloc_report_full(root, stdout);
1679 printf("==== talloc_size(t, 2048)\n");
1680 l1 = talloc_size(t, 2048);
1681 torture_assert("memlimit", l1 != NULL,
1682 "failed: alloc should not fail due to memory limit\n");
1684 talloc_report_full(root, stdout);
1687 /* Test memlimits with pools. */
1688 pool = talloc_pool(NULL, 10*1024);
1689 torture_assert("memlimit", pool != NULL,
1690 "failed: alloc should not fail due to memory limit\n");
1691 talloc_set_memlimit(pool, 10*1024);
1692 for (i = 0; i < 9; i++) {
1693 l1 = talloc_size(pool, 1024);
1694 torture_assert("memlimit", l1 != NULL,
1695 "failed: alloc should not fail due to memory limit\n");
1697 /* The next alloc should fail. */
1698 l2 = talloc_size(pool, 1024);
1699 torture_assert("memlimit", l2 == NULL,
1700 "failed: alloc should fail due to memory limit\n");
1702 /* Moving one of the children shouldn't change the limit,
1703 as it's still inside the pool. */
1704 root = talloc_new(NULL);
1705 talloc_steal(root, l1);
1706 l2 = talloc_size(pool, 1024);
1707 torture_assert("memlimit", l2 == NULL,
1708 "failed: alloc should fail due to memory limit\n");
1712 printf("success: memlimit\n");
1719 #define NUM_THREADS 100
1721 /* Sync variables. */
1722 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1723 static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1724 static void *intermediate_ptr;
1727 static void *thread_fn(void *arg)
1730 const char *ctx_name = (const char *)arg;
1731 void *sub_ctx = NULL;
1733 * Do stuff that creates a new talloc hierarchy in
1736 void *top_ctx = talloc_named_const(NULL, 0, "top");
1737 if (top_ctx == NULL) {
1740 sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1741 if (sub_ctx == NULL) {
1746 * Now transfer a pointer from our hierarchy
1747 * onto the intermediate ptr.
1749 ret = pthread_mutex_lock(&mtx);
1751 talloc_free(top_ctx);
1754 /* Wait for intermediate_ptr to be free. */
1755 while (intermediate_ptr != NULL) {
1756 ret = pthread_cond_wait(&condvar, &mtx);
1758 talloc_free(top_ctx);
1759 ret = pthread_mutex_unlock(&mtx);
1765 /* and move our memory onto it from our toplevel hierarchy. */
1766 intermediate_ptr = talloc_move(NULL, &sub_ctx);
1768 /* Tell the main thread it's ready for pickup. */
1769 pthread_cond_broadcast(&condvar);
1770 ret = pthread_mutex_unlock(&mtx);
1773 talloc_free(top_ctx);
1778 static bool test_pthread_talloc_passing(void)
1782 char str_array[NUM_THREADS][20];
1783 pthread_t thread_id;
1787 * Important ! Null tracking breaks threaded talloc.
1788 * It *must* be turned off.
1790 talloc_disable_null_tracking();
1792 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1794 /* Main thread toplevel context. */
1795 mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1796 if (mem_ctx == NULL) {
1797 printf("failed to create toplevel context\n");
1802 * Spin off NUM_THREADS threads.
1803 * They will use their own toplevel contexts.
1805 for (i = 0; i < NUM_THREADS; i++) {
1806 ret = snprintf(str_array[i],
1811 printf("snprintf %d failed\n", i);
1814 ret = pthread_create(&thread_id,
1819 printf("failed to create thread %d (%d)\n", i, ret);
1824 printf("Created %d threads\n", NUM_THREADS);
1826 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1827 for (i = 0; i < NUM_THREADS; i++) {
1828 ret = pthread_mutex_lock(&mtx);
1830 printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
1831 talloc_free(mem_ctx);
1835 /* Wait for intermediate_ptr to have our data. */
1836 while (intermediate_ptr == NULL) {
1837 ret = pthread_cond_wait(&condvar, &mtx);
1839 printf("pthread_cond_wait %d failed (%d)\n", i,
1841 talloc_free(mem_ctx);
1842 ret = pthread_mutex_unlock(&mtx);
1847 /* and move it onto our toplevel hierarchy. */
1848 (void)talloc_move(mem_ctx, &intermediate_ptr);
1850 /* Tell the sub-threads we're ready for another. */
1851 pthread_cond_broadcast(&condvar);
1852 ret = pthread_mutex_unlock(&mtx);
1856 CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
1858 /* Dump the hierarchy. */
1859 talloc_report(mem_ctx, stdout);
1861 talloc_free(mem_ctx);
1862 printf("success: pthread_talloc_passing\n");
1867 static void test_magic_protection_abort(const char *reason)
1869 /* exit with errcode 42 to communicate successful test to the parent process */
1870 if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
1873 printf("talloc aborted for an unexpected reason\n");
1877 static int test_magic_protection_destructor(int *ptr)
1879 _exit(404); /* Not 42 */
1882 static bool test_magic_protection(void)
1884 void *pool = talloc_pool(NULL, 1024);
1889 printf("test: magic_protection\n");
1890 p1 = talloc(pool, int);
1891 p2 = talloc(pool, int);
1893 /* To avoid complaints from the compiler assign values to the p1 & p2. */
1899 talloc_set_abort_fn(test_magic_protection_abort);
1900 talloc_set_destructor(p2, test_magic_protection_destructor);
1903 * Simulate a security attack
1904 * by triggering a buffer overflow in memset to overwrite the
1905 * constructor in the next pool chunk.
1907 * Real attacks would attempt to set a real destructor.
1909 memset(p1, '\0', 32);
1911 /* Then the attack takes effect when the memory's freed. */
1914 /* Never reached. Make compilers happy */
1918 while (wait(&exit_status) != pid);
1920 if (!WIFEXITED(exit_status)) {
1921 printf("Child exited through unexpected abnormal means\n");
1924 if (WEXITSTATUS(exit_status) != 42) {
1925 printf("Child exited with wrong exit status\n");
1928 if (WIFSIGNALED(exit_status)) {
1929 printf("Child recieved unexpected signal\n");
1933 printf("success: magic_protection\n");
1937 static void test_reset(void)
1939 talloc_set_log_fn(test_log_stdout);
1941 talloc_disable_null_tracking();
1942 talloc_enable_null_tracking_no_autofree();
1945 bool torture_local_talloc(struct torture_context *tctx)
1952 ret &= test_pooled_object();
1954 ret &= test_pool_nest();
1964 ret &= test_unlink1();
1968 ret &= test_realloc();
1970 ret &= test_realloc_child();
1972 ret &= test_steal();
1976 ret &= test_unref_reparent();
1978 ret &= test_realloc_fn();
1982 ret &= test_lifeless();
1986 ret &= test_free_parent_deny_child();
1988 ret &= test_free_parent_reparent_child();
1990 ret &= test_free_parent_reparent_child_in_pool();
1992 ret &= test_talloc_ptrtype();
1994 ret &= test_talloc_free_in_destructor();
1998 ret &= test_pool_steal();
2000 ret &= test_free_ref_null_context();
2002 ret &= test_rusty();
2004 ret &= test_free_children();
2006 ret &= test_memlimit();
2009 ret &= test_pthread_talloc_passing();
2015 ret &= test_speed();
2018 ret &= test_autofree();
2020 ret &= test_magic_protection();
2023 talloc_disable_null_tracking();