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 static struct timeval timeval_current(void)
54 gettimeofday(&tv, NULL);
58 static double timeval_elapsed(struct timeval *tv)
60 struct timeval tv2 = timeval_current();
61 return (tv2.tv_sec - tv->tv_sec) +
62 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
65 #if SAMBA_VERSION_MAJOR<4
74 #define CHECK_SIZE(ptr, tsize) do { \
75 if (talloc_total_size(ptr) != (tsize)) { \
76 printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
78 (unsigned)talloc_total_size(ptr), \
80 talloc_report_full(ptr, stdout); \
85 #define CHECK_BLOCKS(ptr, tblocks) do { \
86 if (talloc_total_blocks(ptr) != (tblocks)) { \
87 printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
89 (unsigned)talloc_total_blocks(ptr), \
91 talloc_report_full(ptr, stdout); \
100 static BOOL test_ref1(void)
102 void *root, *p1, *p2, *ref, *r1;
104 printf("TESTING SINGLE REFERENCE FREE\n");
106 root = talloc_named_const(NULL, 0, "root");
107 p1 = talloc_named_const(root, 1, "p1");
108 p2 = talloc_named_const(p1, 1, "p2");
109 talloc_named_const(p1, 1, "x1");
110 talloc_named_const(p1, 2, "x2");
111 talloc_named_const(p1, 3, "x3");
113 r1 = talloc_named_const(root, 1, "r1");
114 ref = talloc_reference(r1, p2);
115 talloc_report_full(root, stdout);
121 printf("Freeing p2\n");
123 talloc_report_full(root, stdout);
129 printf("Freeing p1\n");
131 talloc_report_full(root, stdout);
135 printf("Freeing r1\n");
137 talloc_report_full(NULL, stdout);
139 printf("Testing NULL\n");
140 if (talloc_reference(root, NULL)) {
144 CHECK_BLOCKS(root, 1);
156 static BOOL test_ref2(void)
158 void *root, *p1, *p2, *ref, *r1;
160 printf("TESTING DOUBLE REFERENCE FREE\n");
162 root = talloc_named_const(NULL, 0, "root");
163 p1 = talloc_named_const(root, 1, "p1");
164 talloc_named_const(p1, 1, "x1");
165 talloc_named_const(p1, 1, "x2");
166 talloc_named_const(p1, 1, "x3");
167 p2 = talloc_named_const(p1, 1, "p2");
169 r1 = talloc_named_const(root, 1, "r1");
170 ref = talloc_reference(r1, p2);
171 talloc_report_full(root, stdout);
177 printf("Freeing ref\n");
179 talloc_report_full(root, stdout);
185 printf("Freeing p2\n");
187 talloc_report_full(root, stdout);
192 printf("Freeing p1\n");
194 talloc_report_full(root, stdout);
198 printf("Freeing r1\n");
200 talloc_report_full(root, stdout);
212 static BOOL test_ref3(void)
214 void *root, *p1, *p2, *ref, *r1;
216 printf("TESTING PARENT REFERENCE FREE\n");
218 root = talloc_named_const(NULL, 0, "root");
219 p1 = talloc_named_const(root, 1, "p1");
220 p2 = talloc_named_const(root, 1, "p2");
221 r1 = talloc_named_const(p1, 1, "r1");
222 ref = talloc_reference(p2, r1);
223 talloc_report_full(root, stdout);
229 printf("Freeing p1\n");
231 talloc_report_full(root, stdout);
236 printf("Freeing p2\n");
238 talloc_report_full(root, stdout);
250 static BOOL test_ref4(void)
252 void *root, *p1, *p2, *ref, *r1;
254 printf("TESTING REFERRER REFERENCE FREE\n");
256 root = talloc_named_const(NULL, 0, "root");
257 p1 = talloc_named_const(root, 1, "p1");
258 talloc_named_const(p1, 1, "x1");
259 talloc_named_const(p1, 1, "x2");
260 talloc_named_const(p1, 1, "x3");
261 p2 = talloc_named_const(p1, 1, "p2");
263 r1 = talloc_named_const(root, 1, "r1");
264 ref = talloc_reference(r1, p2);
265 talloc_report_full(root, stdout);
271 printf("Freeing r1\n");
273 talloc_report_full(root, stdout);
278 printf("Freeing p2\n");
280 talloc_report_full(root, stdout);
284 printf("Freeing p1\n");
286 talloc_report_full(root, stdout);
299 static BOOL test_unlink1(void)
301 void *root, *p1, *p2, *ref, *r1;
303 printf("TESTING UNLINK\n");
305 root = talloc_named_const(NULL, 0, "root");
306 p1 = talloc_named_const(root, 1, "p1");
307 talloc_named_const(p1, 1, "x1");
308 talloc_named_const(p1, 1, "x2");
309 talloc_named_const(p1, 1, "x3");
310 p2 = talloc_named_const(p1, 1, "p2");
312 r1 = talloc_named_const(p1, 1, "r1");
313 ref = talloc_reference(r1, p2);
314 talloc_report_full(root, stdout);
320 printf("Unreferencing r1\n");
321 talloc_unlink(r1, p2);
322 talloc_report_full(root, stdout);
328 printf("Freeing p1\n");
330 talloc_report_full(root, stdout);
339 static int fail_destructor(void *ptr)
345 miscellaneous tests to try to get a higher test coverage percentage
347 static BOOL test_misc(void)
353 printf("TESTING MISCELLANEOUS\n");
355 root = talloc_new(NULL);
357 p1 = talloc_size(root, 0x7fffffff);
359 printf("failed: large talloc allowed\n");
363 p1 = talloc_strdup(root, "foo");
364 talloc_increase_ref_count(p1);
365 talloc_increase_ref_count(p1);
366 talloc_increase_ref_count(p1);
368 CHECK_BLOCKS(root, 2);
371 CHECK_BLOCKS(root, 2);
372 talloc_unlink(NULL, p1);
374 CHECK_BLOCKS(root, 2);
375 p2 = talloc_strdup(p1, "foo");
376 if (talloc_unlink(root, p2) != -1) {
377 printf("failed: talloc_unlink() of non-reference context should return -1\n");
380 if (talloc_unlink(p1, p2) != 0) {
381 printf("failed: talloc_unlink() of parent should succeed\n");
386 CHECK_BLOCKS(root, 2);
388 talloc_set_name(p1, "my name is %s", "foo");
389 if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
390 printf("failed: wrong name after talloc_set_name\n");
394 CHECK_BLOCKS(root, 3);
396 talloc_set_name_const(p1, NULL);
397 if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
398 printf("failed: wrong name after talloc_set_name(NULL)\n");
402 CHECK_BLOCKS(root, 3);
405 if (talloc_free(NULL) != -1) {
406 printf("talloc_free(NULL) should give -1\n");
410 talloc_set_destructor(p1, fail_destructor);
411 if (talloc_free(p1) != -1) {
412 printf("Failed destructor should cause talloc_free to fail\n");
415 talloc_set_destructor(p1, NULL);
417 talloc_report(root, stdout);
420 p2 = talloc_zero_size(p1, 20);
422 printf("Failed to give zero memory\n");
427 if (talloc_strdup(root, NULL) != NULL) {
428 printf("failed: strdup on NULL should give NULL\n");
432 p2 = talloc_strndup(p1, "foo", 2);
433 if (strcmp("fo", p2) != 0) {
434 printf("failed: strndup doesn't work\n");
437 p2 = talloc_asprintf_append(p2, "o%c", 'd');
438 if (strcmp("food", p2) != 0) {
439 printf("failed: talloc_asprintf_append doesn't work\n");
445 p2 = talloc_asprintf_append(NULL, "hello %s", "world");
446 if (strcmp("hello world", p2) != 0) {
447 printf("failed: talloc_asprintf_append doesn't work\n");
454 d = talloc_array(p1, double, 0x20000000);
456 printf("failed: integer overflow not detected\n");
460 d = talloc_realloc(p1, d, double, 0x20000000);
462 printf("failed: integer overflow not detected\n");
467 CHECK_BLOCKS(root, 1);
469 p1 = talloc_named(root, 100, "%d bytes", 100);
471 CHECK_BLOCKS(root, 3);
472 talloc_unlink(root, p1);
474 p1 = talloc_init("%d bytes", 200);
475 p2 = talloc_asprintf(p1, "my test '%s'", "string");
478 CHECK_BLOCKS(root, 1);
479 talloc_unlink(NULL, p1);
481 p1 = talloc_named_const(root, 10, "p1");
482 p2 = talloc_named_const(root, 20, "p2");
483 talloc_reference(p1, p2);
484 talloc_report_full(root, stdout);
485 talloc_unlink(root, p2);
486 talloc_report_full(root, stdout);
489 CHECK_BLOCKS(root, 3);
490 talloc_unlink(p1, p2);
491 talloc_unlink(root, p1);
493 p1 = talloc_named_const(root, 10, "p1");
494 p2 = talloc_named_const(root, 20, "p2");
495 talloc_reference(NULL, p2);
496 talloc_report_full(root, stdout);
497 talloc_unlink(root, p2);
498 talloc_report_full(root, stdout);
501 CHECK_BLOCKS(root, 2);
502 talloc_unlink(NULL, p2);
503 talloc_unlink(root, p1);
505 /* Test that talloc_unlink is a no-op */
507 if (talloc_unlink(root, NULL) != -1) {
508 printf("failed: talloc_unlink(root, NULL) == -1\n");
512 talloc_report(root, stdout);
513 talloc_report(NULL, stdout);
521 talloc_enable_leak_report();
522 talloc_enable_leak_report_full();
531 static BOOL test_realloc(void)
533 void *root, *p1, *p2;
535 printf("TESTING REALLOC\n");
537 root = talloc_new(NULL);
539 p1 = talloc_size(root, 10);
542 p1 = talloc_realloc_size(NULL, p1, 20);
547 p2 = talloc_realloc_size(p1, NULL, 30);
551 p2 = talloc_realloc_size(p1, p2, 40);
554 CHECK_SIZE(root, 60);
557 p1 = talloc_realloc_size(NULL, p1, 20);
560 talloc_increase_ref_count(p2);
561 if (talloc_realloc_size(NULL, p2, 5) != NULL) {
562 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
567 talloc_realloc_size(NULL, p2, 0);
568 talloc_realloc_size(NULL, p2, 0);
571 if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) {
572 printf("failed: oversize talloc should fail\n");
576 talloc_realloc_size(NULL, p1, 0);
578 CHECK_BLOCKS(root, 1);
588 test realloc with a child
590 static BOOL test_realloc_child(void)
597 } **list, **list2, **list3;
601 printf("TESTING REALLOC WITH CHILD\n");
603 root = talloc_new(NULL);
605 el1 = talloc(root, struct el1);
606 el1->list = talloc(el1, struct el2 *);
607 el1->list[0] = talloc(el1->list, struct el2);
608 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
610 el1->list2 = talloc(el1, struct el2 *);
611 el1->list2[0] = talloc(el1->list2, struct el2);
612 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
614 el1->list3 = talloc(el1, struct el2 *);
615 el1->list3[0] = talloc(el1->list3, struct el2);
616 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
618 el2 = talloc(el1->list, struct el2);
619 el2 = talloc(el1->list2, struct el2);
620 el2 = talloc(el1->list3, struct el2);
622 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
623 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
624 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
635 static BOOL test_type(void)
646 printf("TESTING talloc type checking\n");
648 root = talloc_new(NULL);
650 el1 = talloc(root, struct el1);
654 if (talloc_get_type(el1, struct el1) != el1) {
655 printf("type check failed on el1\n");
658 if (talloc_get_type(el1, struct el2) != NULL) {
659 printf("type check failed on el1 with el2\n");
662 talloc_set_type(el1, struct el2);
663 if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) {
664 printf("type set failed on el1 with el2\n");
676 static BOOL test_steal(void)
678 void *root, *p1, *p2;
680 printf("TESTING STEAL\n");
682 root = talloc_new(NULL);
684 p1 = talloc_array(root, char, 10);
687 p2 = talloc_realloc(root, NULL, char, 20);
689 CHECK_SIZE(root, 30);
691 if (talloc_steal(p1, NULL) != NULL) {
692 printf("failed: stealing NULL should give NULL\n");
696 if (talloc_steal(p1, p1) != p1) {
697 printf("failed: stealing to ourselves is a nop\n");
700 CHECK_BLOCKS(root, 3);
701 CHECK_SIZE(root, 30);
703 talloc_steal(NULL, p1);
704 talloc_steal(NULL, p2);
705 CHECK_BLOCKS(root, 1);
709 talloc_steal(root, p2);
710 CHECK_BLOCKS(root, 2);
711 CHECK_SIZE(root, 20);
715 CHECK_BLOCKS(root, 1);
720 p1 = talloc_size(NULL, 3);
721 talloc_report_full(NULL, stdout);
729 test talloc_realloc_fn
731 static BOOL test_realloc_fn(void)
735 printf("TESTING talloc_realloc_fn\n");
737 root = talloc_new(NULL);
739 p1 = talloc_realloc_fn(root, NULL, 10);
740 CHECK_BLOCKS(root, 2);
741 CHECK_SIZE(root, 10);
742 p1 = talloc_realloc_fn(root, p1, 20);
743 CHECK_BLOCKS(root, 2);
744 CHECK_SIZE(root, 20);
745 p1 = talloc_realloc_fn(root, p1, 0);
746 CHECK_BLOCKS(root, 1);
756 static BOOL test_unref_reparent(void)
758 void *root, *p1, *p2, *c1;
760 printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
762 root = talloc_named_const(NULL, 0, "root");
763 p1 = talloc_named_const(root, 1, "orig parent");
764 p2 = talloc_named_const(root, 1, "parent by reference");
766 c1 = talloc_named_const(p1, 1, "child");
767 talloc_reference(p2, c1);
770 talloc_unlink(p2, c1);
781 measure the speed of talloc versus malloc
783 static BOOL test_speed(void)
785 void *ctx = talloc_new(NULL);
789 printf("MEASURING TALLOC VS MALLOC SPEED\n");
791 tv = timeval_current();
795 p1 = talloc_size(ctx, count);
796 p2 = talloc_strdup(p1, "foo bar");
797 p3 = talloc_size(p1, 300);
800 } while (timeval_elapsed(&tv) < 5.0);
802 printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
806 tv = timeval_current();
811 p2 = strdup("foo bar");
817 } while (timeval_elapsed(&tv) < 5.0);
819 printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
825 BOOL test_lifeless(void)
827 char *top = talloc_new(NULL);
828 char *parent, *child;
829 char *child_owner = talloc_new(NULL);
831 printf("TESTING TALLOC_UNLINK LOOP\n");
833 parent = talloc_strdup(top, "parent");
834 child = talloc_strdup(parent, "child");
835 talloc_reference(child, parent);
836 talloc_reference(child_owner, child);
837 talloc_unlink(top, parent);
839 talloc_report_full(top, stdout);
845 BOOL torture_local_talloc(void)
853 ret &= test_unlink1();
855 ret &= test_realloc();
856 ret &= test_realloc_child();
858 ret &= test_unref_reparent();
859 ret &= test_realloc_fn();
861 ret &= test_lifeless();
871 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
874 if (!torture_local_talloc()) {
875 printf("ERROR: TESTSUIE FAILED\n");