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");
663
static BOOL test_steal(void)
665
void *root, *p1, *p2;
667
printf("TESTING STEAL\n");
669
root = talloc_new(NULL);
671
p1 = talloc_array(root, char, 10);
674
p2 = talloc_realloc(root, NULL, char, 20);
676
CHECK_SIZE(root, 30);
678
if (talloc_steal(p1, NULL) != NULL) {
679
printf("failed: stealing NULL should give NULL\n");
683
if (talloc_steal(p1, p1) != p1) {
684
printf("failed: stealing to ourselves is a nop\n");
687
CHECK_BLOCKS(root, 3);
688
CHECK_SIZE(root, 30);
690
talloc_steal(NULL, p1);
691
talloc_steal(NULL, p2);
692
CHECK_BLOCKS(root, 1);
696
talloc_steal(root, p2);
697
CHECK_BLOCKS(root, 2);
698
CHECK_SIZE(root, 20);
702
CHECK_BLOCKS(root, 1);
707
p1 = talloc_size(NULL, 3);
716
test talloc_realloc_fn
718
static BOOL test_realloc_fn(void)
722
printf("TESTING talloc_realloc_fn\n");
724
root = talloc_new(NULL);
726
p1 = talloc_realloc_fn(root, NULL, 10);
727
CHECK_BLOCKS(root, 2);
728
CHECK_SIZE(root, 10);
729
p1 = talloc_realloc_fn(root, p1, 20);
730
CHECK_BLOCKS(root, 2);
731
CHECK_SIZE(root, 20);
732
p1 = talloc_realloc_fn(root, p1, 0);
733
CHECK_BLOCKS(root, 1);
743
static BOOL test_unref_reparent(void)
745
void *root, *p1, *p2, *c1;
747
printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
749
root = talloc_named_const(NULL, 0, "root");
750
p1 = talloc_named_const(root, 1, "orig parent");
751
p2 = talloc_named_const(root, 1, "parent by reference");
753
c1 = talloc_named_const(p1, 1, "child");
754
talloc_reference(p2, c1);
757
talloc_unlink(p2, c1);
768
measure the speed of talloc versus malloc
770
static BOOL test_speed(void)
772
void *ctx = talloc_new(NULL);
776
printf("MEASURING TALLOC VS MALLOC SPEED\n");
778
tv = timeval_current();
782
p1 = talloc_size(ctx, count);
783
p2 = talloc_strdup(p1, "foo bar");
784
p3 = talloc_size(p1, 300);
787
} while (timeval_elapsed(&tv) < 5.0);
789
printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
793
tv = timeval_current();
798
p2 = strdup("foo bar");
804
} while (timeval_elapsed(&tv) < 5.0);
806
printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
812
BOOL torture_local_talloc(void)
820
ret &= test_unlink1();
822
ret &= test_realloc();
823
ret &= test_realloc_child();
824
/* ret &= test_steal(); */
825
ret &= test_unref_reparent();
826
ret &= test_realloc_fn();
837
#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
840
if (!torture_local_talloc()) {
841
printf("ERROR: TESTSUIE FAILED\n");