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 [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
70 test, __location__, #ptr, \
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 [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
81 test, __location__, #ptr, \
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: '%s' has wrong parent: got %p expected %p\n]\n", \
92 test, __location__, #ptr, \
95 talloc_report_full(ptr, stdout); \
96 talloc_report_full(parent, stdout); \
97 talloc_report_full(NULL, stdout); \
102 #define CHECK_NOT_PARENT(test, ptr, parent) do { \
103 if (talloc_parent(ptr) == (parent)) { \
104 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected a difference\n]\n", \
105 test, __location__, #ptr, \
107 talloc_report_full(ptr, stdout); \
108 talloc_report_full(parent, stdout); \
109 talloc_report_full(NULL, stdout); \
114 static unsigned int test_abort_count;
116 static void test_abort_fn(const char *reason)
118 printf("# test_abort_fn(%s)\n", reason);
122 static void test_abort_start(void)
124 test_abort_count = 0;
125 talloc_set_abort_fn(test_abort_fn);
128 static void test_abort_stop(void)
130 test_abort_count = 0;
131 talloc_set_abort_fn(NULL);
137 static bool test_ref1(void)
139 void *root, *p1, *p2, *ref, *r1;
141 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
143 root = talloc_named_const(NULL, 0, "root");
144 p1 = talloc_named_const(root, 1, "p1");
145 p2 = talloc_named_const(p1, 1, "p2");
146 talloc_named_const(p1, 1, "x1");
147 talloc_named_const(p1, 2, "x2");
148 talloc_named_const(p1, 3, "x3");
150 r1 = talloc_named_const(root, 1, "r1");
151 ref = talloc_reference(r1, p2);
152 talloc_report_full(root, stderr);
154 CHECK_BLOCKS("ref1", p1, 5);
155 CHECK_BLOCKS("ref1", p2, 1);
156 CHECK_BLOCKS("ref1", r1, 2);
158 fprintf(stderr, "Freeing p2\n");
160 talloc_report_full(root, stderr);
162 CHECK_BLOCKS("ref1", p1, 4);
163 CHECK_BLOCKS("ref1", p2, 1);
164 CHECK_BLOCKS("ref1", r1, 2);
166 fprintf(stderr, "Freeing p1\n");
168 talloc_report_full(root, stderr);
170 CHECK_BLOCKS("ref1", r1, 2);
172 fprintf(stderr, "Freeing r1\n");
174 talloc_report_full(NULL, stderr);
176 fprintf(stderr, "Testing NULL\n");
177 if (talloc_reference(root, NULL)) {
181 CHECK_BLOCKS("ref1", root, 1);
183 CHECK_SIZE("ref1", root, 0);
186 printf("success: ref1\n");
193 static bool test_ref2(void)
195 void *root, *p1, *p2, *ref, *r1;
197 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
198 root = talloc_named_const(NULL, 0, "root");
199 p1 = talloc_named_const(root, 1, "p1");
200 talloc_named_const(p1, 1, "x1");
201 talloc_named_const(p1, 1, "x2");
202 talloc_named_const(p1, 1, "x3");
203 p2 = talloc_named_const(p1, 1, "p2");
205 r1 = talloc_named_const(root, 1, "r1");
206 ref = talloc_reference(r1, p2);
207 talloc_report_full(root, stderr);
209 CHECK_BLOCKS("ref2", p1, 5);
210 CHECK_BLOCKS("ref2", p2, 1);
211 CHECK_BLOCKS("ref2", r1, 2);
213 fprintf(stderr, "Freeing ref\n");
214 talloc_unlink(r1, ref);
215 talloc_report_full(root, stderr);
217 CHECK_BLOCKS("ref2", p1, 5);
218 CHECK_BLOCKS("ref2", p2, 1);
219 CHECK_BLOCKS("ref2", r1, 1);
221 fprintf(stderr, "Freeing p2\n");
223 talloc_report_full(root, stderr);
225 CHECK_BLOCKS("ref2", p1, 4);
226 CHECK_BLOCKS("ref2", r1, 1);
228 fprintf(stderr, "Freeing p1\n");
230 talloc_report_full(root, stderr);
232 CHECK_BLOCKS("ref2", r1, 1);
234 fprintf(stderr, "Freeing r1\n");
236 talloc_report_full(root, stderr);
238 CHECK_SIZE("ref2", root, 0);
241 printf("success: ref2\n");
248 static bool test_ref3(void)
250 void *root, *p1, *p2, *ref, *r1;
252 printf("test: ref3\n# PARENT REFERENCE FREE\n");
254 root = talloc_named_const(NULL, 0, "root");
255 p1 = talloc_named_const(root, 1, "p1");
256 p2 = talloc_named_const(root, 1, "p2");
257 r1 = talloc_named_const(p1, 1, "r1");
258 ref = talloc_reference(p2, r1);
259 talloc_report_full(root, stderr);
261 CHECK_BLOCKS("ref3", p1, 2);
262 CHECK_BLOCKS("ref3", p2, 2);
263 CHECK_BLOCKS("ref3", r1, 1);
265 fprintf(stderr, "Freeing p1\n");
267 talloc_report_full(root, stderr);
269 CHECK_BLOCKS("ref3", p2, 2);
270 CHECK_BLOCKS("ref3", r1, 1);
272 fprintf(stderr, "Freeing p2\n");
274 talloc_report_full(root, stderr);
276 CHECK_SIZE("ref3", root, 0);
280 printf("success: ref3\n");
287 static bool test_ref4(void)
289 void *root, *p1, *p2, *ref, *r1;
291 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
293 root = talloc_named_const(NULL, 0, "root");
294 p1 = talloc_named_const(root, 1, "p1");
295 talloc_named_const(p1, 1, "x1");
296 talloc_named_const(p1, 1, "x2");
297 talloc_named_const(p1, 1, "x3");
298 p2 = talloc_named_const(p1, 1, "p2");
300 r1 = talloc_named_const(root, 1, "r1");
301 ref = talloc_reference(r1, p2);
302 talloc_report_full(root, stderr);
304 CHECK_BLOCKS("ref4", p1, 5);
305 CHECK_BLOCKS("ref4", p2, 1);
306 CHECK_BLOCKS("ref4", r1, 2);
308 fprintf(stderr, "Freeing r1\n");
310 talloc_report_full(root, stderr);
312 CHECK_BLOCKS("ref4", p1, 5);
313 CHECK_BLOCKS("ref4", p2, 1);
315 fprintf(stderr, "Freeing p2\n");
317 talloc_report_full(root, stderr);
319 CHECK_BLOCKS("ref4", p1, 4);
321 fprintf(stderr, "Freeing p1\n");
323 talloc_report_full(root, stderr);
325 CHECK_SIZE("ref4", root, 0);
329 printf("success: ref4\n");
337 static bool test_unlink1(void)
339 void *root, *p1, *p2, *ref, *r1;
341 printf("test: unlink\n# UNLINK\n");
343 root = talloc_named_const(NULL, 0, "root");
344 p1 = talloc_named_const(root, 1, "p1");
345 talloc_named_const(p1, 1, "x1");
346 talloc_named_const(p1, 1, "x2");
347 talloc_named_const(p1, 1, "x3");
348 p2 = talloc_named_const(p1, 1, "p2");
350 r1 = talloc_named_const(p1, 1, "r1");
351 ref = talloc_reference(r1, p2);
352 talloc_report_full(root, stderr);
354 CHECK_BLOCKS("unlink", p1, 7);
355 CHECK_BLOCKS("unlink", p2, 1);
356 CHECK_BLOCKS("unlink", r1, 2);
358 fprintf(stderr, "Unreferencing r1\n");
359 talloc_unlink(r1, p2);
360 talloc_report_full(root, stderr);
362 CHECK_BLOCKS("unlink", p1, 6);
363 CHECK_BLOCKS("unlink", p2, 1);
364 CHECK_BLOCKS("unlink", r1, 1);
366 fprintf(stderr, "Freeing p1\n");
368 talloc_report_full(root, stderr);
370 CHECK_SIZE("unlink", root, 0);
374 printf("success: unlink\n");
378 static int fail_destructor(void *ptr)
384 miscellaneous tests to try to get a higher test coverage percentage
386 static bool test_misc(void)
393 printf("test: misc\n# MISCELLANEOUS\n");
395 root = talloc_new(NULL);
397 p1 = talloc_size(root, 0x7fffffff);
398 torture_assert("misc", !p1, "failed: large talloc allowed\n");
400 p1 = talloc_strdup(root, "foo");
401 talloc_increase_ref_count(p1);
402 talloc_increase_ref_count(p1);
403 talloc_increase_ref_count(p1);
404 CHECK_BLOCKS("misc", NULL, 7);
405 CHECK_BLOCKS("misc", p1, 1);
406 CHECK_BLOCKS("misc", root, 2);
407 talloc_unlink(NULL, p1);
408 CHECK_BLOCKS("misc", NULL, 6);
409 CHECK_BLOCKS("misc", p1, 1);
410 CHECK_BLOCKS("misc", root, 2);
411 p2 = talloc_strdup(p1, "foo");
412 torture_assert("misc", talloc_unlink(root, p2) == -1,
413 "failed: talloc_unlink() of non-reference context should return -1\n");
414 torture_assert("misc", talloc_unlink(p1, p2) == 0,
415 "failed: talloc_unlink() of parent should succeed\n");
417 CHECK_BLOCKS("misc", NULL, 6);
418 CHECK_BLOCKS("misc", p1, 1);
419 CHECK_BLOCKS("misc", root, 1);
420 talloc_unlink(NULL, p1);
421 CHECK_BLOCKS("misc", NULL, 5);
422 CHECK_BLOCKS("misc", p1, 1);
423 CHECK_BLOCKS("misc", root, 1);
425 name = talloc_set_name(p1, "my name is %s", "foo");
426 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
427 "failed: wrong name after talloc_set_name(my name is foo)");
428 CHECK_BLOCKS("misc", NULL, 6);
429 CHECK_BLOCKS("misc", p1, 2);
430 CHECK_BLOCKS("misc", root, 1);
432 talloc_set_name_const(p1, NULL);
433 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
434 "failed: wrong name after talloc_set_name(NULL)");
435 CHECK_BLOCKS("misc", NULL, 6);
436 CHECK_BLOCKS("misc", p1, 2);
437 CHECK_BLOCKS("misc", root, 1);
439 torture_assert("misc", talloc_free(NULL) == -1,
440 "talloc_free(NULL) should give -1\n");
442 talloc_set_destructor(p1, fail_destructor);
443 torture_assert("misc", talloc_unlink(NULL, p1) == -1,
444 "Failed destructor should cause talloc_unlink to fail\n");
445 talloc_set_destructor(p1, NULL);
446 CHECK_BLOCKS("misc", NULL, 6);
447 CHECK_BLOCKS("misc", p1, 2);
448 CHECK_BLOCKS("misc", root, 1);
450 talloc_report(root, stderr);
453 p2 = (char *)talloc_zero_size(p1, 20);
454 torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
457 torture_assert("misc", talloc_strdup(root, NULL) == NULL,
458 "failed: strdup on NULL should give NULL\n");
460 p2 = talloc_strndup(p1, "foo", 2);
461 torture_assert("misc", strcmp("fo", p2) == 0,
462 "strndup doesn't work\n");
463 p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
464 torture_assert("misc", strcmp("food", p2) == 0,
465 "talloc_asprintf_append_buffer doesn't work\n");
466 CHECK_BLOCKS("misc", p2, 1);
467 CHECK_BLOCKS("misc", p1, 3);
469 p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
470 torture_assert("misc", strcmp("hello world", p2) == 0,
471 "talloc_asprintf_append_buffer doesn't work\n");
472 CHECK_BLOCKS("misc", p2, 1);
473 CHECK_BLOCKS("misc", p1, 3);
476 d = talloc_array(p1, double, 0x20000000);
477 torture_assert("misc", !d, "failed: integer overflow not detected\n");
479 d = talloc_realloc(p1, d, double, 0x20000000);
480 torture_assert("misc", !d, "failed: integer overflow not detected\n");
482 CHECK_BLOCKS("misc", NULL, 7);
483 talloc_unlink(NULL, p1);
484 CHECK_BLOCKS("misc", NULL, 3);
485 CHECK_BLOCKS("misc", root, 1);
487 p1 = talloc_named(root, 100, "%d bytes", 100);
488 CHECK_BLOCKS("misc", NULL, 5);
489 CHECK_BLOCKS("misc", p1, 2);
490 CHECK_BLOCKS("misc", root, 3);
491 talloc_unlink(root, p1);
492 CHECK_BLOCKS("misc", NULL, 3);
493 CHECK_BLOCKS("misc", root, 1);
495 p1 = talloc_init("%d bytes", 200);
496 p2 = talloc_asprintf(p1, "my test '%s'", "string");
497 torture_assert_str_equal("misc", p2, "my test 'string'",
498 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
499 CHECK_BLOCKS("misc", p1, 3);
500 CHECK_SIZE("misc", p2, 17);
501 CHECK_BLOCKS("misc", root, 1);
502 talloc_unlink(NULL, p1);
504 p1 = talloc_named_const(root, 10, "p1");
505 p2 = (char *)talloc_named_const(root, 20, "p2");
506 (void)talloc_reference(p1, p2);
507 talloc_report_full(root, stderr);
508 talloc_unlink(root, p2);
509 talloc_report_full(root, stderr);
510 CHECK_BLOCKS("misc", p2, 1);
511 CHECK_BLOCKS("misc", p1, 2);
512 CHECK_BLOCKS("misc", root, 3);
513 talloc_unlink(p1, p2);
514 talloc_unlink(root, p1);
516 p1 = talloc_named_const(root, 10, "p1");
517 p2 = (char *)talloc_named_const(root, 20, "p2");
518 (void)talloc_reference(NULL, p2);
519 talloc_report_full(root, stderr);
520 talloc_unlink(root, p2);
521 talloc_report_full(root, stderr);
522 CHECK_BLOCKS("misc", p2, 1);
523 CHECK_BLOCKS("misc", p1, 1);
524 CHECK_BLOCKS("misc", root, 2);
525 talloc_unlink(NULL, p2);
526 talloc_unlink(root, p1);
528 /* Test that talloc_unlink is a no-op */
530 torture_assert("misc", talloc_unlink(root, NULL) == -1,
531 "failed: talloc_unlink(root, NULL) == -1\n");
533 talloc_report(root, stderr);
534 talloc_report(NULL, stderr);
536 CHECK_SIZE("misc", root, 0);
540 CHECK_SIZE("misc", NULL, 0);
542 talloc_enable_leak_report();
543 talloc_enable_leak_report_full();
545 printf("success: misc\n");
554 static bool test_realloc(void)
556 void *root, *p1, *p2;
558 printf("test: realloc\n# REALLOC\n");
560 root = talloc_new(NULL);
562 p1 = talloc_size(root, 10);
563 CHECK_SIZE("realloc", p1, 10);
565 p1 = talloc_realloc_size(NULL, p1, 20);
566 CHECK_SIZE("realloc", p1, 20);
570 p2 = talloc_realloc_size(p1, NULL, 30);
574 p2 = talloc_realloc_size(p1, p2, 40);
576 CHECK_SIZE("realloc", p2, 40);
577 CHECK_SIZE("realloc", root, 60);
578 CHECK_BLOCKS("realloc", p1, 4);
580 p1 = talloc_realloc_size(NULL, p1, 20);
581 CHECK_SIZE("realloc", p1, 60);
583 talloc_increase_ref_count(p2);
584 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
585 "failed: talloc_realloc() on a referenced pointer should fail\n");
586 CHECK_BLOCKS("realloc", p1, 4);
588 talloc_realloc_size(NULL, p2, 0);
589 talloc_realloc_size(NULL, p2, 0);
590 CHECK_BLOCKS("realloc", p1, 3);
592 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
593 "failed: oversize talloc should fail\n");
595 talloc_realloc_size(NULL, p1, 0);
597 CHECK_BLOCKS("realloc", root, 1);
598 CHECK_SIZE("realloc", root, 0);
602 printf("success: realloc\n");
608 test realloc with a child
610 static bool test_realloc_child(void)
618 struct el2 **list, **list2, **list3;
621 printf("test: REALLOC WITH CHILD\n");
623 root = talloc_new(NULL);
625 el1 = talloc(root, struct el1);
626 el1->list = talloc(el1, struct el2 *);
627 el1->list[0] = talloc(el1->list, struct el2);
628 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
630 el1->list2 = talloc(el1, struct el2 *);
631 el1->list2[0] = talloc(el1->list2, struct el2);
632 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
634 el1->list3 = talloc(el1, struct el2 *);
635 el1->list3[0] = talloc(el1->list3, struct el2);
636 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
638 el2 = talloc(el1->list, struct el2);
639 el2 = talloc(el1->list2, struct el2);
640 el2 = talloc(el1->list3, struct el2);
642 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
643 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
644 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
648 printf("success: REALLOC WITH CHILD\n");
655 static bool test_type(void)
666 printf("test: type\n# talloc type checking\n");
668 root = talloc_new(NULL);
670 el1 = talloc(root, struct el1);
674 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
675 "type check failed on el1\n");
676 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
677 "type check failed on el1 with el2\n");
678 talloc_set_type(el1, struct el2);
679 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
680 "type set failed on el1 with el2\n");
684 printf("success: type\n");
691 static bool test_steal(void)
693 void *root, *p1, *p2;
695 printf("test: steal\n# STEAL\n");
697 root = talloc_new(NULL);
699 p1 = talloc_array(root, char, 10);
700 CHECK_SIZE("steal", p1, 10);
702 p2 = talloc_realloc(root, NULL, char, 20);
703 CHECK_SIZE("steal", p1, 10);
704 CHECK_SIZE("steal", root, 30);
706 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
707 "failed: stealing NULL should give NULL\n");
709 torture_assert("steal", talloc_steal(p1, p1) == p1,
710 "failed: stealing to ourselves is a nop\n");
711 CHECK_BLOCKS("steal", root, 3);
712 CHECK_SIZE("steal", root, 30);
714 talloc_steal(NULL, p1);
715 talloc_steal(NULL, p2);
716 CHECK_BLOCKS("steal", root, 1);
717 CHECK_SIZE("steal", root, 0);
720 talloc_steal(root, p2);
721 CHECK_BLOCKS("steal", root, 2);
722 CHECK_SIZE("steal", root, 20);
726 CHECK_BLOCKS("steal", root, 1);
727 CHECK_SIZE("steal", root, 0);
731 p1 = talloc_size(NULL, 3);
732 talloc_report_full(NULL, stderr);
733 CHECK_SIZE("steal", NULL, 3);
736 printf("success: steal\n");
743 static bool test_move(void)
751 printf("test: move\n# MOVE\n");
753 root = talloc_new(NULL);
755 t1 = talloc(root, struct t_move);
756 t2 = talloc(root, struct t_move);
757 t1->p = talloc_strdup(t1, "foo");
758 t1->x = talloc(t1, int);
761 t2->p = talloc_move(t2, &t1->p);
762 t2->x = talloc_move(t2, &t1->x);
763 torture_assert("move", t1->p == NULL && t1->x == NULL &&
764 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
765 "talloc move failed");
769 printf("success: move\n");
775 test talloc_realloc_fn
777 static bool test_realloc_fn(void)
781 printf("test: realloc_fn\n# talloc_realloc_fn\n");
783 root = talloc_new(NULL);
785 p1 = talloc_realloc_fn(root, NULL, 10);
786 CHECK_BLOCKS("realloc_fn", root, 2);
787 CHECK_SIZE("realloc_fn", root, 10);
788 p1 = talloc_realloc_fn(root, p1, 20);
789 CHECK_BLOCKS("realloc_fn", root, 2);
790 CHECK_SIZE("realloc_fn", root, 20);
791 p1 = talloc_realloc_fn(root, p1, 0);
792 CHECK_BLOCKS("realloc_fn", root, 1);
793 CHECK_SIZE("realloc_fn", root, 0);
797 printf("success: realloc_fn\n");
802 static bool test_unref_reparent(void)
804 void *root, *p1, *p2, *c1;
806 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
808 root = talloc_named_const(NULL, 0, "root");
809 p1 = talloc_named_const(root, 1, "orig parent");
810 p2 = talloc_named_const(root, 1, "parent by reference");
812 c1 = talloc_named_const(p1, 1, "child");
813 CHECK_BLOCKS("unref_reparent", root, 4);
814 CHECK_SIZE("unref_reparent", root, 3);
815 talloc_reference(p2, c1);
816 CHECK_BLOCKS("unref_reparent", root, 5);
817 CHECK_SIZE("unref_reparent", root, 3);
819 CHECK_BLOCKS("unref_reparent", root, 5);
820 CHECK_SIZE("unref_reparent", root, 3);
821 CHECK_PARENT("unref_reparent", c1, p1);
825 CHECK_BLOCKS("unref_reparent", root, 3);
826 CHECK_SIZE("unref_reparent", root, 1);
827 CHECK_NOT_PARENT("unref_reparent", c1, p2);
829 talloc_unlink(p2, c1);
831 CHECK_BLOCKS("unref_reparent", root, 2);
832 CHECK_SIZE("unref_reparent", root, 1);
837 printf("success: unref_reparent\n");
841 /* If a referenced allocation is explicitly freed the new owner
842 should be the same as if the same allocation is implicitly freed
843 (because it's owner was freed).
844 Traditionally in talloc an explicit free will free the top non-child reference
845 but an implicit free will move the top (any) reference to be the new owner */
846 static bool test_implicit_explicit_free(void)
848 void *root, *p1, *p2, *p3, *ref, *r1;
851 printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE IMPLICIT FREE\n");
853 root = talloc_named_const(NULL, 0, "root");
854 p1 = talloc_named_const(root, 1, "p1");
855 p2 = talloc_named_const(p1, 1, "p2");
856 /* Now root owns p1, and p1 owns p2 */
858 r1 = talloc_named_const(root, 1, "r1");
859 ref = talloc_reference(r1, p2);
860 /* now r1 has ref reference to p2 */
861 talloc_report_full(root, stderr);
863 CHECK_BLOCKS(__FUNCTION__, p1, 2);
864 CHECK_BLOCKS(__FUNCTION__, p2, 1);
865 CHECK_BLOCKS(__FUNCTION__, r1, 2);
867 fprintf(stderr, "Freeing p2\n");
869 /* how many blocks is r1 taking against p2 ? */
870 e=talloc_total_blocks(r1);
872 talloc_report_full(root, stderr);
875 /* now repeat, but this time free p1 */
876 printf("# SINGLE REFERENCE EXPLICIT FREE\n");
878 root = talloc_named_const(NULL, 0, "root");
879 p1 = talloc_named_const(root, 1, "p1");
880 p2 = talloc_named_const(p1, 1, "p2");
881 /* Now root owns p1, and p1 owns p2 */
883 r1 = talloc_named_const(root, 1, "r1");
884 ref = talloc_reference(r1, p2);
885 /* now r1 has ref reference to p2 */
886 talloc_report_full(NULL, stderr);
888 CHECK_BLOCKS(__FUNCTION__, p1, 2);
889 CHECK_BLOCKS(__FUNCTION__, p2, 1);
890 CHECK_BLOCKS(__FUNCTION__, r1, 2);
892 fprintf(stderr, "Freeing p1\n");
894 /* how many blocks is r1 taking against p2 ? */
895 i=talloc_total_blocks(r1);
896 talloc_report_full(NULL, stderr);
898 CHECK_BLOCKS(__FUNCTION__,r1, e);
902 printf("success: ref1\n");
906 /* If take r1 reference to p2 and then free p2's owner p1
907 p2 should still be around by virtue of the reference.
908 steal p2 to p3 and free p3.
909 In current talloc p2 will be freed despite the reference.
910 In proposed talloc r1 will be the reference with no parent for p2*/
911 static bool test_ref_free_steal(void)
913 void *root, *p1, *p2, *p3, *ref, *r1;
915 printf("test: ref_free_self\n# SINGLE REFERENCE FREE SELF FREE\n");
916 talloc_erase_no_owner_context();
918 root = talloc_named_const(NULL, 0, "root");
919 p1 = talloc_named_const(root, 1, "p1");
920 p2 = talloc_named_const(p1, 1, "p2");
921 p3 = talloc_named_const(root, 1, "p3");
922 /* Now root owns p1, and p1 owns p2 */
924 r1 = talloc_named_const(root, 1, "r1");
925 ref = talloc_reference(r1, p2);
926 /* now r1 has ref reference to p2 */
927 talloc_report_full(NULL, stderr);
929 CHECK_BLOCKS(__FUNCTION__, p1, 2);
930 CHECK_BLOCKS(__FUNCTION__, p2, 1);
931 CHECK_BLOCKS(__FUNCTION__, p3, 1);
932 CHECK_BLOCKS(__FUNCTION__, r1, 2);
934 fprintf(stderr, "Freeing p1\n");
936 /* r1 should have ref reference to p2 still */
937 talloc_report_full(NULL, stderr);
938 CHECK_BLOCKS(__FUNCTION__, r1, 2);
940 /* if we talloc_steal p2 to p3, r1 should still have a reference
941 (unless it had been made the parent like in old talloc */
942 fprintf(stderr, "Steal p2 to p3\n");
943 talloc_steal(p3, p2);
944 talloc_report_full(NULL, stderr);
945 //CHECK_BLOCKS(__FUNCTION__, r1, 2);
947 /* now we free p3 and r1 should still have a reference */
948 fprintf(stderr, "free p3\n");
950 talloc_report_full(NULL, stderr);
951 CHECK_BLOCKS(__FUNCTION__, p2, 1);
952 CHECK_BLOCKS(__FUNCTION__, r1, 2);
954 /* if we free r1 then p2 should also vanish */
955 fprintf(stderr, "Freeing r1\n");
958 talloc_report_full(NULL, stderr);
959 CHECK_BLOCKS(__FUNCTION__, root, 1);
962 printf("success: ref1\n");
967 measure the speed of talloc versus malloc
969 static bool test_speed(void)
971 void *ctx = talloc_new(NULL);
973 const int loop = 1000;
977 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
979 tv = timeval_current();
983 for (i=0;i<loop;i++) {
984 p1 = talloc_size(ctx, loop % 100);
985 p2 = talloc_strdup(p1, "foo bar");
986 p3 = talloc_size(p1, 300);
990 } while (timeval_elapsed(&tv) < 5.0);
992 fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
996 ctx = talloc_pool(NULL, 1024);
998 tv = timeval_current();
1002 for (i=0;i<loop;i++) {
1003 p1 = talloc_size(ctx, loop % 100);
1004 p2 = talloc_strdup(p1, "foo bar");
1005 p3 = talloc_size(p1, 300);
1006 talloc_free_children(ctx);
1009 } while (timeval_elapsed(&tv) < 5.0);
1013 fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1015 tv = timeval_current();
1019 for (i=0;i<loop;i++) {
1020 p1 = malloc(loop % 100);
1021 p2 = strdup("foo bar");
1028 } while (timeval_elapsed(&tv) < 5.0);
1029 fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1031 printf("success: speed\n");
1036 static bool test_lifeless(void)
1038 void *top = talloc_named_const(NULL, 0, "top");
1039 char *parent, *child;
1040 void *child_owner = talloc_named_const(NULL, 0, "child_owner");
1042 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
1044 parent = talloc_strdup(top, "parent");
1045 CHECK_BLOCKS("lifeless", NULL, 5);
1046 child = talloc_strdup(parent, "child");
1047 CHECK_BLOCKS("lifeless", NULL, 6);
1048 (void)talloc_reference(child, parent);
1049 CHECK_BLOCKS("lifeless", NULL, 7);
1050 (void)talloc_reference(child_owner, child);
1051 CHECK_BLOCKS("lifeless", NULL, 8);
1052 CHECK_BLOCKS("lifeless", top, 4);
1053 CHECK_BLOCKS("lifeless", child_owner, 2);
1054 talloc_unlink(top, parent);
1055 CHECK_BLOCKS("lifeless", NULL, 8);
1056 CHECK_BLOCKS("lifeless", top, 1);
1057 CHECK_BLOCKS("lifeless", child_owner, 2);
1058 CHECK_BLOCKS("lifeless", child, 2);
1060 CHECK_BLOCKS("lifeless", NULL, 8);
1061 CHECK_BLOCKS("lifeless", top, 1);
1062 CHECK_BLOCKS("lifeless", child_owner, 2);
1063 CHECK_BLOCKS("lifeless", child, 2);
1065 CHECK_BLOCKS("lifeless", NULL, 7);
1066 CHECK_BLOCKS("lifeless", child_owner, 2);
1067 CHECK_BLOCKS("lifeless", child, 2);
1068 talloc_free(child_owner);
1069 CHECK_BLOCKS("lifeless", NULL, 2);
1071 printf("success: lifeless\n");
1075 static int loop_destructor_count;
1077 static int test_loop_destructor(char *ptr)
1079 loop_destructor_count++;
1083 static bool test_loop(void)
1085 void *top = talloc_new(NULL);
1091 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
1093 parent = talloc_strdup(top, "parent");
1094 req1 = talloc(parent, struct req1);
1095 req1->req2 = talloc_strdup(req1, "req2");
1096 talloc_set_destructor(req1->req2, test_loop_destructor);
1097 req1->req3 = talloc_strdup(req1, "req3");
1098 (void)talloc_reference(req1->req3, req1);
1099 talloc_report_full(top, stderr);
1100 talloc_free(parent);
1101 talloc_report_full(top, stderr);
1102 talloc_report_full(NULL, stderr);
1105 torture_assert("loop", loop_destructor_count == 1,
1106 "FAILED TO FIRE LOOP DESTRUCTOR\n");
1107 loop_destructor_count = 0;
1109 printf("success: loop\n");
1113 static int fail_destructor_str(char *ptr)
1118 static bool test_free_parent_deny_child(void)
1120 void *top = talloc_new(NULL);
1125 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1127 level1 = talloc_strdup(top, "level1");
1128 level2 = talloc_strdup(level1, "level2");
1129 level3 = talloc_strdup(level2, "level3");
1131 talloc_set_destructor(level3, fail_destructor_str);
1132 talloc_free(level1);
1133 talloc_set_destructor(level3, NULL);
1135 CHECK_PARENT("free_parent_deny_child", level3, top);
1139 printf("success: free_parent_deny_child\n");
1143 static bool test_talloc_ptrtype(void)
1145 void *top = talloc_new(NULL);
1149 } *s1, *s2, **s3, ***s4;
1150 const char *location1;
1151 const char *location2;
1152 const char *location3;
1153 const char *location4;
1155 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1157 s1 = talloc_ptrtype(top, s1);location1 = __location__;
1159 if (talloc_get_size(s1) != sizeof(struct struct1)) {
1160 printf("failure: ptrtype [\n"
1161 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1162 "]\n", (unsigned long)talloc_get_size(s1),
1163 (unsigned long)sizeof(struct struct1));
1167 if (strcmp(location1, talloc_get_name(s1)) != 0) {
1168 printf("failure: ptrtype [\n"
1169 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1170 talloc_get_name(s1), location1);
1174 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1176 if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1177 printf("failure: ptrtype [\n"
1178 "talloc_array_ptrtype() allocated the wrong size "
1179 "%lu (should be %lu)\n]\n",
1180 (unsigned long)talloc_get_size(s2),
1181 (unsigned long)(sizeof(struct struct1)*10));
1185 if (strcmp(location2, talloc_get_name(s2)) != 0) {
1186 printf("failure: ptrtype [\n"
1187 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1188 talloc_get_name(s2), location2);
1192 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1194 if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1195 printf("failure: ptrtype [\n"
1196 "talloc_array_ptrtype() allocated the wrong size "
1197 "%lu (should be %lu)\n]\n",
1198 (unsigned long)talloc_get_size(s3),
1199 (unsigned long)(sizeof(struct struct1 *)*10));
1203 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1204 "talloc_array_ptrtype() sets the wrong name");
1206 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1208 if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1209 printf("failure: ptrtype [\n"
1210 "talloc_array_ptrtype() allocated the wrong size "
1211 "%lu (should be %lu)\n]\n",
1212 (unsigned long)talloc_get_size(s4),
1213 (unsigned long)(sizeof(struct struct1 **)*10));
1217 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1218 "talloc_array_ptrtype() sets the wrong name");
1222 printf("success: ptrtype\n");
1226 static int _test_talloc_free_in_destructor(void **ptr)
1232 static bool test_talloc_free_in_destructor(void)
1241 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1243 level0 = talloc_new(NULL);
1244 level1 = talloc_new(level0);
1245 level2 = talloc_new(level1);
1246 level3 = talloc_new(level2);
1247 level4 = talloc_new(level3);
1248 level5 = talloc(level4, void *);
1251 (void)talloc_reference(level0, level3);
1252 (void)talloc_reference(level3, level3);
1253 (void)talloc_reference(level5, level3);
1255 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1257 talloc_free(level1);
1259 talloc_free(level0);
1261 printf("success: free_in_destructor\n");
1265 static bool test_autofree(void)
1267 #if _SAMBA_BUILD_ < 4
1268 /* autofree test would kill smbtorture */
1270 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1272 p = talloc_autofree_context();
1275 p = talloc_autofree_context();
1278 printf("success: autofree\n");
1283 static bool test_pool(void)
1286 void *p1, *p2, *p3, *p4;
1288 pool = talloc_pool(NULL, 1024);
1290 p1 = talloc_size(pool, 80);
1291 p2 = talloc_size(pool, 20);
1292 p3 = talloc_size(p1, 50);
1293 p4 = talloc_size(p3, 1000);
1300 static void test_reset(void)
1303 talloc_disable_null_tracking();
1304 talloc_enable_null_tracking();
1307 struct torture_context;
1308 bool torture_local_talloc(struct torture_context *tctx)
1323 ret &= test_unlink1();
1327 ret &= test_realloc();
1329 ret &= test_realloc_child();
1331 ret &= test_steal();
1335 ret &= test_unref_reparent();
1337 ret &= test_realloc_fn();
1341 ret &= test_lifeless();
1345 ret &= test_free_parent_deny_child();
1347 ret &= test_talloc_ptrtype();
1349 ret &= test_talloc_free_in_destructor();
1351 ret &= test_implicit_explicit_free();
1353 ret &= test_ref_free_steal();
1359 ret &= test_speed();
1362 ret &= test_autofree();