6d0fe94479e3b80326e4159ad94f035d20dc0db1
[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 #ifdef HAVE_PTHREAD
31 #include <pthread.h>
32 #endif
33
34 #include "talloc_testsuite.h"
35
36 static struct timeval timeval_current(void)
37 {
38         struct timeval tv;
39         gettimeofday(&tv, NULL);
40         return tv;
41 }
42
43 static double timeval_elapsed(struct timeval *tv)
44 {
45         struct timeval tv2 = timeval_current();
46         return (tv2.tv_sec - tv->tv_sec) + 
47                (tv2.tv_usec - tv->tv_usec)*1.0e-6;
48 }
49
50 #define torture_assert(test, expr, str) if (!(expr)) { \
51         printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
52                 test, __location__, #expr, str); \
53         return false; \
54 }
55
56 #define torture_assert_str_equal(test, arg1, arg2, desc) \
57         if (arg1 == NULL && arg2 == NULL) {                             \
58         } else if (strcmp(arg1, arg2)) {                        \
59                 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
60                    test, __location__, arg1, arg2, desc); \
61                 return false; \
62         }
63
64 #define CHECK_SIZE(test, ptr, tsize) do { \
65         if (talloc_total_size(ptr) != (tsize)) { \
66                 printf("failed: %s [\n%s: wrong '%s' tree size: got %u  expected %u\n]\n", \
67                        test, __location__, #ptr, \
68                        (unsigned)talloc_total_size(ptr), \
69                        (unsigned)tsize); \
70                 talloc_report_full(ptr, stdout); \
71                 return false; \
72         } \
73 } while (0)
74
75 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
76         if (talloc_total_blocks(ptr) != (tblocks)) { \
77                 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u  expected %u\n]\n", \
78                        test, __location__, #ptr, \
79                        (unsigned)talloc_total_blocks(ptr), \
80                        (unsigned)tblocks); \
81                 talloc_report_full(ptr, stdout); \
82                 return false; \
83         } \
84 } while (0)
85
86 #define CHECK_PARENT(test, ptr, parent) do { \
87         if (talloc_parent(ptr) != (parent)) { \
88                 printf("failed: %s [\n%s: '%s' has wrong parent: got %p  expected %p\n]\n", \
89                        test, __location__, #ptr, \
90                        talloc_parent(ptr), \
91                        (parent)); \
92                 talloc_report_full(ptr, stdout); \
93                 talloc_report_full(parent, stdout); \
94                 talloc_report_full(NULL, stdout); \
95                 return false; \
96         } \
97 } while (0)
98
99 static unsigned int test_abort_count;
100
101 #if 0
102 static void test_abort_fn(const char *reason)
103 {
104         printf("# test_abort_fn(%s)\n", reason);
105         test_abort_count++;
106 }
107
108 static void test_abort_start(void)
109 {
110         test_abort_count = 0;
111         talloc_set_abort_fn(test_abort_fn);
112 }
113 #endif
114
115 static void test_abort_stop(void)
116 {
117         test_abort_count = 0;
118         talloc_set_abort_fn(NULL);
119 }
120
121 static void test_log_stdout(const char *message)
122 {
123         fprintf(stdout, "%s", message);
124 }
125
126 /*
127   test references 
128 */
129 static bool test_ref1(void)
130 {
131         void *root, *p1, *p2, *ref, *r1;
132
133         printf("test: ref1\n# SINGLE REFERENCE FREE\n");
134
135         root = talloc_named_const(NULL, 0, "root");
136         p1 = talloc_named_const(root, 1, "p1");
137         p2 = talloc_named_const(p1, 1, "p2");
138         talloc_named_const(p1, 1, "x1");
139         talloc_named_const(p1, 2, "x2");
140         talloc_named_const(p1, 3, "x3");
141
142         r1 = talloc_named_const(root, 1, "r1"); 
143         ref = talloc_reference(r1, p2);
144         talloc_report_full(root, stderr);
145
146         CHECK_BLOCKS("ref1", p1, 5);
147         CHECK_BLOCKS("ref1", p2, 1);
148         CHECK_BLOCKS("ref1", ref, 1);
149         CHECK_BLOCKS("ref1", r1, 2);
150
151         fprintf(stderr, "Freeing p2\n");
152         talloc_unlink(r1, p2);
153         talloc_report_full(root, stderr);
154
155         CHECK_BLOCKS("ref1", p1, 5);
156         CHECK_BLOCKS("ref1", p2, 1);
157         CHECK_BLOCKS("ref1", r1, 1);
158
159         fprintf(stderr, "Freeing p1\n");
160         talloc_free(p1);
161         talloc_report_full(root, stderr);
162
163         CHECK_BLOCKS("ref1", r1, 1);
164
165         fprintf(stderr, "Freeing r1\n");
166         talloc_free(r1);
167         talloc_report_full(NULL, stderr);
168
169         fprintf(stderr, "Testing NULL\n");
170         if (talloc_reference(root, NULL)) {
171                 return false;
172         }
173
174         CHECK_BLOCKS("ref1", root, 1);
175
176         CHECK_SIZE("ref1", root, 0);
177
178         talloc_free(root);
179         printf("success: ref1\n");
180         return true;
181 }
182
183 /*
184   test references 
185 */
186 static bool test_ref2(void)
187 {
188         void *root, *p1, *p2, *ref, *r1;
189
190         printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
191         root = talloc_named_const(NULL, 0, "root");
192         p1 = talloc_named_const(root, 1, "p1");
193         talloc_named_const(p1, 1, "x1");
194         talloc_named_const(p1, 1, "x2");
195         talloc_named_const(p1, 1, "x3");
196         p2 = talloc_named_const(p1, 1, "p2");
197
198         r1 = talloc_named_const(root, 1, "r1"); 
199         ref = talloc_reference(r1, p2);
200         talloc_report_full(root, stderr);
201
202         CHECK_BLOCKS("ref2", p1, 5);
203         CHECK_BLOCKS("ref2", p2, 1);
204         CHECK_BLOCKS("ref2", r1, 2);
205
206         fprintf(stderr, "Freeing ref\n");
207         talloc_unlink(r1, ref);
208         talloc_report_full(root, stderr);
209
210         CHECK_BLOCKS("ref2", p1, 5);
211         CHECK_BLOCKS("ref2", p2, 1);
212         CHECK_BLOCKS("ref2", r1, 1);
213
214         fprintf(stderr, "Freeing p2\n");
215         talloc_free(p2);
216         talloc_report_full(root, stderr);
217
218         CHECK_BLOCKS("ref2", p1, 4);
219         CHECK_BLOCKS("ref2", r1, 1);
220
221         fprintf(stderr, "Freeing p1\n");
222         talloc_free(p1);
223         talloc_report_full(root, stderr);
224
225         CHECK_BLOCKS("ref2", r1, 1);
226
227         fprintf(stderr, "Freeing r1\n");
228         talloc_free(r1);
229         talloc_report_full(root, stderr);
230
231         CHECK_SIZE("ref2", root, 0);
232
233         talloc_free(root);
234         printf("success: ref2\n");
235         return true;
236 }
237
238 /*
239   test references 
240 */
241 static bool test_ref3(void)
242 {
243         void *root, *p1, *p2, *ref, *r1;
244
245         printf("test: ref3\n# PARENT REFERENCE FREE\n");
246
247         root = talloc_named_const(NULL, 0, "root");
248         p1 = talloc_named_const(root, 1, "p1");
249         p2 = talloc_named_const(root, 1, "p2");
250         r1 = talloc_named_const(p1, 1, "r1");
251         ref = talloc_reference(p2, r1);
252         talloc_report_full(root, stderr);
253
254         CHECK_BLOCKS("ref3", p1, 2);
255         CHECK_BLOCKS("ref3", p2, 2);
256         CHECK_BLOCKS("ref3", r1, 1);
257         CHECK_BLOCKS("ref3", ref, 1);
258
259         fprintf(stderr, "Freeing p1\n");
260         talloc_free(p1);
261         talloc_report_full(root, stderr);
262
263         CHECK_BLOCKS("ref3", p2, 2);
264         CHECK_BLOCKS("ref3", r1, 1);
265
266         fprintf(stderr, "Freeing p2\n");
267         talloc_free(p2);
268         talloc_report_full(root, stderr);
269
270         CHECK_SIZE("ref3", root, 0);
271
272         talloc_free(root);
273
274         printf("success: ref3\n");
275         return true;
276 }
277
278 /*
279   test references 
280 */
281 static bool test_ref4(void)
282 {
283         void *root, *p1, *p2, *ref, *r1;
284
285         printf("test: ref4\n# REFERRER REFERENCE FREE\n");
286
287         root = talloc_named_const(NULL, 0, "root");
288         p1 = talloc_named_const(root, 1, "p1");
289         talloc_named_const(p1, 1, "x1");
290         talloc_named_const(p1, 1, "x2");
291         talloc_named_const(p1, 1, "x3");
292         p2 = talloc_named_const(p1, 1, "p2");
293
294         r1 = talloc_named_const(root, 1, "r1"); 
295         ref = talloc_reference(r1, p2);
296         talloc_report_full(root, stderr);
297
298         CHECK_BLOCKS("ref4", p1, 5);
299         CHECK_BLOCKS("ref4", p2, 1);
300         CHECK_BLOCKS("ref4", ref, 1);
301         CHECK_BLOCKS("ref4", r1, 2);
302
303         fprintf(stderr, "Freeing r1\n");
304         talloc_free(r1);
305         talloc_report_full(root, stderr);
306
307         CHECK_BLOCKS("ref4", p1, 5);
308         CHECK_BLOCKS("ref4", p2, 1);
309
310         fprintf(stderr, "Freeing p2\n");
311         talloc_free(p2);
312         talloc_report_full(root, stderr);
313
314         CHECK_BLOCKS("ref4", p1, 4);
315
316         fprintf(stderr, "Freeing p1\n");
317         talloc_free(p1);
318         talloc_report_full(root, stderr);
319
320         CHECK_SIZE("ref4", root, 0);
321
322         talloc_free(root);
323
324         printf("success: ref4\n");
325         return true;
326 }
327
328
329 /*
330   test references 
331 */
332 static bool test_unlink1(void)
333 {
334         void *root, *p1, *p2, *ref, *r1;
335
336         printf("test: unlink\n# UNLINK\n");
337
338         root = talloc_named_const(NULL, 0, "root");
339         p1 = talloc_named_const(root, 1, "p1");
340         talloc_named_const(p1, 1, "x1");
341         talloc_named_const(p1, 1, "x2");
342         talloc_named_const(p1, 1, "x3");
343         p2 = talloc_named_const(p1, 1, "p2");
344
345         r1 = talloc_named_const(p1, 1, "r1");   
346         ref = talloc_reference(r1, p2);
347         talloc_report_full(root, stderr);
348
349         CHECK_BLOCKS("unlink", p1, 7);
350         CHECK_BLOCKS("unlink", p2, 1);
351         CHECK_BLOCKS("unlink", ref, 1);
352         CHECK_BLOCKS("unlink", r1, 2);
353
354         fprintf(stderr, "Unreferencing r1\n");
355         talloc_unlink(r1, p2);
356         talloc_report_full(root, stderr);
357
358         CHECK_BLOCKS("unlink", p1, 6);
359         CHECK_BLOCKS("unlink", p2, 1);
360         CHECK_BLOCKS("unlink", r1, 1);
361
362         fprintf(stderr, "Freeing p1\n");
363         talloc_free(p1);
364         talloc_report_full(root, stderr);
365
366         CHECK_SIZE("unlink", root, 0);
367
368         talloc_free(root);
369
370         printf("success: unlink\n");
371         return true;
372 }
373
374 static int fail_destructor(void *ptr)
375 {
376         return -1;
377 }
378
379 /*
380   miscellaneous tests to try to get a higher test coverage percentage
381 */
382 static bool test_misc(void)
383 {
384         void *root, *p1;
385         char *p2;
386         double *d;
387         const char *name;
388
389         printf("test: misc\n# MISCELLANEOUS\n");
390
391         root = talloc_new(NULL);
392
393         p1 = talloc_size(root, 0x7fffffff);
394         torture_assert("misc", !p1, "failed: large talloc allowed\n");
395
396         p1 = talloc_strdup(root, "foo");
397         talloc_increase_ref_count(p1);
398         talloc_increase_ref_count(p1);
399         talloc_increase_ref_count(p1);
400         CHECK_BLOCKS("misc", p1, 1);
401         CHECK_BLOCKS("misc", root, 2);
402         talloc_unlink(NULL, p1);
403         CHECK_BLOCKS("misc", p1, 1);
404         CHECK_BLOCKS("misc", root, 2);
405         talloc_unlink(NULL, p1);
406         CHECK_BLOCKS("misc", p1, 1);
407         CHECK_BLOCKS("misc", root, 2);
408         p2 = talloc_strdup(p1, "foo");
409         torture_assert("misc", talloc_unlink(root, p2) == -1,
410                                    "failed: talloc_unlink() of non-reference context should return -1\n");
411         torture_assert("misc", talloc_unlink(p1, p2) == 0,
412                 "failed: talloc_unlink() of parent should succeed\n");
413         talloc_unlink(NULL, p1);
414         CHECK_BLOCKS("misc", p1, 1);
415         CHECK_BLOCKS("misc", root, 2);
416
417         name = talloc_set_name(p1, "my name is %s", "foo");
418         torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
419                 "failed: wrong name after talloc_set_name(my name is foo)");
420         torture_assert_str_equal("misc", talloc_get_name(p1), name,
421                 "failed: wrong name after talloc_set_name(my name is foo)");
422         CHECK_BLOCKS("misc", p1, 2);
423         CHECK_BLOCKS("misc", root, 3);
424
425         talloc_set_name_const(p1, NULL);
426         torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
427                 "failed: wrong name after talloc_set_name(NULL)");
428         CHECK_BLOCKS("misc", p1, 2);
429         CHECK_BLOCKS("misc", root, 3);
430
431         torture_assert("misc", talloc_free(NULL) == -1, 
432                                    "talloc_free(NULL) should give -1\n");
433
434         talloc_set_destructor(p1, fail_destructor);
435         torture_assert("misc", talloc_free(p1) == -1, 
436                 "Failed destructor should cause talloc_free to fail\n");
437         talloc_set_destructor(p1, NULL);
438
439         talloc_report(root, stderr);
440
441
442         p2 = (char *)talloc_zero_size(p1, 20);
443         torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
444         talloc_free(p2);
445
446         torture_assert("misc", talloc_strdup(root, NULL) == NULL,
447                 "failed: strdup on NULL should give NULL\n");
448
449         p2 = talloc_strndup(p1, "foo", 2);
450         torture_assert("misc", strcmp("fo", p2) == 0, 
451                                    "strndup doesn't work\n");
452         p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
453         torture_assert("misc", strcmp("food", p2) == 0, 
454                                    "talloc_asprintf_append_buffer doesn't work\n");
455         CHECK_BLOCKS("misc", p2, 1);
456         CHECK_BLOCKS("misc", p1, 3);
457
458         p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
459         torture_assert("misc", strcmp("hello world", p2) == 0,
460                 "talloc_asprintf_append_buffer doesn't work\n");
461         CHECK_BLOCKS("misc", p2, 1);
462         CHECK_BLOCKS("misc", p1, 3);
463         talloc_free(p2);
464
465         d = talloc_array(p1, double, 0x20000000);
466         torture_assert("misc", !d, "failed: integer overflow not detected\n");
467
468         d = talloc_realloc(p1, d, double, 0x20000000);
469         torture_assert("misc", !d, "failed: integer overflow not detected\n");
470
471         talloc_free(p1);
472         CHECK_BLOCKS("misc", root, 1);
473
474         p1 = talloc_named(root, 100, "%d bytes", 100);
475         CHECK_BLOCKS("misc", p1, 2);
476         CHECK_BLOCKS("misc", root, 3);
477         talloc_unlink(root, p1);
478
479         p1 = talloc_init("%d bytes", 200);
480         p2 = talloc_asprintf(p1, "my test '%s'", "string");
481         torture_assert_str_equal("misc", p2, "my test 'string'",
482                 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
483         CHECK_BLOCKS("misc", p1, 3);
484         CHECK_SIZE("misc", p2, 17);
485         CHECK_BLOCKS("misc", root, 1);
486         talloc_unlink(NULL, p1);
487
488         p1 = talloc_named_const(root, 10, "p1");
489         p2 = (char *)talloc_named_const(root, 20, "p2");
490         (void)talloc_reference(p1, p2);
491         talloc_report_full(root, stderr);
492         talloc_unlink(root, p2);
493         talloc_report_full(root, stderr);
494         CHECK_BLOCKS("misc", p2, 1);
495         CHECK_BLOCKS("misc", p1, 2);
496         CHECK_BLOCKS("misc", root, 3);
497         talloc_unlink(p1, p2);
498         talloc_unlink(root, p1);
499
500         p1 = talloc_named_const(root, 10, "p1");
501         p2 = (char *)talloc_named_const(root, 20, "p2");
502         (void)talloc_reference(NULL, p2);
503         talloc_report_full(root, stderr);
504         talloc_unlink(root, p2);
505         talloc_report_full(root, stderr);
506         CHECK_BLOCKS("misc", p2, 1);
507         CHECK_BLOCKS("misc", p1, 1);
508         CHECK_BLOCKS("misc", root, 2);
509         talloc_unlink(NULL, p2);
510         talloc_unlink(root, p1);
511
512         /* Test that talloc_unlink is a no-op */
513
514         torture_assert("misc", talloc_unlink(root, NULL) == -1,
515                 "failed: talloc_unlink(root, NULL) == -1\n");
516
517         talloc_report(root, stderr);
518         talloc_report(NULL, stderr);
519
520         CHECK_SIZE("misc", root, 0);
521
522         talloc_free(root);
523
524         CHECK_SIZE("misc", NULL, 0);
525
526         talloc_enable_null_tracking_no_autofree();
527         talloc_enable_leak_report();
528         talloc_enable_leak_report_full();
529
530         printf("success: misc\n");
531
532         return true;
533 }
534
535
536 /*
537   test realloc
538 */
539 static bool test_realloc(void)
540 {
541         void *root, *p1, *p2;
542
543         printf("test: realloc\n# REALLOC\n");
544
545         root = talloc_new(NULL);
546
547         p1 = talloc_size(root, 10);
548         CHECK_SIZE("realloc", p1, 10);
549
550         p1 = talloc_realloc_size(NULL, p1, 20);
551         CHECK_SIZE("realloc", p1, 20);
552
553         talloc_new(p1);
554
555         p2 = talloc_realloc_size(p1, NULL, 30);
556
557         talloc_new(p1);
558
559         p2 = talloc_realloc_size(p1, p2, 40);
560
561         CHECK_SIZE("realloc", p2, 40);
562         CHECK_SIZE("realloc", root, 60);
563         CHECK_BLOCKS("realloc", p1, 4);
564
565         p1 = talloc_realloc_size(NULL, p1, 20);
566         CHECK_SIZE("realloc", p1, 60);
567
568         talloc_increase_ref_count(p2);
569         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
570                 "failed: talloc_realloc() on a referenced pointer should fail\n");
571         CHECK_BLOCKS("realloc", p1, 4);
572
573         talloc_realloc_size(NULL, p2, 0);
574         talloc_realloc_size(NULL, p2, 0);
575         CHECK_BLOCKS("realloc", p1, 4);
576         talloc_realloc_size(p1, p2, 0);
577         CHECK_BLOCKS("realloc", p1, 3);
578
579         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
580                 "failed: oversize talloc should fail\n");
581
582         talloc_realloc_size(NULL, p1, 0);
583         CHECK_BLOCKS("realloc", root, 4);
584         talloc_realloc_size(root, p1, 0);
585         CHECK_BLOCKS("realloc", root, 1);
586
587         CHECK_SIZE("realloc", root, 0);
588
589         talloc_free(root);
590
591         printf("success: realloc\n");
592
593         return true;
594 }
595
596 /*
597   test realloc with a child
598 */
599 static bool test_realloc_child(void)
600 {
601         void *root;
602         struct el2 {
603                 const char *name;
604         } *el2; 
605         struct el1 {
606                 int count;
607                 struct el2 **list, **list2, **list3;
608         } *el1;
609
610         printf("test: REALLOC WITH CHILD\n");
611
612         root = talloc_new(NULL);
613
614         el1 = talloc(root, struct el1);
615         el1->list = talloc(el1, struct el2 *);
616         el1->list[0] = talloc(el1->list, struct el2);
617         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
618
619         el1->list2 = talloc(el1, struct el2 *);
620         el1->list2[0] = talloc(el1->list2, struct el2);
621         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
622
623         el1->list3 = talloc(el1, struct el2 *);
624         el1->list3[0] = talloc(el1->list3, struct el2);
625         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
626         
627         el2 = talloc(el1->list, struct el2);
628         el2 = talloc(el1->list2, struct el2);
629         el2 = talloc(el1->list3, struct el2);
630         (void)el2;
631
632         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
633         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
634         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
635
636         talloc_free(root);
637
638         printf("success: REALLOC WITH CHILD\n");
639         return true;
640 }
641
642 /*
643   test type checking
644 */
645 static bool test_type(void)
646 {
647         void *root;
648         struct el1 {
649                 int count;
650         };
651         struct el2 {
652                 int count;
653         };
654         struct el1 *el1;
655
656         printf("test: type\n# talloc type checking\n");
657
658         root = talloc_new(NULL);
659
660         el1 = talloc(root, struct el1);
661
662         el1->count = 1;
663
664         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
665                 "type check failed on el1\n");
666         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
667                 "type check failed on el1 with el2\n");
668         talloc_set_type(el1, struct el2);
669         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
670                 "type set failed on el1 with el2\n");
671
672         talloc_free(root);
673
674         printf("success: type\n");
675         return true;
676 }
677
678 /*
679   test steal
680 */
681 static bool test_steal(void)
682 {
683         void *root, *p1, *p2;
684
685         printf("test: steal\n# STEAL\n");
686
687         root = talloc_new(NULL);
688
689         p1 = talloc_array(root, char, 10);
690         CHECK_SIZE("steal", p1, 10);
691
692         p2 = talloc_realloc(root, NULL, char, 20);
693         CHECK_SIZE("steal", p1, 10);
694         CHECK_SIZE("steal", root, 30);
695
696         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
697                 "failed: stealing NULL should give NULL\n");
698
699         torture_assert("steal", talloc_steal(p1, p1) == p1,
700                 "failed: stealing to ourselves is a nop\n");
701         CHECK_BLOCKS("steal", root, 3);
702         CHECK_SIZE("steal", root, 30);
703
704         talloc_steal(NULL, p1);
705         talloc_steal(NULL, p2);
706         CHECK_BLOCKS("steal", root, 1);
707         CHECK_SIZE("steal", root, 0);
708
709         talloc_free(p1);
710         talloc_steal(root, p2);
711         CHECK_BLOCKS("steal", root, 2);
712         CHECK_SIZE("steal", root, 20);
713         
714         talloc_free(p2);
715
716         CHECK_BLOCKS("steal", root, 1);
717         CHECK_SIZE("steal", root, 0);
718
719         talloc_free(root);
720
721         p1 = talloc_size(NULL, 3);
722         talloc_report_full(NULL, stderr);
723         CHECK_SIZE("steal", NULL, 3);
724         talloc_free(p1);
725
726         printf("success: steal\n");
727         return true;
728 }
729
730 /*
731   test move
732 */
733 static bool test_move(void)
734 {
735         void *root;
736         struct t_move {
737                 char *p;
738                 int *x;
739         } *t1, *t2;
740
741         printf("test: move\n# MOVE\n");
742
743         root = talloc_new(NULL);
744
745         t1 = talloc(root, struct t_move);
746         t2 = talloc(root, struct t_move);
747         t1->p = talloc_strdup(t1, "foo");
748         t1->x = talloc(t1, int);
749         *t1->x = 42;
750
751         t2->p = talloc_move(t2, &t1->p);
752         t2->x = talloc_move(t2, &t1->x);
753         torture_assert("move", t1->p == NULL && t1->x == NULL &&
754             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
755                 "talloc move failed");
756
757         talloc_free(root);
758
759         printf("success: move\n");
760
761         return true;
762 }
763
764 /*
765   test talloc_realloc_fn
766 */
767 static bool test_realloc_fn(void)
768 {
769         void *root, *p1;
770
771         printf("test: realloc_fn\n# talloc_realloc_fn\n");
772
773         root = talloc_new(NULL);
774
775         p1 = talloc_realloc_fn(root, NULL, 10);
776         CHECK_BLOCKS("realloc_fn", root, 2);
777         CHECK_SIZE("realloc_fn", root, 10);
778         p1 = talloc_realloc_fn(root, p1, 20);
779         CHECK_BLOCKS("realloc_fn", root, 2);
780         CHECK_SIZE("realloc_fn", root, 20);
781         p1 = talloc_realloc_fn(root, p1, 0);
782         CHECK_BLOCKS("realloc_fn", root, 1);
783         CHECK_SIZE("realloc_fn", root, 0);
784
785         talloc_free(root);
786
787         printf("success: realloc_fn\n");
788         return true;
789 }
790
791
792 static bool test_unref_reparent(void)
793 {
794         void *root, *p1, *p2, *c1;
795
796         printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
797
798         root = talloc_named_const(NULL, 0, "root");
799         p1 = talloc_named_const(root, 1, "orig parent");
800         p2 = talloc_named_const(root, 1, "parent by reference");
801
802         c1 = talloc_named_const(p1, 1, "child");
803         talloc_reference(p2, c1);
804
805         CHECK_PARENT("unref_reparent", c1, p1);
806
807         talloc_free(p1);
808
809         CHECK_PARENT("unref_reparent", c1, p2);
810
811         talloc_unlink(p2, c1);
812
813         CHECK_SIZE("unref_reparent", root, 1);
814
815         talloc_free(p2);
816         talloc_free(root);
817
818         printf("success: unref_reparent\n");
819         return true;
820 }
821
822 /*
823   measure the speed of talloc versus malloc
824 */
825 static bool test_speed(void)
826 {
827         void *ctx = talloc_new(NULL);
828         unsigned count;
829         const int loop = 1000;
830         int i;
831         struct timeval tv;
832
833         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
834
835         tv = timeval_current();
836         count = 0;
837         do {
838                 void *p1, *p2, *p3;
839                 for (i=0;i<loop;i++) {
840                         p1 = talloc_size(ctx, loop % 100);
841                         p2 = talloc_strdup(p1, "foo bar");
842                         p3 = talloc_size(p1, 300);
843                         (void)p2;
844                         (void)p3;
845                         talloc_free(p1);
846                 }
847                 count += 3 * loop;
848         } while (timeval_elapsed(&tv) < 5.0);
849
850         fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
851
852         talloc_free(ctx);
853
854         ctx = talloc_pool(NULL, 1024);
855
856         tv = timeval_current();
857         count = 0;
858         do {
859                 void *p1, *p2, *p3;
860                 for (i=0;i<loop;i++) {
861                         p1 = talloc_size(ctx, loop % 100);
862                         p2 = talloc_strdup(p1, "foo bar");
863                         p3 = talloc_size(p1, 300);
864                         (void)p2;
865                         (void)p3;
866                         talloc_free(p1);
867                 }
868                 count += 3 * loop;
869         } while (timeval_elapsed(&tv) < 5.0);
870
871         talloc_free(ctx);
872
873         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
874
875         tv = timeval_current();
876         count = 0;
877         do {
878                 void *p1, *p2, *p3;
879                 for (i=0;i<loop;i++) {
880                         p1 = malloc(loop % 100);
881                         p2 = strdup("foo bar");
882                         p3 = malloc(300);
883                         free(p1);
884                         free(p2);
885                         free(p3);
886                 }
887                 count += 3 * loop;
888         } while (timeval_elapsed(&tv) < 5.0);
889         fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
890
891         printf("success: speed\n");
892
893         return true;
894 }
895
896 static bool test_lifeless(void)
897 {
898         void *top = talloc_new(NULL);
899         char *parent, *child; 
900         void *child_owner = talloc_new(NULL);
901
902         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
903
904         parent = talloc_strdup(top, "parent");
905         child = talloc_strdup(parent, "child");  
906         (void)talloc_reference(child, parent);
907         (void)talloc_reference(child_owner, child); 
908         talloc_report_full(top, stderr);
909         talloc_unlink(top, parent);
910         talloc_unlink(top, child);
911         talloc_report_full(top, stderr);
912         talloc_free(top);
913         talloc_free(child_owner);
914         talloc_free(child);
915
916         printf("success: lifeless\n");
917         return true;
918 }
919
920 static int loop_destructor_count;
921
922 static int test_loop_destructor(char *ptr)
923 {
924         loop_destructor_count++;
925         return 0;
926 }
927
928 static bool test_loop(void)
929 {
930         void *top = talloc_new(NULL);
931         char *parent;
932         struct req1 {
933                 char *req2, *req3;
934         } *req1;
935
936         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
937
938         parent = talloc_strdup(top, "parent");
939         req1 = talloc(parent, struct req1);
940         req1->req2 = talloc_strdup(req1, "req2");  
941         talloc_set_destructor(req1->req2, test_loop_destructor);
942         req1->req3 = talloc_strdup(req1, "req3");
943         (void)talloc_reference(req1->req3, req1);
944         talloc_report_full(top, stderr);
945         talloc_free(parent);
946         talloc_report_full(top, stderr);
947         talloc_report_full(NULL, stderr);
948         talloc_free(top);
949
950         torture_assert("loop", loop_destructor_count == 1, 
951                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
952         loop_destructor_count = 0;
953
954         printf("success: loop\n");
955         return true;
956 }
957
958 static int fail_destructor_str(char *ptr)
959 {
960         return -1;
961 }
962
963 static bool test_free_parent_deny_child(void)
964 {
965         void *top = talloc_new(NULL);
966         char *level1;
967         char *level2;
968         char *level3;
969
970         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
971
972         level1 = talloc_strdup(top, "level1");
973         level2 = talloc_strdup(level1, "level2");
974         level3 = talloc_strdup(level2, "level3");
975
976         talloc_set_destructor(level3, fail_destructor_str);
977         talloc_free(level1);
978         talloc_set_destructor(level3, NULL);
979
980         CHECK_PARENT("free_parent_deny_child", level3, top);
981
982         talloc_free(top);
983
984         printf("success: free_parent_deny_child\n");
985         return true;
986 }
987
988 struct new_parent {
989         void *new_parent;
990         char val[20];
991 };
992
993 static int reparenting_destructor(struct new_parent *np)
994 {
995         talloc_set_destructor(np, NULL);
996         (void)talloc_move(np->new_parent, &np);
997         return -1;
998 }
999
1000 static bool test_free_parent_reparent_child(void)
1001 {
1002         void *top = talloc_new(NULL);
1003         char *level1;
1004         char *alternate_level1;
1005         char *level2;
1006         struct new_parent *level3;
1007
1008         printf("test: free_parent_reparent_child\n# "
1009                 "TALLOC FREE PARENT REPARENT CHILD\n");
1010
1011         level1 = talloc_strdup(top, "level1");
1012         alternate_level1 = talloc_strdup(top, "alternate_level1");
1013         level2 = talloc_strdup(level1, "level2");
1014         level3 = talloc(level2, struct new_parent);
1015         level3->new_parent = alternate_level1;
1016         memset(level3->val, 'x', sizeof(level3->val));
1017
1018         talloc_set_destructor(level3, reparenting_destructor);
1019         talloc_free(level1);
1020
1021         CHECK_PARENT("free_parent_reparent_child",
1022                 level3, alternate_level1);
1023
1024         talloc_free(top);
1025
1026         printf("success: free_parent_reparent_child\n");
1027         return true;
1028 }
1029
1030 static bool test_free_parent_reparent_child_in_pool(void)
1031 {
1032         void *top = talloc_new(NULL);
1033         char *level1;
1034         char *alternate_level1;
1035         char *level2;
1036         void *pool;
1037         struct new_parent *level3;
1038
1039         printf("test: free_parent_reparent_child_in_pool\n# "
1040                 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1041
1042         pool = talloc_pool(top, 1024);
1043         level1 = talloc_strdup(pool, "level1");
1044         alternate_level1 = talloc_strdup(top, "alternate_level1");
1045         level2 = talloc_strdup(level1, "level2");
1046         level3 = talloc(level2, struct new_parent);
1047         level3->new_parent = alternate_level1;
1048         memset(level3->val, 'x', sizeof(level3->val));
1049
1050         talloc_set_destructor(level3, reparenting_destructor);
1051         talloc_free(level1);
1052         talloc_set_destructor(level3, NULL);
1053
1054         CHECK_PARENT("free_parent_reparent_child_in_pool",
1055                 level3, alternate_level1);
1056
1057         /* Even freeing alternate_level1 should leave pool alone. */
1058         talloc_free(alternate_level1);
1059         talloc_free(top);
1060
1061         printf("success: free_parent_reparent_child_in_pool\n");
1062         return true;
1063 }
1064
1065
1066 static bool test_talloc_ptrtype(void)
1067 {
1068         void *top = talloc_new(NULL);
1069         struct struct1 {
1070                 int foo;
1071                 int bar;
1072         } *s1, *s2, **s3, ***s4;
1073         const char *location1;
1074         const char *location2;
1075         const char *location3;
1076         const char *location4;
1077
1078         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1079
1080         s1 = talloc_ptrtype(top, s1);location1 = __location__;
1081
1082         if (talloc_get_size(s1) != sizeof(struct struct1)) {
1083                 printf("failure: ptrtype [\n"
1084                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1085                   "]\n", (unsigned long)talloc_get_size(s1),
1086                            (unsigned long)sizeof(struct struct1));
1087                 return false;
1088         }
1089
1090         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1091                 printf("failure: ptrtype [\n"
1092                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1093                         talloc_get_name(s1), location1);
1094                 return false;
1095         }
1096
1097         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1098
1099         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1100                 printf("failure: ptrtype [\n"
1101                            "talloc_array_ptrtype() allocated the wrong size "
1102                        "%lu (should be %lu)\n]\n",
1103                         (unsigned long)talloc_get_size(s2),
1104                     (unsigned long)(sizeof(struct struct1)*10));
1105                 return false;
1106         }
1107
1108         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1109                 printf("failure: ptrtype [\n"
1110                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1111                         talloc_get_name(s2), location2);
1112                 return false;
1113         }
1114
1115         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1116
1117         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1118                 printf("failure: ptrtype [\n"
1119                            "talloc_array_ptrtype() allocated the wrong size "
1120                        "%lu (should be %lu)\n]\n",
1121                            (unsigned long)talloc_get_size(s3),
1122                        (unsigned long)(sizeof(struct struct1 *)*10));
1123                 return false;
1124         }
1125
1126         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1127                 "talloc_array_ptrtype() sets the wrong name");
1128
1129         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1130
1131         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1132                 printf("failure: ptrtype [\n"
1133                       "talloc_array_ptrtype() allocated the wrong size "
1134                        "%lu (should be %lu)\n]\n",
1135                            (unsigned long)talloc_get_size(s4),
1136                        (unsigned long)(sizeof(struct struct1 **)*10));
1137                 return false;
1138         }
1139
1140         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1141                 "talloc_array_ptrtype() sets the wrong name");
1142
1143         talloc_free(top);
1144
1145         printf("success: ptrtype\n");
1146         return true;
1147 }
1148
1149 static int _test_talloc_free_in_destructor(void **ptr)
1150 {
1151         talloc_free(*ptr);
1152         return 0;
1153 }
1154
1155 static bool test_talloc_free_in_destructor(void)
1156 {
1157         void *level0;
1158         void *level1;
1159         void *level2;
1160         void *level3;
1161         void *level4;
1162         void **level5;
1163
1164         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1165
1166         level0 = talloc_new(NULL);
1167         level1 = talloc_new(level0);
1168         level2 = talloc_new(level1);
1169         level3 = talloc_new(level2);
1170         level4 = talloc_new(level3);
1171         level5 = talloc(level4, void *);
1172
1173         *level5 = level3;
1174         (void)talloc_reference(level0, level3);
1175         (void)talloc_reference(level3, level3);
1176         (void)talloc_reference(level5, level3);
1177
1178         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1179
1180         talloc_free(level1);
1181
1182         talloc_free(level0);
1183
1184         printf("success: free_in_destructor\n");
1185         return true;
1186 }
1187
1188 static bool test_autofree(void)
1189 {
1190 #if _SAMBA_BUILD_ < 4
1191         /* autofree test would kill smbtorture */
1192         void *p;
1193         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1194
1195         p = talloc_autofree_context();
1196         talloc_free(p);
1197
1198         p = talloc_autofree_context();
1199         talloc_free(p);
1200
1201         printf("success: autofree\n");
1202 #endif
1203         return true;
1204 }
1205
1206 static bool test_pool(void)
1207 {
1208         void *pool;
1209         void *p1, *p2, *p3, *p4;
1210         void *p2_2;
1211
1212         pool = talloc_pool(NULL, 1024);
1213
1214         p1 = talloc_size(pool, 80);
1215         memset(p1, 0x11, talloc_get_size(p1));
1216         p2 = talloc_size(pool, 20);
1217         memset(p2, 0x11, talloc_get_size(p2));
1218         p3 = talloc_size(p1, 50);
1219         memset(p3, 0x11, talloc_get_size(p3));
1220         p4 = talloc_size(p3, 1000);
1221         memset(p4, 0x11, talloc_get_size(p4));
1222
1223 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1224         p2_2 = talloc_realloc_size(pool, p2, 20+1);
1225         torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1226         memset(p2, 0x11, talloc_get_size(p2));
1227         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1228         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1229         memset(p2, 0x11, talloc_get_size(p2));
1230         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1231         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1232         memset(p2, 0x11, talloc_get_size(p2));
1233
1234         talloc_free(p3);
1235
1236         /* this should reclaim the memory of p4 and p3 */
1237         p2_2 = talloc_realloc_size(pool, p2, 400);
1238         torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1239         memset(p2, 0x11, talloc_get_size(p2));
1240
1241         talloc_free(p1);
1242
1243         /* this should reclaim the memory of p1 */
1244         p2_2 = talloc_realloc_size(pool, p2, 800);
1245         torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1246         p2 = p2_2;
1247         memset(p2, 0x11, talloc_get_size(p2));
1248
1249         /* this should do a malloc */
1250         p2_2 = talloc_realloc_size(pool, p2, 1800);
1251         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1252         p2 = p2_2;
1253         memset(p2, 0x11, talloc_get_size(p2));
1254
1255         /* this should reclaim the memory from the pool */
1256         p3 = talloc_size(pool, 80);
1257         torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1258         memset(p3, 0x11, talloc_get_size(p3));
1259
1260         talloc_free(p2);
1261         talloc_free(p3);
1262
1263         p1 = talloc_size(pool, 80);
1264         memset(p1, 0x11, talloc_get_size(p1));
1265         p2 = talloc_size(pool, 20);
1266         memset(p2, 0x11, talloc_get_size(p2));
1267
1268         talloc_free(p1);
1269
1270         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1271         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1272         memset(p2, 0x11, talloc_get_size(p2));
1273         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1274         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1275         memset(p2, 0x11, talloc_get_size(p2));
1276
1277         /* this should do a malloc */
1278         p2_2 = talloc_realloc_size(pool, p2, 1800);
1279         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1280         p2 = p2_2;
1281         memset(p2, 0x11, talloc_get_size(p2));
1282
1283         /* this should reclaim the memory from the pool */
1284         p3 = talloc_size(pool, 800);
1285         torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1286         memset(p3, 0x11, talloc_get_size(p3));
1287
1288 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1289
1290         talloc_free(pool);
1291
1292         return true;
1293 }
1294
1295 static bool test_pool_steal(void)
1296 {
1297         void *root;
1298         void *pool;
1299         void *p1, *p2;
1300         void *p1_2, *p2_2;
1301         size_t hdr;
1302         size_t ofs1, ofs2;
1303
1304         root = talloc_new(NULL);
1305         pool = talloc_pool(root, 1024);
1306
1307         p1 = talloc_size(pool, 4 * 16);
1308         torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1309         memset(p1, 0x11, talloc_get_size(p1));
1310         p2 = talloc_size(pool, 4 * 16);
1311         torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1312         memset(p2, 0x11, talloc_get_size(p2));
1313
1314         ofs1 = PTR_DIFF(p2, p1);
1315         hdr = ofs1 - talloc_get_size(p1);
1316
1317         talloc_steal(root, p1);
1318         talloc_steal(root, p2);
1319
1320         talloc_free(pool);
1321
1322         p1_2 = p1;
1323
1324 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1325         p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1326         torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1327         memset(p1_2, 0x11, talloc_get_size(p1_2));
1328         ofs1 = PTR_DIFF(p1_2, p2);
1329         ofs2 = talloc_get_size(p2) + hdr;
1330
1331         torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1332
1333         p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1334         torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1335         memset(p2_2, 0x11, talloc_get_size(p2_2));
1336 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1337
1338         talloc_free(p1_2);
1339
1340         p2_2 = p2;
1341
1342 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1343         /* now we should reclaim the full pool */
1344         p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1345         torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1346         p2 = p2_2;
1347         memset(p2_2, 0x11, talloc_get_size(p2_2));
1348
1349         /* now we malloc and free the full pool space */
1350         p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1351         torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1352         memset(p2_2, 0x11, talloc_get_size(p2_2));
1353
1354 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1355
1356         talloc_free(p2_2);
1357
1358         talloc_free(root);
1359
1360         return true;
1361 }
1362
1363 static bool test_pool_nest(void)
1364 {
1365         void *p1, *p2, *p3;
1366         void *e = talloc_new(NULL);
1367
1368         p1 = talloc_pool(NULL, 1024);
1369         torture_assert("talloc_pool", p1 != NULL, "failed");
1370
1371         p2 = talloc_pool(p1, 500);
1372         torture_assert("talloc_pool", p2 != NULL, "failed");
1373
1374         p3 = talloc_size(p2, 10);
1375
1376         talloc_steal(e, p3);
1377
1378         talloc_free(p2);
1379
1380         talloc_free(p3);
1381
1382         talloc_free(p1);
1383
1384         return true;
1385 }
1386
1387 struct pooled {
1388         char *s1;
1389         char *s2;
1390         char *s3;
1391 };
1392
1393 static bool test_pooled_object(void)
1394 {
1395         struct pooled *p;
1396         const char *s1 = "hello";
1397         const char *s2 = "world";
1398         const char *s3 = "";
1399
1400         p = talloc_pooled_object(NULL, struct pooled, 3,
1401                         strlen(s1)+strlen(s2)+strlen(s3)+3);
1402
1403         if (talloc_get_size(p) != sizeof(struct pooled)) {
1404                 return false;
1405         }
1406
1407         p->s1 = talloc_strdup(p, s1);
1408
1409         TALLOC_FREE(p->s1);
1410         p->s1 = talloc_strdup(p, s2);
1411         TALLOC_FREE(p->s1);
1412
1413         p->s1 = talloc_strdup(p, s1);
1414         p->s2 = talloc_strdup(p, s2);
1415         p->s3 = talloc_strdup(p, s3);
1416
1417         TALLOC_FREE(p);
1418         return true;
1419 }
1420
1421 static bool test_free_ref_null_context(void)
1422 {
1423         void *p1, *p2, *p3;
1424         int ret;
1425
1426         talloc_disable_null_tracking();
1427         p1 = talloc_new(NULL);
1428         p2 = talloc_new(NULL);
1429
1430         p3 = talloc_reference(p2, p1);
1431         torture_assert("reference", p3 == p1, "failed: reference on null");
1432
1433         ret = talloc_free(p1);
1434         torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1435         talloc_free(p2);
1436
1437         talloc_enable_null_tracking_no_autofree();
1438         p1 = talloc_new(NULL);
1439         p2 = talloc_new(NULL);
1440
1441         p3 = talloc_reference(p2, p1);
1442         torture_assert("reference", p3 == p1, "failed: reference on null");
1443
1444         ret = talloc_free(p1);
1445         torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1446         talloc_free(p2);
1447
1448         return true;
1449 }
1450
1451 static bool test_rusty(void)
1452 {
1453         void *root;
1454         const char *p1;
1455
1456         talloc_enable_null_tracking();
1457         root = talloc_new(NULL);
1458         p1 = talloc_strdup(root, "foo");
1459         talloc_increase_ref_count(p1);
1460         talloc_report_full(root, stdout);
1461         talloc_free(root);
1462         CHECK_BLOCKS("null_context", NULL, 2);
1463         return true;
1464 }
1465
1466 static bool test_free_children(void)
1467 {
1468         void *root;
1469         char *p1, *p2;
1470         const char *name, *name2;
1471
1472         talloc_enable_null_tracking();
1473         root = talloc_new(NULL);
1474         p1 = talloc_strdup(root, "foo1");
1475         p2 = talloc_strdup(p1, "foo2");
1476         (void)p2;
1477
1478         talloc_set_name(p1, "%s", "testname");
1479         talloc_free_children(p1);
1480         /* check its still a valid talloc ptr */
1481         talloc_get_size(talloc_get_name(p1));
1482         if (strcmp(talloc_get_name(p1), "testname") != 0) {
1483                 return false;
1484         }
1485
1486         talloc_set_name(p1, "%s", "testname");
1487         name = talloc_get_name(p1);
1488         talloc_free_children(p1);
1489         /* check its still a valid talloc ptr */
1490         talloc_get_size(talloc_get_name(p1));
1491         torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
1492         torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
1493                        "wrong name");
1494         CHECK_BLOCKS("name1", p1, 2);
1495
1496         /* note that this does not free the old child name */
1497         talloc_set_name_const(p1, "testname2");
1498         name2 = talloc_get_name(p1);
1499         /* but this does */
1500         talloc_free_children(p1);
1501         (void)name2;
1502         torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1503                        "wrong name");
1504         CHECK_BLOCKS("name1", p1, 1);
1505
1506         talloc_report_full(root, stdout);
1507         talloc_free(root);
1508         return true;
1509 }
1510
1511 static bool test_memlimit(void)
1512 {
1513         void *root;
1514         char *l1, *l2, *l3, *l4, *l5, *t;
1515         char *pool;
1516         int i;
1517
1518         printf("test: memlimit\n# MEMORY LIMITS\n");
1519
1520         printf("==== talloc_new(NULL)\n");
1521         root = talloc_new(NULL);
1522
1523         talloc_report_full(root, stdout);
1524
1525         printf("==== talloc_size(root, 2048)\n");
1526         l1 = talloc_size(root, 2048);
1527         torture_assert("memlimit", l1 != NULL,
1528                 "failed: alloc should not fail due to memory limit\n");
1529
1530         talloc_report_full(root, stdout);
1531
1532         printf("==== talloc_free(l1)\n");
1533         talloc_free(l1);
1534
1535         talloc_report_full(root, stdout);
1536
1537         printf("==== talloc_strdup(root, level 1)\n");
1538         l1 = talloc_strdup(root, "level 1");
1539         torture_assert("memlimit", l1 != NULL,
1540                 "failed: alloc should not fail due to memory limit\n");
1541
1542         talloc_report_full(root, stdout);
1543
1544         printf("==== talloc_set_memlimit(l1, 2048)\n");
1545         torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
1546                 "failed: setting memlimit should never fail\n");
1547
1548         talloc_report_full(root, stdout);
1549
1550         printf("==== talloc_size(root, 2048)\n");
1551         l2 = talloc_size(l1, 2048);
1552         torture_assert("memlimit", l2 == NULL,
1553                 "failed: alloc should fail due to memory limit\n");
1554
1555         talloc_report_full(root, stdout);
1556
1557         printf("==== talloc_strdup(l1, level 2)\n");
1558         l2 = talloc_strdup(l1, "level 2");
1559         torture_assert("memlimit", l2 != NULL,
1560                 "failed: alloc should not fail due to memory limit\n");
1561
1562         talloc_report_full(root, stdout);
1563
1564         printf("==== talloc_free(l2)\n");
1565         talloc_free(l2);
1566
1567         talloc_report_full(root, stdout);
1568
1569         printf("==== talloc_size(NULL, 2048)\n");
1570         l2 = talloc_size(NULL, 2048);
1571
1572         talloc_report_full(root, stdout);
1573
1574         printf("==== talloc_steal(l1, l2)\n");
1575         talloc_steal(l1, l2);
1576
1577         talloc_report_full(root, stdout);
1578
1579         printf("==== talloc_strdup(l2, level 3)\n");
1580         l3 = talloc_strdup(l2, "level 3");
1581         torture_assert("memlimit", l3 == NULL,
1582                 "failed: alloc should fail due to memory limit\n");
1583
1584         talloc_report_full(root, stdout);
1585
1586         printf("==== talloc_free(l2)\n");
1587         talloc_free(l2);
1588
1589         talloc_report_full(root, stdout);
1590
1591         printf("==== talloc_strdup(NULL, level 2)\n");
1592         l2 = talloc_strdup(NULL, "level 2");
1593         talloc_steal(l1, l2);
1594
1595         talloc_report_full(root, stdout);
1596
1597         printf("==== talloc_strdup(l2, level 3)\n");
1598         l3 = talloc_strdup(l2, "level 3");
1599         torture_assert("memlimit", l3 != NULL,
1600                 "failed: alloc should not fail due to memory limit\n");
1601
1602         talloc_report_full(root, stdout);
1603
1604         printf("==== talloc_set_memlimit(l3, 1024)\n");
1605         torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
1606                 "failed: setting memlimit should never fail\n");
1607
1608         talloc_report_full(root, stdout);
1609
1610         printf("==== talloc_strdup(l3, level 4)\n");
1611         l4 = talloc_strdup(l3, "level 4");
1612         torture_assert("memlimit", l4 != NULL,
1613                 "failed: alloc should not fail due to memory limit\n");
1614
1615         talloc_report_full(root, stdout);
1616
1617         printf("==== talloc_set_memlimit(l4, 512)\n");
1618         torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1619                 "failed: setting memlimit should never fail\n");
1620
1621         talloc_report_full(root, stdout);
1622
1623         printf("==== talloc_strdup(l4, level 5)\n");
1624         l5 = talloc_strdup(l4, "level 5");
1625         torture_assert("memlimit", l5 != NULL,
1626                 "failed: alloc should not fail due to memory limit\n");
1627
1628         talloc_report_full(root, stdout);
1629
1630         printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1631         t = talloc_realloc(NULL, l5, char, 600);
1632         torture_assert("memlimit", t == NULL,
1633                 "failed: alloc should fail due to memory limit\n");
1634
1635         talloc_report_full(root, stdout);
1636
1637         printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1638         l5 = talloc_realloc(NULL, l5, char, 5);
1639         torture_assert("memlimit", l5 != NULL,
1640                 "failed: alloc should not fail due to memory limit\n");
1641
1642         talloc_report_full(root, stdout);
1643
1644         printf("==== talloc_strdup(l3, level 4)\n");
1645         l4 = talloc_strdup(l3, "level 4");
1646         torture_assert("memlimit", l4 != NULL,
1647                 "failed: alloc should not fail due to memory limit\n");
1648
1649         talloc_report_full(root, stdout);
1650
1651         printf("==== talloc_set_memlimit(l4, 512)\n");
1652         torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1653                 "failed: setting memlimit should never fail\n");
1654
1655         talloc_report_full(root, stdout);
1656
1657         printf("==== talloc_strdup(l4, level 5)\n");
1658         l5 = talloc_strdup(l4, "level 5");
1659         torture_assert("memlimit", l5 != NULL,
1660                 "failed: alloc should not fail due to memory limit\n");
1661
1662         talloc_report_full(root, stdout);
1663
1664         printf("==== Make new temp context and steal l5\n");
1665         t = talloc_new(root);
1666         talloc_steal(t, l5);
1667
1668         talloc_report_full(root, stdout);
1669
1670         printf("==== talloc_size(t, 2048)\n");
1671         l1 = talloc_size(t, 2048);
1672         torture_assert("memlimit", l1 != NULL,
1673                 "failed: alloc should not fail due to memory limit\n");
1674
1675         talloc_report_full(root, stdout);
1676         talloc_free(root);
1677
1678         /* Test memlimits with pools. */
1679         pool = talloc_pool(NULL, 10*1024);
1680         torture_assert("memlimit", pool != NULL,
1681                 "failed: alloc should not fail due to memory limit\n");
1682         talloc_set_memlimit(pool, 10*1024);
1683         for (i = 0; i < 9; i++) {
1684                 l1 = talloc_size(pool, 1024);
1685                 torture_assert("memlimit", l1 != NULL,
1686                         "failed: alloc should not fail due to memory limit\n");
1687         }
1688         /* The next alloc should fail. */
1689         l2 = talloc_size(pool, 1024);
1690         torture_assert("memlimit", l2 == NULL,
1691                         "failed: alloc should fail due to memory limit\n");
1692
1693         /* Moving one of the children shouldn't change the limit,
1694            as it's still inside the pool. */
1695         root = talloc_new(NULL);
1696         talloc_steal(root, l1);
1697         l2 = talloc_size(pool, 1024);
1698         torture_assert("memlimit", l2 == NULL,
1699                         "failed: alloc should fail due to memory limit\n");
1700
1701         talloc_free(pool);
1702         talloc_free(root);
1703         printf("success: memlimit\n");
1704
1705         return true;
1706 }
1707
1708 #ifdef HAVE_PTHREAD
1709
1710 #define NUM_THREADS 100
1711
1712 /* Sync variables. */
1713 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1714 static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1715 static void *intermediate_ptr;
1716
1717 /* Subthread. */
1718 static void *thread_fn(void *arg)
1719 {
1720         int ret;
1721         const char *ctx_name = (const char *)arg;
1722         void *sub_ctx = NULL;
1723         /*
1724          * Do stuff that creates a new talloc hierarchy in
1725          * this thread.
1726          */
1727         void *top_ctx = talloc_named_const(NULL, 0, "top");
1728         if (top_ctx == NULL) {
1729                 return NULL;
1730         }
1731         sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1732         if (sub_ctx == NULL) {
1733                 return NULL;
1734         }
1735
1736         /*
1737          * Now transfer a pointer from our hierarchy
1738          * onto the intermediate ptr.
1739          */
1740         ret = pthread_mutex_lock(&mtx);
1741         if (ret != 0) {
1742                 talloc_free(top_ctx);
1743                 return NULL;
1744         }
1745         /* Wait for intermediate_ptr to be free. */
1746         while (intermediate_ptr != NULL) {
1747                 ret = pthread_cond_wait(&condvar, &mtx);
1748                 if (ret != 0) {
1749                         talloc_free(top_ctx);
1750                         return NULL;
1751                 }
1752         }
1753
1754         /* and move our memory onto it from our toplevel hierarchy. */
1755         intermediate_ptr = talloc_move(NULL, &sub_ctx);
1756
1757         /* Tell the main thread it's ready for pickup. */
1758         pthread_cond_broadcast(&condvar);
1759         pthread_mutex_unlock(&mtx);
1760
1761         talloc_free(top_ctx);
1762         return NULL;
1763 }
1764
1765 /* Main thread. */
1766 static bool test_pthread_talloc_passing(void)
1767 {
1768         int i;
1769         int ret;
1770         char str_array[NUM_THREADS][20];
1771         pthread_t thread_id;
1772         void *mem_ctx;
1773
1774         /*
1775          * Important ! Null tracking breaks threaded talloc.
1776          * It *must* be turned off.
1777          */
1778         talloc_disable_null_tracking();
1779
1780         printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1781
1782         /* Main thread toplevel context. */
1783         mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1784         if (mem_ctx == NULL) {
1785                 printf("failed to create toplevel context\n");
1786                 return false;
1787         }
1788
1789         /*
1790          * Spin off NUM_THREADS threads.
1791          * They will use their own toplevel contexts.
1792          */
1793         for (i = 0; i < NUM_THREADS; i++) {
1794                 (void)snprintf(str_array[i],
1795                                 20,
1796                                 "thread:%d",
1797                                 i);
1798                 if (str_array[i] == NULL) {
1799                         printf("snprintf %d failed\n", i);
1800                         return false;
1801                 }
1802                 ret = pthread_create(&thread_id,
1803                                 NULL,
1804                                 thread_fn,
1805                                 str_array[i]);
1806                 if (ret != 0) {
1807                         printf("failed to create thread %d (%d)\n", i, ret);
1808                         return false;
1809                 }
1810         }
1811
1812         printf("Created %d threads\n", NUM_THREADS);
1813
1814         /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1815         for (i = 0; i < NUM_THREADS; i++) {
1816                 ret = pthread_mutex_lock(&mtx);
1817                 if (ret != 0) {
1818                         printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
1819                         talloc_free(mem_ctx);
1820                         return false;
1821                 }
1822
1823                 /* Wait for intermediate_ptr to have our data. */
1824                 while (intermediate_ptr == NULL) {
1825                         ret = pthread_cond_wait(&condvar, &mtx);
1826                         if (ret != 0) {
1827                                 printf("pthread_cond_wait %d failed (%d)\n", i,
1828                                         ret);
1829                                 talloc_free(mem_ctx);
1830                                 return false;
1831                         }
1832                 }
1833
1834                 /* and move it onto our toplevel hierarchy. */
1835                 (void)talloc_move(mem_ctx, &intermediate_ptr);
1836
1837                 /* Tell the sub-threads we're ready for another. */
1838                 pthread_cond_broadcast(&condvar);
1839                 pthread_mutex_unlock(&mtx);
1840         }
1841
1842         CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
1843 #if 1
1844         /* Dump the hierarchy. */
1845         talloc_report(mem_ctx, stdout);
1846 #endif
1847         talloc_free(mem_ctx);
1848         printf("success: pthread_talloc_passing\n");
1849         return true;
1850 }
1851 #endif
1852
1853 static void test_reset(void)
1854 {
1855         talloc_set_log_fn(test_log_stdout);
1856         test_abort_stop();
1857         talloc_disable_null_tracking();
1858         talloc_enable_null_tracking_no_autofree();
1859 }
1860
1861 bool torture_local_talloc(struct torture_context *tctx)
1862 {
1863         bool ret = true;
1864
1865         setlinebuf(stdout);
1866
1867         test_reset();
1868         ret &= test_pooled_object();
1869         test_reset();
1870         ret &= test_pool_nest();
1871         test_reset();
1872         ret &= test_ref1();
1873         test_reset();
1874         ret &= test_ref2();
1875         test_reset();
1876         ret &= test_ref3();
1877         test_reset();
1878         ret &= test_ref4();
1879         test_reset();
1880         ret &= test_unlink1(); 
1881         test_reset();
1882         ret &= test_misc();
1883         test_reset();
1884         ret &= test_realloc();
1885         test_reset();
1886         ret &= test_realloc_child(); 
1887         test_reset();
1888         ret &= test_steal(); 
1889         test_reset();
1890         ret &= test_move(); 
1891         test_reset();
1892         ret &= test_unref_reparent();
1893         test_reset();
1894         ret &= test_realloc_fn(); 
1895         test_reset();
1896         ret &= test_type();
1897         test_reset();
1898         ret &= test_lifeless(); 
1899         test_reset();
1900         ret &= test_loop();
1901         test_reset();
1902         ret &= test_free_parent_deny_child(); 
1903         test_reset();
1904         ret &= test_free_parent_reparent_child();
1905         test_reset();
1906         ret &= test_free_parent_reparent_child_in_pool();
1907         test_reset();
1908         ret &= test_talloc_ptrtype();
1909         test_reset();
1910         ret &= test_talloc_free_in_destructor();
1911         test_reset();
1912         ret &= test_pool();
1913         test_reset();
1914         ret &= test_pool_steal();
1915         test_reset();
1916         ret &= test_free_ref_null_context();
1917         test_reset();
1918         ret &= test_rusty();
1919         test_reset();
1920         ret &= test_free_children();
1921         test_reset();
1922         ret &= test_memlimit();
1923 #ifdef HAVE_PTHREAD
1924         test_reset();
1925         ret &= test_pthread_talloc_passing();
1926 #endif
1927
1928
1929         if (ret) {
1930                 test_reset();
1931                 ret &= test_speed();
1932         }
1933         test_reset();
1934         ret &= test_autofree();
1935
1936         test_reset();
1937         talloc_disable_null_tracking();
1938         return ret;
1939 }