r8032: added loop detection into talloc. Robert Collins found a way to make a
[kamenim/samba.git] / source4 / 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    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.
12    
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.
17    
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.
21 */
22
23 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #ifdef HAVE_STDARG_H
29 #include <stdarg.h>
30 #endif
31
32 #include <sys/time.h>
33 #include <time.h>
34
35 #include "talloc.h"
36
37 #ifndef False
38 #define False 0
39 #endif
40 #ifndef True
41 #define True 1
42 #endif
43 #ifndef BOOL
44 #define BOOL int
45 #endif
46
47 static struct timeval timeval_current(void)
48 {
49         struct timeval tv;
50         gettimeofday(&tv, NULL);
51         return tv;
52 }
53
54 static double timeval_elapsed(struct timeval *tv)
55 {
56         struct timeval tv2 = timeval_current();
57         return (tv2.tv_sec - tv->tv_sec) + 
58                (tv2.tv_usec - tv->tv_usec)*1.0e-6;
59 }
60
61 #if SAMBA_VERSION_MAJOR<4
62 #ifdef malloc
63 #undef malloc
64 #endif
65 #ifdef strdup
66 #undef strdup
67 #endif
68 #endif
69
70 #define CHECK_SIZE(ptr, tsize) do { \
71         if (talloc_total_size(ptr) != (tsize)) { \
72                 printf(__location__ " failed: wrong '%s' tree size: got %u  expected %u\n", \
73                        #ptr, \
74                        (unsigned)talloc_total_size(ptr), \
75                        (unsigned)tsize); \
76                 talloc_report_full(ptr, stdout); \
77                 return False; \
78         } \
79 } while (0)
80
81 #define CHECK_BLOCKS(ptr, tblocks) do { \
82         if (talloc_total_blocks(ptr) != (tblocks)) { \
83                 printf(__location__ " failed: wrong '%s' tree blocks: got %u  expected %u\n", \
84                        #ptr, \
85                        (unsigned)talloc_total_blocks(ptr), \
86                        (unsigned)tblocks); \
87                 talloc_report_full(ptr, stdout); \
88                 return False; \
89         } \
90 } while (0)
91
92
93 /*
94   test references 
95 */
96 static BOOL test_ref1(void)
97 {
98         void *root, *p1, *p2, *ref, *r1;
99
100         printf("TESTING SINGLE REFERENCE FREE\n");
101
102         root = talloc_named_const(NULL, 0, "root");
103         p1 = talloc_named_const(root, 1, "p1");
104         p2 = talloc_named_const(p1, 1, "p2");
105         talloc_named_const(p1, 1, "x1");
106         talloc_named_const(p1, 2, "x2");
107         talloc_named_const(p1, 3, "x3");
108
109         r1 = talloc_named_const(root, 1, "r1"); 
110         ref = talloc_reference(r1, p2);
111         talloc_report_full(root, stdout);
112
113         CHECK_BLOCKS(p1, 5);
114         CHECK_BLOCKS(p2, 1);
115         CHECK_BLOCKS(r1, 2);
116
117         printf("Freeing p2\n");
118         talloc_free(p2);
119         talloc_report_full(root, stdout);
120
121         CHECK_BLOCKS(p1, 5);
122         CHECK_BLOCKS(p2, 1);
123         CHECK_BLOCKS(r1, 1);
124
125         printf("Freeing p1\n");
126         talloc_free(p1);
127         talloc_report_full(root, stdout);
128
129         CHECK_BLOCKS(r1, 1);
130
131         printf("Freeing r1\n");
132         talloc_free(r1);
133         talloc_report_full(NULL, stdout);
134
135         printf("Testing NULL\n");
136         if (talloc_reference(root, NULL)) {
137                 return False;
138         }
139
140         CHECK_BLOCKS(root, 1);
141
142         CHECK_SIZE(root, 0);
143
144         talloc_free(root);
145
146         return True;
147 }
148
149 /*
150   test references 
151 */
152 static BOOL test_ref2(void)
153 {
154         void *root, *p1, *p2, *ref, *r1;
155
156         printf("TESTING DOUBLE REFERENCE FREE\n");
157
158         root = talloc_named_const(NULL, 0, "root");
159         p1 = talloc_named_const(root, 1, "p1");
160         talloc_named_const(p1, 1, "x1");
161         talloc_named_const(p1, 1, "x2");
162         talloc_named_const(p1, 1, "x3");
163         p2 = talloc_named_const(p1, 1, "p2");
164
165         r1 = talloc_named_const(root, 1, "r1"); 
166         ref = talloc_reference(r1, p2);
167         talloc_report_full(root, stdout);
168
169         CHECK_BLOCKS(p1, 5);
170         CHECK_BLOCKS(p2, 1);
171         CHECK_BLOCKS(r1, 2);
172
173         printf("Freeing ref\n");
174         talloc_free(ref);
175         talloc_report_full(root, stdout);
176
177         CHECK_BLOCKS(p1, 5);
178         CHECK_BLOCKS(p2, 1);
179         CHECK_BLOCKS(r1, 1);
180
181         printf("Freeing p2\n");
182         talloc_free(p2);
183         talloc_report_full(root, stdout);
184
185         CHECK_BLOCKS(p1, 4);
186         CHECK_BLOCKS(r1, 1);
187
188         printf("Freeing p1\n");
189         talloc_free(p1);
190         talloc_report_full(root, stdout);
191
192         CHECK_BLOCKS(r1, 1);
193
194         printf("Freeing r1\n");
195         talloc_free(r1);
196         talloc_report_full(root, stdout);
197
198         CHECK_SIZE(root, 0);
199
200         talloc_free(root);
201
202         return True;
203 }
204
205 /*
206   test references 
207 */
208 static BOOL test_ref3(void)
209 {
210         void *root, *p1, *p2, *ref, *r1;
211
212         printf("TESTING PARENT REFERENCE FREE\n");
213
214         root = talloc_named_const(NULL, 0, "root");
215         p1 = talloc_named_const(root, 1, "p1");
216         p2 = talloc_named_const(root, 1, "p2");
217         r1 = talloc_named_const(p1, 1, "r1");
218         ref = talloc_reference(p2, r1);
219         talloc_report_full(root, stdout);
220
221         CHECK_BLOCKS(p1, 2);
222         CHECK_BLOCKS(p2, 2);
223         CHECK_BLOCKS(r1, 1);
224
225         printf("Freeing p1\n");
226         talloc_free(p1);
227         talloc_report_full(root, stdout);
228
229         CHECK_BLOCKS(p2, 2);
230         CHECK_BLOCKS(r1, 1);
231
232         printf("Freeing p2\n");
233         talloc_free(p2);
234         talloc_report_full(root, stdout);
235
236         CHECK_SIZE(root, 0);
237
238         talloc_free(root);
239
240         return True;
241 }
242
243 /*
244   test references 
245 */
246 static BOOL test_ref4(void)
247 {
248         void *root, *p1, *p2, *ref, *r1;
249
250         printf("TESTING REFERRER REFERENCE FREE\n");
251
252         root = talloc_named_const(NULL, 0, "root");
253         p1 = talloc_named_const(root, 1, "p1");
254         talloc_named_const(p1, 1, "x1");
255         talloc_named_const(p1, 1, "x2");
256         talloc_named_const(p1, 1, "x3");
257         p2 = talloc_named_const(p1, 1, "p2");
258
259         r1 = talloc_named_const(root, 1, "r1"); 
260         ref = talloc_reference(r1, p2);
261         talloc_report_full(root, stdout);
262
263         CHECK_BLOCKS(p1, 5);
264         CHECK_BLOCKS(p2, 1);
265         CHECK_BLOCKS(r1, 2);
266
267         printf("Freeing r1\n");
268         talloc_free(r1);
269         talloc_report_full(root, stdout);
270
271         CHECK_BLOCKS(p1, 5);
272         CHECK_BLOCKS(p2, 1);
273
274         printf("Freeing p2\n");
275         talloc_free(p2);
276         talloc_report_full(root, stdout);
277
278         CHECK_BLOCKS(p1, 4);
279
280         printf("Freeing p1\n");
281         talloc_free(p1);
282         talloc_report_full(root, stdout);
283
284         CHECK_SIZE(root, 0);
285
286         talloc_free(root);
287
288         return True;
289 }
290
291
292 /*
293   test references 
294 */
295 static BOOL test_unlink1(void)
296 {
297         void *root, *p1, *p2, *ref, *r1;
298
299         printf("TESTING UNLINK\n");
300
301         root = talloc_named_const(NULL, 0, "root");
302         p1 = talloc_named_const(root, 1, "p1");
303         talloc_named_const(p1, 1, "x1");
304         talloc_named_const(p1, 1, "x2");
305         talloc_named_const(p1, 1, "x3");
306         p2 = talloc_named_const(p1, 1, "p2");
307
308         r1 = talloc_named_const(p1, 1, "r1");   
309         ref = talloc_reference(r1, p2);
310         talloc_report_full(root, stdout);
311
312         CHECK_BLOCKS(p1, 7);
313         CHECK_BLOCKS(p2, 1);
314         CHECK_BLOCKS(r1, 2);
315
316         printf("Unreferencing r1\n");
317         talloc_unlink(r1, p2);
318         talloc_report_full(root, stdout);
319
320         CHECK_BLOCKS(p1, 6);
321         CHECK_BLOCKS(p2, 1);
322         CHECK_BLOCKS(r1, 1);
323
324         printf("Freeing p1\n");
325         talloc_free(p1);
326         talloc_report_full(root, stdout);
327
328         CHECK_SIZE(root, 0);
329
330         talloc_free(root);
331
332         return True;
333 }
334
335 static int fail_destructor(void *ptr)
336 {
337         return -1;
338 }
339
340 /*
341   miscellaneous tests to try to get a higher test coverage percentage
342 */
343 static BOOL test_misc(void)
344 {
345         void *root, *p1;
346         char *p2;
347         double *d;
348
349         printf("TESTING MISCELLANEOUS\n");
350
351         root = talloc_new(NULL);
352
353         p1 = talloc_size(root, 0x7fffffff);
354         if (p1) {
355                 printf("failed: large talloc allowed\n");
356                 return False;
357         }
358
359         p1 = talloc_strdup(root, "foo");
360         talloc_increase_ref_count(p1);
361         talloc_increase_ref_count(p1);
362         talloc_increase_ref_count(p1);
363         CHECK_BLOCKS(p1, 1);
364         CHECK_BLOCKS(root, 2);
365         talloc_free(p1);
366         CHECK_BLOCKS(p1, 1);
367         CHECK_BLOCKS(root, 2);
368         talloc_unlink(NULL, p1);
369         CHECK_BLOCKS(p1, 1);
370         CHECK_BLOCKS(root, 2);
371         p2 = talloc_strdup(p1, "foo");
372         if (talloc_unlink(root, p2) != -1) {
373                 printf("failed: talloc_unlink() of non-reference context should return -1\n");
374                 return False;
375         }
376         if (talloc_unlink(p1, p2) != 0) {
377                 printf("failed: talloc_unlink() of parent should succeed\n");
378                 return False;
379         }
380         talloc_free(p1);
381         CHECK_BLOCKS(p1, 1);
382         CHECK_BLOCKS(root, 2);
383
384         talloc_set_name(p1, "my name is %s", "foo");
385         if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
386                 printf("failed: wrong name after talloc_set_name\n");
387                 return False;
388         }
389         CHECK_BLOCKS(p1, 2);
390         CHECK_BLOCKS(root, 3);
391
392         talloc_set_name_const(p1, NULL);
393         if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
394                 printf("failed: wrong name after talloc_set_name(NULL)\n");
395                 return False;
396         }
397         CHECK_BLOCKS(p1, 2);
398         CHECK_BLOCKS(root, 3);
399         
400
401         if (talloc_free(NULL) != -1) {
402                 printf("talloc_free(NULL) should give -1\n");
403                 return False;
404         }
405
406         talloc_set_destructor(p1, fail_destructor);
407         if (talloc_free(p1) != -1) {
408                 printf("Failed destructor should cause talloc_free to fail\n");
409                 return False;
410         }
411         talloc_set_destructor(p1, NULL);
412
413         talloc_report(root, stdout);
414
415
416         p2 = talloc_zero_size(p1, 20);
417         if (p2[19] != 0) {
418                 printf("Failed to give zero memory\n");
419                 return False;
420         }
421         talloc_free(p2);
422
423         if (talloc_strdup(root, NULL) != NULL) {
424                 printf("failed: strdup on NULL should give NULL\n");
425                 return False;
426         }
427
428         p2 = talloc_strndup(p1, "foo", 2);
429         if (strcmp("fo", p2) != 0) {
430                 printf("failed: strndup doesn't work\n");
431                 return False;
432         }
433         p2 = talloc_asprintf_append(p2, "o%c", 'd');
434         if (strcmp("food", p2) != 0) {
435                 printf("failed: talloc_asprintf_append doesn't work\n");
436                 return False;
437         }
438         CHECK_BLOCKS(p2, 1);
439         CHECK_BLOCKS(p1, 3);
440
441         p2 = talloc_asprintf_append(NULL, "hello %s", "world");
442         if (strcmp("hello world", p2) != 0) {
443                 printf("failed: talloc_asprintf_append doesn't work\n");
444                 return False;
445         }
446         CHECK_BLOCKS(p2, 1);
447         CHECK_BLOCKS(p1, 3);
448         talloc_free(p2);
449
450         d = talloc_array(p1, double, 0x20000000);
451         if (d) {
452                 printf("failed: integer overflow not detected\n");
453                 return False;
454         }
455
456         d = talloc_realloc(p1, d, double, 0x20000000);
457         if (d) {
458                 printf("failed: integer overflow not detected\n");
459                 return False;
460         }
461
462         talloc_free(p1);
463         CHECK_BLOCKS(root, 1);
464
465         p1 = talloc_named(root, 100, "%d bytes", 100);
466         CHECK_BLOCKS(p1, 2);
467         CHECK_BLOCKS(root, 3);
468         talloc_unlink(root, p1);
469
470         p1 = talloc_init("%d bytes", 200);
471         p2 = talloc_asprintf(p1, "my test '%s'", "string");
472         CHECK_BLOCKS(p1, 3);
473         CHECK_SIZE(p2, 17);
474         CHECK_BLOCKS(root, 1);
475         talloc_unlink(NULL, p1);
476
477         p1 = talloc_named_const(root, 10, "p1");
478         p2 = talloc_named_const(root, 20, "p2");
479         talloc_reference(p1, p2);
480         talloc_report_full(root, stdout);
481         talloc_unlink(root, p2);
482         talloc_report_full(root, stdout);
483         CHECK_BLOCKS(p2, 1);
484         CHECK_BLOCKS(p1, 2);
485         CHECK_BLOCKS(root, 3);
486         talloc_unlink(p1, p2);
487         talloc_unlink(root, p1);
488
489         p1 = talloc_named_const(root, 10, "p1");
490         p2 = talloc_named_const(root, 20, "p2");
491         talloc_reference(NULL, p2);
492         talloc_report_full(root, stdout);
493         talloc_unlink(root, p2);
494         talloc_report_full(root, stdout);
495         CHECK_BLOCKS(p2, 1);
496         CHECK_BLOCKS(p1, 1);
497         CHECK_BLOCKS(root, 2);
498         talloc_unlink(NULL, p2);
499         talloc_unlink(root, p1);
500
501         /* Test that talloc_unlink is a no-op */
502
503         if (talloc_unlink(root, NULL) != -1) {
504                 printf("failed: talloc_unlink(root, NULL) == -1\n");
505                 return False;
506         }
507
508         talloc_report(root, stdout);
509         talloc_report(NULL, stdout);
510
511         CHECK_SIZE(root, 0);
512
513         talloc_free(root);
514
515         CHECK_SIZE(NULL, 0);
516
517         talloc_enable_leak_report();
518         talloc_enable_leak_report_full();
519
520         return True;
521 }
522
523
524 /*
525   test realloc
526 */
527 static BOOL test_realloc(void)
528 {
529         void *root, *p1, *p2;
530
531         printf("TESTING REALLOC\n");
532
533         root = talloc_new(NULL);
534
535         p1 = talloc_size(root, 10);
536         CHECK_SIZE(p1, 10);
537
538         p1 = talloc_realloc_size(NULL, p1, 20);
539         CHECK_SIZE(p1, 20);
540
541         talloc_new(p1);
542
543         p2 = talloc_realloc_size(p1, NULL, 30);
544
545         talloc_new(p1);
546
547         p2 = talloc_realloc_size(p1, p2, 40);
548
549         CHECK_SIZE(p2, 40);
550         CHECK_SIZE(root, 60);
551         CHECK_BLOCKS(p1, 4);
552
553         p1 = talloc_realloc_size(NULL, p1, 20);
554         CHECK_SIZE(p1, 60);
555
556         talloc_increase_ref_count(p2);
557         if (talloc_realloc_size(NULL, p2, 5) != NULL) {
558                 printf("failed: talloc_realloc() on a referenced pointer should fail\n");
559                 return False;
560         }
561         CHECK_BLOCKS(p1, 4);
562
563         talloc_realloc_size(NULL, p2, 0);
564         talloc_realloc_size(NULL, p2, 0);
565         CHECK_BLOCKS(p1, 3);
566
567         if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) {
568                 printf("failed: oversize talloc should fail\n");
569                 return False;
570         }
571
572         talloc_realloc_size(NULL, p1, 0);
573
574         CHECK_BLOCKS(root, 1);
575         CHECK_SIZE(root, 0);
576
577         talloc_free(root);
578
579         return True;
580 }
581
582
583 /*
584   test realloc with a child
585 */
586 static BOOL test_realloc_child(void)
587 {
588         void *root;
589         struct el1 {
590                 int count;
591                 struct el2 {
592                         const char *name;
593                 } **list, **list2, **list3;
594         } *el1;
595         struct el2 *el2;
596
597         printf("TESTING REALLOC WITH CHILD\n");
598
599         root = talloc_new(NULL);
600
601         el1 = talloc(root, struct el1);
602         el1->list = talloc(el1, struct el2 *);
603         el1->list[0] = talloc(el1->list, struct el2);
604         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
605
606         el1->list2 = talloc(el1, struct el2 *);
607         el1->list2[0] = talloc(el1->list2, struct el2);
608         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
609
610         el1->list3 = talloc(el1, struct el2 *);
611         el1->list3[0] = talloc(el1->list3, struct el2);
612         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
613         
614         el2 = talloc(el1->list, struct el2);
615         el2 = talloc(el1->list2, struct el2);
616         el2 = talloc(el1->list3, struct el2);
617
618         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
619         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
620         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
621
622         talloc_free(root);
623
624         return True;
625 }
626
627
628 /*
629   test type checking
630 */
631 static BOOL test_type(void)
632 {
633         void *root;
634         struct el1 {
635                 int count;
636         };
637         struct el2 {
638                 int count;
639         };
640         struct el1 *el1;
641
642         printf("TESTING talloc type checking\n");
643
644         root = talloc_new(NULL);
645
646         el1 = talloc(root, struct el1);
647
648         el1->count = 1;
649
650         if (talloc_get_type(el1, struct el1) != el1) {
651                 printf("type check failed on el1\n");
652                 return False;
653         }
654         if (talloc_get_type(el1, struct el2) != NULL) {
655                 printf("type check failed on el1 with el2\n");
656                 return False;
657         }
658         talloc_set_type(el1, struct el2);
659         if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) {
660                 printf("type set failed on el1 with el2\n");
661                 return False;
662         }
663
664         talloc_free(root);
665
666         return True;
667 }
668
669 /*
670   test steal
671 */
672 static BOOL test_steal(void)
673 {
674         void *root, *p1, *p2;
675
676         printf("TESTING STEAL\n");
677
678         root = talloc_new(NULL);
679
680         p1 = talloc_array(root, char, 10);
681         CHECK_SIZE(p1, 10);
682
683         p2 = talloc_realloc(root, NULL, char, 20);
684         CHECK_SIZE(p1, 10);
685         CHECK_SIZE(root, 30);
686
687         if (talloc_steal(p1, NULL) != NULL) {
688                 printf("failed: stealing NULL should give NULL\n");
689                 return False;
690         }
691
692         if (talloc_steal(p1, p1) != p1) {
693                 printf("failed: stealing to ourselves is a nop\n");
694                 return False;
695         }
696         CHECK_BLOCKS(root, 3);
697         CHECK_SIZE(root, 30);
698
699         talloc_steal(NULL, p1);
700         talloc_steal(NULL, p2);
701         CHECK_BLOCKS(root, 1);
702         CHECK_SIZE(root, 0);
703
704         talloc_free(p1);
705         talloc_steal(root, p2);
706         CHECK_BLOCKS(root, 2);
707         CHECK_SIZE(root, 20);
708         
709         talloc_free(p2);
710
711         CHECK_BLOCKS(root, 1);
712         CHECK_SIZE(root, 0);
713
714         talloc_free(root);
715
716         p1 = talloc_size(NULL, 3);
717         talloc_report_full(NULL, stdout);
718         CHECK_SIZE(NULL, 3);
719         talloc_free(p1);
720
721         return True;
722 }
723
724 /*
725   test talloc_realloc_fn
726 */
727 static BOOL test_realloc_fn(void)
728 {
729         void *root, *p1;
730
731         printf("TESTING talloc_realloc_fn\n");
732
733         root = talloc_new(NULL);
734
735         p1 = talloc_realloc_fn(root, NULL, 10);
736         CHECK_BLOCKS(root, 2);
737         CHECK_SIZE(root, 10);
738         p1 = talloc_realloc_fn(root, p1, 20);
739         CHECK_BLOCKS(root, 2);
740         CHECK_SIZE(root, 20);
741         p1 = talloc_realloc_fn(root, p1, 0);
742         CHECK_BLOCKS(root, 1);
743         CHECK_SIZE(root, 0);
744
745         talloc_free(root);
746
747
748         return True;
749 }
750
751
752 static BOOL test_unref_reparent(void)
753 {
754         void *root, *p1, *p2, *c1;
755
756         printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
757
758         root = talloc_named_const(NULL, 0, "root");
759         p1 = talloc_named_const(root, 1, "orig parent");
760         p2 = talloc_named_const(root, 1, "parent by reference");
761
762         c1 = talloc_named_const(p1, 1, "child");
763         talloc_reference(p2, c1);
764
765         talloc_free(p1);
766         talloc_unlink(p2, c1);
767
768         CHECK_SIZE(root, 1);
769
770         talloc_free(p2);
771         talloc_free(root);
772
773         return True;
774 }
775
776 /*
777   measure the speed of talloc versus malloc
778 */
779 static BOOL test_speed(void)
780 {
781         void *ctx = talloc_new(NULL);
782         unsigned count;
783         struct timeval tv;
784
785         printf("MEASURING TALLOC VS MALLOC SPEED\n");
786
787         tv = timeval_current();
788         count = 0;
789         do {
790                 void *p1, *p2, *p3;
791                 p1 = talloc_size(ctx, count);
792                 p2 = talloc_strdup(p1, "foo bar");
793                 p3 = talloc_size(p1, 300);
794                 talloc_free(p1);
795                 count += 3;
796         } while (timeval_elapsed(&tv) < 5.0);
797
798         printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
799
800         talloc_free(ctx);
801
802         tv = timeval_current();
803         count = 0;
804         do {
805                 void *p1, *p2, *p3;
806                 p1 = malloc(count);
807                 p2 = strdup("foo bar");
808                 p3 = malloc(300);
809                 free(p1);
810                 free(p2);
811                 free(p3);
812                 count += 3;
813         } while (timeval_elapsed(&tv) < 5.0);
814
815         printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
816
817         return True;    
818 }
819
820
821 BOOL test_lifeless(void)
822 {
823         char *top = talloc_new(NULL);
824         char *parent, *child; 
825         char *child_owner = talloc_new(NULL);
826
827         printf("TESTING TALLOC_UNLINK LOOP\n");
828
829         parent = talloc_strdup(top, "parent");
830         child = talloc_strdup(parent, "child");  
831         talloc_reference(child, parent);
832         talloc_reference(child_owner, child); 
833         talloc_unlink(top, parent);
834         talloc_free(child);
835         talloc_report_full(top, stdout);
836         talloc_free(top);
837         return True;
838 }
839
840
841 BOOL torture_local_talloc(void) 
842 {
843         BOOL ret = True;
844
845         ret &= test_ref1();
846         ret &= test_ref2();
847         ret &= test_ref3();
848         ret &= test_ref4();
849         ret &= test_unlink1();
850         ret &= test_misc();
851         ret &= test_realloc();
852         ret &= test_realloc_child();
853         ret &= test_steal();
854         ret &= test_unref_reparent();
855         ret &= test_realloc_fn();
856         ret &= test_type();
857         ret &= test_lifeless();
858         if (ret) {
859                 ret &= test_speed();
860         }
861
862         return ret;
863 }
864
865
866
867 #if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
868  int main(void)
869 {
870         if (!torture_local_talloc()) {
871                 printf("ERROR: TESTSUIE FAILED\n");
872                 return -1;
873         }
874         return 0;
875 }
876 #endif