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;
39 static struct timeval timeval_current(void)
42 gettimeofday(&tv, NULL);
46 static double timeval_elapsed(struct timeval *tv)
48 struct timeval tv2 = timeval_current();
49 return (tv2.tv_sec - tv->tv_sec) +
50 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
52 #endif /* _SAMBA_BUILD_ */
55 #define CHECK_SIZE(ptr, tsize) do { \
56 if (talloc_total_size(ptr) != (tsize)) { \
57 printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
59 (unsigned)talloc_total_size(ptr), \
61 talloc_report_full(ptr, stdout); \
66 #define CHECK_BLOCKS(ptr, tblocks) do { \
67 if (talloc_total_blocks(ptr) != (tblocks)) { \
68 printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
70 (unsigned)talloc_total_blocks(ptr), \
72 talloc_report_full(ptr, stdout); \
81 static BOOL test_ref1(void)
83 void *root, *p1, *p2, *ref, *r1;
85 printf("TESTING SINGLE REFERENCE FREE\n");
87 root = talloc_named_const(NULL, 0, "root");
88 p1 = talloc_named_const(root, 1, "p1");
89 p2 = talloc_named_const(p1, 1, "p2");
90 talloc_named_const(p1, 1, "x1");
91 talloc_named_const(p1, 2, "x2");
92 talloc_named_const(p1, 3, "x3");
94 r1 = talloc_named_const(root, 1, "r1");
95 ref = talloc_reference(r1, p2);
96 talloc_report_full(root, stdout);
102 printf("Freeing p2\n");
104 talloc_report_full(root, stdout);
110 printf("Freeing p1\n");
112 talloc_report_full(root, stdout);
116 printf("Freeing r1\n");
118 talloc_report_full(NULL, stdout);
120 printf("Testing NULL\n");
121 if (talloc_reference(root, NULL)) {
125 CHECK_BLOCKS(root, 1);
137 static BOOL test_ref2(void)
139 void *root, *p1, *p2, *ref, *r1;
141 printf("TESTING DOUBLE REFERENCE FREE\n");
143 root = talloc_named_const(NULL, 0, "root");
144 p1 = talloc_named_const(root, 1, "p1");
145 talloc_named_const(p1, 1, "x1");
146 talloc_named_const(p1, 1, "x2");
147 talloc_named_const(p1, 1, "x3");
148 p2 = talloc_named_const(p1, 1, "p2");
150 r1 = talloc_named_const(root, 1, "r1");
151 ref = talloc_reference(r1, p2);
152 talloc_report_full(root, stdout);
158 printf("Freeing ref\n");
160 talloc_report_full(root, stdout);
166 printf("Freeing p2\n");
168 talloc_report_full(root, stdout);
173 printf("Freeing p1\n");
175 talloc_report_full(root, stdout);
179 printf("Freeing r1\n");
181 talloc_report_full(root, stdout);
193 static BOOL test_ref3(void)
195 void *root, *p1, *p2, *ref, *r1;
197 printf("TESTING PARENT REFERENCE FREE\n");
199 root = talloc_named_const(NULL, 0, "root");
200 p1 = talloc_named_const(root, 1, "p1");
201 p2 = talloc_named_const(root, 1, "p2");
202 r1 = talloc_named_const(p1, 1, "r1");
203 ref = talloc_reference(p2, r1);
204 talloc_report_full(root, stdout);
210 printf("Freeing p1\n");
212 talloc_report_full(root, stdout);
217 printf("Freeing p2\n");
219 talloc_report_full(root, stdout);
231 static BOOL test_ref4(void)
233 void *root, *p1, *p2, *ref, *r1;
235 printf("TESTING REFERRER REFERENCE FREE\n");
237 root = talloc_named_const(NULL, 0, "root");
238 p1 = talloc_named_const(root, 1, "p1");
239 talloc_named_const(p1, 1, "x1");
240 talloc_named_const(p1, 1, "x2");
241 talloc_named_const(p1, 1, "x3");
242 p2 = talloc_named_const(p1, 1, "p2");
244 r1 = talloc_named_const(root, 1, "r1");
245 ref = talloc_reference(r1, p2);
246 talloc_report_full(root, stdout);
252 printf("Freeing r1\n");
254 talloc_report_full(root, stdout);
259 printf("Freeing p2\n");
261 talloc_report_full(root, stdout);
265 printf("Freeing p1\n");
267 talloc_report_full(root, stdout);
280 static BOOL test_unlink1(void)
282 void *root, *p1, *p2, *ref, *r1;
284 printf("TESTING UNLINK\n");
286 root = talloc_named_const(NULL, 0, "root");
287 p1 = talloc_named_const(root, 1, "p1");
288 talloc_named_const(p1, 1, "x1");
289 talloc_named_const(p1, 1, "x2");
290 talloc_named_const(p1, 1, "x3");
291 p2 = talloc_named_const(p1, 1, "p2");
293 r1 = talloc_named_const(p1, 1, "r1");
294 ref = talloc_reference(r1, p2);
295 talloc_report_full(root, stdout);
301 printf("Unreferencing r1\n");
302 talloc_unlink(r1, p2);
303 talloc_report_full(root, stdout);
309 printf("Freeing p1\n");
311 talloc_report_full(root, stdout);
320 static int fail_destructor(void *ptr)
326 miscellaneous tests to try to get a higher test coverage percentage
328 static BOOL test_misc(void)
334 printf("TESTING MISCELLANEOUS\n");
336 root = talloc_new(NULL);
338 p1 = talloc_size(root, 0x7fffffff);
340 printf("failed: large talloc allowed\n");
344 p1 = talloc_strdup(root, "foo");
345 talloc_increase_ref_count(p1);
346 talloc_increase_ref_count(p1);
347 talloc_increase_ref_count(p1);
349 CHECK_BLOCKS(root, 2);
352 CHECK_BLOCKS(root, 2);
353 talloc_unlink(NULL, p1);
355 CHECK_BLOCKS(root, 2);
356 p2 = talloc_strdup(p1, "foo");
357 if (talloc_unlink(root, p2) != -1) {
358 printf("failed: talloc_unlink() of non-reference context should return -1\n");
361 if (talloc_unlink(p1, p2) != 0) {
362 printf("failed: talloc_unlink() of parent should succeed\n");
367 CHECK_BLOCKS(root, 2);
369 talloc_set_name(p1, "my name is %s", "foo");
370 if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
371 printf("failed: wrong name after talloc_set_name\n");
375 CHECK_BLOCKS(root, 3);
377 talloc_set_name_const(p1, NULL);
378 if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
379 printf("failed: wrong name after talloc_set_name(NULL)\n");
383 CHECK_BLOCKS(root, 3);
386 if (talloc_free(NULL) != -1) {
387 printf("talloc_free(NULL) should give -1\n");
391 talloc_set_destructor(p1, fail_destructor);
392 if (talloc_free(p1) != -1) {
393 printf("Failed destructor should cause talloc_free to fail\n");
396 talloc_set_destructor(p1, NULL);
398 talloc_report(root, stdout);
401 p2 = talloc_zero(p1, 20);
403 printf("Failed to give zero memory\n");
408 if (talloc_strdup(root, NULL) != NULL) {
409 printf("failed: strdup on NULL should give NULL\n");
413 p2 = talloc_strndup(p1, "foo", 2);
414 if (strcmp("fo", p2) != 0) {
415 printf("failed: strndup doesn't work\n");
418 p2 = talloc_asprintf_append(p2, "o%c", 'd');
419 if (strcmp("food", p2) != 0) {
420 printf("failed: talloc_asprintf_append doesn't work\n");
426 p2 = talloc_asprintf_append(NULL, "hello %s", "world");
427 if (strcmp("hello world", p2) != 0) {
428 printf("failed: talloc_asprintf_append doesn't work\n");
435 d = talloc_array_p(p1, double, 0x20000000);
437 printf("failed: integer overflow not detected\n");
441 d = talloc_realloc_p(p1, d, double, 0x20000000);
443 printf("failed: integer overflow not detected\n");
448 CHECK_BLOCKS(root, 1);
450 p1 = talloc_named(root, 100, "%d bytes", 100);
452 CHECK_BLOCKS(root, 3);
453 talloc_unlink(root, p1);
455 p1 = talloc_init("%d bytes", 200);
456 p2 = talloc_asprintf(p1, "my test '%s'", "string");
459 CHECK_BLOCKS(root, 1);
460 talloc_unlink(NULL, p1);
462 p1 = talloc_named_const(root, 10, "p1");
463 p2 = talloc_named_const(root, 20, "p2");
464 talloc_reference(p1, p2);
465 talloc_report_full(root, stdout);
466 talloc_unlink(root, p2);
467 talloc_report_full(root, stdout);
470 CHECK_BLOCKS(root, 3);
471 talloc_unlink(p1, p2);
472 talloc_unlink(root, p1);
474 p1 = talloc_named_const(root, 10, "p1");
475 p2 = talloc_named_const(root, 20, "p2");
476 talloc_reference(NULL, p2);
477 talloc_report_full(root, stdout);
478 talloc_unlink(root, p2);
479 talloc_report_full(root, stdout);
482 CHECK_BLOCKS(root, 2);
483 talloc_unlink(NULL, p2);
484 talloc_unlink(root, p1);
486 /* Test that talloc_unlink is a no-op */
488 if (talloc_unlink(root, NULL) != -1) {
489 printf("failed: talloc_unlink(root, NULL) == -1\n");
493 talloc_report(root, stdout);
494 talloc_report(NULL, stdout);
502 talloc_enable_leak_report();
503 talloc_enable_leak_report_full();
512 static BOOL test_realloc(void)
514 void *root, *p1, *p2;
516 printf("TESTING REALLOC\n");
518 root = talloc_new(NULL);
520 p1 = talloc_size(root, 10);
523 p1 = talloc_realloc(NULL, p1, 20);
528 p2 = talloc_realloc(p1, NULL, 30);
532 p2 = talloc_realloc(p1, p2, 40);
535 CHECK_SIZE(root, 60);
538 p1 = talloc_realloc(NULL, p1, 20);
541 talloc_increase_ref_count(p2);
542 if (talloc_realloc(NULL, p2, 5) != NULL) {
543 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
548 talloc_realloc(NULL, p2, 0);
549 talloc_realloc(NULL, p2, 0);
552 if (talloc_realloc(NULL, p1, 0x7fffffff) != NULL) {
553 printf("failed: oversize talloc should fail\n");
557 talloc_realloc(NULL, p1, 0);
559 CHECK_BLOCKS(root, 1);
569 test realloc with a child
571 static BOOL test_realloc_child(void)
582 printf("TESTING REALLOC WITH CHILD\n");
584 root = talloc_new(NULL);
586 el1 = talloc_p(root, struct el1);
587 el1->list = talloc_p(el1, struct el2 *);
588 el1->list[0] = talloc_p(el1->list, struct el2);
589 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
591 el2 = talloc_p(el1->list, struct el2);
593 el1->list = talloc_realloc_p(el1, el1->list, struct el2 *, 2);
604 static BOOL test_steal(void)
606 void *root, *p1, *p2;
608 printf("TESTING STEAL\n");
610 root = talloc_new(NULL);
612 p1 = talloc_array_p(root, char, 10);
615 p2 = talloc_realloc_p(root, NULL, char, 20);
617 CHECK_SIZE(root, 30);
619 if (talloc_steal(p1, NULL) != NULL) {
620 printf("failed: stealing NULL should give NULL\n");
624 if (talloc_steal(p1, p1) != p1) {
625 printf("failed: stealing to ourselves is a nop\n");
628 CHECK_BLOCKS(root, 3);
629 CHECK_SIZE(root, 30);
631 talloc_steal(NULL, p1);
632 talloc_steal(NULL, p2);
633 CHECK_BLOCKS(root, 1);
637 talloc_steal(root, p2);
638 CHECK_BLOCKS(root, 2);
639 CHECK_SIZE(root, 20);
643 CHECK_BLOCKS(root, 1);
648 p1 = talloc_new(NULL);
658 static BOOL test_ldb(void)
662 printf("TESTING LDB\n");
664 root = talloc_new(NULL);
666 p1 = talloc_realloc_fn(root, NULL, 10);
667 CHECK_BLOCKS(root, 2);
668 CHECK_SIZE(root, 10);
669 p1 = talloc_realloc_fn(root, p1, 20);
670 CHECK_BLOCKS(root, 2);
671 CHECK_SIZE(root, 20);
672 p1 = talloc_realloc_fn(root, p1, 0);
673 CHECK_BLOCKS(root, 1);
683 static BOOL test_unref_reparent(void)
685 void *root, *p1, *p2, *c1;
687 printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
689 root = talloc_named_const(NULL, 0, "root");
690 p1 = talloc_named_const(root, 1, "orig parent");
691 p2 = talloc_named_const(root, 1, "parent by reference");
693 c1 = talloc_named_const(p1, 1, "child");
694 talloc_reference(p2, c1);
697 talloc_unlink(p2, c1);
708 measure the speed of talloc versus malloc
710 static BOOL test_speed(void)
712 void *ctx = talloc_new(NULL);
716 printf("MEASURING TALLOC VS MALLOC SPEED\n");
718 tv = timeval_current();
722 p1 = talloc_size(ctx, count);
723 p2 = talloc_strdup(p1, "foo bar");
724 p3 = talloc_size(p1, 300);
727 } while (timeval_elapsed(&tv) < 5.0);
729 printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
733 tv = timeval_current();
738 p2 = strdup("foo bar");
744 } while (timeval_elapsed(&tv) < 5.0);
746 printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
752 BOOL torture_local_talloc(void)
760 ret &= test_unlink1();
762 ret &= test_realloc();
763 ret &= test_realloc_child();
765 ret &= test_unref_reparent();
776 #ifndef _SAMBA_BUILD_
779 if (!torture_local_talloc()) {
780 printf("ERROR: TESTSUIE FAILED\n");