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