6057fc11c5fea4317495957d0596c9f2a37d5cbe
[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: ref1\n");
903         return true;
904 }
905
906 /* If take r1 reference to p2 and then free p2's owner p1
907    p2 should still be around by virtue of the reference.
908    steal p2 to p3 and free p3.
909    In current talloc p2 will be freed despite the reference.
910    In proposed talloc r1 will be the reference with no parent for p2*/
911 static bool test_ref_free_steal(void)
912 {
913         void *root, *p1, *p2, *p3, *ref, *r1;
914
915         printf("test: ref_free_self\n# SINGLE REFERENCE FREE SELF FREE\n");
916         talloc_erase_no_owner_context();
917
918         root = talloc_named_const(NULL, 0, "root");
919         p1 = talloc_named_const(root, 1, "p1");
920         p2 = talloc_named_const(p1, 1, "p2");
921         p3 = talloc_named_const(root, 1, "p3");
922         /* Now root owns p1, and p1 owns p2 */
923
924         r1 = talloc_named_const(root, 1, "r1");
925         ref = talloc_reference(r1, p2);
926         /* now r1 has ref reference to p2 */
927         talloc_report_full(NULL, stderr);
928
929         CHECK_BLOCKS(__FUNCTION__, p1, 2);
930         CHECK_BLOCKS(__FUNCTION__, p2, 1);
931         CHECK_BLOCKS(__FUNCTION__, p3, 1);
932         CHECK_BLOCKS(__FUNCTION__, r1, 2);
933
934         fprintf(stderr, "Freeing p1\n");
935         talloc_free(p1);
936         /* r1 should have ref reference to p2 still */
937         talloc_report_full(NULL, stderr);
938         CHECK_BLOCKS(__FUNCTION__, r1, 2);
939
940         /* if we talloc_steal p2 to p3, r1 should still have a reference
941            (unless it had been made the parent like in old talloc */
942         fprintf(stderr, "Steal p2 to p3\n");
943         talloc_steal(p3, p2);
944         talloc_report_full(NULL, stderr);
945         //CHECK_BLOCKS(__FUNCTION__, r1, 2);
946
947         /* now we free p3 and r1 should still have a reference */
948         fprintf(stderr, "free p3\n");
949         talloc_free(p3);
950         talloc_report_full(NULL, stderr);
951         CHECK_BLOCKS(__FUNCTION__, p2, 1);
952         CHECK_BLOCKS(__FUNCTION__, r1, 2);
953
954         /* if we free r1 then p2 should also vanish */
955         fprintf(stderr, "Freeing r1\n");
956         talloc_free(r1);
957
958         talloc_report_full(NULL, stderr);
959         CHECK_BLOCKS(__FUNCTION__, root, 1);
960
961         talloc_free(root);
962         printf("success: ref1\n");
963         return true;
964 }
965
966 /*
967   measure the speed of talloc versus malloc
968 */
969 static bool test_speed(void)
970 {
971         void *ctx = talloc_new(NULL);
972         unsigned count;
973         const int loop = 1000;
974         int i;
975         struct timeval tv;
976
977         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
978
979         tv = timeval_current();
980         count = 0;
981         do {
982                 void *p1, *p2, *p3;
983                 for (i=0;i<loop;i++) {
984                         p1 = talloc_size(ctx, loop % 100);
985                         p2 = talloc_strdup(p1, "foo bar");
986                         p3 = talloc_size(p1, 300);
987                         talloc_free(p1);
988                 }
989                 count += 3 * loop;
990         } while (timeval_elapsed(&tv) < 5.0);
991
992         fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
993
994         talloc_free(ctx);
995
996         ctx = talloc_pool(NULL, 1024);
997
998         tv = timeval_current();
999         count = 0;
1000         do {
1001                 void *p1, *p2, *p3;
1002                 for (i=0;i<loop;i++) {
1003                         p1 = talloc_size(ctx, loop % 100);
1004                         p2 = talloc_strdup(p1, "foo bar");
1005                         p3 = talloc_size(p1, 300);
1006                         talloc_free_children(ctx);
1007                 }
1008                 count += 3 * loop;
1009         } while (timeval_elapsed(&tv) < 5.0);
1010
1011         talloc_free(ctx);
1012
1013         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1014
1015         tv = timeval_current();
1016         count = 0;
1017         do {
1018                 void *p1, *p2, *p3;
1019                 for (i=0;i<loop;i++) {
1020                         p1 = malloc(loop % 100);
1021                         p2 = strdup("foo bar");
1022                         p3 = malloc(300);
1023                         free(p1);
1024                         free(p2);
1025                         free(p3);
1026                 }
1027                 count += 3 * loop;
1028         } while (timeval_elapsed(&tv) < 5.0);
1029         fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1030
1031         printf("success: speed\n");
1032
1033         return true;
1034 }
1035
1036 static bool test_lifeless(void)
1037 {
1038         void *top = talloc_named_const(NULL, 0, "top");
1039         char *parent, *child; 
1040         void *child_owner = talloc_named_const(NULL, 0, "child_owner");
1041
1042         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
1043
1044         parent = talloc_strdup(top, "parent");
1045         CHECK_BLOCKS("lifeless", NULL, 5);
1046         child = talloc_strdup(parent, "child");  
1047         CHECK_BLOCKS("lifeless", NULL, 6);
1048         (void)talloc_reference(child, parent);
1049         CHECK_BLOCKS("lifeless", NULL, 7);
1050         (void)talloc_reference(child_owner, child); 
1051         CHECK_BLOCKS("lifeless", NULL, 8);
1052         CHECK_BLOCKS("lifeless", top, 4);
1053         CHECK_BLOCKS("lifeless", child_owner, 2);
1054         talloc_unlink(top, parent);
1055         CHECK_BLOCKS("lifeless", NULL, 8);
1056         CHECK_BLOCKS("lifeless", top, 1);
1057         CHECK_BLOCKS("lifeless", child_owner, 2);
1058         CHECK_BLOCKS("lifeless", child, 2);
1059         talloc_free(child);
1060         CHECK_BLOCKS("lifeless", NULL, 8);
1061         CHECK_BLOCKS("lifeless", top, 1);
1062         CHECK_BLOCKS("lifeless", child_owner, 2);
1063         CHECK_BLOCKS("lifeless", child, 2);
1064         talloc_free(top);
1065         CHECK_BLOCKS("lifeless", NULL, 7);
1066         CHECK_BLOCKS("lifeless", child_owner, 2);
1067         CHECK_BLOCKS("lifeless", child, 2);
1068         talloc_free(child_owner);
1069         CHECK_BLOCKS("lifeless", NULL, 2);
1070
1071         printf("success: lifeless\n");
1072         return true;
1073 }
1074
1075 static int loop_destructor_count;
1076
1077 static int test_loop_destructor(char *ptr)
1078 {
1079         loop_destructor_count++;
1080         return 0;
1081 }
1082
1083 static bool test_loop(void)
1084 {
1085         void *top = talloc_new(NULL);
1086         char *parent;
1087         struct req1 {
1088                 char *req2, *req3;
1089         } *req1;
1090
1091         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
1092
1093         parent = talloc_strdup(top, "parent");
1094         req1 = talloc(parent, struct req1);
1095         req1->req2 = talloc_strdup(req1, "req2");  
1096         talloc_set_destructor(req1->req2, test_loop_destructor);
1097         req1->req3 = talloc_strdup(req1, "req3");
1098         (void)talloc_reference(req1->req3, req1);
1099         talloc_report_full(top, stderr);
1100         talloc_free(parent);
1101         talloc_report_full(top, stderr);
1102         talloc_report_full(NULL, stderr);
1103         talloc_free(top);
1104
1105         torture_assert("loop", loop_destructor_count == 1, 
1106                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
1107         loop_destructor_count = 0;
1108
1109         printf("success: loop\n");
1110         return true;
1111 }
1112
1113 static int fail_destructor_str(char *ptr)
1114 {
1115         return -1;
1116 }
1117
1118 static bool test_free_parent_deny_child(void)
1119 {
1120         void *top = talloc_new(NULL);
1121         char *level1;
1122         char *level2;
1123         char *level3;
1124
1125         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1126
1127         level1 = talloc_strdup(top, "level1");
1128         level2 = talloc_strdup(level1, "level2");
1129         level3 = talloc_strdup(level2, "level3");
1130
1131         talloc_set_destructor(level3, fail_destructor_str);
1132         talloc_free(level1);
1133         talloc_set_destructor(level3, NULL);
1134
1135         CHECK_PARENT("free_parent_deny_child", level3, top);
1136
1137         talloc_free(top);
1138
1139         printf("success: free_parent_deny_child\n");
1140         return true;
1141 }
1142
1143 static bool test_talloc_ptrtype(void)
1144 {
1145         void *top = talloc_new(NULL);
1146         struct struct1 {
1147                 int foo;
1148                 int bar;
1149         } *s1, *s2, **s3, ***s4;
1150         const char *location1;
1151         const char *location2;
1152         const char *location3;
1153         const char *location4;
1154
1155         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1156
1157         s1 = talloc_ptrtype(top, s1);location1 = __location__;
1158
1159         if (talloc_get_size(s1) != sizeof(struct struct1)) {
1160                 printf("failure: ptrtype [\n"
1161                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1162                   "]\n", (unsigned long)talloc_get_size(s1),
1163                            (unsigned long)sizeof(struct struct1));
1164                 return false;
1165         }
1166
1167         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1168                 printf("failure: ptrtype [\n"
1169                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1170                         talloc_get_name(s1), location1);
1171                 return false;
1172         }
1173
1174         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1175
1176         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1177                 printf("failure: ptrtype [\n"
1178                            "talloc_array_ptrtype() allocated the wrong size "
1179                        "%lu (should be %lu)\n]\n",
1180                         (unsigned long)talloc_get_size(s2),
1181                     (unsigned long)(sizeof(struct struct1)*10));
1182                 return false;
1183         }
1184
1185         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1186                 printf("failure: ptrtype [\n"
1187                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1188                         talloc_get_name(s2), location2);
1189                 return false;
1190         }
1191
1192         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1193
1194         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1195                 printf("failure: ptrtype [\n"
1196                            "talloc_array_ptrtype() allocated the wrong size "
1197                        "%lu (should be %lu)\n]\n",
1198                            (unsigned long)talloc_get_size(s3),
1199                        (unsigned long)(sizeof(struct struct1 *)*10));
1200                 return false;
1201         }
1202
1203         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1204                 "talloc_array_ptrtype() sets the wrong name");
1205
1206         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1207
1208         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1209                 printf("failure: ptrtype [\n"
1210                       "talloc_array_ptrtype() allocated the wrong size "
1211                        "%lu (should be %lu)\n]\n",
1212                            (unsigned long)talloc_get_size(s4),
1213                        (unsigned long)(sizeof(struct struct1 **)*10));
1214                 return false;
1215         }
1216
1217         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1218                 "talloc_array_ptrtype() sets the wrong name");
1219
1220         talloc_free(top);
1221
1222         printf("success: ptrtype\n");
1223         return true;
1224 }
1225
1226 static int _test_talloc_free_in_destructor(void **ptr)
1227 {
1228         talloc_free(*ptr);
1229         return 0;
1230 }
1231
1232 static bool test_talloc_free_in_destructor(void)
1233 {
1234         void *level0;
1235         void *level1;
1236         void *level2;
1237         void *level3;
1238         void *level4;
1239         void **level5;
1240
1241         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1242
1243         level0 = talloc_new(NULL);
1244         level1 = talloc_new(level0);
1245         level2 = talloc_new(level1);
1246         level3 = talloc_new(level2);
1247         level4 = talloc_new(level3);
1248         level5 = talloc(level4, void *);
1249
1250         *level5 = level3;
1251         (void)talloc_reference(level0, level3);
1252         (void)talloc_reference(level3, level3);
1253         (void)talloc_reference(level5, level3);
1254
1255         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1256
1257         talloc_free(level1);
1258
1259         talloc_free(level0);
1260
1261         printf("success: free_in_destructor\n");
1262         return true;
1263 }
1264
1265 static bool test_autofree(void)
1266 {
1267 #if _SAMBA_BUILD_ < 4
1268         /* autofree test would kill smbtorture */
1269         void *p;
1270         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1271
1272         p = talloc_autofree_context();
1273         talloc_free(p);
1274
1275         p = talloc_autofree_context();
1276         talloc_free(p);
1277
1278         printf("success: autofree\n");
1279 #endif
1280         return true;
1281 }
1282
1283 static bool test_pool(void)
1284 {
1285         void *pool;
1286         void *p1, *p2, *p3, *p4;
1287
1288         pool = talloc_pool(NULL, 1024);
1289
1290         p1 = talloc_size(pool, 80);
1291         p2 = talloc_size(pool, 20);
1292         p3 = talloc_size(p1, 50);
1293         p4 = talloc_size(p3, 1000);
1294
1295         talloc_free(pool);
1296
1297         return true;
1298 }
1299
1300 static void test_reset(void)
1301 {
1302         test_abort_stop();
1303         talloc_disable_null_tracking();
1304         talloc_enable_null_tracking();
1305 }
1306
1307 struct torture_context;
1308 bool torture_local_talloc(struct torture_context *tctx)
1309 {
1310         bool ret = true;
1311
1312         setlinebuf(stdout);
1313
1314         test_reset();
1315         ret &= test_ref1();
1316         test_reset();
1317         ret &= test_ref2();
1318         test_reset();
1319         ret &= test_ref3();
1320         test_reset();
1321         ret &= test_ref4();
1322         test_reset();
1323         ret &= test_unlink1(); 
1324         test_reset();
1325         ret &= test_misc();
1326         test_reset();
1327         ret &= test_realloc();
1328         test_reset();
1329         ret &= test_realloc_child(); 
1330         test_reset();
1331         ret &= test_steal(); 
1332         test_reset();
1333         ret &= test_move(); 
1334         test_reset();
1335         ret &= test_unref_reparent();
1336         test_reset();
1337         ret &= test_realloc_fn(); 
1338         test_reset();
1339         ret &= test_type();
1340         test_reset();
1341         ret &= test_lifeless(); 
1342         test_reset();
1343         ret &= test_loop();
1344         test_reset();
1345         ret &= test_free_parent_deny_child(); 
1346         test_reset();
1347         ret &= test_talloc_ptrtype();
1348         test_reset();
1349         ret &= test_talloc_free_in_destructor();
1350         test_reset();
1351         ret &= test_implicit_explicit_free();
1352         test_reset();
1353         ret &= test_ref_free_steal();
1354         test_reset();
1355         ret &= test_pool();
1356
1357         if (ret) {
1358                 test_reset();
1359                 ret &= test_speed();
1360         }
1361         test_reset();
1362         ret &= test_autofree();
1363
1364         test_reset();
1365
1366         return ret;
1367 }