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 2 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, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 struct torture_context;
53 static struct timeval timeval_current(void)
56 gettimeofday(&tv, NULL);
60 static double timeval_elapsed(struct timeval *tv)
62 struct timeval tv2 = timeval_current();
63 return (tv2.tv_sec - tv->tv_sec) +
64 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
67 #if SAMBA_VERSION_MAJOR<4
76 #define CHECK_SIZE(ptr, tsize) do { \
77 if (talloc_total_size(ptr) != (tsize)) { \
78 printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
80 (unsigned)talloc_total_size(ptr), \
82 talloc_report_full(ptr, stdout); \
87 #define CHECK_BLOCKS(ptr, tblocks) do { \
88 if (talloc_total_blocks(ptr) != (tblocks)) { \
89 printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
91 (unsigned)talloc_total_blocks(ptr), \
93 talloc_report_full(ptr, stdout); \
102 static BOOL test_ref1(void)
104 void *root, *p1, *p2, *ref, *r1;
106 printf("TESTING SINGLE REFERENCE FREE\n");
108 root = talloc_named_const(NULL, 0, "root");
109 p1 = talloc_named_const(root, 1, "p1");
110 p2 = talloc_named_const(p1, 1, "p2");
111 talloc_named_const(p1, 1, "x1");
112 talloc_named_const(p1, 2, "x2");
113 talloc_named_const(p1, 3, "x3");
115 r1 = talloc_named_const(root, 1, "r1");
116 ref = talloc_reference(r1, p2);
117 talloc_report_full(root, stdout);
123 printf("Freeing p2\n");
125 talloc_report_full(root, stdout);
131 printf("Freeing p1\n");
133 talloc_report_full(root, stdout);
137 printf("Freeing r1\n");
139 talloc_report_full(NULL, stdout);
141 printf("Testing NULL\n");
142 if (talloc_reference(root, NULL)) {
146 CHECK_BLOCKS(root, 1);
158 static BOOL test_ref2(void)
160 void *root, *p1, *p2, *ref, *r1;
162 printf("TESTING DOUBLE REFERENCE FREE\n");
164 root = talloc_named_const(NULL, 0, "root");
165 p1 = talloc_named_const(root, 1, "p1");
166 talloc_named_const(p1, 1, "x1");
167 talloc_named_const(p1, 1, "x2");
168 talloc_named_const(p1, 1, "x3");
169 p2 = talloc_named_const(p1, 1, "p2");
171 r1 = talloc_named_const(root, 1, "r1");
172 ref = talloc_reference(r1, p2);
173 talloc_report_full(root, stdout);
179 printf("Freeing ref\n");
181 talloc_report_full(root, stdout);
187 printf("Freeing p2\n");
189 talloc_report_full(root, stdout);
194 printf("Freeing p1\n");
196 talloc_report_full(root, stdout);
200 printf("Freeing r1\n");
202 talloc_report_full(root, stdout);
214 static BOOL test_ref3(void)
216 void *root, *p1, *p2, *ref, *r1;
218 printf("TESTING PARENT REFERENCE FREE\n");
220 root = talloc_named_const(NULL, 0, "root");
221 p1 = talloc_named_const(root, 1, "p1");
222 p2 = talloc_named_const(root, 1, "p2");
223 r1 = talloc_named_const(p1, 1, "r1");
224 ref = talloc_reference(p2, r1);
225 talloc_report_full(root, stdout);
231 printf("Freeing p1\n");
233 talloc_report_full(root, stdout);
238 printf("Freeing p2\n");
240 talloc_report_full(root, stdout);
252 static BOOL test_ref4(void)
254 void *root, *p1, *p2, *ref, *r1;
256 printf("TESTING REFERRER REFERENCE FREE\n");
258 root = talloc_named_const(NULL, 0, "root");
259 p1 = talloc_named_const(root, 1, "p1");
260 talloc_named_const(p1, 1, "x1");
261 talloc_named_const(p1, 1, "x2");
262 talloc_named_const(p1, 1, "x3");
263 p2 = talloc_named_const(p1, 1, "p2");
265 r1 = talloc_named_const(root, 1, "r1");
266 ref = talloc_reference(r1, p2);
267 talloc_report_full(root, stdout);
273 printf("Freeing r1\n");
275 talloc_report_full(root, stdout);
280 printf("Freeing p2\n");
282 talloc_report_full(root, stdout);
286 printf("Freeing p1\n");
288 talloc_report_full(root, stdout);
301 static BOOL test_unlink1(void)
303 void *root, *p1, *p2, *ref, *r1;
305 printf("TESTING UNLINK\n");
307 root = talloc_named_const(NULL, 0, "root");
308 p1 = talloc_named_const(root, 1, "p1");
309 talloc_named_const(p1, 1, "x1");
310 talloc_named_const(p1, 1, "x2");
311 talloc_named_const(p1, 1, "x3");
312 p2 = talloc_named_const(p1, 1, "p2");
314 r1 = talloc_named_const(p1, 1, "r1");
315 ref = talloc_reference(r1, p2);
316 talloc_report_full(root, stdout);
322 printf("Unreferencing r1\n");
323 talloc_unlink(r1, p2);
324 talloc_report_full(root, stdout);
330 printf("Freeing p1\n");
332 talloc_report_full(root, stdout);
341 static int fail_destructor(void *ptr)
347 miscellaneous tests to try to get a higher test coverage percentage
349 static BOOL test_misc(void)
355 printf("TESTING MISCELLANEOUS\n");
357 root = talloc_new(NULL);
359 p1 = talloc_size(root, 0x7fffffff);
361 printf("failed: large talloc allowed\n");
365 p1 = talloc_strdup(root, "foo");
366 talloc_increase_ref_count(p1);
367 talloc_increase_ref_count(p1);
368 talloc_increase_ref_count(p1);
370 CHECK_BLOCKS(root, 2);
373 CHECK_BLOCKS(root, 2);
374 talloc_unlink(NULL, p1);
376 CHECK_BLOCKS(root, 2);
377 p2 = talloc_strdup(p1, "foo");
378 if (talloc_unlink(root, p2) != -1) {
379 printf("failed: talloc_unlink() of non-reference context should return -1\n");
382 if (talloc_unlink(p1, p2) != 0) {
383 printf("failed: talloc_unlink() of parent should succeed\n");
388 CHECK_BLOCKS(root, 2);
390 talloc_set_name(p1, "my name is %s", "foo");
391 if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
392 printf("failed: wrong name after talloc_set_name\n");
396 CHECK_BLOCKS(root, 3);
398 talloc_set_name_const(p1, NULL);
399 if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
400 printf("failed: wrong name after talloc_set_name(NULL)\n");
404 CHECK_BLOCKS(root, 3);
407 if (talloc_free(NULL) != -1) {
408 printf("talloc_free(NULL) should give -1\n");
412 talloc_set_destructor(p1, fail_destructor);
413 if (talloc_free(p1) != -1) {
414 printf("Failed destructor should cause talloc_free to fail\n");
417 talloc_set_destructor(p1, NULL);
419 talloc_report(root, stdout);
422 p2 = talloc_zero_size(p1, 20);
424 printf("Failed to give zero memory\n");
429 if (talloc_strdup(root, NULL) != NULL) {
430 printf("failed: strdup on NULL should give NULL\n");
434 p2 = talloc_strndup(p1, "foo", 2);
435 if (strcmp("fo", p2) != 0) {
436 printf("failed: strndup doesn't work\n");
439 p2 = talloc_asprintf_append(p2, "o%c", 'd');
440 if (strcmp("food", p2) != 0) {
441 printf("failed: talloc_asprintf_append doesn't work\n");
447 p2 = talloc_asprintf_append(NULL, "hello %s", "world");
448 if (strcmp("hello world", p2) != 0) {
449 printf("failed: talloc_asprintf_append doesn't work\n");
456 d = talloc_array(p1, double, 0x20000000);
458 printf("failed: integer overflow not detected\n");
462 d = talloc_realloc(p1, d, double, 0x20000000);
464 printf("failed: integer overflow not detected\n");
469 CHECK_BLOCKS(root, 1);
471 p1 = talloc_named(root, 100, "%d bytes", 100);
473 CHECK_BLOCKS(root, 3);
474 talloc_unlink(root, p1);
476 p1 = talloc_init("%d bytes", 200);
477 p2 = talloc_asprintf(p1, "my test '%s'", "string");
480 CHECK_BLOCKS(root, 1);
481 talloc_unlink(NULL, p1);
483 p1 = talloc_named_const(root, 10, "p1");
484 p2 = talloc_named_const(root, 20, "p2");
485 talloc_reference(p1, p2);
486 talloc_report_full(root, stdout);
487 talloc_unlink(root, p2);
488 talloc_report_full(root, stdout);
491 CHECK_BLOCKS(root, 3);
492 talloc_unlink(p1, p2);
493 talloc_unlink(root, p1);
495 p1 = talloc_named_const(root, 10, "p1");
496 p2 = talloc_named_const(root, 20, "p2");
497 talloc_reference(NULL, p2);
498 talloc_report_full(root, stdout);
499 talloc_unlink(root, p2);
500 talloc_report_full(root, stdout);
503 CHECK_BLOCKS(root, 2);
504 talloc_unlink(NULL, p2);
505 talloc_unlink(root, p1);
507 /* Test that talloc_unlink is a no-op */
509 if (talloc_unlink(root, NULL) != -1) {
510 printf("failed: talloc_unlink(root, NULL) == -1\n");
514 talloc_report(root, stdout);
515 talloc_report(NULL, stdout);
523 talloc_enable_leak_report();
524 talloc_enable_leak_report_full();
533 static BOOL test_realloc(void)
535 void *root, *p1, *p2;
537 printf("TESTING REALLOC\n");
539 root = talloc_new(NULL);
541 p1 = talloc_size(root, 10);
544 p1 = talloc_realloc_size(NULL, p1, 20);
549 p2 = talloc_realloc_size(p1, NULL, 30);
553 p2 = talloc_realloc_size(p1, p2, 40);
556 CHECK_SIZE(root, 60);
559 p1 = talloc_realloc_size(NULL, p1, 20);
562 talloc_increase_ref_count(p2);
563 if (talloc_realloc_size(NULL, p2, 5) != NULL) {
564 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
569 talloc_realloc_size(NULL, p2, 0);
570 talloc_realloc_size(NULL, p2, 0);
573 if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) {
574 printf("failed: oversize talloc should fail\n");
578 talloc_realloc_size(NULL, p1, 0);
580 CHECK_BLOCKS(root, 1);
590 test realloc with a child
592 static BOOL test_realloc_child(void)
599 } **list, **list2, **list3;
603 printf("TESTING REALLOC WITH CHILD\n");
605 root = talloc_new(NULL);
607 el1 = talloc(root, struct el1);
608 el1->list = talloc(el1, struct el2 *);
609 el1->list[0] = talloc(el1->list, struct el2);
610 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
612 el1->list2 = talloc(el1, struct el2 *);
613 el1->list2[0] = talloc(el1->list2, struct el2);
614 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
616 el1->list3 = talloc(el1, struct el2 *);
617 el1->list3[0] = talloc(el1->list3, struct el2);
618 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
620 el2 = talloc(el1->list, struct el2);
621 el2 = talloc(el1->list2, struct el2);
622 el2 = talloc(el1->list3, struct el2);
624 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
625 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
626 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
637 static BOOL test_type(void)
648 printf("TESTING talloc type checking\n");
650 root = talloc_new(NULL);
652 el1 = talloc(root, struct el1);
656 if (talloc_get_type(el1, struct el1) != el1) {
657 printf("type check failed on el1\n");
660 if (talloc_get_type(el1, struct el2) != NULL) {
661 printf("type check failed on el1 with el2\n");
664 talloc_set_type(el1, struct el2);
665 if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) {
666 printf("type set failed on el1 with el2\n");
678 static BOOL test_steal(void)
680 void *root, *p1, *p2;
682 printf("TESTING STEAL\n");
684 root = talloc_new(NULL);
686 p1 = talloc_array(root, char, 10);
689 p2 = talloc_realloc(root, NULL, char, 20);
691 CHECK_SIZE(root, 30);
693 if (talloc_steal(p1, NULL) != NULL) {
694 printf("failed: stealing NULL should give NULL\n");
698 if (talloc_steal(p1, p1) != p1) {
699 printf("failed: stealing to ourselves is a nop\n");
702 CHECK_BLOCKS(root, 3);
703 CHECK_SIZE(root, 30);
705 talloc_steal(NULL, p1);
706 talloc_steal(NULL, p2);
707 CHECK_BLOCKS(root, 1);
711 talloc_steal(root, p2);
712 CHECK_BLOCKS(root, 2);
713 CHECK_SIZE(root, 20);
717 CHECK_BLOCKS(root, 1);
722 p1 = talloc_size(NULL, 3);
723 talloc_report_full(NULL, stdout);
731 test talloc_realloc_fn
733 static BOOL test_realloc_fn(void)
737 printf("TESTING talloc_realloc_fn\n");
739 root = talloc_new(NULL);
741 p1 = talloc_realloc_fn(root, NULL, 10);
742 CHECK_BLOCKS(root, 2);
743 CHECK_SIZE(root, 10);
744 p1 = talloc_realloc_fn(root, p1, 20);
745 CHECK_BLOCKS(root, 2);
746 CHECK_SIZE(root, 20);
747 p1 = talloc_realloc_fn(root, p1, 0);
748 CHECK_BLOCKS(root, 1);
758 static BOOL test_unref_reparent(void)
760 void *root, *p1, *p2, *c1;
762 printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
764 root = talloc_named_const(NULL, 0, "root");
765 p1 = talloc_named_const(root, 1, "orig parent");
766 p2 = talloc_named_const(root, 1, "parent by reference");
768 c1 = talloc_named_const(p1, 1, "child");
769 talloc_reference(p2, c1);
772 talloc_unlink(p2, c1);
783 measure the speed of talloc versus malloc
785 static BOOL test_speed(void)
787 void *ctx = talloc_new(NULL);
791 printf("MEASURING TALLOC VS MALLOC SPEED\n");
793 tv = timeval_current();
797 p1 = talloc_size(ctx, count);
798 p2 = talloc_strdup(p1, "foo bar");
799 p3 = talloc_size(p1, 300);
802 } while (timeval_elapsed(&tv) < 5.0);
804 printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
808 tv = timeval_current();
813 p2 = strdup("foo bar");
819 } while (timeval_elapsed(&tv) < 5.0);
821 printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
827 BOOL test_lifeless(void)
829 char *top = talloc_new(NULL);
830 char *parent, *child;
831 char *child_owner = talloc_new(NULL);
833 printf("TESTING TALLOC_UNLINK LOOP\n");
835 parent = talloc_strdup(top, "parent");
836 child = talloc_strdup(parent, "child");
837 talloc_reference(child, parent);
838 talloc_reference(child_owner, child);
839 talloc_unlink(top, parent);
841 talloc_report_full(top, stdout);
847 BOOL torture_local_talloc(struct torture_context *torture)
855 ret &= test_unlink1();
857 ret &= test_realloc();
858 ret &= test_realloc_child();
860 ret &= test_unref_reparent();
861 ret &= test_realloc_fn();
863 ret &= test_lifeless();
873 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
876 if (!torture_local_talloc(NULL)) {
877 printf("ERROR: TESTSUITE FAILED\n");