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