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.
35 /* the test suite can be built standalone, or as part of Samba */
37 typedef enum {False
=0,True
=1} BOOL
;
40 /* Samba3 does not define the timeval functions below */
41 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
43 static struct timeval
timeval_current(void)
46 gettimeofday(&tv
, NULL
);
50 static double timeval_elapsed(struct timeval
*tv
)
52 struct timeval tv2
= timeval_current();
53 return (tv2
.tv_sec
- tv
->tv_sec
) +
54 (tv2
.tv_usec
- tv
->tv_usec
)*1.0e-6;
56 #endif /* _SAMBA_BUILD_ */
58 #if SAMBA_VERSION_MAJOR<4
67 #define CHECK_SIZE(ptr, tsize) do { \
68 if (talloc_total_size(ptr) != (tsize)) { \
69 printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
71 (unsigned)talloc_total_size(ptr), \
73 talloc_report_full(ptr, stdout); \
78 #define CHECK_BLOCKS(ptr, tblocks) do { \
79 if (talloc_total_blocks(ptr) != (tblocks)) { \
80 printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
82 (unsigned)talloc_total_blocks(ptr), \
84 talloc_report_full(ptr, stdout); \
93 static BOOL
test_ref1(void)
95 void *root
, *p1
, *p2
, *ref
, *r1
;
97 printf("TESTING SINGLE REFERENCE FREE\n");
99 root
= talloc_named_const(NULL
, 0, "root");
100 p1
= talloc_named_const(root
, 1, "p1");
101 p2
= talloc_named_const(p1
, 1, "p2");
102 talloc_named_const(p1
, 1, "x1");
103 talloc_named_const(p1
, 2, "x2");
104 talloc_named_const(p1
, 3, "x3");
106 r1
= talloc_named_const(root
, 1, "r1");
107 ref
= talloc_reference(r1
, p2
);
108 talloc_report_full(root
, stdout
);
114 printf("Freeing p2\n");
116 talloc_report_full(root
, stdout
);
122 printf("Freeing p1\n");
124 talloc_report_full(root
, stdout
);
128 printf("Freeing r1\n");
130 talloc_report_full(NULL
, stdout
);
132 printf("Testing NULL\n");
133 if (talloc_reference(root
, NULL
)) {
137 CHECK_BLOCKS(root
, 1);
149 static BOOL
test_ref2(void)
151 void *root
, *p1
, *p2
, *ref
, *r1
;
153 printf("TESTING DOUBLE REFERENCE FREE\n");
155 root
= talloc_named_const(NULL
, 0, "root");
156 p1
= talloc_named_const(root
, 1, "p1");
157 talloc_named_const(p1
, 1, "x1");
158 talloc_named_const(p1
, 1, "x2");
159 talloc_named_const(p1
, 1, "x3");
160 p2
= talloc_named_const(p1
, 1, "p2");
162 r1
= talloc_named_const(root
, 1, "r1");
163 ref
= talloc_reference(r1
, p2
);
164 talloc_report_full(root
, stdout
);
170 printf("Freeing ref\n");
172 talloc_report_full(root
, stdout
);
178 printf("Freeing p2\n");
180 talloc_report_full(root
, stdout
);
185 printf("Freeing p1\n");
187 talloc_report_full(root
, stdout
);
191 printf("Freeing r1\n");
193 talloc_report_full(root
, stdout
);
205 static BOOL
test_ref3(void)
207 void *root
, *p1
, *p2
, *ref
, *r1
;
209 printf("TESTING PARENT REFERENCE FREE\n");
211 root
= talloc_named_const(NULL
, 0, "root");
212 p1
= talloc_named_const(root
, 1, "p1");
213 p2
= talloc_named_const(root
, 1, "p2");
214 r1
= talloc_named_const(p1
, 1, "r1");
215 ref
= talloc_reference(p2
, r1
);
216 talloc_report_full(root
, stdout
);
222 printf("Freeing p1\n");
224 talloc_report_full(root
, stdout
);
229 printf("Freeing p2\n");
231 talloc_report_full(root
, stdout
);
243 static BOOL
test_ref4(void)
245 void *root
, *p1
, *p2
, *ref
, *r1
;
247 printf("TESTING REFERRER REFERENCE FREE\n");
249 root
= talloc_named_const(NULL
, 0, "root");
250 p1
= talloc_named_const(root
, 1, "p1");
251 talloc_named_const(p1
, 1, "x1");
252 talloc_named_const(p1
, 1, "x2");
253 talloc_named_const(p1
, 1, "x3");
254 p2
= talloc_named_const(p1
, 1, "p2");
256 r1
= talloc_named_const(root
, 1, "r1");
257 ref
= talloc_reference(r1
, p2
);
258 talloc_report_full(root
, stdout
);
264 printf("Freeing r1\n");
266 talloc_report_full(root
, stdout
);
271 printf("Freeing p2\n");
273 talloc_report_full(root
, stdout
);
277 printf("Freeing p1\n");
279 talloc_report_full(root
, stdout
);
292 static BOOL
test_unlink1(void)
294 void *root
, *p1
, *p2
, *ref
, *r1
;
296 printf("TESTING UNLINK\n");
298 root
= talloc_named_const(NULL
, 0, "root");
299 p1
= talloc_named_const(root
, 1, "p1");
300 talloc_named_const(p1
, 1, "x1");
301 talloc_named_const(p1
, 1, "x2");
302 talloc_named_const(p1
, 1, "x3");
303 p2
= talloc_named_const(p1
, 1, "p2");
305 r1
= talloc_named_const(p1
, 1, "r1");
306 ref
= talloc_reference(r1
, p2
);
307 talloc_report_full(root
, stdout
);
313 printf("Unreferencing r1\n");
314 talloc_unlink(r1
, p2
);
315 talloc_report_full(root
, stdout
);
321 printf("Freeing p1\n");
323 talloc_report_full(root
, stdout
);
332 static int fail_destructor(void *ptr
)
338 miscellaneous tests to try to get a higher test coverage percentage
340 static BOOL
test_misc(void)
346 printf("TESTING MISCELLANEOUS\n");
348 root
= talloc_new(NULL
);
350 p1
= talloc_size(root
, 0x7fffffff);
352 printf("failed: large talloc allowed\n");
356 p1
= talloc_strdup(root
, "foo");
357 talloc_increase_ref_count(p1
);
358 talloc_increase_ref_count(p1
);
359 talloc_increase_ref_count(p1
);
361 CHECK_BLOCKS(root
, 2);
364 CHECK_BLOCKS(root
, 2);
365 talloc_unlink(NULL
, p1
);
367 CHECK_BLOCKS(root
, 2);
368 p2
= talloc_strdup(p1
, "foo");
369 if (talloc_unlink(root
, p2
) != -1) {
370 printf("failed: talloc_unlink() of non-reference context should return -1\n");
373 if (talloc_unlink(p1
, p2
) != 0) {
374 printf("failed: talloc_unlink() of parent should succeed\n");
379 CHECK_BLOCKS(root
, 2);
381 talloc_set_name(p1
, "my name is %s", "foo");
382 if (strcmp(talloc_get_name(p1
), "my name is foo") != 0) {
383 printf("failed: wrong name after talloc_set_name\n");
387 CHECK_BLOCKS(root
, 3);
389 talloc_set_name_const(p1
, NULL
);
390 if (strcmp(talloc_get_name(p1
), "UNNAMED") != 0) {
391 printf("failed: wrong name after talloc_set_name(NULL)\n");
395 CHECK_BLOCKS(root
, 3);
398 if (talloc_free(NULL
) != -1) {
399 printf("talloc_free(NULL) should give -1\n");
403 talloc_set_destructor(p1
, fail_destructor
);
404 if (talloc_free(p1
) != -1) {
405 printf("Failed destructor should cause talloc_free to fail\n");
408 talloc_set_destructor(p1
, NULL
);
410 talloc_report(root
, stdout
);
413 p2
= talloc_zero_size(p1
, 20);
415 printf("Failed to give zero memory\n");
420 if (talloc_strdup(root
, NULL
) != NULL
) {
421 printf("failed: strdup on NULL should give NULL\n");
425 p2
= talloc_strndup(p1
, "foo", 2);
426 if (strcmp("fo", p2
) != 0) {
427 printf("failed: strndup doesn't work\n");
430 p2
= talloc_asprintf_append(p2
, "o%c", 'd');
431 if (strcmp("food", p2
) != 0) {
432 printf("failed: talloc_asprintf_append doesn't work\n");
438 p2
= talloc_asprintf_append(NULL
, "hello %s", "world");
439 if (strcmp("hello world", p2
) != 0) {
440 printf("failed: talloc_asprintf_append doesn't work\n");
447 d
= talloc_array(p1
, double, 0x20000000);
449 printf("failed: integer overflow not detected\n");
453 d
= talloc_realloc(p1
, d
, double, 0x20000000);
455 printf("failed: integer overflow not detected\n");
460 CHECK_BLOCKS(root
, 1);
462 p1
= talloc_named(root
, 100, "%d bytes", 100);
464 CHECK_BLOCKS(root
, 3);
465 talloc_unlink(root
, p1
);
467 p1
= talloc_init("%d bytes", 200);
468 p2
= talloc_asprintf(p1
, "my test '%s'", "string");
471 CHECK_BLOCKS(root
, 1);
472 talloc_unlink(NULL
, p1
);
474 p1
= talloc_named_const(root
, 10, "p1");
475 p2
= talloc_named_const(root
, 20, "p2");
476 talloc_reference(p1
, p2
);
477 talloc_report_full(root
, stdout
);
478 talloc_unlink(root
, p2
);
479 talloc_report_full(root
, stdout
);
482 CHECK_BLOCKS(root
, 3);
483 talloc_unlink(p1
, p2
);
484 talloc_unlink(root
, p1
);
486 p1
= talloc_named_const(root
, 10, "p1");
487 p2
= talloc_named_const(root
, 20, "p2");
488 talloc_reference(NULL
, p2
);
489 talloc_report_full(root
, stdout
);
490 talloc_unlink(root
, p2
);
491 talloc_report_full(root
, stdout
);
494 CHECK_BLOCKS(root
, 2);
495 talloc_unlink(NULL
, p2
);
496 talloc_unlink(root
, p1
);
498 /* Test that talloc_unlink is a no-op */
500 if (talloc_unlink(root
, NULL
) != -1) {
501 printf("failed: talloc_unlink(root, NULL) == -1\n");
505 talloc_report(root
, stdout
);
506 talloc_report(NULL
, stdout
);
514 talloc_enable_leak_report();
515 talloc_enable_leak_report_full();
524 static BOOL
test_realloc(void)
526 void *root
, *p1
, *p2
;
528 printf("TESTING REALLOC\n");
530 root
= talloc_new(NULL
);
532 p1
= talloc_size(root
, 10);
535 p1
= talloc_realloc_size(NULL
, p1
, 20);
540 p2
= talloc_realloc_size(p1
, NULL
, 30);
544 p2
= talloc_realloc_size(p1
, p2
, 40);
547 CHECK_SIZE(root
, 60);
550 p1
= talloc_realloc_size(NULL
, p1
, 20);
553 talloc_increase_ref_count(p2
);
554 if (talloc_realloc_size(NULL
, p2
, 5) != NULL
) {
555 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
560 talloc_realloc_size(NULL
, p2
, 0);
561 talloc_realloc_size(NULL
, p2
, 0);
564 if (talloc_realloc_size(NULL
, p1
, 0x7fffffff) != NULL
) {
565 printf("failed: oversize talloc should fail\n");
569 talloc_realloc_size(NULL
, p1
, 0);
571 CHECK_BLOCKS(root
, 1);
581 test realloc with a child
583 static BOOL
test_realloc_child(void)
590 } **list
, **list2
, **list3
;
594 printf("TESTING REALLOC WITH CHILD\n");
596 root
= talloc_new(NULL
);
598 el1
= talloc(root
, struct el1
);
599 el1
->list
= talloc(el1
, struct el2
*);
600 el1
->list
[0] = talloc(el1
->list
, struct el2
);
601 el1
->list
[0]->name
= talloc_strdup(el1
->list
[0], "testing");
603 el1
->list2
= talloc(el1
, struct el2
*);
604 el1
->list2
[0] = talloc(el1
->list2
, struct el2
);
605 el1
->list2
[0]->name
= talloc_strdup(el1
->list2
[0], "testing2");
607 el1
->list3
= talloc(el1
, struct el2
*);
608 el1
->list3
[0] = talloc(el1
->list3
, struct el2
);
609 el1
->list3
[0]->name
= talloc_strdup(el1
->list3
[0], "testing2");
611 el2
= talloc(el1
->list
, struct el2
);
612 el2
= talloc(el1
->list2
, struct el2
);
613 el2
= talloc(el1
->list3
, struct el2
);
615 el1
->list
= talloc_realloc(el1
, el1
->list
, struct el2
*, 100);
616 el1
->list2
= talloc_realloc(el1
, el1
->list2
, struct el2
*, 200);
617 el1
->list3
= talloc_realloc(el1
, el1
->list3
, struct el2
*, 300);
628 static BOOL
test_type(void)
639 printf("TESTING talloc type checking\n");
641 root
= talloc_new(NULL
);
643 el1
= talloc(root
, struct el1
);
647 if (talloc_get_type(el1
, struct el1
) != el1
) {
648 printf("type check failed on el1\n");
651 if (talloc_get_type(el1
, struct el2
) != NULL
) {
652 printf("type check failed on el1 with el2\n");
655 talloc_set_type(el1
, struct el2
);
656 if (talloc_get_type(el1
, struct el2
) != (struct el2
*)el1
) {
657 printf("type set failed on el1 with el2\n");
669 static BOOL
test_steal(void)
671 void *root
, *p1
, *p2
;
673 printf("TESTING STEAL\n");
675 root
= talloc_new(NULL
);
677 p1
= talloc_array(root
, char, 10);
680 p2
= talloc_realloc(root
, NULL
, char, 20);
682 CHECK_SIZE(root
, 30);
684 if (talloc_steal(p1
, NULL
) != NULL
) {
685 printf("failed: stealing NULL should give NULL\n");
689 if (talloc_steal(p1
, p1
) != p1
) {
690 printf("failed: stealing to ourselves is a nop\n");
693 CHECK_BLOCKS(root
, 3);
694 CHECK_SIZE(root
, 30);
696 talloc_steal(NULL
, p1
);
697 talloc_steal(NULL
, p2
);
698 CHECK_BLOCKS(root
, 1);
702 talloc_steal(root
, p2
);
703 CHECK_BLOCKS(root
, 2);
704 CHECK_SIZE(root
, 20);
708 CHECK_BLOCKS(root
, 1);
713 p1
= talloc_size(NULL
, 3);
721 test talloc_realloc_fn
723 static BOOL
test_realloc_fn(void)
727 printf("TESTING talloc_realloc_fn\n");
729 root
= talloc_new(NULL
);
731 p1
= talloc_realloc_fn(root
, NULL
, 10);
732 CHECK_BLOCKS(root
, 2);
733 CHECK_SIZE(root
, 10);
734 p1
= talloc_realloc_fn(root
, p1
, 20);
735 CHECK_BLOCKS(root
, 2);
736 CHECK_SIZE(root
, 20);
737 p1
= talloc_realloc_fn(root
, p1
, 0);
738 CHECK_BLOCKS(root
, 1);
748 static BOOL
test_unref_reparent(void)
750 void *root
, *p1
, *p2
, *c1
;
752 printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
754 root
= talloc_named_const(NULL
, 0, "root");
755 p1
= talloc_named_const(root
, 1, "orig parent");
756 p2
= talloc_named_const(root
, 1, "parent by reference");
758 c1
= talloc_named_const(p1
, 1, "child");
759 talloc_reference(p2
, c1
);
762 talloc_unlink(p2
, c1
);
773 measure the speed of talloc versus malloc
775 static BOOL
test_speed(void)
777 void *ctx
= talloc_new(NULL
);
781 printf("MEASURING TALLOC VS MALLOC SPEED\n");
783 tv
= timeval_current();
787 p1
= talloc_size(ctx
, count
);
788 p2
= talloc_strdup(p1
, "foo bar");
789 p3
= talloc_size(p1
, 300);
792 } while (timeval_elapsed(&tv
) < 5.0);
794 printf("talloc: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
798 tv
= timeval_current();
803 p2
= strdup("foo bar");
809 } while (timeval_elapsed(&tv
) < 5.0);
811 printf("malloc: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
817 BOOL
torture_local_talloc(void)
825 ret
&= test_unlink1();
827 ret
&= test_realloc();
828 ret
&= test_realloc_child();
830 ret
&= test_unref_reparent();
831 ret
&= test_realloc_fn();
842 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
845 if (!torture_local_talloc()) {
846 printf("ERROR: TESTSUIE FAILED\n");