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