45d73bd1c0a4b945c0273f798f1bc360c046a891
[samba.git] / source / lib / talloc / testsuite.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of talloc routines.
5
6    Copyright (C) Andrew Tridgell 2004
7    
8      ** NOTE! The following LGPL license applies to the talloc
9      ** library. This does NOT imply that all of Samba is released
10      ** under the LGPL
11    
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 2 of the License, or (at your option) any later version.
16
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Lesser General Public License for more details.
21
22    You should have received a copy of the GNU Lesser General Public
23    License along with this library; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25 */
26
27 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifdef HAVE_STDARG_H
33 #include <stdarg.h>
34 #endif
35
36 #include <sys/time.h>
37 #include <time.h>
38
39 #include "talloc.h"
40
41 #ifndef False
42 #define False 0
43 #endif
44 #ifndef True
45 #define True 1
46 #endif
47 #ifndef BOOL
48 #define BOOL int
49 #endif
50
51 struct torture_context;
52
53 static struct timeval timeval_current(void)
54 {
55         struct timeval tv;
56         gettimeofday(&tv, NULL);
57         return tv;
58 }
59
60 static double timeval_elapsed(struct timeval *tv)
61 {
62         struct timeval tv2 = timeval_current();
63         return (tv2.tv_sec - tv->tv_sec) + 
64                (tv2.tv_usec - tv->tv_usec)*1.0e-6;
65 }
66
67 #if SAMBA_VERSION_MAJOR<4
68 #ifdef malloc
69 #undef malloc
70 #endif
71 #ifdef strdup
72 #undef strdup
73 #endif
74 #endif
75
76 #define CHECK_SIZE(ptr, tsize) do { \
77         if (talloc_total_size(ptr) != (tsize)) { \
78                 printf(__location__ " failed: wrong '%s' tree size: got %u  expected %u\n", \
79                        #ptr, \
80                        (unsigned)talloc_total_size(ptr), \
81                        (unsigned)tsize); \
82                 talloc_report_full(ptr, stdout); \
83                 return False; \
84         } \
85 } while (0)
86
87 #define CHECK_BLOCKS(ptr, tblocks) do { \
88         if (talloc_total_blocks(ptr) != (tblocks)) { \
89                 printf(__location__ " failed: wrong '%s' tree blocks: got %u  expected %u\n", \
90                        #ptr, \
91                        (unsigned)talloc_total_blocks(ptr), \
92                        (unsigned)tblocks); \
93                 talloc_report_full(ptr, stdout); \
94                 return False; \
95         } \
96 } while (0)
97
98 #define CHECK_PARENT(ptr, parent) do { \
99         if (talloc_parent(ptr) != (parent)) { \
100                 printf(__location__ " failed: '%s' has wrong parent: got %p  expected %p\n", \
101                        #ptr, \
102                        talloc_parent(ptr), \
103                        (parent)); \
104                 talloc_report_full(ptr, stdout); \
105                 talloc_report_full(parent, stdout); \
106                 talloc_report_full(NULL, stdout); \
107                 return False; \
108         } \
109 } while (0)
110
111
112 /*
113   test references 
114 */
115 static BOOL test_ref1(void)
116 {
117         void *root, *p1, *p2, *ref, *r1;
118
119         printf("TESTING SINGLE REFERENCE FREE\n");
120
121         root = talloc_named_const(NULL, 0, "root");
122         p1 = talloc_named_const(root, 1, "p1");
123         p2 = talloc_named_const(p1, 1, "p2");
124         talloc_named_const(p1, 1, "x1");
125         talloc_named_const(p1, 2, "x2");
126         talloc_named_const(p1, 3, "x3");
127
128         r1 = talloc_named_const(root, 1, "r1"); 
129         ref = talloc_reference(r1, p2);
130         talloc_report_full(root, stdout);
131
132         CHECK_BLOCKS(p1, 5);
133         CHECK_BLOCKS(p2, 1);
134         CHECK_BLOCKS(r1, 2);
135
136         printf("Freeing p2\n");
137         talloc_free(p2);
138         talloc_report_full(root, stdout);
139
140         CHECK_BLOCKS(p1, 5);
141         CHECK_BLOCKS(p2, 1);
142         CHECK_BLOCKS(r1, 1);
143
144         printf("Freeing p1\n");
145         talloc_free(p1);
146         talloc_report_full(root, stdout);
147
148         CHECK_BLOCKS(r1, 1);
149
150         printf("Freeing r1\n");
151         talloc_free(r1);
152         talloc_report_full(NULL, stdout);
153
154         printf("Testing NULL\n");
155         if (talloc_reference(root, NULL)) {
156                 return False;
157         }
158
159         CHECK_BLOCKS(root, 1);
160
161         CHECK_SIZE(root, 0);
162
163         talloc_free(root);
164
165         return True;
166 }
167
168 /*
169   test references 
170 */
171 static BOOL test_ref2(void)
172 {
173         void *root, *p1, *p2, *ref, *r1;
174
175         printf("TESTING DOUBLE REFERENCE FREE\n");
176
177         root = talloc_named_const(NULL, 0, "root");
178         p1 = talloc_named_const(root, 1, "p1");
179         talloc_named_const(p1, 1, "x1");
180         talloc_named_const(p1, 1, "x2");
181         talloc_named_const(p1, 1, "x3");
182         p2 = talloc_named_const(p1, 1, "p2");
183
184         r1 = talloc_named_const(root, 1, "r1"); 
185         ref = talloc_reference(r1, p2);
186         talloc_report_full(root, stdout);
187
188         CHECK_BLOCKS(p1, 5);
189         CHECK_BLOCKS(p2, 1);
190         CHECK_BLOCKS(r1, 2);
191
192         printf("Freeing ref\n");
193         talloc_free(ref);
194         talloc_report_full(root, stdout);
195
196         CHECK_BLOCKS(p1, 5);
197         CHECK_BLOCKS(p2, 1);
198         CHECK_BLOCKS(r1, 1);
199
200         printf("Freeing p2\n");
201         talloc_free(p2);
202         talloc_report_full(root, stdout);
203
204         CHECK_BLOCKS(p1, 4);
205         CHECK_BLOCKS(r1, 1);
206
207         printf("Freeing p1\n");
208         talloc_free(p1);
209         talloc_report_full(root, stdout);
210
211         CHECK_BLOCKS(r1, 1);
212
213         printf("Freeing r1\n");
214         talloc_free(r1);
215         talloc_report_full(root, stdout);
216
217         CHECK_SIZE(root, 0);
218
219         talloc_free(root);
220
221         return True;
222 }
223
224 /*
225   test references 
226 */
227 static BOOL test_ref3(void)
228 {
229         void *root, *p1, *p2, *ref, *r1;
230
231         printf("TESTING PARENT REFERENCE FREE\n");
232
233         root = talloc_named_const(NULL, 0, "root");
234         p1 = talloc_named_const(root, 1, "p1");
235         p2 = talloc_named_const(root, 1, "p2");
236         r1 = talloc_named_const(p1, 1, "r1");
237         ref = talloc_reference(p2, r1);
238         talloc_report_full(root, stdout);
239
240         CHECK_BLOCKS(p1, 2);
241         CHECK_BLOCKS(p2, 2);
242         CHECK_BLOCKS(r1, 1);
243
244         printf("Freeing p1\n");
245         talloc_free(p1);
246         talloc_report_full(root, stdout);
247
248         CHECK_BLOCKS(p2, 2);
249         CHECK_BLOCKS(r1, 1);
250
251         printf("Freeing p2\n");
252         talloc_free(p2);
253         talloc_report_full(root, stdout);
254
255         CHECK_SIZE(root, 0);
256
257         talloc_free(root);
258
259         return True;
260 }
261
262 /*
263   test references 
264 */
265 static BOOL test_ref4(void)
266 {
267         void *root, *p1, *p2, *ref, *r1;
268
269         printf("TESTING REFERRER REFERENCE FREE\n");
270
271         root = talloc_named_const(NULL, 0, "root");
272         p1 = talloc_named_const(root, 1, "p1");
273         talloc_named_const(p1, 1, "x1");
274         talloc_named_const(p1, 1, "x2");
275         talloc_named_const(p1, 1, "x3");
276         p2 = talloc_named_const(p1, 1, "p2");
277
278         r1 = talloc_named_const(root, 1, "r1"); 
279         ref = talloc_reference(r1, p2);
280         talloc_report_full(root, stdout);
281
282         CHECK_BLOCKS(p1, 5);
283         CHECK_BLOCKS(p2, 1);
284         CHECK_BLOCKS(r1, 2);
285
286         printf("Freeing r1\n");
287         talloc_free(r1);
288         talloc_report_full(root, stdout);
289
290         CHECK_BLOCKS(p1, 5);
291         CHECK_BLOCKS(p2, 1);
292
293         printf("Freeing p2\n");
294         talloc_free(p2);
295         talloc_report_full(root, stdout);
296
297         CHECK_BLOCKS(p1, 4);
298
299         printf("Freeing p1\n");
300         talloc_free(p1);
301         talloc_report_full(root, stdout);
302
303         CHECK_SIZE(root, 0);
304
305         talloc_free(root);
306
307         return True;
308 }
309
310
311 /*
312   test references 
313 */
314 static BOOL test_unlink1(void)
315 {
316         void *root, *p1, *p2, *ref, *r1;
317
318         printf("TESTING UNLINK\n");
319
320         root = talloc_named_const(NULL, 0, "root");
321         p1 = talloc_named_const(root, 1, "p1");
322         talloc_named_const(p1, 1, "x1");
323         talloc_named_const(p1, 1, "x2");
324         talloc_named_const(p1, 1, "x3");
325         p2 = talloc_named_const(p1, 1, "p2");
326
327         r1 = talloc_named_const(p1, 1, "r1");   
328         ref = talloc_reference(r1, p2);
329         talloc_report_full(root, stdout);
330
331         CHECK_BLOCKS(p1, 7);
332         CHECK_BLOCKS(p2, 1);
333         CHECK_BLOCKS(r1, 2);
334
335         printf("Unreferencing r1\n");
336         talloc_unlink(r1, p2);
337         talloc_report_full(root, stdout);
338
339         CHECK_BLOCKS(p1, 6);
340         CHECK_BLOCKS(p2, 1);
341         CHECK_BLOCKS(r1, 1);
342
343         printf("Freeing p1\n");
344         talloc_free(p1);
345         talloc_report_full(root, stdout);
346
347         CHECK_SIZE(root, 0);
348
349         talloc_free(root);
350
351         return True;
352 }
353
354 static int fail_destructor(void *ptr)
355 {
356         return -1;
357 }
358
359 /*
360   miscellaneous tests to try to get a higher test coverage percentage
361 */
362 static BOOL test_misc(void)
363 {
364         void *root, *p1;
365         char *p2;
366         double *d;
367         const char *name;
368
369         printf("TESTING MISCELLANEOUS\n");
370
371         root = talloc_new(NULL);
372
373         p1 = talloc_size(root, 0x7fffffff);
374         if (p1) {
375                 printf("failed: large talloc allowed\n");
376                 return False;
377         }
378
379         p1 = talloc_strdup(root, "foo");
380         talloc_increase_ref_count(p1);
381         talloc_increase_ref_count(p1);
382         talloc_increase_ref_count(p1);
383         CHECK_BLOCKS(p1, 1);
384         CHECK_BLOCKS(root, 2);
385         talloc_free(p1);
386         CHECK_BLOCKS(p1, 1);
387         CHECK_BLOCKS(root, 2);
388         talloc_unlink(NULL, p1);
389         CHECK_BLOCKS(p1, 1);
390         CHECK_BLOCKS(root, 2);
391         p2 = talloc_strdup(p1, "foo");
392         if (talloc_unlink(root, p2) != -1) {
393                 printf("failed: talloc_unlink() of non-reference context should return -1\n");
394                 return False;
395         }
396         if (talloc_unlink(p1, p2) != 0) {
397                 printf("failed: talloc_unlink() of parent should succeed\n");
398                 return False;
399         }
400         talloc_free(p1);
401         CHECK_BLOCKS(p1, 1);
402         CHECK_BLOCKS(root, 2);
403
404         name = talloc_set_name(p1, "my name is %s", "foo");
405         if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
406                 printf("failed: wrong name after talloc_set_name(my name is foo) - '%s'=>'%s'\n",
407                         (name?name:"NULL"), talloc_get_name(p1));
408                 return False;
409         }
410         CHECK_BLOCKS(p1, 2);
411         CHECK_BLOCKS(root, 3);
412
413         talloc_set_name_const(p1, NULL);
414         if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
415                 printf("failed: wrong name after talloc_set_name(NULL) - '%s'\n",
416                         talloc_get_name(p1));
417                 return False;
418         }
419         CHECK_BLOCKS(p1, 2);
420         CHECK_BLOCKS(root, 3);
421         
422
423         if (talloc_free(NULL) != -1) {
424                 printf("talloc_free(NULL) should give -1\n");
425                 return False;
426         }
427
428         talloc_set_destructor(p1, fail_destructor);
429         if (talloc_free(p1) != -1) {
430                 printf("Failed destructor should cause talloc_free to fail\n");
431                 return False;
432         }
433         talloc_set_destructor(p1, NULL);
434
435         talloc_report(root, stdout);
436
437
438         p2 = talloc_zero_size(p1, 20);
439         if (p2[19] != 0) {
440                 printf("Failed to give zero memory\n");
441                 return False;
442         }
443         talloc_free(p2);
444
445         if (talloc_strdup(root, NULL) != NULL) {
446                 printf("failed: strdup on NULL should give NULL\n");
447                 return False;
448         }
449
450         p2 = talloc_strndup(p1, "foo", 2);
451         if (strcmp("fo", p2) != 0) {
452                 printf("failed: strndup doesn't work\n");
453                 return False;
454         }
455         p2 = talloc_asprintf_append(p2, "o%c", 'd');
456         if (strcmp("food", p2) != 0) {
457                 printf("failed: talloc_asprintf_append doesn't work\n");
458                 return False;
459         }
460         CHECK_BLOCKS(p2, 1);
461         CHECK_BLOCKS(p1, 3);
462
463         p2 = talloc_asprintf_append(NULL, "hello %s", "world");
464         if (strcmp("hello world", p2) != 0) {
465                 printf("failed: talloc_asprintf_append doesn't work\n");
466                 return False;
467         }
468         CHECK_BLOCKS(p2, 1);
469         CHECK_BLOCKS(p1, 3);
470         talloc_free(p2);
471
472         d = talloc_array(p1, double, 0x20000000);
473         if (d) {
474                 printf("failed: integer overflow not detected\n");
475                 return False;
476         }
477
478         d = talloc_realloc(p1, d, double, 0x20000000);
479         if (d) {
480                 printf("failed: integer overflow not detected\n");
481                 return False;
482         }
483
484         talloc_free(p1);
485         CHECK_BLOCKS(root, 1);
486
487         p1 = talloc_named(root, 100, "%d bytes", 100);
488         CHECK_BLOCKS(p1, 2);
489         CHECK_BLOCKS(root, 3);
490         talloc_unlink(root, p1);
491
492         p1 = talloc_init("%d bytes", 200);
493         p2 = talloc_asprintf(p1, "my test '%s'", "string");
494         if (strcmp(p2, "my test 'string'") != 0) {
495                 printf("failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"\n", p2);
496                 return False;
497         }
498         CHECK_BLOCKS(p1, 3);
499         CHECK_SIZE(p2, 17);
500         CHECK_BLOCKS(root, 1);
501         talloc_unlink(NULL, p1);
502
503         p1 = talloc_named_const(root, 10, "p1");
504         p2 = talloc_named_const(root, 20, "p2");
505         talloc_reference(p1, p2);
506         talloc_report_full(root, stdout);
507         talloc_unlink(root, p2);
508         talloc_report_full(root, stdout);
509         CHECK_BLOCKS(p2, 1);
510         CHECK_BLOCKS(p1, 2);
511         CHECK_BLOCKS(root, 3);
512         talloc_unlink(p1, p2);
513         talloc_unlink(root, p1);
514
515         p1 = talloc_named_const(root, 10, "p1");
516         p2 = talloc_named_const(root, 20, "p2");
517         talloc_reference(NULL, p2);
518         talloc_report_full(root, stdout);
519         talloc_unlink(root, p2);
520         talloc_report_full(root, stdout);
521         CHECK_BLOCKS(p2, 1);
522         CHECK_BLOCKS(p1, 1);
523         CHECK_BLOCKS(root, 2);
524         talloc_unlink(NULL, p2);
525         talloc_unlink(root, p1);
526
527         /* Test that talloc_unlink is a no-op */
528
529         if (talloc_unlink(root, NULL) != -1) {
530                 printf("failed: talloc_unlink(root, NULL) == -1\n");
531                 return False;
532         }
533
534         talloc_report(root, stdout);
535         talloc_report(NULL, stdout);
536
537         CHECK_SIZE(root, 0);
538
539         talloc_free(root);
540
541         CHECK_SIZE(NULL, 0);
542
543         talloc_enable_leak_report();
544         talloc_enable_leak_report_full();
545
546         return True;
547 }
548
549
550 /*
551   test realloc
552 */
553 static BOOL test_realloc(void)
554 {
555         void *root, *p1, *p2;
556
557         printf("TESTING REALLOC\n");
558
559         root = talloc_new(NULL);
560
561         p1 = talloc_size(root, 10);
562         CHECK_SIZE(p1, 10);
563
564         p1 = talloc_realloc_size(NULL, p1, 20);
565         CHECK_SIZE(p1, 20);
566
567         talloc_new(p1);
568
569         p2 = talloc_realloc_size(p1, NULL, 30);
570
571         talloc_new(p1);
572
573         p2 = talloc_realloc_size(p1, p2, 40);
574
575         CHECK_SIZE(p2, 40);
576         CHECK_SIZE(root, 60);
577         CHECK_BLOCKS(p1, 4);
578
579         p1 = talloc_realloc_size(NULL, p1, 20);
580         CHECK_SIZE(p1, 60);
581
582         talloc_increase_ref_count(p2);
583         if (talloc_realloc_size(NULL, p2, 5) != NULL) {
584                 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
585                 return False;
586         }
587         CHECK_BLOCKS(p1, 4);
588
589         talloc_realloc_size(NULL, p2, 0);
590         talloc_realloc_size(NULL, p2, 0);
591         CHECK_BLOCKS(p1, 3);
592
593         if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) {
594                 printf("failed: oversize talloc should fail\n");
595                 return False;
596         }
597
598         talloc_realloc_size(NULL, p1, 0);
599
600         CHECK_BLOCKS(root, 1);
601         CHECK_SIZE(root, 0);
602
603         talloc_free(root);
604
605         return True;
606 }
607
608
609 /*
610   test realloc with a child
611 */
612 static BOOL test_realloc_child(void)
613 {
614         void *root;
615         struct el1 {
616                 int count;
617                 struct el2 {
618                         const char *name;
619                 } **list, **list2, **list3;
620         } *el1;
621         struct el2 *el2;
622
623         printf("TESTING REALLOC WITH CHILD\n");
624
625         root = talloc_new(NULL);
626
627         el1 = talloc(root, struct el1);
628         el1->list = talloc(el1, struct el2 *);
629         el1->list[0] = talloc(el1->list, struct el2);
630         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
631
632         el1->list2 = talloc(el1, struct el2 *);
633         el1->list2[0] = talloc(el1->list2, struct el2);
634         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
635
636         el1->list3 = talloc(el1, struct el2 *);
637         el1->list3[0] = talloc(el1->list3, struct el2);
638         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
639         
640         el2 = talloc(el1->list, struct el2);
641         el2 = talloc(el1->list2, struct el2);
642         el2 = talloc(el1->list3, struct el2);
643
644         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
645         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
646         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
647
648         talloc_free(root);
649
650         return True;
651 }
652
653
654 /*
655   test type checking
656 */
657 static BOOL test_type(void)
658 {
659         void *root;
660         struct el1 {
661                 int count;
662         };
663         struct el2 {
664                 int count;
665         };
666         struct el1 *el1;
667
668         printf("TESTING talloc type checking\n");
669
670         root = talloc_new(NULL);
671
672         el1 = talloc(root, struct el1);
673
674         el1->count = 1;
675
676         if (talloc_get_type(el1, struct el1) != el1) {
677                 printf("type check failed on el1\n");
678                 return False;
679         }
680         if (talloc_get_type(el1, struct el2) != NULL) {
681                 printf("type check failed on el1 with el2\n");
682                 return False;
683         }
684         talloc_set_type(el1, struct el2);
685         if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) {
686                 printf("type set failed on el1 with el2\n");
687                 return False;
688         }
689
690         talloc_free(root);
691
692         return True;
693 }
694
695 /*
696   test steal
697 */
698 static BOOL test_steal(void)
699 {
700         void *root, *p1, *p2;
701
702         printf("TESTING STEAL\n");
703
704         root = talloc_new(NULL);
705
706         p1 = talloc_array(root, char, 10);
707         CHECK_SIZE(p1, 10);
708
709         p2 = talloc_realloc(root, NULL, char, 20);
710         CHECK_SIZE(p1, 10);
711         CHECK_SIZE(root, 30);
712
713         if (talloc_steal(p1, NULL) != NULL) {
714                 printf("failed: stealing NULL should give NULL\n");
715                 return False;
716         }
717
718         if (talloc_steal(p1, p1) != p1) {
719                 printf("failed: stealing to ourselves is a nop\n");
720                 return False;
721         }
722         CHECK_BLOCKS(root, 3);
723         CHECK_SIZE(root, 30);
724
725         talloc_steal(NULL, p1);
726         talloc_steal(NULL, p2);
727         CHECK_BLOCKS(root, 1);
728         CHECK_SIZE(root, 0);
729
730         talloc_free(p1);
731         talloc_steal(root, p2);
732         CHECK_BLOCKS(root, 2);
733         CHECK_SIZE(root, 20);
734         
735         talloc_free(p2);
736
737         CHECK_BLOCKS(root, 1);
738         CHECK_SIZE(root, 0);
739
740         talloc_free(root);
741
742         p1 = talloc_size(NULL, 3);
743         talloc_report_full(NULL, stdout);
744         CHECK_SIZE(NULL, 3);
745         talloc_free(p1);
746
747         return True;
748 }
749
750 /*
751   test talloc_realloc_fn
752 */
753 static BOOL test_realloc_fn(void)
754 {
755         void *root, *p1;
756
757         printf("TESTING talloc_realloc_fn\n");
758
759         root = talloc_new(NULL);
760
761         p1 = talloc_realloc_fn(root, NULL, 10);
762         CHECK_BLOCKS(root, 2);
763         CHECK_SIZE(root, 10);
764         p1 = talloc_realloc_fn(root, p1, 20);
765         CHECK_BLOCKS(root, 2);
766         CHECK_SIZE(root, 20);
767         p1 = talloc_realloc_fn(root, p1, 0);
768         CHECK_BLOCKS(root, 1);
769         CHECK_SIZE(root, 0);
770
771         talloc_free(root);
772
773
774         return True;
775 }
776
777
778 static BOOL test_unref_reparent(void)
779 {
780         void *root, *p1, *p2, *c1;
781
782         printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
783
784         root = talloc_named_const(NULL, 0, "root");
785         p1 = talloc_named_const(root, 1, "orig parent");
786         p2 = talloc_named_const(root, 1, "parent by reference");
787
788         c1 = talloc_named_const(p1, 1, "child");
789         talloc_reference(p2, c1);
790
791         CHECK_PARENT(c1, p1);
792
793         talloc_free(p1);
794
795         CHECK_PARENT(c1, p2);
796
797         talloc_unlink(p2, c1);
798
799         CHECK_SIZE(root, 1);
800
801         talloc_free(p2);
802         talloc_free(root);
803
804         return True;
805 }
806
807 /*
808   measure the speed of talloc versus malloc
809 */
810 static BOOL test_speed(void)
811 {
812         void *ctx = talloc_new(NULL);
813         unsigned count;
814         struct timeval tv;
815
816         printf("MEASURING TALLOC VS MALLOC SPEED\n");
817
818         tv = timeval_current();
819         count = 0;
820         do {
821                 void *p1, *p2, *p3;
822                 p1 = talloc_size(ctx, count);
823                 p2 = talloc_strdup(p1, "foo bar");
824                 p3 = talloc_size(p1, 300);
825                 talloc_free(p1);
826                 count += 3;
827         } while (timeval_elapsed(&tv) < 5.0);
828
829         printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
830
831         talloc_free(ctx);
832
833         tv = timeval_current();
834         count = 0;
835         do {
836                 void *p1, *p2, *p3;
837                 p1 = malloc(count);
838                 p2 = strdup("foo bar");
839                 p3 = malloc(300);
840                 free(p1);
841                 free(p2);
842                 free(p3);
843                 count += 3;
844         } while (timeval_elapsed(&tv) < 5.0);
845
846         printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
847
848         return True;    
849 }
850
851
852 static BOOL test_lifeless(void)
853 {
854         char *top = talloc_new(NULL);
855         char *parent, *child; 
856         char *child_owner = talloc_new(NULL);
857
858         printf("TESTING TALLOC_UNLINK LOOP\n");
859
860         parent = talloc_strdup(top, "parent");
861         child = talloc_strdup(parent, "child");  
862         talloc_reference(child, parent);
863         talloc_reference(child_owner, child); 
864         talloc_report_full(top, stdout);
865         talloc_unlink(top, parent);
866         talloc_free(child);
867         talloc_report_full(top, stdout);
868         talloc_free(top);
869         talloc_free(child_owner);
870         talloc_free(child);
871
872         return True;
873 }
874
875 static int loop_destructor_count;
876
877 static int test_loop_destructor(char *ptr)
878 {
879         printf("loop destructor\n");
880         loop_destructor_count++;
881         return 0;
882 }
883
884 static BOOL test_loop(void)
885 {
886         char *top = talloc_new(NULL);
887         char *parent;
888         struct req1 {
889                 char *req2, *req3;
890         } *req1;
891
892         printf("TESTING TALLOC LOOP DESTRUCTION\n");
893         parent = talloc_strdup(top, "parent");
894         req1 = talloc(parent, struct req1);
895         req1->req2 = talloc_strdup(req1, "req2");  
896         talloc_set_destructor(req1->req2, test_loop_destructor);
897         req1->req3 = talloc_strdup(req1, "req3");
898         talloc_reference(req1->req3, req1);
899         talloc_report_full(top, stdout);
900         talloc_free(parent);
901         talloc_report_full(top, stdout);
902         talloc_report_full(NULL, stdout);
903         talloc_free(top);
904
905         if (loop_destructor_count != 1) {
906                 printf("FAILED TO FIRE LOOP DESTRUCTOR\n");
907                 return False;
908         }
909
910         return True;
911 }
912
913 static int fail_destructor_str(char *ptr)
914 {
915         return -1;
916 }
917
918 static BOOL test_free_parent_deny_child(void)
919 {
920         char *top = talloc_new(NULL);
921         char *level1;
922         char *level2;
923         char *level3;
924
925         printf("TESTING TALLOC FREE PARENT DENY CHILD\n");
926         level1 = talloc_strdup(top, "level1");
927         level2 = talloc_strdup(level1, "level2");
928         level3 = talloc_strdup(level2, "level3");
929
930         talloc_set_destructor(level3, fail_destructor_str);
931         talloc_free(level1);
932         talloc_set_destructor(level3, NULL);
933
934         CHECK_PARENT(level3, top);
935
936         talloc_free(top);
937
938         return True;
939 }
940
941 static BOOL test_talloc_ptrtype(void)
942 {
943         BOOL ret = True;
944         char *top = talloc_new(NULL);
945         struct struct1 {
946                 int foo;
947                 int bar;
948         } *s1, *s2, **s3, ***s4;
949         const char *location1;
950         const char *location2;
951         const char *location3;
952         const char *location4;
953
954         printf("TESTING TALLOC PTRTYPE\n");
955         s1 = talloc_ptrtype(top, s1);location1 = __location__;
956
957         if (talloc_get_size(s1) != sizeof(struct struct1)) {
958                 printf("%s: talloc_ptrtype() allocated the wrong size %u (should be %u)\n",
959                         __location__, talloc_get_size(s1), sizeof(struct struct1));
960                 ret = False;
961         }
962
963         if (strcmp(location1, talloc_get_name(s1)) != 0) {
964                 printf("%s: talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n",
965                         __location__, talloc_get_name(s1), location1);
966                 ret = False;
967         }
968
969         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
970
971         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
972                 printf("%s: talloc_array_ptrtype() allocated the wrong size %u (should be %u)\n",
973                         __location__, talloc_get_size(s2), (sizeof(struct struct1)*10));
974                 ret = False;
975         }
976
977         if (strcmp(location2, talloc_get_name(s2)) != 0) {
978                 printf("%s: talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n",
979                         __location__, talloc_get_name(s2), location2);
980                 ret = False;
981         }
982
983         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
984
985         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
986                 printf("%s: talloc_array_ptrtype() allocated the wrong size %u (should be %u)\n",
987                         __location__, talloc_get_size(s3), (sizeof(struct struct1 *)*10));
988                 ret = False;
989         }
990
991         if (strcmp(location3, talloc_get_name(s3)) != 0) {
992                 printf("%s: talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n",
993                         __location__, talloc_get_name(s3), location3);
994                 ret = False;
995         }
996
997         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
998
999         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1000                 printf("%s: talloc_array_ptrtype() allocated the wrong size %u (should be %u)\n",
1001                         __location__, talloc_get_size(s4), (sizeof(struct struct1 **)*10));
1002                 ret = False;
1003         }
1004
1005         if (strcmp(location4, talloc_get_name(s4)) != 0) {
1006                 printf("%s: talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n",
1007                         __location__, talloc_get_name(s4), location4);
1008                 ret = False;
1009         }
1010
1011         talloc_free(top);
1012
1013         return ret;
1014 }
1015
1016 BOOL torture_local_talloc(struct torture_context *torture) 
1017 {
1018         BOOL ret = True;
1019
1020         talloc_enable_null_tracking();
1021
1022         ret &= test_ref1();
1023         ret &= test_ref2();
1024         ret &= test_ref3();
1025         ret &= test_ref4();
1026         ret &= test_unlink1();
1027         ret &= test_misc();
1028         ret &= test_realloc();
1029         ret &= test_realloc_child();
1030         ret &= test_steal();
1031         ret &= test_unref_reparent();
1032         ret &= test_realloc_fn();
1033         ret &= test_type();
1034         ret &= test_lifeless();
1035         ret &= test_loop();
1036         ret &= test_free_parent_deny_child();
1037         ret &= test_talloc_ptrtype();
1038         if (ret) {
1039                 ret &= test_speed();
1040         }
1041
1042         return ret;
1043 }
1044
1045
1046
1047 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
1048  int main(void)
1049 {
1050         if (!torture_local_talloc(NULL)) {
1051                 printf("ERROR: TESTSUITE FAILED\n");
1052                 return -1;
1053         }
1054         return 0;
1055 }
1056 #endif