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