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