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