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"
30 static struct timeval timeval_current(void)
33 gettimeofday(&tv, NULL);
37 static double timeval_elapsed(struct timeval *tv)
39 struct timeval tv2 = timeval_current();
40 return (tv2.tv_sec - tv->tv_sec) +
41 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
44 #define torture_assert(test, expr, str) if (!(expr)) { \
45 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
46 test, __location__, #expr, str); \
50 #define torture_assert_str_equal(test, arg1, arg2, desc) \
51 if (arg1 == NULL && arg2 == NULL) { \
52 } else if (strcmp(arg1, arg2)) { \
53 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
54 test, __location__, arg1, arg2, desc); \
67 #define CHECK_SIZE(test, ptr, tsize) do { \
68 if (talloc_total_size(ptr) != (tsize)) { \
69 printf("failed: %s [\nwrong '%s' tree size: got %u expected %u\n]\n", \
71 (unsigned)talloc_total_size(ptr), \
73 talloc_report_full(ptr, stdout); \
78 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
79 if (talloc_total_blocks(ptr) != (tblocks)) { \
80 printf("failed: %s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \
82 (unsigned)talloc_total_blocks(ptr), \
84 talloc_report_full(ptr, stdout); \
89 #define CHECK_PARENT(test, ptr, parent) do { \
90 if (talloc_parent(ptr) != (parent)) { \
91 printf("failed: %s [\n'%s' has wrong parent: got %p expected %p\n]\n", \
95 talloc_report_full(ptr, stdout); \
96 talloc_report_full(parent, stdout); \
97 talloc_report_full(NULL, stdout); \
106 static bool test_ref1(void)
108 void *root, *p1, *p2, *ref, *r1;
110 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
112 root = talloc_named_const(NULL, 0, "root");
113 p1 = talloc_named_const(root, 1, "p1");
114 p2 = talloc_named_const(p1, 1, "p2");
115 talloc_named_const(p1, 1, "x1");
116 talloc_named_const(p1, 2, "x2");
117 talloc_named_const(p1, 3, "x3");
119 r1 = talloc_named_const(root, 1, "r1");
120 ref = talloc_reference(r1, p2);
121 talloc_report_full(root, stderr);
123 CHECK_BLOCKS("ref1", p1, 5);
124 CHECK_BLOCKS("ref1", p2, 1);
125 CHECK_BLOCKS("ref1", r1, 2);
127 fprintf(stderr, "Freeing p2\n");
129 talloc_report_full(root, stderr);
131 CHECK_BLOCKS("ref1", p1, 5);
132 CHECK_BLOCKS("ref1", p2, 1);
133 CHECK_BLOCKS("ref1", r1, 1);
135 fprintf(stderr, "Freeing p1\n");
137 talloc_report_full(root, stderr);
139 CHECK_BLOCKS("ref1", r1, 1);
141 fprintf(stderr, "Freeing r1\n");
143 talloc_report_full(NULL, stderr);
145 fprintf(stderr, "Testing NULL\n");
146 if (talloc_reference(root, NULL)) {
150 CHECK_BLOCKS("ref1", root, 1);
152 CHECK_SIZE("ref1", root, 0);
155 printf("success: ref1\n");
162 static bool test_ref2(void)
164 void *root, *p1, *p2, *ref, *r1;
166 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
167 root = talloc_named_const(NULL, 0, "root");
168 p1 = talloc_named_const(root, 1, "p1");
169 talloc_named_const(p1, 1, "x1");
170 talloc_named_const(p1, 1, "x2");
171 talloc_named_const(p1, 1, "x3");
172 p2 = talloc_named_const(p1, 1, "p2");
174 r1 = talloc_named_const(root, 1, "r1");
175 ref = talloc_reference(r1, p2);
176 talloc_report_full(root, stderr);
178 CHECK_BLOCKS("ref2", p1, 5);
179 CHECK_BLOCKS("ref2", p2, 1);
180 CHECK_BLOCKS("ref2", r1, 2);
182 fprintf(stderr, "Freeing ref\n");
184 talloc_report_full(root, stderr);
186 CHECK_BLOCKS("ref2", p1, 5);
187 CHECK_BLOCKS("ref2", p2, 1);
188 CHECK_BLOCKS("ref2", r1, 1);
190 fprintf(stderr, "Freeing p2\n");
192 talloc_report_full(root, stderr);
194 CHECK_BLOCKS("ref2", p1, 4);
195 CHECK_BLOCKS("ref2", r1, 1);
197 fprintf(stderr, "Freeing p1\n");
199 talloc_report_full(root, stderr);
201 CHECK_BLOCKS("ref2", r1, 1);
203 fprintf(stderr, "Freeing r1\n");
205 talloc_report_full(root, stderr);
207 CHECK_SIZE("ref2", root, 0);
210 printf("success: ref2\n");
217 static bool test_ref3(void)
219 void *root, *p1, *p2, *ref, *r1;
221 printf("test: ref3\n# PARENT REFERENCE FREE\n");
223 root = talloc_named_const(NULL, 0, "root");
224 p1 = talloc_named_const(root, 1, "p1");
225 p2 = talloc_named_const(root, 1, "p2");
226 r1 = talloc_named_const(p1, 1, "r1");
227 ref = talloc_reference(p2, r1);
228 talloc_report_full(root, stderr);
230 CHECK_BLOCKS("ref3", p1, 2);
231 CHECK_BLOCKS("ref3", p2, 2);
232 CHECK_BLOCKS("ref3", r1, 1);
234 fprintf(stderr, "Freeing p1\n");
236 talloc_report_full(root, stderr);
238 CHECK_BLOCKS("ref3", p2, 2);
239 CHECK_BLOCKS("ref3", r1, 1);
241 fprintf(stderr, "Freeing p2\n");
243 talloc_report_full(root, stderr);
245 CHECK_SIZE("ref3", root, 0);
249 printf("success: ref3\n");
256 static bool test_ref4(void)
258 void *root, *p1, *p2, *ref, *r1;
260 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
262 root = talloc_named_const(NULL, 0, "root");
263 p1 = talloc_named_const(root, 1, "p1");
264 talloc_named_const(p1, 1, "x1");
265 talloc_named_const(p1, 1, "x2");
266 talloc_named_const(p1, 1, "x3");
267 p2 = talloc_named_const(p1, 1, "p2");
269 r1 = talloc_named_const(root, 1, "r1");
270 ref = talloc_reference(r1, p2);
271 talloc_report_full(root, stderr);
273 CHECK_BLOCKS("ref4", p1, 5);
274 CHECK_BLOCKS("ref4", p2, 1);
275 CHECK_BLOCKS("ref4", r1, 2);
277 fprintf(stderr, "Freeing r1\n");
279 talloc_report_full(root, stderr);
281 CHECK_BLOCKS("ref4", p1, 5);
282 CHECK_BLOCKS("ref4", p2, 1);
284 fprintf(stderr, "Freeing p2\n");
286 talloc_report_full(root, stderr);
288 CHECK_BLOCKS("ref4", p1, 4);
290 fprintf(stderr, "Freeing p1\n");
292 talloc_report_full(root, stderr);
294 CHECK_SIZE("ref4", root, 0);
298 printf("success: ref4\n");
306 static bool test_unlink1(void)
308 void *root, *p1, *p2, *ref, *r1;
310 printf("test: unlink\n# UNLINK\n");
312 root = talloc_named_const(NULL, 0, "root");
313 p1 = talloc_named_const(root, 1, "p1");
314 talloc_named_const(p1, 1, "x1");
315 talloc_named_const(p1, 1, "x2");
316 talloc_named_const(p1, 1, "x3");
317 p2 = talloc_named_const(p1, 1, "p2");
319 r1 = talloc_named_const(p1, 1, "r1");
320 ref = talloc_reference(r1, p2);
321 talloc_report_full(root, stderr);
323 CHECK_BLOCKS("unlink", p1, 7);
324 CHECK_BLOCKS("unlink", p2, 1);
325 CHECK_BLOCKS("unlink", r1, 2);
327 fprintf(stderr, "Unreferencing r1\n");
328 talloc_unlink(r1, p2);
329 talloc_report_full(root, stderr);
331 CHECK_BLOCKS("unlink", p1, 6);
332 CHECK_BLOCKS("unlink", p2, 1);
333 CHECK_BLOCKS("unlink", r1, 1);
335 fprintf(stderr, "Freeing p1\n");
337 talloc_report_full(root, stderr);
339 CHECK_SIZE("unlink", root, 0);
343 printf("success: unlink\n");
347 static int fail_destructor(void *ptr)
353 miscellaneous tests to try to get a higher test coverage percentage
355 static bool test_misc(void)
362 printf("test: misc\n# MISCELLANEOUS\n");
364 root = talloc_new(NULL);
366 p1 = talloc_size(root, 0x7fffffff);
367 torture_assert("misc", !p1, "failed: large talloc allowed\n");
369 p1 = talloc_strdup(root, "foo");
370 talloc_increase_ref_count(p1);
371 talloc_increase_ref_count(p1);
372 talloc_increase_ref_count(p1);
373 CHECK_BLOCKS("misc", p1, 1);
374 CHECK_BLOCKS("misc", root, 2);
376 CHECK_BLOCKS("misc", p1, 1);
377 CHECK_BLOCKS("misc", root, 2);
378 talloc_unlink(NULL, p1);
379 CHECK_BLOCKS("misc", p1, 1);
380 CHECK_BLOCKS("misc", root, 2);
381 p2 = talloc_strdup(p1, "foo");
382 torture_assert("misc", talloc_unlink(root, p2) == -1,
383 "failed: talloc_unlink() of non-reference context should return -1\n");
384 torture_assert("misc", talloc_unlink(p1, p2) == 0,
385 "failed: talloc_unlink() of parent should succeed\n");
387 CHECK_BLOCKS("misc", p1, 1);
388 CHECK_BLOCKS("misc", root, 2);
390 name = talloc_set_name(p1, "my name is %s", "foo");
391 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
392 "failed: wrong name after talloc_set_name(my name is foo)");
393 CHECK_BLOCKS("misc", p1, 2);
394 CHECK_BLOCKS("misc", root, 3);
396 talloc_set_name_const(p1, NULL);
397 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
398 "failed: wrong name after talloc_set_name(NULL)");
399 CHECK_BLOCKS("misc", p1, 2);
400 CHECK_BLOCKS("misc", root, 3);
402 torture_assert("misc", talloc_free(NULL) == -1,
403 "talloc_free(NULL) should give -1\n");
405 talloc_set_destructor(p1, fail_destructor);
406 torture_assert("misc", talloc_free(p1) == -1,
407 "Failed destructor should cause talloc_free to fail\n");
408 talloc_set_destructor(p1, NULL);
410 talloc_report(root, stderr);
413 p2 = (char *)talloc_zero_size(p1, 20);
414 torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
417 torture_assert("misc", talloc_strdup(root, NULL) == NULL,
418 "failed: strdup on NULL should give NULL\n");
420 p2 = talloc_strndup(p1, "foo", 2);
421 torture_assert("misc", strcmp("fo", p2) == 0,
422 "strndup doesn't work\n");
423 p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
424 torture_assert("misc", strcmp("food", p2) == 0,
425 "talloc_asprintf_append_buffer doesn't work\n");
426 CHECK_BLOCKS("misc", p2, 1);
427 CHECK_BLOCKS("misc", p1, 3);
429 p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
430 torture_assert("misc", strcmp("hello world", p2) == 0,
431 "talloc_asprintf_append_buffer doesn't work\n");
432 CHECK_BLOCKS("misc", p2, 1);
433 CHECK_BLOCKS("misc", p1, 3);
436 d = talloc_array(p1, double, 0x20000000);
437 torture_assert("misc", !d, "failed: integer overflow not detected\n");
439 d = talloc_realloc(p1, d, double, 0x20000000);
440 torture_assert("misc", !d, "failed: integer overflow not detected\n");
443 CHECK_BLOCKS("misc", root, 1);
445 p1 = talloc_named(root, 100, "%d bytes", 100);
446 CHECK_BLOCKS("misc", p1, 2);
447 CHECK_BLOCKS("misc", root, 3);
448 talloc_unlink(root, p1);
450 p1 = talloc_init("%d bytes", 200);
451 p2 = talloc_asprintf(p1, "my test '%s'", "string");
452 torture_assert_str_equal("misc", p2, "my test 'string'",
453 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
454 CHECK_BLOCKS("misc", p1, 3);
455 CHECK_SIZE("misc", p2, 17);
456 CHECK_BLOCKS("misc", root, 1);
457 talloc_unlink(NULL, p1);
459 p1 = talloc_named_const(root, 10, "p1");
460 p2 = (char *)talloc_named_const(root, 20, "p2");
461 (void)talloc_reference(p1, p2);
462 talloc_report_full(root, stderr);
463 talloc_unlink(root, p2);
464 talloc_report_full(root, stderr);
465 CHECK_BLOCKS("misc", p2, 1);
466 CHECK_BLOCKS("misc", p1, 2);
467 CHECK_BLOCKS("misc", root, 3);
468 talloc_unlink(p1, p2);
469 talloc_unlink(root, p1);
471 p1 = talloc_named_const(root, 10, "p1");
472 p2 = (char *)talloc_named_const(root, 20, "p2");
473 (void)talloc_reference(NULL, p2);
474 talloc_report_full(root, stderr);
475 talloc_unlink(root, p2);
476 talloc_report_full(root, stderr);
477 CHECK_BLOCKS("misc", p2, 1);
478 CHECK_BLOCKS("misc", p1, 1);
479 CHECK_BLOCKS("misc", root, 2);
480 talloc_unlink(NULL, p2);
481 talloc_unlink(root, p1);
483 /* Test that talloc_unlink is a no-op */
485 torture_assert("misc", talloc_unlink(root, NULL) == -1,
486 "failed: talloc_unlink(root, NULL) == -1\n");
488 talloc_report(root, stderr);
489 talloc_report(NULL, stderr);
491 CHECK_SIZE("misc", root, 0);
495 CHECK_SIZE("misc", NULL, 0);
497 talloc_enable_leak_report();
498 talloc_enable_leak_report_full();
500 printf("success: misc\n");
509 static bool test_realloc(void)
511 void *root, *p1, *p2;
513 printf("test: realloc\n# REALLOC\n");
515 root = talloc_new(NULL);
517 p1 = talloc_size(root, 10);
518 CHECK_SIZE("realloc", p1, 10);
520 p1 = talloc_realloc_size(NULL, p1, 20);
521 CHECK_SIZE("realloc", p1, 20);
525 p2 = talloc_realloc_size(p1, NULL, 30);
529 p2 = talloc_realloc_size(p1, p2, 40);
531 CHECK_SIZE("realloc", p2, 40);
532 CHECK_SIZE("realloc", root, 60);
533 CHECK_BLOCKS("realloc", p1, 4);
535 p1 = talloc_realloc_size(NULL, p1, 20);
536 CHECK_SIZE("realloc", p1, 60);
538 talloc_increase_ref_count(p2);
539 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
540 "failed: talloc_realloc() on a referenced pointer should fail\n");
541 CHECK_BLOCKS("realloc", p1, 4);
543 talloc_realloc_size(NULL, p2, 0);
544 talloc_realloc_size(NULL, p2, 0);
545 CHECK_BLOCKS("realloc", p1, 3);
547 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
548 "failed: oversize talloc should fail\n");
550 talloc_realloc_size(NULL, p1, 0);
552 CHECK_BLOCKS("realloc", root, 1);
553 CHECK_SIZE("realloc", root, 0);
557 printf("success: realloc\n");
563 test realloc with a child
565 static bool test_realloc_child(void)
573 struct el2 **list, **list2, **list3;
576 printf("test: REALLOC WITH CHILD\n");
578 root = talloc_new(NULL);
580 el1 = talloc(root, struct el1);
581 el1->list = talloc(el1, struct el2 *);
582 el1->list[0] = talloc(el1->list, struct el2);
583 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
585 el1->list2 = talloc(el1, struct el2 *);
586 el1->list2[0] = talloc(el1->list2, struct el2);
587 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
589 el1->list3 = talloc(el1, struct el2 *);
590 el1->list3[0] = talloc(el1->list3, struct el2);
591 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
593 el2 = talloc(el1->list, struct el2);
594 el2 = talloc(el1->list2, struct el2);
595 el2 = talloc(el1->list3, struct el2);
597 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
598 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
599 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
603 printf("success: REALLOC WITH CHILD\n");
610 static bool test_type(void)
621 printf("test: type\n# talloc type checking\n");
623 root = talloc_new(NULL);
625 el1 = talloc(root, struct el1);
629 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
630 "type check failed on el1\n");
631 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
632 "type check failed on el1 with el2\n");
633 talloc_set_type(el1, struct el2);
634 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
635 "type set failed on el1 with el2\n");
639 printf("success: type\n");
646 static bool test_steal(void)
648 void *root, *p1, *p2;
650 printf("test: steal\n# STEAL\n");
652 root = talloc_new(NULL);
654 p1 = talloc_array(root, char, 10);
655 CHECK_SIZE("steal", p1, 10);
657 p2 = talloc_realloc(root, NULL, char, 20);
658 CHECK_SIZE("steal", p1, 10);
659 CHECK_SIZE("steal", root, 30);
661 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
662 "failed: stealing NULL should give NULL\n");
664 torture_assert("steal", talloc_steal(p1, p1) == p1,
665 "failed: stealing to ourselves is a nop\n");
666 CHECK_BLOCKS("steal", root, 3);
667 CHECK_SIZE("steal", root, 30);
669 talloc_steal(NULL, p1);
670 talloc_steal(NULL, p2);
671 CHECK_BLOCKS("steal", root, 1);
672 CHECK_SIZE("steal", root, 0);
675 talloc_steal(root, p2);
676 CHECK_BLOCKS("steal", root, 2);
677 CHECK_SIZE("steal", root, 20);
681 CHECK_BLOCKS("steal", root, 1);
682 CHECK_SIZE("steal", root, 0);
686 p1 = talloc_size(NULL, 3);
687 talloc_report_full(NULL, stderr);
688 CHECK_SIZE("steal", NULL, 3);
691 printf("success: steal\n");
698 static bool test_move(void)
706 printf("test: move\n# MOVE\n");
708 root = talloc_new(NULL);
710 t1 = talloc(root, struct t_move);
711 t2 = talloc(root, struct t_move);
712 t1->p = talloc_strdup(t1, "foo");
713 t1->x = talloc(t1, int);
716 t2->p = talloc_move(t2, &t1->p);
717 t2->x = talloc_move(t2, &t1->x);
718 torture_assert("move", t1->p == NULL && t1->x == NULL &&
719 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
720 "talloc move failed");
724 printf("success: move\n");
730 test talloc_realloc_fn
732 static bool test_realloc_fn(void)
736 printf("test: realloc_fn\n# talloc_realloc_fn\n");
738 root = talloc_new(NULL);
740 p1 = talloc_realloc_fn(root, NULL, 10);
741 CHECK_BLOCKS("realloc_fn", root, 2);
742 CHECK_SIZE("realloc_fn", root, 10);
743 p1 = talloc_realloc_fn(root, p1, 20);
744 CHECK_BLOCKS("realloc_fn", root, 2);
745 CHECK_SIZE("realloc_fn", root, 20);
746 p1 = talloc_realloc_fn(root, p1, 0);
747 CHECK_BLOCKS("realloc_fn", root, 1);
748 CHECK_SIZE("realloc_fn", root, 0);
752 printf("success: realloc_fn\n");
757 static bool test_unref_reparent(void)
759 void *root, *p1, *p2, *c1;
761 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
763 root = talloc_named_const(NULL, 0, "root");
764 p1 = talloc_named_const(root, 1, "orig parent");
765 p2 = talloc_named_const(root, 1, "parent by reference");
767 c1 = talloc_named_const(p1, 1, "child");
768 talloc_reference(p2, c1);
770 CHECK_PARENT("unref_reparent", c1, p1);
774 CHECK_PARENT("unref_reparent", c1, p2);
776 talloc_unlink(p2, c1);
778 CHECK_SIZE("unref_reparent", root, 1);
783 printf("success: unref_reparent\n");
787 /* If a referenced allocation is explicitly freed the new owner
788 should be the same as if the same allocation is implicitly freed
789 (because it's owner was freed).
790 Traditionally in talloc an explicit free will free the top non-child reference
791 but an implicit free will move the top (any) reference to be the new owner */
792 static bool test_implicit_explicit_free(void)
794 void *root, *p1, *p2, *p3, *ref, *r1;
797 printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE IMPLICIT FREE\n");
799 root = talloc_named_const(NULL, 0, "root");
800 p1 = talloc_named_const(root, 1, "p1");
801 p2 = talloc_named_const(p1, 1, "p2");
802 /* Now root owns p1, and p1 owns p2 */
804 r1 = talloc_named_const(root, 1, "r1");
805 ref = talloc_reference(r1, p2);
806 /* now r1 has ref reference to p2 */
807 talloc_report_full(root, stderr);
809 CHECK_BLOCKS(__FUNCTION__, p1, 2);
810 CHECK_BLOCKS(__FUNCTION__, p2, 1);
811 CHECK_BLOCKS(__FUNCTION__, r1, 2);
813 fprintf(stderr, "Freeing p2\n");
815 /* how many blocks is r1 taking against p2 ? */
816 e=talloc_total_blocks(r1);
818 talloc_report_full(root, stderr);
821 /* now repeat, but this time free p1 */
822 printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE EXPLICIT FREE\n");
824 root = talloc_named_const(NULL, 0, "root");
825 p1 = talloc_named_const(root, 1, "p1");
826 p2 = talloc_named_const(p1, 1, "p2");
827 /* Now root owns p1, and p1 owns p2 */
829 r1 = talloc_named_const(root, 1, "r1");
830 ref = talloc_reference(r1, p2);
831 /* now r1 has ref reference to p2 */
832 talloc_report_full(NULL, stderr);
834 CHECK_BLOCKS(__FUNCTION__, p1, 2);
835 CHECK_BLOCKS(__FUNCTION__, p2, 1);
836 CHECK_BLOCKS(__FUNCTION__, r1, 2);
838 fprintf(stderr, "Freeing p1\n");
840 /* how many blocks is r1 taking against p2 ? */
841 i=talloc_total_blocks(r1);
842 talloc_report_full(NULL, stderr);
844 CHECK_BLOCKS(__FUNCTION__,r1, e);
848 printf("success: ref1\n");
853 measure the speed of talloc versus malloc
855 static bool test_speed(void)
857 void *ctx = talloc_new(NULL);
859 const int loop = 1000;
863 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
865 tv = 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);
876 } while (timeval_elapsed(&tv) < 5.0);
878 fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
882 ctx = talloc_pool(NULL, 1024);
884 tv = timeval_current();
888 for (i=0;i<loop;i++) {
889 p1 = talloc_size(ctx, loop % 100);
890 p2 = talloc_strdup(p1, "foo bar");
891 p3 = talloc_size(p1, 300);
892 talloc_free_children(ctx);
895 } while (timeval_elapsed(&tv) < 5.0);
899 fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
901 tv = timeval_current();
905 for (i=0;i<loop;i++) {
906 p1 = malloc(loop % 100);
907 p2 = strdup("foo bar");
914 } while (timeval_elapsed(&tv) < 5.0);
915 fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
917 printf("success: speed\n");
922 static bool test_lifeless(void)
924 void *top = talloc_new(NULL);
925 char *parent, *child;
926 void *child_owner = talloc_new(NULL);
928 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
930 parent = talloc_strdup(top, "parent");
931 child = talloc_strdup(parent, "child");
932 (void)talloc_reference(child, parent);
933 (void)talloc_reference(child_owner, child);
934 talloc_report_full(top, stderr);
935 talloc_unlink(top, parent);
937 talloc_report_full(top, stderr);
939 talloc_free(child_owner);
942 printf("success: lifeless\n");
946 static int loop_destructor_count;
948 static int test_loop_destructor(char *ptr)
950 loop_destructor_count++;
954 static bool test_loop(void)
956 void *top = talloc_new(NULL);
962 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
964 parent = talloc_strdup(top, "parent");
965 req1 = talloc(parent, struct req1);
966 req1->req2 = talloc_strdup(req1, "req2");
967 talloc_set_destructor(req1->req2, test_loop_destructor);
968 req1->req3 = talloc_strdup(req1, "req3");
969 (void)talloc_reference(req1->req3, req1);
970 talloc_report_full(top, stderr);
972 talloc_report_full(top, stderr);
973 talloc_report_full(NULL, stderr);
976 torture_assert("loop", loop_destructor_count == 1,
977 "FAILED TO FIRE LOOP DESTRUCTOR\n");
978 loop_destructor_count = 0;
980 printf("success: loop\n");
984 static int fail_destructor_str(char *ptr)
989 static bool test_free_parent_deny_child(void)
991 void *top = talloc_new(NULL);
996 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
998 level1 = talloc_strdup(top, "level1");
999 level2 = talloc_strdup(level1, "level2");
1000 level3 = talloc_strdup(level2, "level3");
1002 talloc_set_destructor(level3, fail_destructor_str);
1003 talloc_free(level1);
1004 talloc_set_destructor(level3, NULL);
1006 CHECK_PARENT("free_parent_deny_child", level3, top);
1010 printf("success: free_parent_deny_child\n");
1014 static bool test_talloc_ptrtype(void)
1016 void *top = talloc_new(NULL);
1020 } *s1, *s2, **s3, ***s4;
1021 const char *location1;
1022 const char *location2;
1023 const char *location3;
1024 const char *location4;
1026 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1028 s1 = talloc_ptrtype(top, s1);location1 = __location__;
1030 if (talloc_get_size(s1) != sizeof(struct struct1)) {
1031 printf("failure: ptrtype [\n"
1032 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1033 "]\n", (unsigned long)talloc_get_size(s1),
1034 (unsigned long)sizeof(struct struct1));
1038 if (strcmp(location1, talloc_get_name(s1)) != 0) {
1039 printf("failure: ptrtype [\n"
1040 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1041 talloc_get_name(s1), location1);
1045 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1047 if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1048 printf("failure: ptrtype [\n"
1049 "talloc_array_ptrtype() allocated the wrong size "
1050 "%lu (should be %lu)\n]\n",
1051 (unsigned long)talloc_get_size(s2),
1052 (unsigned long)(sizeof(struct struct1)*10));
1056 if (strcmp(location2, talloc_get_name(s2)) != 0) {
1057 printf("failure: ptrtype [\n"
1058 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1059 talloc_get_name(s2), location2);
1063 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1065 if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1066 printf("failure: ptrtype [\n"
1067 "talloc_array_ptrtype() allocated the wrong size "
1068 "%lu (should be %lu)\n]\n",
1069 (unsigned long)talloc_get_size(s3),
1070 (unsigned long)(sizeof(struct struct1 *)*10));
1074 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1075 "talloc_array_ptrtype() sets the wrong name");
1077 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1079 if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1080 printf("failure: ptrtype [\n"
1081 "talloc_array_ptrtype() allocated the wrong size "
1082 "%lu (should be %lu)\n]\n",
1083 (unsigned long)talloc_get_size(s4),
1084 (unsigned long)(sizeof(struct struct1 **)*10));
1088 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1089 "talloc_array_ptrtype() sets the wrong name");
1093 printf("success: ptrtype\n");
1097 static int _test_talloc_free_in_destructor(void **ptr)
1103 static bool test_talloc_free_in_destructor(void)
1112 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1114 level0 = talloc_new(NULL);
1115 level1 = talloc_new(level0);
1116 level2 = talloc_new(level1);
1117 level3 = talloc_new(level2);
1118 level4 = talloc_new(level3);
1119 level5 = talloc(level4, void *);
1122 (void)talloc_reference(level0, level3);
1123 (void)talloc_reference(level3, level3);
1124 (void)talloc_reference(level5, level3);
1126 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1128 talloc_free(level1);
1130 talloc_free(level0);
1132 printf("success: free_in_destructor\n");
1136 static bool test_autofree(void)
1138 #if _SAMBA_BUILD_ < 4
1139 /* autofree test would kill smbtorture */
1141 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1143 p = talloc_autofree_context();
1146 p = talloc_autofree_context();
1149 printf("success: autofree\n");
1154 static bool test_pool(void)
1157 void *p1, *p2, *p3, *p4;
1159 pool = talloc_pool(NULL, 1024);
1161 p1 = talloc_size(pool, 80);
1162 p2 = talloc_size(pool, 20);
1163 p3 = talloc_size(p1, 50);
1164 p4 = talloc_size(p3, 1000);
1171 struct torture_context;
1172 bool torture_local_talloc(struct torture_context *tctx)
1178 talloc_disable_null_tracking();
1179 talloc_enable_null_tracking();
1185 ret &= test_unlink1();
1187 ret &= test_realloc();
1188 ret &= test_realloc_child();
1189 ret &= test_steal();
1191 ret &= test_unref_reparent();
1192 ret &= test_realloc_fn();
1194 ret &= test_lifeless();
1196 ret &= test_free_parent_deny_child();
1197 ret &= test_talloc_ptrtype();
1198 ret &= test_talloc_free_in_destructor();
1200 ret &= test_implicit_explicit_free();
1203 ret &= test_speed();
1205 ret &= test_autofree();