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 double timeval_elapsed(struct timeval
*tv
)
45 struct timeval tv2
= timeval_current();
46 return (tv2
.tv_sec
- tv
->tv_sec
) +
47 (tv2
.tv_usec
- tv
->tv_usec
)*1.0e-6;
49 #endif /* _SAMBA_BUILD_ */
51 #if SAMBA_VERSION_MAJOR<4
60 #define CHECK_SIZE(ptr, tsize) do { \
61 if (talloc_total_size(ptr) != (tsize)) { \
62 printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
64 (unsigned)talloc_total_size(ptr), \
66 talloc_report_full(ptr, stdout); \
71 #define CHECK_BLOCKS(ptr, tblocks) do { \
72 if (talloc_total_blocks(ptr) != (tblocks)) { \
73 printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
75 (unsigned)talloc_total_blocks(ptr), \
77 talloc_report_full(ptr, stdout); \
86 static BOOL
test_ref1(void)
88 void *root
, *p1
, *p2
, *ref
, *r1
;
90 printf("TESTING SINGLE REFERENCE FREE\n");
92 root
= talloc_named_const(NULL
, 0, "root");
93 p1
= talloc_named_const(root
, 1, "p1");
94 p2
= talloc_named_const(p1
, 1, "p2");
95 talloc_named_const(p1
, 1, "x1");
96 talloc_named_const(p1
, 2, "x2");
97 talloc_named_const(p1
, 3, "x3");
99 r1
= talloc_named_const(root
, 1, "r1");
100 ref
= talloc_reference(r1
, p2
);
101 talloc_report_full(root
, stdout
);
107 printf("Freeing p2\n");
109 talloc_report_full(root
, stdout
);
115 printf("Freeing p1\n");
117 talloc_report_full(root
, stdout
);
121 printf("Freeing r1\n");
123 talloc_report_full(NULL
, stdout
);
125 printf("Testing NULL\n");
126 if (talloc_reference(root
, NULL
)) {
130 CHECK_BLOCKS(root
, 1);
142 static BOOL
test_ref2(void)
144 void *root
, *p1
, *p2
, *ref
, *r1
;
146 printf("TESTING DOUBLE REFERENCE FREE\n");
148 root
= talloc_named_const(NULL
, 0, "root");
149 p1
= talloc_named_const(root
, 1, "p1");
150 talloc_named_const(p1
, 1, "x1");
151 talloc_named_const(p1
, 1, "x2");
152 talloc_named_const(p1
, 1, "x3");
153 p2
= talloc_named_const(p1
, 1, "p2");
155 r1
= talloc_named_const(root
, 1, "r1");
156 ref
= talloc_reference(r1
, p2
);
157 talloc_report_full(root
, stdout
);
163 printf("Freeing ref\n");
165 talloc_report_full(root
, stdout
);
171 printf("Freeing p2\n");
173 talloc_report_full(root
, stdout
);
178 printf("Freeing p1\n");
180 talloc_report_full(root
, stdout
);
184 printf("Freeing r1\n");
186 talloc_report_full(root
, stdout
);
198 static BOOL
test_ref3(void)
200 void *root
, *p1
, *p2
, *ref
, *r1
;
202 printf("TESTING PARENT REFERENCE FREE\n");
204 root
= talloc_named_const(NULL
, 0, "root");
205 p1
= talloc_named_const(root
, 1, "p1");
206 p2
= talloc_named_const(root
, 1, "p2");
207 r1
= talloc_named_const(p1
, 1, "r1");
208 ref
= talloc_reference(p2
, r1
);
209 talloc_report_full(root
, stdout
);
215 printf("Freeing p1\n");
217 talloc_report_full(root
, stdout
);
222 printf("Freeing p2\n");
224 talloc_report_full(root
, stdout
);
236 static BOOL
test_ref4(void)
238 void *root
, *p1
, *p2
, *ref
, *r1
;
240 printf("TESTING REFERRER REFERENCE FREE\n");
242 root
= talloc_named_const(NULL
, 0, "root");
243 p1
= talloc_named_const(root
, 1, "p1");
244 talloc_named_const(p1
, 1, "x1");
245 talloc_named_const(p1
, 1, "x2");
246 talloc_named_const(p1
, 1, "x3");
247 p2
= talloc_named_const(p1
, 1, "p2");
249 r1
= talloc_named_const(root
, 1, "r1");
250 ref
= talloc_reference(r1
, p2
);
251 talloc_report_full(root
, stdout
);
257 printf("Freeing r1\n");
259 talloc_report_full(root
, stdout
);
264 printf("Freeing p2\n");
266 talloc_report_full(root
, stdout
);
270 printf("Freeing p1\n");
272 talloc_report_full(root
, stdout
);
285 static BOOL
test_unlink1(void)
287 void *root
, *p1
, *p2
, *ref
, *r1
;
289 printf("TESTING UNLINK\n");
291 root
= talloc_named_const(NULL
, 0, "root");
292 p1
= talloc_named_const(root
, 1, "p1");
293 talloc_named_const(p1
, 1, "x1");
294 talloc_named_const(p1
, 1, "x2");
295 talloc_named_const(p1
, 1, "x3");
296 p2
= talloc_named_const(p1
, 1, "p2");
298 r1
= talloc_named_const(p1
, 1, "r1");
299 ref
= talloc_reference(r1
, p2
);
300 talloc_report_full(root
, stdout
);
306 printf("Unreferencing r1\n");
307 talloc_unlink(r1
, p2
);
308 talloc_report_full(root
, stdout
);
314 printf("Freeing p1\n");
316 talloc_report_full(root
, stdout
);
325 static int fail_destructor(void *ptr
)
331 miscellaneous tests to try to get a higher test coverage percentage
333 static BOOL
test_misc(void)
339 printf("TESTING MISCELLANEOUS\n");
341 root
= talloc_new(NULL
);
343 p1
= talloc_size(root
, 0x7fffffff);
345 printf("failed: large talloc allowed\n");
349 p1
= talloc_strdup(root
, "foo");
350 talloc_increase_ref_count(p1
);
351 talloc_increase_ref_count(p1
);
352 talloc_increase_ref_count(p1
);
354 CHECK_BLOCKS(root
, 2);
357 CHECK_BLOCKS(root
, 2);
358 talloc_unlink(NULL
, p1
);
360 CHECK_BLOCKS(root
, 2);
361 p2
= talloc_strdup(p1
, "foo");
362 if (talloc_unlink(root
, p2
) != -1) {
363 printf("failed: talloc_unlink() of non-reference context should return -1\n");
366 if (talloc_unlink(p1
, p2
) != 0) {
367 printf("failed: talloc_unlink() of parent should succeed\n");
372 CHECK_BLOCKS(root
, 2);
374 talloc_set_name(p1
, "my name is %s", "foo");
375 if (strcmp(talloc_get_name(p1
), "my name is foo") != 0) {
376 printf("failed: wrong name after talloc_set_name\n");
380 CHECK_BLOCKS(root
, 3);
382 talloc_set_name_const(p1
, NULL
);
383 if (strcmp(talloc_get_name(p1
), "UNNAMED") != 0) {
384 printf("failed: wrong name after talloc_set_name(NULL)\n");
388 CHECK_BLOCKS(root
, 3);
391 if (talloc_free(NULL
) != -1) {
392 printf("talloc_free(NULL) should give -1\n");
396 talloc_set_destructor(p1
, fail_destructor
);
397 if (talloc_free(p1
) != -1) {
398 printf("Failed destructor should cause talloc_free to fail\n");
401 talloc_set_destructor(p1
, NULL
);
403 talloc_report(root
, stdout
);
406 p2
= talloc_zero_size(p1
, 20);
408 printf("Failed to give zero memory\n");
413 if (talloc_strdup(root
, NULL
) != NULL
) {
414 printf("failed: strdup on NULL should give NULL\n");
418 p2
= talloc_strndup(p1
, "foo", 2);
419 if (strcmp("fo", p2
) != 0) {
420 printf("failed: strndup doesn't work\n");
423 p2
= talloc_asprintf_append(p2
, "o%c", 'd');
424 if (strcmp("food", p2
) != 0) {
425 printf("failed: talloc_asprintf_append doesn't work\n");
431 p2
= talloc_asprintf_append(NULL
, "hello %s", "world");
432 if (strcmp("hello world", p2
) != 0) {
433 printf("failed: talloc_asprintf_append doesn't work\n");
440 d
= talloc_array(p1
, double, 0x20000000);
442 printf("failed: integer overflow not detected\n");
446 d
= talloc_realloc(p1
, d
, double, 0x20000000);
448 printf("failed: integer overflow not detected\n");
453 CHECK_BLOCKS(root
, 1);
455 p1
= talloc_named(root
, 100, "%d bytes", 100);
457 CHECK_BLOCKS(root
, 3);
458 talloc_unlink(root
, p1
);
460 p1
= talloc_init("%d bytes", 200);
461 p2
= talloc_asprintf(p1
, "my test '%s'", "string");
464 CHECK_BLOCKS(root
, 1);
465 talloc_unlink(NULL
, p1
);
467 p1
= talloc_named_const(root
, 10, "p1");
468 p2
= talloc_named_const(root
, 20, "p2");
469 talloc_reference(p1
, p2
);
470 talloc_report_full(root
, stdout
);
471 talloc_unlink(root
, p2
);
472 talloc_report_full(root
, stdout
);
475 CHECK_BLOCKS(root
, 3);
476 talloc_unlink(p1
, p2
);
477 talloc_unlink(root
, p1
);
479 p1
= talloc_named_const(root
, 10, "p1");
480 p2
= talloc_named_const(root
, 20, "p2");
481 talloc_reference(NULL
, p2
);
482 talloc_report_full(root
, stdout
);
483 talloc_unlink(root
, p2
);
484 talloc_report_full(root
, stdout
);
487 CHECK_BLOCKS(root
, 2);
488 talloc_unlink(NULL
, p2
);
489 talloc_unlink(root
, p1
);
491 /* Test that talloc_unlink is a no-op */
493 if (talloc_unlink(root
, NULL
) != -1) {
494 printf("failed: talloc_unlink(root, NULL) == -1\n");
498 talloc_report(root
, stdout
);
499 talloc_report(NULL
, stdout
);
507 talloc_enable_leak_report();
508 talloc_enable_leak_report_full();
517 static BOOL
test_realloc(void)
519 void *root
, *p1
, *p2
;
521 printf("TESTING REALLOC\n");
523 root
= talloc_new(NULL
);
525 p1
= talloc_size(root
, 10);
528 p1
= talloc_realloc_size(NULL
, p1
, 20);
533 p2
= talloc_realloc_size(p1
, NULL
, 30);
537 p2
= talloc_realloc_size(p1
, p2
, 40);
540 CHECK_SIZE(root
, 60);
543 p1
= talloc_realloc_size(NULL
, p1
, 20);
546 talloc_increase_ref_count(p2
);
547 if (talloc_realloc_size(NULL
, p2
, 5) != NULL
) {
548 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
553 talloc_realloc_size(NULL
, p2
, 0);
554 talloc_realloc_size(NULL
, p2
, 0);
557 if (talloc_realloc_size(NULL
, p1
, 0x7fffffff) != NULL
) {
558 printf("failed: oversize talloc should fail\n");
562 talloc_realloc_size(NULL
, p1
, 0);
564 CHECK_BLOCKS(root
, 1);
574 test realloc with a child
576 static BOOL
test_realloc_child(void)
583 } **list
, **list2
, **list3
;
587 printf("TESTING REALLOC WITH CHILD\n");
589 root
= talloc_new(NULL
);
591 el1
= talloc(root
, struct el1
);
592 el1
->list
= talloc(el1
, struct el2
*);
593 el1
->list
[0] = talloc(el1
->list
, struct el2
);
594 el1
->list
[0]->name
= talloc_strdup(el1
->list
[0], "testing");
596 el1
->list2
= talloc(el1
, struct el2
*);
597 el1
->list2
[0] = talloc(el1
->list2
, struct el2
);
598 el1
->list2
[0]->name
= talloc_strdup(el1
->list2
[0], "testing2");
600 el1
->list3
= talloc(el1
, struct el2
*);
601 el1
->list3
[0] = talloc(el1
->list3
, struct el2
);
602 el1
->list3
[0]->name
= talloc_strdup(el1
->list3
[0], "testing2");
604 el2
= talloc(el1
->list
, struct el2
);
605 el2
= talloc(el1
->list2
, struct el2
);
606 el2
= talloc(el1
->list3
, struct el2
);
608 el1
->list
= talloc_realloc(el1
, el1
->list
, struct el2
*, 100);
609 el1
->list2
= talloc_realloc(el1
, el1
->list2
, struct el2
*, 200);
610 el1
->list3
= talloc_realloc(el1
, el1
->list3
, struct el2
*, 300);
621 static BOOL
test_type(void)
632 printf("TESTING talloc type checking\n");
634 root
= talloc_new(NULL
);
636 el1
= talloc(root
, struct el1
);
640 if (talloc_get_type(el1
, struct el1
) != el1
) {
641 printf("type check failed on el1\n");
644 if (talloc_get_type(el1
, struct el2
) != NULL
) {
645 printf("type check failed on el1 with el2\n");
648 talloc_set_type(el1
, struct el2
);
649 if (talloc_get_type(el1
, struct el2
) != (struct el2
*)el1
) {
650 printf("type set failed on el1 with el2\n");
662 static BOOL
test_steal(void)
664 void *root
, *p1
, *p2
;
666 printf("TESTING STEAL\n");
668 root
= talloc_new(NULL
);
670 p1
= talloc_array(root
, char, 10);
673 p2
= talloc_realloc(root
, NULL
, char, 20);
675 CHECK_SIZE(root
, 30);
677 if (talloc_steal(p1
, NULL
) != NULL
) {
678 printf("failed: stealing NULL should give NULL\n");
682 if (talloc_steal(p1
, p1
) != p1
) {
683 printf("failed: stealing to ourselves is a nop\n");
686 CHECK_BLOCKS(root
, 3);
687 CHECK_SIZE(root
, 30);
689 talloc_steal(NULL
, p1
);
690 talloc_steal(NULL
, p2
);
691 CHECK_BLOCKS(root
, 1);
695 talloc_steal(root
, p2
);
696 CHECK_BLOCKS(root
, 2);
697 CHECK_SIZE(root
, 20);
701 CHECK_BLOCKS(root
, 1);
706 p1
= talloc_size(NULL
, 3);
714 test talloc_realloc_fn
716 static BOOL
test_realloc_fn(void)
720 printf("TESTING talloc_realloc_fn\n");
722 root
= talloc_new(NULL
);
724 p1
= talloc_realloc_fn(root
, NULL
, 10);
725 CHECK_BLOCKS(root
, 2);
726 CHECK_SIZE(root
, 10);
727 p1
= talloc_realloc_fn(root
, p1
, 20);
728 CHECK_BLOCKS(root
, 2);
729 CHECK_SIZE(root
, 20);
730 p1
= talloc_realloc_fn(root
, p1
, 0);
731 CHECK_BLOCKS(root
, 1);
741 static BOOL
test_unref_reparent(void)
743 void *root
, *p1
, *p2
, *c1
;
745 printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
747 root
= talloc_named_const(NULL
, 0, "root");
748 p1
= talloc_named_const(root
, 1, "orig parent");
749 p2
= talloc_named_const(root
, 1, "parent by reference");
751 c1
= talloc_named_const(p1
, 1, "child");
752 talloc_reference(p2
, c1
);
755 talloc_unlink(p2
, c1
);
766 measure the speed of talloc versus malloc
768 static BOOL
test_speed(void)
770 void *ctx
= talloc_new(NULL
);
774 printf("MEASURING TALLOC VS MALLOC SPEED\n");
776 tv
= timeval_current();
780 p1
= talloc_size(ctx
, count
);
781 p2
= talloc_strdup(p1
, "foo bar");
782 p3
= talloc_size(p1
, 300);
785 } while (timeval_elapsed(&tv
) < 5.0);
787 printf("talloc: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
791 tv
= timeval_current();
796 p2
= strdup("foo bar");
802 } while (timeval_elapsed(&tv
) < 5.0);
804 printf("malloc: %.0f ops/sec\n", count
/timeval_elapsed(&tv
));
810 BOOL
torture_local_talloc(void)
818 ret
&= test_unlink1();
820 ret
&= test_realloc();
821 ret
&= test_realloc_child();
823 ret
&= test_unref_reparent();
824 ret
&= test_realloc_fn();
835 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
838 if (!torture_local_talloc()) {
839 printf("ERROR: TESTSUIE FAILED\n");