2 Unix SMB/CIFS implementation.
4 local testing of talloc routines.
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37 /* the test suite can be built standalone, or as part of Samba */
39 typedef enum {False=0,True=1} BOOL;
42 /* Samba3 does not define the timeval functions below */
43 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
45 static struct timeval timeval_current(void)
48 gettimeofday(&tv, NULL);
52 static double timeval_elapsed(struct timeval *tv)
54 struct timeval tv2 = timeval_current();
55 return (tv2.tv_sec - tv->tv_sec) +
56 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
58 #endif /* _SAMBA_BUILD_ */
60 #if SAMBA_VERSION_MAJOR<4
69 #define CHECK_SIZE(ptr, tsize) do { \
70 if (talloc_total_size(ptr) != (tsize)) { \
71 printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
73 (unsigned)talloc_total_size(ptr), \
75 talloc_report_full(ptr, stdout); \
80 #define CHECK_BLOCKS(ptr, tblocks) do { \
81 if (talloc_total_blocks(ptr) != (tblocks)) { \
82 printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
84 (unsigned)talloc_total_blocks(ptr), \
86 talloc_report_full(ptr, stdout); \
95 static BOOL test_ref1(void)
97 void *root, *p1, *p2, *ref, *r1;
99 printf("TESTING SINGLE REFERENCE FREE\n");
101 root = talloc_named_const(NULL, 0, "root");
102 p1 = talloc_named_const(root, 1, "p1");
103 p2 = talloc_named_const(p1, 1, "p2");
104 talloc_named_const(p1, 1, "x1");
105 talloc_named_const(p1, 2, "x2");
106 talloc_named_const(p1, 3, "x3");
108 r1 = talloc_named_const(root, 1, "r1");
109 ref = talloc_reference(r1, p2);
110 talloc_report_full(root, stdout);
116 printf("Freeing p2\n");
118 talloc_report_full(root, stdout);
124 printf("Freeing p1\n");
126 talloc_report_full(root, stdout);
130 printf("Freeing r1\n");
132 talloc_report_full(NULL, stdout);
134 printf("Testing NULL\n");
135 if (talloc_reference(root, NULL)) {
139 CHECK_BLOCKS(root, 1);
151 static BOOL test_ref2(void)
153 void *root, *p1, *p2, *ref, *r1;
155 printf("TESTING DOUBLE REFERENCE FREE\n");
157 root = talloc_named_const(NULL, 0, "root");
158 p1 = talloc_named_const(root, 1, "p1");
159 talloc_named_const(p1, 1, "x1");
160 talloc_named_const(p1, 1, "x2");
161 talloc_named_const(p1, 1, "x3");
162 p2 = talloc_named_const(p1, 1, "p2");
164 r1 = talloc_named_const(root, 1, "r1");
165 ref = talloc_reference(r1, p2);
166 talloc_report_full(root, stdout);
172 printf("Freeing ref\n");
174 talloc_report_full(root, stdout);
180 printf("Freeing p2\n");
182 talloc_report_full(root, stdout);
187 printf("Freeing p1\n");
189 talloc_report_full(root, stdout);
193 printf("Freeing r1\n");
195 talloc_report_full(root, stdout);
207 static BOOL test_ref3(void)
209 void *root, *p1, *p2, *ref, *r1;
211 printf("TESTING PARENT REFERENCE FREE\n");
213 root = talloc_named_const(NULL, 0, "root");
214 p1 = talloc_named_const(root, 1, "p1");
215 p2 = talloc_named_const(root, 1, "p2");
216 r1 = talloc_named_const(p1, 1, "r1");
217 ref = talloc_reference(p2, r1);
218 talloc_report_full(root, stdout);
224 printf("Freeing p1\n");
226 talloc_report_full(root, stdout);
231 printf("Freeing p2\n");
233 talloc_report_full(root, stdout);
245 static BOOL test_ref4(void)
247 void *root, *p1, *p2, *ref, *r1;
249 printf("TESTING REFERRER REFERENCE FREE\n");
251 root = talloc_named_const(NULL, 0, "root");
252 p1 = talloc_named_const(root, 1, "p1");
253 talloc_named_const(p1, 1, "x1");
254 talloc_named_const(p1, 1, "x2");
255 talloc_named_const(p1, 1, "x3");
256 p2 = talloc_named_const(p1, 1, "p2");
258 r1 = talloc_named_const(root, 1, "r1");
259 ref = talloc_reference(r1, p2);
260 talloc_report_full(root, stdout);
266 printf("Freeing r1\n");
268 talloc_report_full(root, stdout);
273 printf("Freeing p2\n");
275 talloc_report_full(root, stdout);
279 printf("Freeing p1\n");
281 talloc_report_full(root, stdout);
294 static BOOL test_unlink1(void)
296 void *root, *p1, *p2, *ref, *r1;
298 printf("TESTING UNLINK\n");
300 root = talloc_named_const(NULL, 0, "root");
301 p1 = talloc_named_const(root, 1, "p1");
302 talloc_named_const(p1, 1, "x1");
303 talloc_named_const(p1, 1, "x2");
304 talloc_named_const(p1, 1, "x3");
305 p2 = talloc_named_const(p1, 1, "p2");
307 r1 = talloc_named_const(p1, 1, "r1");
308 ref = talloc_reference(r1, p2);
309 talloc_report_full(root, stdout);
315 printf("Unreferencing r1\n");
316 talloc_unlink(r1, p2);
317 talloc_report_full(root, stdout);
323 printf("Freeing p1\n");
325 talloc_report_full(root, stdout);
334 static int fail_destructor(void *ptr)
340 miscellaneous tests to try to get a higher test coverage percentage
342 static BOOL test_misc(void)
348 printf("TESTING MISCELLANEOUS\n");
350 root = talloc_new(NULL);
352 p1 = talloc_size(root, 0x7fffffff);
354 printf("failed: large talloc allowed\n");
358 p1 = talloc_strdup(root, "foo");
359 talloc_increase_ref_count(p1);
360 talloc_increase_ref_count(p1);
361 talloc_increase_ref_count(p1);
363 CHECK_BLOCKS(root, 2);
366 CHECK_BLOCKS(root, 2);
367 talloc_unlink(NULL, p1);
369 CHECK_BLOCKS(root, 2);
370 p2 = talloc_strdup(p1, "foo");
371 if (talloc_unlink(root, p2) != -1) {
372 printf("failed: talloc_unlink() of non-reference context should return -1\n");
375 if (talloc_unlink(p1, p2) != 0) {
376 printf("failed: talloc_unlink() of parent should succeed\n");
381 CHECK_BLOCKS(root, 2);
383 talloc_set_name(p1, "my name is %s", "foo");
384 if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
385 printf("failed: wrong name after talloc_set_name\n");
389 CHECK_BLOCKS(root, 3);
391 talloc_set_name_const(p1, NULL);
392 if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
393 printf("failed: wrong name after talloc_set_name(NULL)\n");
397 CHECK_BLOCKS(root, 3);
400 if (talloc_free(NULL) != -1) {
401 printf("talloc_free(NULL) should give -1\n");
405 talloc_set_destructor(p1, fail_destructor);
406 if (talloc_free(p1) != -1) {
407 printf("Failed destructor should cause talloc_free to fail\n");
410 talloc_set_destructor(p1, NULL);
412 talloc_report(root, stdout);
415 p2 = talloc_zero_size(p1, 20);
417 printf("Failed to give zero memory\n");
422 if (talloc_strdup(root, NULL) != NULL) {
423 printf("failed: strdup on NULL should give NULL\n");
427 p2 = talloc_strndup(p1, "foo", 2);
428 if (strcmp("fo", p2) != 0) {
429 printf("failed: strndup doesn't work\n");
432 p2 = talloc_asprintf_append(p2, "o%c", 'd');
433 if (strcmp("food", p2) != 0) {
434 printf("failed: talloc_asprintf_append doesn't work\n");
440 p2 = talloc_asprintf_append(NULL, "hello %s", "world");
441 if (strcmp("hello world", p2) != 0) {
442 printf("failed: talloc_asprintf_append doesn't work\n");
449 d = talloc_array(p1, double, 0x20000000);
451 printf("failed: integer overflow not detected\n");
455 d = talloc_realloc(p1, d, double, 0x20000000);
457 printf("failed: integer overflow not detected\n");
462 CHECK_BLOCKS(root, 1);
464 p1 = talloc_named(root, 100, "%d bytes", 100);
466 CHECK_BLOCKS(root, 3);
467 talloc_unlink(root, p1);
469 p1 = talloc_init("%d bytes", 200);
470 p2 = talloc_asprintf(p1, "my test '%s'", "string");
473 CHECK_BLOCKS(root, 1);
474 talloc_unlink(NULL, p1);
476 p1 = talloc_named_const(root, 10, "p1");
477 p2 = talloc_named_const(root, 20, "p2");
478 talloc_reference(p1, p2);
479 talloc_report_full(root, stdout);
480 talloc_unlink(root, p2);
481 talloc_report_full(root, stdout);
484 CHECK_BLOCKS(root, 3);
485 talloc_unlink(p1, p2);
486 talloc_unlink(root, p1);
488 p1 = talloc_named_const(root, 10, "p1");
489 p2 = talloc_named_const(root, 20, "p2");
490 talloc_reference(NULL, p2);
491 talloc_report_full(root, stdout);
492 talloc_unlink(root, p2);
493 talloc_report_full(root, stdout);
496 CHECK_BLOCKS(root, 2);
497 talloc_unlink(NULL, p2);
498 talloc_unlink(root, p1);
500 /* Test that talloc_unlink is a no-op */
502 if (talloc_unlink(root, NULL) != -1) {
503 printf("failed: talloc_unlink(root, NULL) == -1\n");
507 talloc_report(root, stdout);
508 talloc_report(NULL, stdout);
516 talloc_enable_leak_report();
517 talloc_enable_leak_report_full();
526 static BOOL test_realloc(void)
528 void *root, *p1, *p2;
530 printf("TESTING REALLOC\n");
532 root = talloc_new(NULL);
534 p1 = talloc_size(root, 10);
537 p1 = talloc_realloc_size(NULL, p1, 20);
542 p2 = talloc_realloc_size(p1, NULL, 30);
546 p2 = talloc_realloc_size(p1, p2, 40);
549 CHECK_SIZE(root, 60);
552 p1 = talloc_realloc_size(NULL, p1, 20);
555 talloc_increase_ref_count(p2);
556 if (talloc_realloc_size(NULL, p2, 5) != NULL) {
557 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
562 talloc_realloc_size(NULL, p2, 0);
563 talloc_realloc_size(NULL, p2, 0);
566 if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) {
567 printf("failed: oversize talloc should fail\n");
571 talloc_realloc_size(NULL, p1, 0);
573 CHECK_BLOCKS(root, 1);
583 test realloc with a child
585 static BOOL test_realloc_child(void)
592 } **list, **list2, **list3;
596 printf("TESTING REALLOC WITH CHILD\n");
598 root = talloc_new(NULL);
600 el1 = talloc(root, struct el1);
601 el1->list = talloc(el1, struct el2 *);
602 el1->list[0] = talloc(el1->list, struct el2);
603 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
605 el1->list2 = talloc(el1, struct el2 *);
606 el1->list2[0] = talloc(el1->list2, struct el2);
607 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
609 el1->list3 = talloc(el1, struct el2 *);
610 el1->list3[0] = talloc(el1->list3, struct el2);
611 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
613 el2 = talloc(el1->list, struct el2);
614 el2 = talloc(el1->list2, struct el2);
615 el2 = talloc(el1->list3, struct el2);
617 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
618 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
619 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
630 static BOOL test_type(void)
641 printf("TESTING talloc type checking\n");
643 root = talloc_new(NULL);
645 el1 = talloc(root, struct el1);
649 if (talloc_get_type(el1, struct el1) != el1) {
650 printf("type check failed on el1\n");
653 if (talloc_get_type(el1, struct el2) != NULL) {
654 printf("type check failed on el1 with el2\n");
657 talloc_set_type(el1, struct el2);
658 if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) {
659 printf("type set failed on el1 with el2\n");
671 static BOOL test_steal(void)
673 void *root, *p1, *p2;
675 printf("TESTING STEAL\n");
677 root = talloc_new(NULL);
679 p1 = talloc_array(root, char, 10);
682 p2 = talloc_realloc(root, NULL, char, 20);
684 CHECK_SIZE(root, 30);
686 if (talloc_steal(p1, NULL) != NULL) {
687 printf("failed: stealing NULL should give NULL\n");
691 if (talloc_steal(p1, p1) != p1) {
692 printf("failed: stealing to ourselves is a nop\n");
695 CHECK_BLOCKS(root, 3);
696 CHECK_SIZE(root, 30);
698 talloc_steal(NULL, p1);
699 talloc_steal(NULL, p2);
700 CHECK_BLOCKS(root, 1);
704 talloc_steal(root, p2);
705 CHECK_BLOCKS(root, 2);
706 CHECK_SIZE(root, 20);
710 CHECK_BLOCKS(root, 1);
715 p1 = talloc_size(NULL, 3);
723 test talloc_realloc_fn
725 static BOOL test_realloc_fn(void)
729 printf("TESTING talloc_realloc_fn\n");
731 root = talloc_new(NULL);
733 p1 = talloc_realloc_fn(root, NULL, 10);
734 CHECK_BLOCKS(root, 2);
735 CHECK_SIZE(root, 10);
736 p1 = talloc_realloc_fn(root, p1, 20);
737 CHECK_BLOCKS(root, 2);
738 CHECK_SIZE(root, 20);
739 p1 = talloc_realloc_fn(root, p1, 0);
740 CHECK_BLOCKS(root, 1);
750 static BOOL test_unref_reparent(void)
752 void *root, *p1, *p2, *c1;
754 printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
756 root = talloc_named_const(NULL, 0, "root");
757 p1 = talloc_named_const(root, 1, "orig parent");
758 p2 = talloc_named_const(root, 1, "parent by reference");
760 c1 = talloc_named_const(p1, 1, "child");
761 talloc_reference(p2, c1);
764 talloc_unlink(p2, c1);
775 measure the speed of talloc versus malloc
777 static BOOL test_speed(void)
779 void *ctx = talloc_new(NULL);
783 printf("MEASURING TALLOC VS MALLOC SPEED\n");
785 tv = timeval_current();
789 p1 = talloc_size(ctx, count);
790 p2 = talloc_strdup(p1, "foo bar");
791 p3 = talloc_size(p1, 300);
794 } while (timeval_elapsed(&tv) < 5.0);
796 printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
800 tv = timeval_current();
805 p2 = strdup("foo bar");
811 } while (timeval_elapsed(&tv) < 5.0);
813 printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
819 BOOL torture_local_talloc(void)
827 ret &= test_unlink1();
829 ret &= test_realloc();
830 ret &= test_realloc_child();
832 ret &= test_unref_reparent();
833 ret &= test_realloc_fn();
844 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
847 if (!torture_local_talloc()) {
848 printf("ERROR: TESTSUIE FAILED\n");