talloc testsuite: test (ref, free, steal) destroys reference
[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:%d [\nwrong '%s' tree size: got %u  expected %u\n]\n", \
70                        test, __LINE__, #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:%d [\nwrong '%s' tree blocks: got %u  expected %u\n]\n", \
81                        test, __LINE__, #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:%d [\n'%s' has wrong parent: got %p  expected %p\n]\n", \
92                        test, __LINE__, #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 void talloc_erase_no_owner_context();
103 void* talloc_no_owner_context ();
104
105 /*
106   test references 
107 */
108 static bool test_ref1(void)
109 {
110         void *root, *p1, *p2, *ref, *r1;
111
112         printf("test: ref1\n# SINGLE REFERENCE FREE\n");
113         talloc_erase_no_owner_context();
114
115         root = talloc_named_const(NULL, 0, "root");
116         p1 = talloc_named_const(root, 1, "p1");
117         p2 = talloc_named_const(p1, 1, "p2");
118         talloc_named_const(p1, 1, "x1");
119         talloc_named_const(p1, 2, "x2");
120         talloc_named_const(p1, 3, "x3");
121
122         r1 = talloc_named_const(root, 1, "r1"); 
123         ref = talloc_reference(r1, p2);
124         talloc_report_full(root, stderr);
125
126         CHECK_BLOCKS("ref1", p1, 5);
127         CHECK_BLOCKS("ref1", p2, 1);
128         CHECK_BLOCKS("ref1", r1, 2);
129
130         fprintf(stderr, "Freeing p2\n");
131         talloc_free(p2);
132         talloc_report_full(root, stderr);
133
134 //      CHECK_BLOCKS("ref1", p1, 5);
135 // p2 owner was removed, not reference! p2 now belongs to no_owner_context, not p1
136         CHECK_BLOCKS("ref1", p1, 4);
137         CHECK_BLOCKS("ref1", p2, 1);
138 // r1 reference was not destroyed by free(p2) any more
139 //      CHECK_BLOCKS("ref1", r1, 1);
140         CHECK_BLOCKS("ref1", r1, 2);
141
142         fprintf(stderr, "Freeing p1\n");
143         talloc_free(p1);
144         talloc_report_full(root, stderr);
145
146 // r1 still has reference to p2
147 //      CHECK_BLOCKS("ref1", r1, 1);
148         CHECK_BLOCKS("ref1", r1, 2);
149
150         fprintf(stderr, "Freeing r1\n");
151         talloc_free(r1);
152         talloc_report_full(NULL, stderr);
153
154         fprintf(stderr, "Testing NULL\n");
155         if (talloc_reference(root, NULL)) {
156                 return false;
157         }
158
159         CHECK_BLOCKS("ref1", root, 1);
160
161         CHECK_SIZE("ref1", root, 0);
162
163         talloc_free(root);
164         printf("success: ref1\n");
165         return true;
166 }
167
168 /*
169   test references 
170 */
171 static bool test_ref2(void)
172 {
173         void *root, *p1, *p2, *ref, *r1;
174
175         printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
176         talloc_erase_no_owner_context();
177
178         root = talloc_named_const(NULL, 0, "root");
179         p1 = talloc_named_const(root, 1, "p1");
180         talloc_named_const(p1, 1, "x1");
181         talloc_named_const(p1, 1, "x2");
182         talloc_named_const(p1, 1, "x3");
183         p2 = talloc_named_const(p1, 1, "p2");
184
185         r1 = talloc_named_const(root, 1, "r1"); 
186         ref = talloc_reference(r1, p2);
187         talloc_report_full(NULL, stderr);
188
189         CHECK_BLOCKS("ref2", p1, 5);
190         CHECK_BLOCKS("ref2", p2, 1);
191         CHECK_BLOCKS("ref2", r1, 2);
192
193         fprintf(stderr, "Freeing ref\n");
194         talloc_free(ref);
195         talloc_report_full(NULL, stderr);
196
197 //      CHECK_BLOCKS("ref1", p1, 5);
198 // p2 owner was removed, not reference! p2 now belongs to no_owner_context, not to p1
199         CHECK_BLOCKS("ref1", p1, 4);
200         CHECK_BLOCKS("ref2", p2, 1);
201 // r1 reference was not destroyed by free(p2) any more
202 //      CHECK_BLOCKS("ref1", r1, 1);
203         CHECK_BLOCKS("ref1", r1, 2);
204
205         fprintf(stderr, "Freeing p2\n");
206         talloc_free(p2);
207         talloc_report_full(NULL, stderr);
208
209         CHECK_BLOCKS("ref2", p1, 4);
210 //      p2 hasn't been destroyed because r1 still references it, the reference wasn't
211 //      CHECK_BLOCKS("ref2", r1, 1);
212         CHECK_BLOCKS("ref2", r1, 2);
213
214         fprintf(stderr, "Freeing p1\n");
215         talloc_free(p1);
216         talloc_report_full(NULL, stderr);
217
218 //  r1 still has reference
219 //      CHECK_BLOCKS("ref2", r1, 1);
220         CHECK_BLOCKS("ref2", r1, 2);
221
222         fprintf(stderr, "Freeing r1\n");
223         talloc_free(r1);
224         talloc_report_full(root, stderr);
225
226         CHECK_SIZE("ref2", root, 0);
227
228         talloc_free(root);
229         printf("success: ref2\n");
230         return true;
231 }
232
233 /*
234   test references 
235 */
236 static bool test_ref3(void)
237 {
238         void *root, *p1, *p2, *ref, *r1;
239
240         printf("test: ref3\n# PARENT REFERENCE FREE\n");
241         talloc_erase_no_owner_context();
242
243         root = talloc_named_const(NULL, 0, "root");
244         p1 = talloc_named_const(root, 1, "p1");
245         p2 = talloc_named_const(root, 1, "p2");
246         r1 = talloc_named_const(p1, 1, "r1");
247         ref = talloc_reference(p2, r1);
248         talloc_report_full(root, stderr);
249
250         CHECK_BLOCKS("ref3", p1, 2);
251         CHECK_BLOCKS("ref3", p2, 2);
252         CHECK_BLOCKS("ref3", r1, 1);
253
254         fprintf(stderr, "Freeing p1\n");
255         talloc_free(p1);
256         talloc_report_full(root, stderr);
257
258         CHECK_BLOCKS("ref3", p2, 2);
259         CHECK_BLOCKS("ref3", r1, 1);
260
261         fprintf(stderr, "Freeing p2\n");
262         talloc_free(p2);
263         talloc_report_full(root, stderr);
264
265         CHECK_SIZE("ref3", root, 0);
266
267         talloc_free(root);
268
269         printf("success: ref3\n");
270         return true;
271 }
272
273 /*
274   test references 
275 */
276 static bool test_ref4(void)
277 {
278         void *root, *p1, *p2, *ref, *r1;
279
280         printf("test: ref4\n# REFERRER REFERENCE FREE\n");
281         talloc_erase_no_owner_context();
282
283         root = talloc_named_const(NULL, 0, "root");
284         p1 = talloc_named_const(root, 1, "p1");
285         talloc_named_const(p1, 1, "x1");
286         talloc_named_const(p1, 1, "x2");
287         talloc_named_const(p1, 1, "x3");
288         p2 = talloc_named_const(p1, 1, "p2");
289
290         r1 = talloc_named_const(root, 1, "r1"); 
291         ref = talloc_reference(r1, p2);
292         talloc_report_full(root, stderr);
293
294         CHECK_BLOCKS("ref4", p1, 5);
295         CHECK_BLOCKS("ref4", p2, 1);
296         CHECK_BLOCKS("ref4", r1, 2);
297
298         fprintf(stderr, "Freeing r1\n");
299         talloc_free(r1);
300         talloc_report_full(root, stderr);
301
302         CHECK_BLOCKS("ref4", p1, 5);
303         CHECK_BLOCKS("ref4", p2, 1);
304
305         fprintf(stderr, "Freeing p2\n");
306         talloc_free(p2);
307         talloc_report_full(root, stderr);
308
309         CHECK_BLOCKS("ref4", p1, 4);
310
311         fprintf(stderr, "Freeing p1\n");
312         talloc_free(p1);
313         talloc_report_full(root, stderr);
314
315         CHECK_SIZE("ref4", root, 0);
316
317         talloc_free(root);
318
319         printf("success: ref4\n");
320         return true;
321 }
322
323
324 /*
325   test references 
326 */
327 static bool test_unlink1(void)
328 {
329         void *root, *p1, *p2, *ref, *r1;
330
331         printf("test: unlink\n# UNLINK\n");
332         talloc_erase_no_owner_context();
333
334         root = talloc_named_const(NULL, 0, "root");
335         p1 = talloc_named_const(root, 1, "p1");
336         talloc_named_const(p1, 1, "x1");
337         talloc_named_const(p1, 1, "x2");
338         talloc_named_const(p1, 1, "x3");
339         p2 = talloc_named_const(p1, 1, "p2");
340
341         r1 = talloc_named_const(p1, 1, "r1");   
342         ref = talloc_reference(r1, p2);
343         talloc_report_full(root, stderr);
344
345         CHECK_BLOCKS("unlink", p1, 7);
346         CHECK_BLOCKS("unlink", p2, 1);
347         CHECK_BLOCKS("unlink", r1, 2);
348
349         fprintf(stderr, "Unreferencing r1\n");
350         talloc_unlink(r1, p2);
351         talloc_report_full(root, stderr);
352
353         CHECK_BLOCKS("unlink", p1, 6);
354         CHECK_BLOCKS("unlink", p2, 1);
355         CHECK_BLOCKS("unlink", r1, 1);
356
357         fprintf(stderr, "Freeing p1\n");
358         talloc_free(p1);
359         talloc_report_full(root, stderr);
360
361         CHECK_SIZE("unlink", root, 0);
362
363         talloc_free(root);
364
365         printf("success: unlink\n");
366         return true;
367 }
368
369 static int fail_destructor(void *ptr)
370 {
371         return -1;
372 }
373
374 /*
375   miscellaneous tests to try to get a higher test coverage percentage
376 */
377 static bool test_misc(void)
378 {
379         void *root, *p1;
380         char *p2;
381         double *d;
382         const char *name;
383
384         printf("test: misc\n# MISCELLANEOUS\n");
385         talloc_erase_no_owner_context();
386
387         root = talloc_new(NULL);
388
389         p1 = talloc_size(root, 0x7fffffff);
390         torture_assert("misc", !p1, "failed: large talloc allowed\n");
391
392         p1 = talloc_strdup(root, "foo");
393         talloc_increase_ref_count(p1);
394         talloc_increase_ref_count(p1);
395         talloc_increase_ref_count(p1);
396         CHECK_BLOCKS("misc", p1, 1);
397         CHECK_BLOCKS("misc", root, 2);
398         talloc_free(p1);
399         CHECK_BLOCKS("misc", p1, 1);
400 //  p1 now has no owner but 3 references still
401 //      CHECK_BLOCKS("misc", root, 2);
402         CHECK_BLOCKS("misc", root, 1);
403         talloc_unlink(NULL, p1);
404         CHECK_BLOCKS("misc", p1, 1);
405 //  p1 now has no owner but 2 references still
406 //      CHECK_BLOCKS("misc", root, 2);
407         CHECK_BLOCKS("misc", root, 1);
408         p2 = talloc_strdup(p1, "foo");
409         torture_assert("misc", talloc_unlink(root, p2) == -1,
410                                    "failed: talloc_unlink() of non-reference context should return -1\n");
411         torture_assert("misc", talloc_unlink(p1, p2) == 0,
412                 "failed: talloc_unlink() of parent should succeed\n");
413 //  p1 is already "free" but has one reference
414 //      talloc_free(p1);
415         talloc_unlink(NULL, p1);
416         CHECK_BLOCKS("misc", p1, 1);
417 //  p1 now has no owner but 1 references still
418 //      CHECK_BLOCKS("misc", root, 2);
419         CHECK_BLOCKS("misc", root, 1);
420
421         name = talloc_set_name(p1, "my name is %s", "foo");
422         torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
423                 "failed: wrong name after talloc_set_name(my name is foo)");
424         CHECK_BLOCKS("misc", p1, 2);
425 //  p1 now has no owner but 1 references still
426 //      CHECK_BLOCKS("misc", root, 3);
427         CHECK_BLOCKS("misc", root, 1);
428
429         talloc_set_name_const(p1, NULL);
430         torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
431                 "failed: wrong name after talloc_set_name(NULL)");
432         CHECK_BLOCKS("misc", p1, 2);
433 //  p1 now has no owner but 1 references still
434 //      CHECK_BLOCKS("misc", root, 3);
435         CHECK_BLOCKS("misc", root, 1);
436
437         torture_assert("misc", talloc_free(NULL) == -1, 
438                                    "talloc_free(NULL) should give -1\n");
439
440 // put test back on original track
441         talloc_steal(root, p1);
442         talloc_unlink(NULL, p1);
443
444         talloc_set_destructor(p1, fail_destructor);
445         torture_assert("misc", talloc_free(p1) == -1, 
446                 "Failed destructor should cause talloc_free to fail\n");
447         talloc_set_destructor(p1, NULL);
448
449         p2 = (char *)talloc_zero_size(p1, 20);
450         torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
451         talloc_free(p2);
452
453         torture_assert("misc", talloc_strdup(root, NULL) == NULL,
454                 "failed: strdup on NULL should give NULL\n");
455
456         p2 = talloc_strndup(p1, "foo", 2);
457         torture_assert("misc", strcmp("fo", p2) == 0, 
458                                    "strndup doesn't work\n");
459         p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
460         torture_assert("misc", strcmp("food", p2) == 0, 
461                                    "talloc_asprintf_append_buffer doesn't work\n");
462         CHECK_BLOCKS("misc", p2, 1);
463         CHECK_BLOCKS("misc", p1, 3);
464
465         p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
466         torture_assert("misc", strcmp("hello world", p2) == 0,
467                 "talloc_asprintf_append_buffer doesn't work\n");
468         CHECK_BLOCKS("misc", p2, 1);
469         CHECK_BLOCKS("misc", p1, 3);
470         talloc_free(p2);
471
472         d = talloc_array(p1, double, 0x20000000);
473         torture_assert("misc", !d, "failed: integer overflow not detected\n");
474
475         d = talloc_realloc(p1, d, double, 0x20000000);
476         torture_assert("misc", !d, "failed: integer overflow not detected\n");
477
478         talloc_free(p1);
479         CHECK_BLOCKS("misc", root, 1);
480
481         p1 = talloc_named(root, 100, "%d bytes", 100);
482         CHECK_BLOCKS("misc", p1, 2);
483         CHECK_BLOCKS("misc", root, 3);
484         talloc_unlink(root, p1);
485
486         p1 = talloc_init("%d bytes", 200);
487         p2 = talloc_asprintf(p1, "my test '%s'", "string");
488         torture_assert_str_equal("misc", p2, "my test 'string'",
489                 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
490         CHECK_BLOCKS("misc", p1, 3);
491         CHECK_SIZE("misc", p2, 17);
492         CHECK_BLOCKS("misc", root, 1);
493         talloc_unlink(NULL, p1);
494
495         p1 = talloc_named_const(root, 10, "p1");
496         p2 = (char *)talloc_named_const(root, 20, "p2");
497         (void)talloc_reference(p1, p2);
498         talloc_report_full(root, stderr);
499         talloc_unlink(root, p2);
500         talloc_report_full(root, stderr);
501         CHECK_BLOCKS("misc", p2, 1);
502         CHECK_BLOCKS("misc", p1, 2);
503         CHECK_BLOCKS("misc", root, 3);
504         talloc_unlink(p1, p2);
505         talloc_unlink(root, p1);
506
507         p1 = talloc_named_const(root, 10, "p1");
508         p2 = (char *)talloc_named_const(root, 20, "p2");
509         (void)talloc_reference(NULL, p2);
510         talloc_report_full(root, stderr);
511         talloc_unlink(root, p2);
512         talloc_report_full(root, stderr);
513         CHECK_BLOCKS("misc", p2, 1);
514         CHECK_BLOCKS("misc", p1, 1);
515         CHECK_BLOCKS("misc", root, 2);
516         talloc_unlink(NULL, p2);
517         talloc_unlink(root, p1);
518
519         /* Test that talloc_unlink is a no-op */
520
521         torture_assert("misc", talloc_unlink(root, NULL) == -1,
522                 "failed: talloc_unlink(root, NULL) == -1\n");
523
524         talloc_report(root, stderr);
525         talloc_report(NULL, stderr);
526
527         CHECK_SIZE("misc", root, 0);
528
529         talloc_free(root);
530         talloc_report(NULL, stderr);
531
532         CHECK_SIZE("misc", NULL, 0);
533
534         talloc_enable_leak_report();
535         talloc_enable_leak_report_full();
536
537         printf("success: misc\n");
538
539         return true;
540 }
541
542
543 /*
544   test realloc
545 */
546 static bool test_realloc(void)
547 {
548         void *root, *p1, *p2;
549
550         printf("test: realloc\n# REALLOC\n");
551         talloc_erase_no_owner_context();
552
553         root = talloc_new(NULL);
554
555         p1 = talloc_size(root, 10);
556         CHECK_SIZE("realloc", p1, 10);
557
558         p1 = talloc_realloc_size(NULL, p1, 20);
559         CHECK_SIZE("realloc", p1, 20);
560
561         talloc_new(p1);
562
563         p2 = talloc_realloc_size(p1, NULL, 30);
564
565         talloc_new(p1);
566
567         p2 = talloc_realloc_size(p1, p2, 40);
568
569         CHECK_SIZE("realloc", p2, 40);
570         CHECK_SIZE("realloc", root, 60);
571         CHECK_BLOCKS("realloc", p1, 4);
572
573         p1 = talloc_realloc_size(NULL, p1, 20);
574         CHECK_SIZE("realloc", p1, 60);
575
576         talloc_increase_ref_count(p2);
577         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
578                 "failed: talloc_realloc() on a referenced pointer should fail\n");
579         CHECK_BLOCKS("realloc", p1, 4);
580
581         talloc_realloc_size(NULL, p2, 0);
582         talloc_realloc_size(NULL, p2, 0);
583         CHECK_BLOCKS("realloc", p1, 3);
584
585         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
586                 "failed: oversize talloc should fail\n");
587
588         talloc_realloc_size(NULL, p1, 0);
589
590         CHECK_BLOCKS("realloc", root, 1);
591         CHECK_SIZE("realloc", root, 0);
592
593 // get rid of next line when loop detection works
594         talloc_unlink(NULL, p2);
595         talloc_free(root);
596
597         printf("success: realloc\n");
598
599         return true;
600 }
601
602 /*
603   test realloc with a child
604 */
605 static bool test_realloc_child(void)
606 {
607         void *root;
608         struct el2 {
609                 const char *name;
610         } *el2; 
611         struct el1 {
612                 int count;
613                 struct el2 **list, **list2, **list3;
614         } *el1;
615
616         printf("test: REALLOC WITH CHILD\n");
617         talloc_erase_no_owner_context();
618
619         root = talloc_new(NULL);
620
621         el1 = talloc(root, struct el1);
622         el1->list = talloc(el1, struct el2 *);
623         el1->list[0] = talloc(el1->list, struct el2);
624         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
625
626         el1->list2 = talloc(el1, struct el2 *);
627         el1->list2[0] = talloc(el1->list2, struct el2);
628         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
629
630         el1->list3 = talloc(el1, struct el2 *);
631         el1->list3[0] = talloc(el1->list3, struct el2);
632         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
633         
634         el2 = talloc(el1->list, struct el2);
635         el2 = talloc(el1->list2, struct el2);
636         el2 = talloc(el1->list3, struct el2);
637
638         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
639         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
640         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
641
642         talloc_free(root);
643
644         printf("success: REALLOC WITH CHILD\n");
645         return true;
646 }
647
648 /*
649   test type checking
650 */
651 static bool test_type(void)
652 {
653         void *root;
654         struct el1 {
655                 int count;
656         };
657         struct el2 {
658                 int count;
659         };
660         struct el1 *el1;
661
662         printf("test: type\n# talloc type checking\n");
663         talloc_erase_no_owner_context();
664
665         root = talloc_new(NULL);
666
667         el1 = talloc(root, struct el1);
668
669         el1->count = 1;
670
671         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
672                 "type check failed on el1\n");
673         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
674                 "type check failed on el1 with el2\n");
675         talloc_set_type(el1, struct el2);
676         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
677                 "type set failed on el1 with el2\n");
678
679         talloc_free(root);
680
681         printf("success: type\n");
682         return true;
683 }
684
685 /*
686   test steal
687 */
688 static bool test_steal(void)
689 {
690         void *root, *p1, *p2;
691
692         printf("test: steal\n# STEAL\n");
693         talloc_erase_no_owner_context();
694         talloc_report_full(NULL, stderr);
695
696         root = talloc_new(NULL);
697
698         p1 = talloc_array(root, char, 10);
699         CHECK_SIZE("steal", p1, 10);
700
701         p2 = talloc_realloc(root, NULL, char, 20);
702         CHECK_SIZE("steal", p1, 10);
703         CHECK_SIZE("steal", root, 30);
704
705         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
706                 "failed: stealing NULL should give NULL\n");
707
708         torture_assert("steal", talloc_steal(p1, p1) == p1,
709                 "failed: stealing to ourselves is a nop\n");
710         CHECK_BLOCKS("steal", root, 3);
711         CHECK_SIZE("steal", root, 30);
712
713         talloc_steal(NULL, p1);
714         talloc_steal(NULL, p2);
715         CHECK_BLOCKS("steal", root, 1);
716         CHECK_SIZE("steal", root, 0);
717
718         talloc_free(p1);
719         talloc_steal(root, p2);
720         CHECK_BLOCKS("steal", root, 2);
721         CHECK_SIZE("steal", root, 20);
722         
723         talloc_free(p2);
724
725         CHECK_BLOCKS("steal", root, 1);
726         CHECK_SIZE("steal", root, 0);
727
728         talloc_free(root);
729
730         p1 = talloc_size(NULL, 3);
731         talloc_report_full(NULL, stderr);
732         CHECK_SIZE("steal", NULL, 3);
733         talloc_free(p1);
734
735         printf("success: steal\n");
736         return true;
737 }
738
739 /*
740   test move
741 */
742 static bool test_move(void)
743 {
744         void *root;
745         struct t_move {
746                 char *p;
747                 int *x;
748         } *t1, *t2;
749
750         printf("test: move\n# MOVE\n");
751         talloc_erase_no_owner_context();
752
753         root = talloc_new(NULL);
754
755         t1 = talloc(root, struct t_move);
756         t2 = talloc(root, struct t_move);
757         t1->p = talloc_strdup(t1, "foo");
758         t1->x = talloc(t1, int);
759         *t1->x = 42;
760
761         t2->p = talloc_move(t2, &t1->p);
762         t2->x = talloc_move(t2, &t1->x);
763         torture_assert("move", t1->p == NULL && t1->x == NULL &&
764             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
765                 "talloc move failed");
766
767         talloc_free(root);
768
769         printf("success: move\n");
770
771         return true;
772 }
773
774 /*
775   test talloc_realloc_fn
776 */
777 static bool test_realloc_fn(void)
778 {
779         void *root, *p1;
780
781         printf("test: realloc_fn\n# talloc_realloc_fn\n");
782         talloc_erase_no_owner_context();
783
784         root = talloc_new(NULL);
785
786         p1 = talloc_realloc_fn(root, NULL, 10);
787         CHECK_BLOCKS("realloc_fn", root, 2);
788         CHECK_SIZE("realloc_fn", root, 10);
789         p1 = talloc_realloc_fn(root, p1, 20);
790         CHECK_BLOCKS("realloc_fn", root, 2);
791         CHECK_SIZE("realloc_fn", root, 20);
792         p1 = talloc_realloc_fn(root, p1, 0);
793         CHECK_BLOCKS("realloc_fn", root, 1);
794         CHECK_SIZE("realloc_fn", root, 0);
795
796         talloc_free(root);
797
798         printf("success: realloc_fn\n");
799         return true;
800 }
801
802
803 static bool test_unref_reparent(void)
804 {
805         void *root, *p1, *p2, *c1;
806
807         printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
808         talloc_erase_no_owner_context();
809
810         root = talloc_named_const(NULL, 0, "root");
811         p1 = talloc_named_const(root, 1, "orig parent");
812         p2 = talloc_named_const(root, 1, "parent by reference");
813
814         c1 = talloc_named_const(p1, 1, "child");
815         talloc_reference(p2, c1);
816
817         CHECK_PARENT("unref_reparent", c1, p1);
818
819         talloc_free(p1);
820
821 //  parent will not be p2, but no_owner_context
822 //      CHECK_PARENT("unref_reparent", c1, p2);
823
824         talloc_unlink(p2, c1);
825
826         CHECK_SIZE("unref_reparent", root, 1);
827
828         talloc_free(p2);
829         talloc_free(root);
830
831         printf("success: unref_reparent\n");
832         return true;
833 }
834
835 /* If a referenced allocation is explicitly freed the new owner
836    should be the same as if the same allocation is implicitly freed
837    (because it's owner was freed).
838    Traditionally in talloc an explicit free will free the top non-child reference
839    but an implicit free will move the top (any) reference to be the new owner */
840 static bool test_implicit_explicit_free(void)
841 {
842         void *root, *p1, *p2, *p3, *ref, *r1;
843         int e, i;
844
845         printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE IMPLICIT FREE\n");
846         talloc_erase_no_owner_context();
847
848         root = talloc_named_const(NULL, 0, "root");
849         p1 = talloc_named_const(root, 1, "p1");
850         p2 = talloc_named_const(p1, 1, "p2");
851         /* Now root owns p1, and p1 owns p2 */
852
853         r1 = talloc_named_const(root, 1, "r1");
854         ref = talloc_reference(r1, p2);
855         /* now r1 has ref reference to p2 */
856         talloc_report_full(root, stderr);
857
858         CHECK_BLOCKS(__FUNCTION__, p1, 2);
859         CHECK_BLOCKS(__FUNCTION__, p2, 1);
860         CHECK_BLOCKS(__FUNCTION__, r1, 2);
861
862         fprintf(stderr, "Freeing p2\n");
863         talloc_free(p2);
864         /* how many blocks is r1 taking against p2 ? */
865         e=talloc_total_blocks(r1);
866
867         talloc_report_full(root, stderr);
868         talloc_free(root);
869
870         /* now repeat, but this time free p1 */
871         printf("# SINGLE REFERENCE EXPLICIT FREE\n");
872
873         root = talloc_named_const(NULL, 0, "root");
874         p1 = talloc_named_const(root, 1, "p1");
875         p2 = talloc_named_const(p1, 1, "p2");
876         /* Now root owns p1, and p1 owns p2 */
877
878         r1 = talloc_named_const(root, 1, "r1");
879         ref = talloc_reference(r1, p2);
880         /* now r1 has ref reference to p2 */
881         talloc_report_full(NULL, stderr);
882
883         CHECK_BLOCKS(__FUNCTION__, p1, 2);
884         CHECK_BLOCKS(__FUNCTION__, p2, 1);
885         CHECK_BLOCKS(__FUNCTION__, r1, 2);
886
887         fprintf(stderr, "Freeing p1\n");
888         talloc_free(p1);
889         /* how many blocks is r1 taking against p2 ? */
890         i=talloc_total_blocks(r1);
891         talloc_report_full(root, stderr);
892
893         CHECK_BLOCKS("Implicit",r1, e);
894
895         talloc_free(root);
896
897         printf("success: ref1\n");
898         return true;
899 }
900
901 /* If take r1 reference to p2 and then free p2's parent
902    p2 should still be around by virtue of the reference.
903    In current talloc r1 will be the parent
904    In proposed talloc r1 will be the reference with no parent */
905 static bool test_ref_free_owner(void)
906 {
907         void *root, *p1, *p2, *p3, *ref, *r1;
908
909         printf("test: ref_free_owner\n# SINGLE REFERENCE FREE OWNER FREE\n");
910         talloc_erase_no_owner_context();
911
912         root = talloc_named_const(NULL, 0, "root");
913         p1 = talloc_named_const(root, 1, "p1");
914         p2 = talloc_named_const(p1, 1, "p2");
915         p3 = talloc_named_const(root, 1, "p3");
916         /* Now root owns p1 ,and p2 owns p2 */
917
918         r1 = talloc_named_const(root, 1, "r1");
919         ref = talloc_reference(r1, p2);
920         /* now r1 has ref reference to p2 */
921         talloc_report_full(root, stderr);
922
923         CHECK_BLOCKS(__FUNCTION__, p1, 2);
924         CHECK_BLOCKS(__FUNCTION__, p2, 1);
925         CHECK_BLOCKS(__FUNCTION__, r1, 2);
926
927         fprintf(stderr, "Freeing p1\n");
928         talloc_free(p1);
929         /* r1 should have ref reference to p2 still */
930         talloc_report_full(NULL, stderr);
931         CHECK_BLOCKS(__FUNCTION__, r1, 2);
932
933         /* if we talloc_steal p2 to p3, r1 should still have a reference
934            (unless it had been made the parent like in old talloc */
935         fprintf(stderr, "Stealing p2 to p3\n");
936         talloc_steal(p3, p2);
937         talloc_report_full(NULL, stderr);
938         CHECK_BLOCKS(__FUNCTION__, r1, 2);
939
940         /* now we free p3 and r1 should still have a reference */
941         fprintf(stderr, "free p3\n");
942         talloc_free(p3);
943         talloc_report_full(NULL, stderr);
944         CHECK_BLOCKS(__FUNCTION__, r1, 2);
945
946         /* if we free r1 then p2 should vanish */
947         fprintf(stderr, "Freeing r1\n");
948         talloc_free(r1);
949
950         talloc_report_full(NULL, stderr);
951         CHECK_BLOCKS(__FUNCTION__, root, 1);
952
953         talloc_free(root);
954         printf("success: ref1\n");
955         return true;
956 }
957
958 /* If take r1 reference to p2 and then free p2
959    p2 should still be around by virtue of the reference.
960    In current talloc r1 will be the parent
961    In proposed talloc r1 will be the reference with no parent */
962 static bool test_ref_free_self(void)
963 {
964         void *root, *p1, *p2, *p3, *ref, *r1;
965
966         printf("test: ref_free_self\n# SINGLE REFERENCE FREE SELF FREE\n");
967         talloc_erase_no_owner_context();
968
969         root = talloc_named_const(NULL, 0, "root");
970         p1 = talloc_named_const(root, 1, "p1");
971         p2 = talloc_named_const(p1, 1, "p2");
972         p3 = talloc_named_const(root, 1, "p3");
973         /* Now root owns p1, and p1 owns p2 */
974
975         r1 = talloc_named_const(root, 1, "r1");
976         ref = talloc_reference(r1, p2);
977         /* now r1 has ref reference to p2 */
978         talloc_report_full(NULL, stderr);
979
980         CHECK_BLOCKS(__FUNCTION__, p1, 2);
981         CHECK_BLOCKS(__FUNCTION__, p2, 1);
982         CHECK_BLOCKS(__FUNCTION__, p3, 1);
983         CHECK_BLOCKS(__FUNCTION__, r1, 2);
984
985         fprintf(stderr, "Freeing p2\n");
986         talloc_free(p2);
987         /* r1 should have ref reference to p2 still */
988         talloc_report_full(NULL, stderr);
989         CHECK_BLOCKS(__FUNCTION__, r1, 2);
990
991         /* if we talloc_steal p2 to p3, r1 should still have a reference
992            (unless it had been made the parent like in old talloc */
993         fprintf(stderr, "Steal p2 to p3\n");
994         talloc_steal(p3, p2);
995         talloc_report_full(NULL, stderr);
996         CHECK_BLOCKS(__FUNCTION__, r1, 2);
997
998         /* now we free p3 and r1 should still have a reference */
999         fprintf(stderr, "free p3\n");
1000         talloc_free(p3);
1001         talloc_report_full(NULL, stderr);
1002         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1003
1004         /* if we free r1 then p2 should also vanish */
1005         fprintf(stderr, "Freeing r1\n");
1006         talloc_free(r1);
1007
1008         fprintf(stderr, "Checking that p1 is empty and freeing p1\n");
1009         CHECK_BLOCKS(__FUNCTION__, p1, 1);
1010         talloc_free(p1);
1011
1012         talloc_report_full(NULL, stderr);
1013         CHECK_BLOCKS(__FUNCTION__, root, 1);
1014
1015         talloc_free(root);
1016         printf("success: ref1\n");
1017         return true;
1018 }
1019
1020 /* check that an allocation that is freed while also referenced finally goes
1021    away when the reference is released */
1022 static bool test_ref_free(void)
1023 {
1024         void *root, *p1, *p2, *ref, *r1;
1025
1026         printf("test: test_ref_free\n# FREE ON SINGLE REFERENCE FREE\n");
1027         talloc_erase_no_owner_context();
1028
1029         root = talloc_named_const(NULL, 0, "root");
1030         p1 = talloc_named_const(root, 1, "p1");
1031         p2 = talloc_named_const(p1, 1, "p2");
1032         /* Now root owns p1, and p1 owns p2 */
1033
1034         r1 = talloc_named_const(root, 1, "r1");
1035         ref = talloc_reference(r1, p2);
1036         /* now r1 has ref reference to p2 */
1037         talloc_report_full(root, stderr);
1038
1039         CHECK_BLOCKS(__FUNCTION__, p1, 2);
1040         CHECK_BLOCKS(__FUNCTION__, p2, 1);
1041         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1042
1043         fprintf(stderr, "Freeing p2\n");
1044         talloc_free(p2);
1045         /* r1 should have ref reference to p2 still */
1046         talloc_report_full(root, stderr);
1047
1048         CHECK_BLOCKS(__FUNCTION__, p1, 1);
1049         CHECK_BLOCKS(__FUNCTION__, root, 4);
1050         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1051
1052         /* if we free r1 then p2 should also vanish */
1053         fprintf(stderr, "Freeing r1\n");
1054         talloc_free(r1);
1055         /* p2 should have gone away  */
1056         talloc_report_full(NULL, stderr);
1057         CHECK_BLOCKS(__FUNCTION__, root, 2);
1058         CHECK_BLOCKS(__FUNCTION__, p1, 1);
1059
1060         talloc_free(root);
1061         printf("success: ref1\n");
1062         return true;
1063 }
1064
1065 /* If an object having references from children that are also referenced is
1066    freed, the child reference will be removed, but the child will survive
1067    (because of it's reference) and the object will still be freed leaving
1068    a dangling reference */
1069 static bool test_dangling_loop(void)
1070 {
1071         void *root, *p1, *p2, *ref, *r1, *r2;
1072
1073         printf("test: %s\n# FREE ON SINGLE REFERENCE FREE\n",__FUNCTION__);
1074         talloc_erase_no_owner_context();
1075
1076         root = talloc_named_const(NULL, 0, "root");
1077         p1 = talloc_named_const(root, 1, "p1");
1078         p2 = talloc_named_const(p1, 1, "p2");
1079         /* Now root owns p1, and p1 owns p2 */
1080
1081         /* someone takes a ref on p2 */
1082         r1 = talloc_named_const(root, 1, "r1");
1083         ref = talloc_reference(r1, p2);
1084
1085         /* p2 takes a ref on p1 */
1086         talloc_reference(p2, p1);
1087
1088         talloc_report_full(NULL, stderr);
1089
1090         CHECK_BLOCKS(__FUNCTION__, root, 6);
1091         CHECK_BLOCKS(__FUNCTION__, p1, 3);
1092         CHECK_BLOCKS(__FUNCTION__, p2, 2);
1093         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1094
1095         /* talloc will wrongly spot a loop and free p2's ref, and then p1
1096            leaving a dangling pointer */
1097         fprintf(stderr, "Freeing p1\n");
1098         talloc_free(p1);
1099         /* p1 should not get freed as it is referenced from something (a child) that won't free */
1100         /* r1 should have ref reference to p2 still */
1101         talloc_report_full(NULL, stderr);
1102
1103         CHECK_BLOCKS(__FUNCTION__, root, 3);
1104         /* The ugly talloc de-child-looping code will delete p2's reference
1105            leaving p2 having a dangling pointer. p2's reference should remain */
1106         CHECK_BLOCKS(__FUNCTION__, p2, 2);
1107         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1108
1109         /* if we free r1 then p2 should also vanish as it is owned by something that
1110            is not owned, but we can't track that yet. Once p2 vanishes it's reference
1111            to p1 should vanish letting p1 vanish.
1112            We can often make sub-tree's from no-owner-context, by checking when references
1113            of things child-of no-owner-context die
1114         */
1115         fprintf(stderr, "Freeing r1\n");
1116         talloc_free(r1);
1117         talloc_report_full(NULL, stderr);
1118         CHECK_BLOCKS(__FUNCTION__, root, 1);
1119
1120         talloc_free(root);
1121         printf("success: ref1\n");
1122
1123         talloc_erase_no_owner_context();
1124         talloc_report_full(NULL, stderr);
1125         return true;
1126 }
1127
1128 /* If take r1 reference to p2 and then free p2's owner p1
1129    p2 should still be around by virtue of the reference.
1130    steal p2 to p3 and free p3.
1131    In current talloc p2 will be freed despite the reference.
1132    In proposed talloc r1 will be the reference with no parent for p2*/
1133 static bool test_ref_free_steal(void)
1134 {
1135         void *root, *p1, *p2, *p3, *ref, *r1;
1136
1137         printf("test: ref_free_self\n# SINGLE REFERENCE FREE SELF FREE\n");
1138         talloc_erase_no_owner_context();
1139
1140         root = talloc_named_const(NULL, 0, "root");
1141         p1 = talloc_named_const(root, 1, "p1");
1142         p2 = talloc_named_const(p1, 1, "p2");
1143         p3 = talloc_named_const(root, 1, "p3");
1144         /* Now root owns p1, and p1 owns p2 */
1145
1146         r1 = talloc_named_const(root, 1, "r1");
1147         ref = talloc_reference(r1, p2);
1148         /* now r1 has ref reference to p2 */
1149         talloc_report_full(NULL, stderr);
1150
1151         CHECK_BLOCKS(__FUNCTION__, p1, 2);
1152         CHECK_BLOCKS(__FUNCTION__, p2, 1);
1153         CHECK_BLOCKS(__FUNCTION__, p3, 1);
1154         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1155
1156         fprintf(stderr, "Freeing p1\n");
1157         talloc_free(p1);
1158         /* r1 should have ref reference to p2 still */
1159         talloc_report_full(NULL, stderr);
1160         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1161
1162         /* if we talloc_steal p2 to p3, r1 should still have a reference
1163            (unless it had been made the parent like in old talloc */
1164         fprintf(stderr, "Steal p2 to p3\n");
1165         talloc_steal(p3, p2);
1166         talloc_report_full(NULL, stderr);
1167         //CHECK_BLOCKS(__FUNCTION__, r1, 2);
1168
1169         /* now we free p3 and r1 should still have a reference */
1170         fprintf(stderr, "free p3\n");
1171         talloc_free(p3);
1172         talloc_report_full(NULL, stderr);
1173         CHECK_BLOCKS(__FUNCTION__, p2, 1);
1174         CHECK_BLOCKS(__FUNCTION__, r1, 2);
1175
1176         /* if we free r1 then p2 should also vanish */
1177         fprintf(stderr, "Freeing r1\n");
1178         talloc_free(r1);
1179
1180         talloc_report_full(NULL, stderr);
1181         CHECK_BLOCKS(__FUNCTION__, root, 1);
1182
1183         talloc_free(root);
1184         printf("success: ref1\n");
1185         return true;
1186 }
1187
1188 /*
1189   measure the speed of talloc versus malloc
1190 */
1191 static bool test_speed(void)
1192 {
1193         void *ctx = talloc_new(NULL);
1194         unsigned count;
1195         const int loop = 1000;
1196         int i;
1197         struct timeval tv;
1198
1199         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
1200         talloc_erase_no_owner_context();
1201
1202         tv = timeval_current();
1203         count = 0;
1204         do {
1205                 void *p1, *p2, *p3;
1206                 for (i=0;i<loop;i++) {
1207                         p1 = talloc_size(ctx, loop % 100);
1208                         p2 = talloc_strdup(p1, "foo bar");
1209                         p3 = talloc_size(p1, 300);
1210                         talloc_free(p1);
1211                 }
1212                 count += 3 * loop;
1213         } while (timeval_elapsed(&tv) < 5.0);
1214
1215         fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1216
1217         talloc_free(ctx);
1218
1219         ctx = talloc_pool(NULL, 1024);
1220
1221         tv = timeval_current();
1222         count = 0;
1223         do {
1224                 void *p1, *p2, *p3;
1225                 for (i=0;i<loop;i++) {
1226                         p1 = talloc_size(ctx, loop % 100);
1227                         p2 = talloc_strdup(p1, "foo bar");
1228                         p3 = talloc_size(p1, 300);
1229                         talloc_free_children(ctx);
1230                 }
1231                 count += 3 * loop;
1232         } while (timeval_elapsed(&tv) < 5.0);
1233
1234         talloc_free(ctx);
1235
1236         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1237
1238         tv = timeval_current();
1239         count = 0;
1240         do {
1241                 void *p1, *p2, *p3;
1242                 for (i=0;i<loop;i++) {
1243                         p1 = malloc(loop % 100);
1244                         p2 = strdup("foo bar");
1245                         p3 = malloc(300);
1246                         free(p1);
1247                         free(p2);
1248                         free(p3);
1249                 }
1250                 count += 3 * loop;
1251         } while (timeval_elapsed(&tv) < 5.0);
1252         fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1253
1254         printf("success: speed\n");
1255
1256         return true;
1257 }
1258
1259 static bool test_lifeless(void)
1260 {
1261         void *top = talloc_new(NULL);
1262         char *parent, *child; 
1263         void *child_owner = talloc_new(NULL);
1264
1265         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
1266         talloc_erase_no_owner_context();
1267
1268         parent = talloc_strdup(top, "parent");
1269         child = talloc_strdup(parent, "child");  
1270         (void)talloc_reference(child, parent);
1271         (void)talloc_reference(child_owner, child); 
1272         talloc_report_full(NULL, stderr);
1273         talloc_unlink(top, parent);
1274         /* parent is now owner by no_owner_context */
1275         talloc_report_full(NULL, stderr);
1276         talloc_free(child);
1277         /* child also has no owner, but is still referenced */
1278         talloc_report_full(NULL, stderr);
1279         /* top owns nothing anyway */
1280         talloc_free(top);
1281         /* child_owner has reference to child which is un-owned */
1282         talloc_free(child_owner);
1283 // child will already be free
1284 //      talloc_free(child);
1285
1286     /* prove that parent and child have been freed */
1287         talloc_report_full(NULL, stderr);
1288         CHECK_BLOCKS("lifeless", talloc_no_owner_context (), 1);
1289
1290         printf("success: lifeless\n");
1291         return true;
1292 }
1293
1294 static int loop_destructor_count;
1295
1296 static int test_loop_destructor(char *ptr)
1297 {
1298         loop_destructor_count++;
1299         return 0;
1300 }
1301
1302 static bool test_loop(void)
1303 {
1304         void *top = talloc_new(NULL);
1305         char *parent;
1306         struct req1 {
1307                 char *req2, *req3;
1308         } *req1;
1309
1310         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
1311         talloc_erase_no_owner_context();
1312
1313         parent = talloc_strdup(top, "parent");
1314         req1 = talloc(parent, struct req1);
1315         req1->req2 = talloc_strdup(req1, "req2");  
1316         talloc_set_destructor(req1->req2, test_loop_destructor);
1317         req1->req3 = talloc_strdup(req1, "req3");
1318         (void)talloc_reference(req1->req3, req1);
1319         talloc_report_full(top, stderr);
1320         talloc_free(parent);
1321         talloc_report_full(top, stderr);
1322         talloc_report_full(NULL, stderr);
1323         talloc_free(top);
1324
1325         torture_assert("loop", loop_destructor_count == 1, 
1326                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
1327         loop_destructor_count = 0;
1328
1329         printf("success: loop\n");
1330         return true;
1331 }
1332
1333 static int fail_destructor_str(char *ptr)
1334 {
1335         return -1;
1336 }
1337
1338 static bool test_free_parent_deny_child(void)
1339 {
1340         void *top = talloc_new(NULL);
1341         char *level1;
1342         char *level2;
1343         char *level3;
1344
1345         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1346         talloc_erase_no_owner_context();
1347
1348         level1 = talloc_strdup(top, "level1");
1349         level2 = talloc_strdup(level1, "level2");
1350         level3 = talloc_strdup(level2, "level3");
1351
1352         fprintf(stderr,"level1 %p\nlevel2 %p\nlevel3 %p\n", level1, level2, level3);
1353         talloc_set_destructor(level3, fail_destructor_str);
1354         talloc_free(level1);
1355         talloc_set_destructor(level3, NULL);
1356
1357 // should it be owned by no_owner_context or by top given that the destructor held it back?
1358 // we might want another chance at destructing...
1359 //      CHECK_PARENT("free_parent_deny_child", level3, top);
1360         CHECK_PARENT("free_parent_deny_child", level3, talloc_no_owner_context ());
1361
1362         talloc_free(top);
1363
1364         printf("success: free_parent_deny_child\n");
1365         return true;
1366 }
1367
1368 static bool test_talloc_ptrtype(void)
1369 {
1370         void *top = talloc_new(NULL);
1371         struct struct1 {
1372                 int foo;
1373                 int bar;
1374         } *s1, *s2, **s3, ***s4;
1375         const char *location1;
1376         const char *location2;
1377         const char *location3;
1378         const char *location4;
1379
1380         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1381         talloc_erase_no_owner_context();
1382
1383         s1 = talloc_ptrtype(top, s1);location1 = __location__;
1384
1385         if (talloc_get_size(s1) != sizeof(struct struct1)) {
1386                 printf("failure: ptrtype [\n"
1387                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1388                   "]\n", (unsigned long)talloc_get_size(s1),
1389                            (unsigned long)sizeof(struct struct1));
1390                 return false;
1391         }
1392
1393         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1394                 printf("failure: ptrtype [\n"
1395                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1396                         talloc_get_name(s1), location1);
1397                 return false;
1398         }
1399
1400         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1401
1402         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1403                 printf("failure: ptrtype [\n"
1404                            "talloc_array_ptrtype() allocated the wrong size "
1405                        "%lu (should be %lu)\n]\n",
1406                         (unsigned long)talloc_get_size(s2),
1407                     (unsigned long)(sizeof(struct struct1)*10));
1408                 return false;
1409         }
1410
1411         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1412                 printf("failure: ptrtype [\n"
1413                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1414                         talloc_get_name(s2), location2);
1415                 return false;
1416         }
1417
1418         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1419
1420         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1421                 printf("failure: ptrtype [\n"
1422                            "talloc_array_ptrtype() allocated the wrong size "
1423                        "%lu (should be %lu)\n]\n",
1424                            (unsigned long)talloc_get_size(s3),
1425                        (unsigned long)(sizeof(struct struct1 *)*10));
1426                 return false;
1427         }
1428
1429         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1430                 "talloc_array_ptrtype() sets the wrong name");
1431
1432         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1433
1434         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1435                 printf("failure: ptrtype [\n"
1436                       "talloc_array_ptrtype() allocated the wrong size "
1437                        "%lu (should be %lu)\n]\n",
1438                            (unsigned long)talloc_get_size(s4),
1439                        (unsigned long)(sizeof(struct struct1 **)*10));
1440                 return false;
1441         }
1442
1443         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1444                 "talloc_array_ptrtype() sets the wrong name");
1445
1446         talloc_free(top);
1447
1448         printf("success: ptrtype\n");
1449         return true;
1450 }
1451
1452 static int _test_talloc_free_in_destructor(void **ptr)
1453 {
1454         talloc_free(*ptr);
1455         return 0;
1456 }
1457
1458 static bool test_talloc_free_in_destructor(void)
1459 {
1460         void *level0;
1461         void *level1;
1462         void *level2;
1463         void *level3;
1464         void *level4;
1465         void **level5;
1466
1467         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1468         talloc_erase_no_owner_context();
1469
1470         level0 = talloc_new(NULL);
1471         level1 = talloc_new(level0);
1472         level2 = talloc_new(level1);
1473         level3 = talloc_new(level2);
1474         level4 = talloc_new(level3);
1475         level5 = talloc(level4, void *);
1476
1477         *level5 = level3;
1478         (void)talloc_reference(level0, level3);
1479         (void)talloc_reference(level3, level3);
1480         (void)talloc_reference(level5, level3);
1481
1482         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1483
1484         talloc_free(level1);
1485
1486         talloc_free(level0);
1487
1488         printf("success: free_in_destructor\n");
1489         return true;
1490 }
1491
1492 static bool test_autofree(void)
1493 {
1494 #if _SAMBA_BUILD_ < 4
1495         /* autofree test would kill smbtorture */
1496         void *p;
1497         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1498         talloc_erase_no_owner_context();
1499
1500         p = talloc_autofree_context();
1501         talloc_free(p);
1502
1503         p = talloc_autofree_context();
1504         talloc_free(p);
1505
1506         printf("success: autofree\n");
1507 #endif
1508         return true;
1509 }
1510
1511 static bool test_pool(void)
1512 {
1513         void *pool;
1514         void *p1, *p2, *p3, *p4;
1515
1516         pool = talloc_pool(NULL, 1024);
1517
1518         p1 = talloc_size(pool, 80);
1519         p2 = talloc_size(pool, 20);
1520         p3 = talloc_size(p1, 50);
1521         p4 = talloc_size(p3, 1000);
1522
1523         talloc_free(pool);
1524
1525         return true;
1526 }
1527
1528 struct torture_context;
1529 bool torture_local_talloc(struct torture_context *tctx)
1530 {
1531         bool ret = true;
1532
1533         setlinebuf(stdout);
1534
1535         talloc_disable_null_tracking();
1536         talloc_enable_null_tracking();
1537
1538         ret &= test_ref1();
1539         ret &= test_ref2();
1540         ret &= test_ref3();
1541         ret &= test_ref4();
1542         ret &= test_unlink1(); 
1543         ret &= test_misc();
1544         ret &= test_realloc();
1545         ret &= test_realloc_child(); 
1546         ret &= test_steal(); 
1547         ret &= test_move(); 
1548         ret &= test_unref_reparent();
1549         ret &= test_realloc_fn(); 
1550         ret &= test_type();
1551         ret &= test_lifeless(); 
1552         ret &= test_loop();
1553         ret &= test_free_parent_deny_child(); 
1554         ret &= test_talloc_ptrtype();
1555         ret &= test_talloc_free_in_destructor();
1556         ret &= test_implicit_explicit_free();
1557         ret &= test_dangling_loop();
1558         ret &= test_ref_free_steal();
1559         ret &= test_ref_free_owner();
1560         ret &= test_ref_free_self();
1561         ret &= test_ref_free();
1562         ret &= test_pool();
1563
1564         if (ret) {
1565                 ret &= test_speed();
1566         }
1567         ret &= test_autofree();
1568
1569         return ret;
1570 }