Merge commit 'release-4-0-0alpha15' into master4-tmp
[nivanova/samba-autobuild/.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 #include "talloc_testsuite.h"
31
32 static struct timeval timeval_current(void)
33 {
34         struct timeval tv;
35         gettimeofday(&tv, NULL);
36         return tv;
37 }
38
39 static double timeval_elapsed(struct timeval *tv)
40 {
41         struct timeval tv2 = timeval_current();
42         return (tv2.tv_sec - tv->tv_sec) + 
43                (tv2.tv_usec - tv->tv_usec)*1.0e-6;
44 }
45
46 #define torture_assert(test, expr, str) if (!(expr)) { \
47         printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
48                 test, __location__, #expr, str); \
49         return false; \
50 }
51
52 #define torture_assert_str_equal(test, arg1, arg2, desc) \
53         if (arg1 == NULL && arg2 == NULL) {                             \
54         } else if (strcmp(arg1, arg2)) {                        \
55                 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
56                    test, __location__, arg1, arg2, desc); \
57                 return false; \
58         }
59
60 #if _SAMBA_BUILD_==3
61 #ifdef malloc
62 #undef malloc
63 #endif
64 #ifdef strdup
65 #undef strdup
66 #endif
67 #endif
68
69 #define CHECK_SIZE(test, ptr, tsize) do { \
70         if (talloc_total_size(ptr) != (tsize)) { \
71                 printf("failed: %s [\n%s: wrong '%s' tree size: got %u  expected %u\n]\n", \
72                        test, __location__, #ptr, \
73                        (unsigned)talloc_total_size(ptr), \
74                        (unsigned)tsize); \
75                 talloc_report_full(ptr, stdout); \
76                 return false; \
77         } \
78 } while (0)
79
80 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
81         if (talloc_total_blocks(ptr) != (tblocks)) { \
82                 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u  expected %u\n]\n", \
83                        test, __location__, #ptr, \
84                        (unsigned)talloc_total_blocks(ptr), \
85                        (unsigned)tblocks); \
86                 talloc_report_full(ptr, stdout); \
87                 return false; \
88         } \
89 } while (0)
90
91 #define CHECK_PARENT(test, ptr, parent) do { \
92         if (talloc_parent(ptr) != (parent)) { \
93                 printf("failed: %s [\n%s: '%s' has wrong parent: got %p  expected %p\n]\n", \
94                        test, __location__, #ptr, \
95                        talloc_parent(ptr), \
96                        (parent)); \
97                 talloc_report_full(ptr, stdout); \
98                 talloc_report_full(parent, stdout); \
99                 talloc_report_full(NULL, stdout); \
100                 return false; \
101         } \
102 } while (0)
103
104 static unsigned int test_abort_count;
105
106 #if 0
107 static void test_abort_fn(const char *reason)
108 {
109         printf("# test_abort_fn(%s)\n", reason);
110         test_abort_count++;
111 }
112
113 static void test_abort_start(void)
114 {
115         test_abort_count = 0;
116         talloc_set_abort_fn(test_abort_fn);
117 }
118 #endif
119
120 static void test_abort_stop(void)
121 {
122         test_abort_count = 0;
123         talloc_set_abort_fn(NULL);
124 }
125
126 static void test_log_stdout(const char *message)
127 {
128         fprintf(stdout, "%s", message);
129 }
130
131 /*
132   test references 
133 */
134 static bool test_ref1(void)
135 {
136         void *root, *p1, *p2, *ref, *r1;
137
138         printf("test: ref1\n# SINGLE REFERENCE FREE\n");
139
140         root = talloc_named_const(NULL, 0, "root");
141         p1 = talloc_named_const(root, 1, "p1");
142         p2 = talloc_named_const(p1, 1, "p2");
143         talloc_named_const(p1, 1, "x1");
144         talloc_named_const(p1, 2, "x2");
145         talloc_named_const(p1, 3, "x3");
146
147         r1 = talloc_named_const(root, 1, "r1"); 
148         ref = talloc_reference(r1, p2);
149         talloc_report_full(root, stderr);
150
151         CHECK_BLOCKS("ref1", p1, 5);
152         CHECK_BLOCKS("ref1", p2, 1);
153         CHECK_BLOCKS("ref1", r1, 2);
154
155         fprintf(stderr, "Freeing p2\n");
156         talloc_unlink(r1, p2);
157         talloc_report_full(root, stderr);
158
159         CHECK_BLOCKS("ref1", p1, 5);
160         CHECK_BLOCKS("ref1", p2, 1);
161         CHECK_BLOCKS("ref1", r1, 1);
162
163         fprintf(stderr, "Freeing p1\n");
164         talloc_free(p1);
165         talloc_report_full(root, stderr);
166
167         CHECK_BLOCKS("ref1", r1, 1);
168
169         fprintf(stderr, "Freeing r1\n");
170         talloc_free(r1);
171         talloc_report_full(NULL, stderr);
172
173         fprintf(stderr, "Testing NULL\n");
174         if (talloc_reference(root, NULL)) {
175                 return false;
176         }
177
178         CHECK_BLOCKS("ref1", root, 1);
179
180         CHECK_SIZE("ref1", root, 0);
181
182         talloc_free(root);
183         printf("success: ref1\n");
184         return true;
185 }
186
187 /*
188   test references 
189 */
190 static bool test_ref2(void)
191 {
192         void *root, *p1, *p2, *ref, *r1;
193
194         printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
195         root = talloc_named_const(NULL, 0, "root");
196         p1 = talloc_named_const(root, 1, "p1");
197         talloc_named_const(p1, 1, "x1");
198         talloc_named_const(p1, 1, "x2");
199         talloc_named_const(p1, 1, "x3");
200         p2 = talloc_named_const(p1, 1, "p2");
201
202         r1 = talloc_named_const(root, 1, "r1"); 
203         ref = talloc_reference(r1, p2);
204         talloc_report_full(root, stderr);
205
206         CHECK_BLOCKS("ref2", p1, 5);
207         CHECK_BLOCKS("ref2", p2, 1);
208         CHECK_BLOCKS("ref2", r1, 2);
209
210         fprintf(stderr, "Freeing ref\n");
211         talloc_unlink(r1, ref);
212         talloc_report_full(root, stderr);
213
214         CHECK_BLOCKS("ref2", p1, 5);
215         CHECK_BLOCKS("ref2", p2, 1);
216         CHECK_BLOCKS("ref2", r1, 1);
217
218         fprintf(stderr, "Freeing p2\n");
219         talloc_free(p2);
220         talloc_report_full(root, stderr);
221
222         CHECK_BLOCKS("ref2", p1, 4);
223         CHECK_BLOCKS("ref2", r1, 1);
224
225         fprintf(stderr, "Freeing p1\n");
226         talloc_free(p1);
227         talloc_report_full(root, stderr);
228
229         CHECK_BLOCKS("ref2", r1, 1);
230
231         fprintf(stderr, "Freeing r1\n");
232         talloc_free(r1);
233         talloc_report_full(root, stderr);
234
235         CHECK_SIZE("ref2", root, 0);
236
237         talloc_free(root);
238         printf("success: ref2\n");
239         return true;
240 }
241
242 /*
243   test references 
244 */
245 static bool test_ref3(void)
246 {
247         void *root, *p1, *p2, *ref, *r1;
248
249         printf("test: ref3\n# PARENT REFERENCE FREE\n");
250
251         root = talloc_named_const(NULL, 0, "root");
252         p1 = talloc_named_const(root, 1, "p1");
253         p2 = talloc_named_const(root, 1, "p2");
254         r1 = talloc_named_const(p1, 1, "r1");
255         ref = talloc_reference(p2, r1);
256         talloc_report_full(root, stderr);
257
258         CHECK_BLOCKS("ref3", p1, 2);
259         CHECK_BLOCKS("ref3", p2, 2);
260         CHECK_BLOCKS("ref3", r1, 1);
261
262         fprintf(stderr, "Freeing p1\n");
263         talloc_free(p1);
264         talloc_report_full(root, stderr);
265
266         CHECK_BLOCKS("ref3", p2, 2);
267         CHECK_BLOCKS("ref3", r1, 1);
268
269         fprintf(stderr, "Freeing p2\n");
270         talloc_free(p2);
271         talloc_report_full(root, stderr);
272
273         CHECK_SIZE("ref3", root, 0);
274
275         talloc_free(root);
276
277         printf("success: ref3\n");
278         return true;
279 }
280
281 /*
282   test references 
283 */
284 static bool test_ref4(void)
285 {
286         void *root, *p1, *p2, *ref, *r1;
287
288         printf("test: ref4\n# REFERRER REFERENCE FREE\n");
289
290         root = talloc_named_const(NULL, 0, "root");
291         p1 = talloc_named_const(root, 1, "p1");
292         talloc_named_const(p1, 1, "x1");
293         talloc_named_const(p1, 1, "x2");
294         talloc_named_const(p1, 1, "x3");
295         p2 = talloc_named_const(p1, 1, "p2");
296
297         r1 = talloc_named_const(root, 1, "r1"); 
298         ref = talloc_reference(r1, p2);
299         talloc_report_full(root, stderr);
300
301         CHECK_BLOCKS("ref4", p1, 5);
302         CHECK_BLOCKS("ref4", p2, 1);
303         CHECK_BLOCKS("ref4", r1, 2);
304
305         fprintf(stderr, "Freeing r1\n");
306         talloc_free(r1);
307         talloc_report_full(root, stderr);
308
309         CHECK_BLOCKS("ref4", p1, 5);
310         CHECK_BLOCKS("ref4", p2, 1);
311
312         fprintf(stderr, "Freeing p2\n");
313         talloc_free(p2);
314         talloc_report_full(root, stderr);
315
316         CHECK_BLOCKS("ref4", p1, 4);
317
318         fprintf(stderr, "Freeing p1\n");
319         talloc_free(p1);
320         talloc_report_full(root, stderr);
321
322         CHECK_SIZE("ref4", root, 0);
323
324         talloc_free(root);
325
326         printf("success: ref4\n");
327         return true;
328 }
329
330
331 /*
332   test references 
333 */
334 static bool test_unlink1(void)
335 {
336         void *root, *p1, *p2, *ref, *r1;
337
338         printf("test: unlink\n# UNLINK\n");
339
340         root = talloc_named_const(NULL, 0, "root");
341         p1 = talloc_named_const(root, 1, "p1");
342         talloc_named_const(p1, 1, "x1");
343         talloc_named_const(p1, 1, "x2");
344         talloc_named_const(p1, 1, "x3");
345         p2 = talloc_named_const(p1, 1, "p2");
346
347         r1 = talloc_named_const(p1, 1, "r1");   
348         ref = talloc_reference(r1, p2);
349         talloc_report_full(root, stderr);
350
351         CHECK_BLOCKS("unlink", p1, 7);
352         CHECK_BLOCKS("unlink", p2, 1);
353         CHECK_BLOCKS("unlink", r1, 2);
354
355         fprintf(stderr, "Unreferencing r1\n");
356         talloc_unlink(r1, p2);
357         talloc_report_full(root, stderr);
358
359         CHECK_BLOCKS("unlink", p1, 6);
360         CHECK_BLOCKS("unlink", p2, 1);
361         CHECK_BLOCKS("unlink", r1, 1);
362
363         fprintf(stderr, "Freeing p1\n");
364         talloc_free(p1);
365         talloc_report_full(root, stderr);
366
367         CHECK_SIZE("unlink", root, 0);
368
369         talloc_free(root);
370
371         printf("success: unlink\n");
372         return true;
373 }
374
375 static int fail_destructor(void *ptr)
376 {
377         return -1;
378 }
379
380 /*
381   miscellaneous tests to try to get a higher test coverage percentage
382 */
383 static bool test_misc(void)
384 {
385         void *root, *p1;
386         char *p2;
387         double *d;
388         const char *name;
389
390         printf("test: misc\n# MISCELLANEOUS\n");
391
392         root = talloc_new(NULL);
393
394         p1 = talloc_size(root, 0x7fffffff);
395         torture_assert("misc", !p1, "failed: large talloc allowed\n");
396
397         p1 = talloc_strdup(root, "foo");
398         talloc_increase_ref_count(p1);
399         talloc_increase_ref_count(p1);
400         talloc_increase_ref_count(p1);
401         CHECK_BLOCKS("misc", p1, 1);
402         CHECK_BLOCKS("misc", root, 2);
403         talloc_unlink(NULL, p1);
404         CHECK_BLOCKS("misc", p1, 1);
405         CHECK_BLOCKS("misc", root, 2);
406         talloc_unlink(NULL, p1);
407         CHECK_BLOCKS("misc", p1, 1);
408         CHECK_BLOCKS("misc", root, 2);
409         p2 = talloc_strdup(p1, "foo");
410         torture_assert("misc", talloc_unlink(root, p2) == -1,
411                                    "failed: talloc_unlink() of non-reference context should return -1\n");
412         torture_assert("misc", talloc_unlink(p1, p2) == 0,
413                 "failed: talloc_unlink() of parent should succeed\n");
414         talloc_unlink(NULL, p1);
415         CHECK_BLOCKS("misc", p1, 1);
416         CHECK_BLOCKS("misc", root, 2);
417
418         name = talloc_set_name(p1, "my name is %s", "foo");
419         torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
420                 "failed: wrong name after talloc_set_name(my name is foo)");
421         CHECK_BLOCKS("misc", p1, 2);
422         CHECK_BLOCKS("misc", root, 3);
423
424         talloc_set_name_const(p1, NULL);
425         torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
426                 "failed: wrong name after talloc_set_name(NULL)");
427         CHECK_BLOCKS("misc", p1, 2);
428         CHECK_BLOCKS("misc", root, 3);
429
430         torture_assert("misc", talloc_free(NULL) == -1, 
431                                    "talloc_free(NULL) should give -1\n");
432
433         talloc_set_destructor(p1, fail_destructor);
434         torture_assert("misc", talloc_free(p1) == -1, 
435                 "Failed destructor should cause talloc_free to fail\n");
436         talloc_set_destructor(p1, NULL);
437
438         talloc_report(root, stderr);
439
440
441         p2 = (char *)talloc_zero_size(p1, 20);
442         torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
443         talloc_free(p2);
444
445         torture_assert("misc", talloc_strdup(root, NULL) == NULL,
446                 "failed: strdup on NULL should give NULL\n");
447
448         p2 = talloc_strndup(p1, "foo", 2);
449         torture_assert("misc", strcmp("fo", p2) == 0, 
450                                    "strndup doesn't work\n");
451         p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
452         torture_assert("misc", strcmp("food", p2) == 0, 
453                                    "talloc_asprintf_append_buffer doesn't work\n");
454         CHECK_BLOCKS("misc", p2, 1);
455         CHECK_BLOCKS("misc", p1, 3);
456
457         p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
458         torture_assert("misc", strcmp("hello world", p2) == 0,
459                 "talloc_asprintf_append_buffer doesn't work\n");
460         CHECK_BLOCKS("misc", p2, 1);
461         CHECK_BLOCKS("misc", p1, 3);
462         talloc_free(p2);
463
464         d = talloc_array(p1, double, 0x20000000);
465         torture_assert("misc", !d, "failed: integer overflow not detected\n");
466
467         d = talloc_realloc(p1, d, double, 0x20000000);
468         torture_assert("misc", !d, "failed: integer overflow not detected\n");
469
470         talloc_free(p1);
471         CHECK_BLOCKS("misc", root, 1);
472
473         p1 = talloc_named(root, 100, "%d bytes", 100);
474         CHECK_BLOCKS("misc", p1, 2);
475         CHECK_BLOCKS("misc", root, 3);
476         talloc_unlink(root, p1);
477
478         p1 = talloc_init("%d bytes", 200);
479         p2 = talloc_asprintf(p1, "my test '%s'", "string");
480         torture_assert_str_equal("misc", p2, "my test 'string'",
481                 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
482         CHECK_BLOCKS("misc", p1, 3);
483         CHECK_SIZE("misc", p2, 17);
484         CHECK_BLOCKS("misc", root, 1);
485         talloc_unlink(NULL, p1);
486
487         p1 = talloc_named_const(root, 10, "p1");
488         p2 = (char *)talloc_named_const(root, 20, "p2");
489         (void)talloc_reference(p1, p2);
490         talloc_report_full(root, stderr);
491         talloc_unlink(root, p2);
492         talloc_report_full(root, stderr);
493         CHECK_BLOCKS("misc", p2, 1);
494         CHECK_BLOCKS("misc", p1, 2);
495         CHECK_BLOCKS("misc", root, 3);
496         talloc_unlink(p1, p2);
497         talloc_unlink(root, p1);
498
499         p1 = talloc_named_const(root, 10, "p1");
500         p2 = (char *)talloc_named_const(root, 20, "p2");
501         (void)talloc_reference(NULL, p2);
502         talloc_report_full(root, stderr);
503         talloc_unlink(root, p2);
504         talloc_report_full(root, stderr);
505         CHECK_BLOCKS("misc", p2, 1);
506         CHECK_BLOCKS("misc", p1, 1);
507         CHECK_BLOCKS("misc", root, 2);
508         talloc_unlink(NULL, p2);
509         talloc_unlink(root, p1);
510
511         /* Test that talloc_unlink is a no-op */
512
513         torture_assert("misc", talloc_unlink(root, NULL) == -1,
514                 "failed: talloc_unlink(root, NULL) == -1\n");
515
516         talloc_report(root, stderr);
517         talloc_report(NULL, stderr);
518
519         CHECK_SIZE("misc", root, 0);
520
521         talloc_free(root);
522
523         CHECK_SIZE("misc", NULL, 0);
524
525         talloc_enable_null_tracking_no_autofree();
526         talloc_enable_leak_report();
527         talloc_enable_leak_report_full();
528
529         printf("success: misc\n");
530
531         return true;
532 }
533
534
535 /*
536   test realloc
537 */
538 static bool test_realloc(void)
539 {
540         void *root, *p1, *p2;
541
542         printf("test: realloc\n# REALLOC\n");
543
544         root = talloc_new(NULL);
545
546         p1 = talloc_size(root, 10);
547         CHECK_SIZE("realloc", p1, 10);
548
549         p1 = talloc_realloc_size(NULL, p1, 20);
550         CHECK_SIZE("realloc", p1, 20);
551
552         talloc_new(p1);
553
554         p2 = talloc_realloc_size(p1, NULL, 30);
555
556         talloc_new(p1);
557
558         p2 = talloc_realloc_size(p1, p2, 40);
559
560         CHECK_SIZE("realloc", p2, 40);
561         CHECK_SIZE("realloc", root, 60);
562         CHECK_BLOCKS("realloc", p1, 4);
563
564         p1 = talloc_realloc_size(NULL, p1, 20);
565         CHECK_SIZE("realloc", p1, 60);
566
567         talloc_increase_ref_count(p2);
568         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
569                 "failed: talloc_realloc() on a referenced pointer should fail\n");
570         CHECK_BLOCKS("realloc", p1, 4);
571
572         talloc_realloc_size(NULL, p2, 0);
573         talloc_realloc_size(NULL, p2, 0);
574         CHECK_BLOCKS("realloc", p1, 4);
575         talloc_realloc_size(p1, p2, 0);
576         CHECK_BLOCKS("realloc", p1, 3);
577
578         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
579                 "failed: oversize talloc should fail\n");
580
581         talloc_realloc_size(NULL, p1, 0);
582         CHECK_BLOCKS("realloc", root, 4);
583         talloc_realloc_size(root, p1, 0);
584         CHECK_BLOCKS("realloc", root, 1);
585
586         CHECK_SIZE("realloc", root, 0);
587
588         talloc_free(root);
589
590         printf("success: realloc\n");
591
592         return true;
593 }
594
595 /*
596   test realloc with a child
597 */
598 static bool test_realloc_child(void)
599 {
600         void *root;
601         struct el2 {
602                 const char *name;
603         } *el2; 
604         struct el1 {
605                 int count;
606                 struct el2 **list, **list2, **list3;
607         } *el1;
608
609         printf("test: REALLOC WITH CHILD\n");
610
611         root = talloc_new(NULL);
612
613         el1 = talloc(root, struct el1);
614         el1->list = talloc(el1, struct el2 *);
615         el1->list[0] = talloc(el1->list, struct el2);
616         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
617
618         el1->list2 = talloc(el1, struct el2 *);
619         el1->list2[0] = talloc(el1->list2, struct el2);
620         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
621
622         el1->list3 = talloc(el1, struct el2 *);
623         el1->list3[0] = talloc(el1->list3, struct el2);
624         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
625         
626         el2 = talloc(el1->list, struct el2);
627         el2 = talloc(el1->list2, struct el2);
628         el2 = talloc(el1->list3, struct el2);
629
630         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
631         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
632         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
633
634         talloc_free(root);
635
636         printf("success: REALLOC WITH CHILD\n");
637         return true;
638 }
639
640 /*
641   test type checking
642 */
643 static bool test_type(void)
644 {
645         void *root;
646         struct el1 {
647                 int count;
648         };
649         struct el2 {
650                 int count;
651         };
652         struct el1 *el1;
653
654         printf("test: type\n# talloc type checking\n");
655
656         root = talloc_new(NULL);
657
658         el1 = talloc(root, struct el1);
659
660         el1->count = 1;
661
662         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
663                 "type check failed on el1\n");
664         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
665                 "type check failed on el1 with el2\n");
666         talloc_set_type(el1, struct el2);
667         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
668                 "type set failed on el1 with el2\n");
669
670         talloc_free(root);
671
672         printf("success: type\n");
673         return true;
674 }
675
676 /*
677   test steal
678 */
679 static bool test_steal(void)
680 {
681         void *root, *p1, *p2;
682
683         printf("test: steal\n# STEAL\n");
684
685         root = talloc_new(NULL);
686
687         p1 = talloc_array(root, char, 10);
688         CHECK_SIZE("steal", p1, 10);
689
690         p2 = talloc_realloc(root, NULL, char, 20);
691         CHECK_SIZE("steal", p1, 10);
692         CHECK_SIZE("steal", root, 30);
693
694         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
695                 "failed: stealing NULL should give NULL\n");
696
697         torture_assert("steal", talloc_steal(p1, p1) == p1,
698                 "failed: stealing to ourselves is a nop\n");
699         CHECK_BLOCKS("steal", root, 3);
700         CHECK_SIZE("steal", root, 30);
701
702         talloc_steal(NULL, p1);
703         talloc_steal(NULL, p2);
704         CHECK_BLOCKS("steal", root, 1);
705         CHECK_SIZE("steal", root, 0);
706
707         talloc_free(p1);
708         talloc_steal(root, p2);
709         CHECK_BLOCKS("steal", root, 2);
710         CHECK_SIZE("steal", root, 20);
711         
712         talloc_free(p2);
713
714         CHECK_BLOCKS("steal", root, 1);
715         CHECK_SIZE("steal", root, 0);
716
717         talloc_free(root);
718
719         p1 = talloc_size(NULL, 3);
720         talloc_report_full(NULL, stderr);
721         CHECK_SIZE("steal", NULL, 3);
722         talloc_free(p1);
723
724         printf("success: steal\n");
725         return true;
726 }
727
728 /*
729   test move
730 */
731 static bool test_move(void)
732 {
733         void *root;
734         struct t_move {
735                 char *p;
736                 int *x;
737         } *t1, *t2;
738
739         printf("test: move\n# MOVE\n");
740
741         root = talloc_new(NULL);
742
743         t1 = talloc(root, struct t_move);
744         t2 = talloc(root, struct t_move);
745         t1->p = talloc_strdup(t1, "foo");
746         t1->x = talloc(t1, int);
747         *t1->x = 42;
748
749         t2->p = talloc_move(t2, &t1->p);
750         t2->x = talloc_move(t2, &t1->x);
751         torture_assert("move", t1->p == NULL && t1->x == NULL &&
752             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
753                 "talloc move failed");
754
755         talloc_free(root);
756
757         printf("success: move\n");
758
759         return true;
760 }
761
762 /*
763   test talloc_realloc_fn
764 */
765 static bool test_realloc_fn(void)
766 {
767         void *root, *p1;
768
769         printf("test: realloc_fn\n# talloc_realloc_fn\n");
770
771         root = talloc_new(NULL);
772
773         p1 = talloc_realloc_fn(root, NULL, 10);
774         CHECK_BLOCKS("realloc_fn", root, 2);
775         CHECK_SIZE("realloc_fn", root, 10);
776         p1 = talloc_realloc_fn(root, p1, 20);
777         CHECK_BLOCKS("realloc_fn", root, 2);
778         CHECK_SIZE("realloc_fn", root, 20);
779         p1 = talloc_realloc_fn(root, p1, 0);
780         CHECK_BLOCKS("realloc_fn", root, 1);
781         CHECK_SIZE("realloc_fn", root, 0);
782
783         talloc_free(root);
784
785         printf("success: realloc_fn\n");
786         return true;
787 }
788
789
790 static bool test_unref_reparent(void)
791 {
792         void *root, *p1, *p2, *c1;
793
794         printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
795
796         root = talloc_named_const(NULL, 0, "root");
797         p1 = talloc_named_const(root, 1, "orig parent");
798         p2 = talloc_named_const(root, 1, "parent by reference");
799
800         c1 = talloc_named_const(p1, 1, "child");
801         talloc_reference(p2, c1);
802
803         CHECK_PARENT("unref_reparent", c1, p1);
804
805         talloc_free(p1);
806
807         CHECK_PARENT("unref_reparent", c1, p2);
808
809         talloc_unlink(p2, c1);
810
811         CHECK_SIZE("unref_reparent", root, 1);
812
813         talloc_free(p2);
814         talloc_free(root);
815
816         printf("success: unref_reparent\n");
817         return true;
818 }
819
820 /*
821   measure the speed of talloc versus malloc
822 */
823 static bool test_speed(void)
824 {
825         void *ctx = talloc_new(NULL);
826         unsigned count;
827         const int loop = 1000;
828         int i;
829         struct timeval tv;
830
831         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
832
833         tv = timeval_current();
834         count = 0;
835         do {
836                 void *p1, *p2, *p3;
837                 for (i=0;i<loop;i++) {
838                         p1 = talloc_size(ctx, loop % 100);
839                         p2 = talloc_strdup(p1, "foo bar");
840                         p3 = talloc_size(p1, 300);
841                         talloc_free(p1);
842                 }
843                 count += 3 * loop;
844         } while (timeval_elapsed(&tv) < 5.0);
845
846         fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
847
848         talloc_free(ctx);
849
850         ctx = talloc_pool(NULL, 1024);
851
852         tv = timeval_current();
853         count = 0;
854         do {
855                 void *p1, *p2, *p3;
856                 for (i=0;i<loop;i++) {
857                         p1 = talloc_size(ctx, loop % 100);
858                         p2 = talloc_strdup(p1, "foo bar");
859                         p3 = talloc_size(p1, 300);
860                         talloc_free_children(ctx);
861                 }
862                 count += 3 * loop;
863         } while (timeval_elapsed(&tv) < 5.0);
864
865         talloc_free(ctx);
866
867         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
868
869         tv = timeval_current();
870         count = 0;
871         do {
872                 void *p1, *p2, *p3;
873                 for (i=0;i<loop;i++) {
874                         p1 = malloc(loop % 100);
875                         p2 = strdup("foo bar");
876                         p3 = malloc(300);
877                         free(p1);
878                         free(p2);
879                         free(p3);
880                 }
881                 count += 3 * loop;
882         } while (timeval_elapsed(&tv) < 5.0);
883         fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
884
885         printf("success: speed\n");
886
887         return true;
888 }
889
890 static bool test_lifeless(void)
891 {
892         void *top = talloc_new(NULL);
893         char *parent, *child; 
894         void *child_owner = talloc_new(NULL);
895
896         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
897
898         parent = talloc_strdup(top, "parent");
899         child = talloc_strdup(parent, "child");  
900         (void)talloc_reference(child, parent);
901         (void)talloc_reference(child_owner, child); 
902         talloc_report_full(top, stderr);
903         talloc_unlink(top, parent);
904         talloc_unlink(top, child);
905         talloc_report_full(top, stderr);
906         talloc_free(top);
907         talloc_free(child_owner);
908         talloc_free(child);
909
910         printf("success: lifeless\n");
911         return true;
912 }
913
914 static int loop_destructor_count;
915
916 static int test_loop_destructor(char *ptr)
917 {
918         loop_destructor_count++;
919         return 0;
920 }
921
922 static bool test_loop(void)
923 {
924         void *top = talloc_new(NULL);
925         char *parent;
926         struct req1 {
927                 char *req2, *req3;
928         } *req1;
929
930         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
931
932         parent = talloc_strdup(top, "parent");
933         req1 = talloc(parent, struct req1);
934         req1->req2 = talloc_strdup(req1, "req2");  
935         talloc_set_destructor(req1->req2, test_loop_destructor);
936         req1->req3 = talloc_strdup(req1, "req3");
937         (void)talloc_reference(req1->req3, req1);
938         talloc_report_full(top, stderr);
939         talloc_free(parent);
940         talloc_report_full(top, stderr);
941         talloc_report_full(NULL, stderr);
942         talloc_free(top);
943
944         torture_assert("loop", loop_destructor_count == 1, 
945                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
946         loop_destructor_count = 0;
947
948         printf("success: loop\n");
949         return true;
950 }
951
952 static int fail_destructor_str(char *ptr)
953 {
954         return -1;
955 }
956
957 static bool test_free_parent_deny_child(void)
958 {
959         void *top = talloc_new(NULL);
960         char *level1;
961         char *level2;
962         char *level3;
963
964         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
965
966         level1 = talloc_strdup(top, "level1");
967         level2 = talloc_strdup(level1, "level2");
968         level3 = talloc_strdup(level2, "level3");
969
970         talloc_set_destructor(level3, fail_destructor_str);
971         talloc_free(level1);
972         talloc_set_destructor(level3, NULL);
973
974         CHECK_PARENT("free_parent_deny_child", level3, top);
975
976         talloc_free(top);
977
978         printf("success: free_parent_deny_child\n");
979         return true;
980 }
981
982 static bool test_talloc_ptrtype(void)
983 {
984         void *top = talloc_new(NULL);
985         struct struct1 {
986                 int foo;
987                 int bar;
988         } *s1, *s2, **s3, ***s4;
989         const char *location1;
990         const char *location2;
991         const char *location3;
992         const char *location4;
993
994         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
995
996         s1 = talloc_ptrtype(top, s1);location1 = __location__;
997
998         if (talloc_get_size(s1) != sizeof(struct struct1)) {
999                 printf("failure: ptrtype [\n"
1000                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1001                   "]\n", (unsigned long)talloc_get_size(s1),
1002                            (unsigned long)sizeof(struct struct1));
1003                 return false;
1004         }
1005
1006         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1007                 printf("failure: ptrtype [\n"
1008                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1009                         talloc_get_name(s1), location1);
1010                 return false;
1011         }
1012
1013         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1014
1015         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1016                 printf("failure: ptrtype [\n"
1017                            "talloc_array_ptrtype() allocated the wrong size "
1018                        "%lu (should be %lu)\n]\n",
1019                         (unsigned long)talloc_get_size(s2),
1020                     (unsigned long)(sizeof(struct struct1)*10));
1021                 return false;
1022         }
1023
1024         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1025                 printf("failure: ptrtype [\n"
1026                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1027                         talloc_get_name(s2), location2);
1028                 return false;
1029         }
1030
1031         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1032
1033         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1034                 printf("failure: ptrtype [\n"
1035                            "talloc_array_ptrtype() allocated the wrong size "
1036                        "%lu (should be %lu)\n]\n",
1037                            (unsigned long)talloc_get_size(s3),
1038                        (unsigned long)(sizeof(struct struct1 *)*10));
1039                 return false;
1040         }
1041
1042         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1043                 "talloc_array_ptrtype() sets the wrong name");
1044
1045         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1046
1047         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1048                 printf("failure: ptrtype [\n"
1049                       "talloc_array_ptrtype() allocated the wrong size "
1050                        "%lu (should be %lu)\n]\n",
1051                            (unsigned long)talloc_get_size(s4),
1052                        (unsigned long)(sizeof(struct struct1 **)*10));
1053                 return false;
1054         }
1055
1056         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1057                 "talloc_array_ptrtype() sets the wrong name");
1058
1059         talloc_free(top);
1060
1061         printf("success: ptrtype\n");
1062         return true;
1063 }
1064
1065 static int _test_talloc_free_in_destructor(void **ptr)
1066 {
1067         talloc_free(*ptr);
1068         return 0;
1069 }
1070
1071 static bool test_talloc_free_in_destructor(void)
1072 {
1073         void *level0;
1074         void *level1;
1075         void *level2;
1076         void *level3;
1077         void *level4;
1078         void **level5;
1079
1080         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1081
1082         level0 = talloc_new(NULL);
1083         level1 = talloc_new(level0);
1084         level2 = talloc_new(level1);
1085         level3 = talloc_new(level2);
1086         level4 = talloc_new(level3);
1087         level5 = talloc(level4, void *);
1088
1089         *level5 = level3;
1090         (void)talloc_reference(level0, level3);
1091         (void)talloc_reference(level3, level3);
1092         (void)talloc_reference(level5, level3);
1093
1094         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1095
1096         talloc_free(level1);
1097
1098         talloc_free(level0);
1099
1100         printf("success: free_in_destructor\n");
1101         return true;
1102 }
1103
1104 static bool test_autofree(void)
1105 {
1106 #if _SAMBA_BUILD_ < 4
1107         /* autofree test would kill smbtorture */
1108         void *p;
1109         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1110
1111         p = talloc_autofree_context();
1112         talloc_free(p);
1113
1114         p = talloc_autofree_context();
1115         talloc_free(p);
1116
1117         printf("success: autofree\n");
1118 #endif
1119         return true;
1120 }
1121
1122 static bool test_pool(void)
1123 {
1124         void *pool;
1125         void *p1, *p2, *p3, *p4;
1126         void *p2_2;
1127
1128         pool = talloc_pool(NULL, 1024);
1129
1130         p1 = talloc_size(pool, 80);
1131         memset(p1, 0x11, talloc_get_size(p1));
1132         p2 = talloc_size(pool, 20);
1133         memset(p2, 0x11, talloc_get_size(p2));
1134         p3 = talloc_size(p1, 50);
1135         memset(p3, 0x11, talloc_get_size(p3));
1136         p4 = talloc_size(p3, 1000);
1137         memset(p4, 0x11, talloc_get_size(p4));
1138
1139 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1140         p2_2 = talloc_realloc_size(pool, p2, 20+1);
1141         torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1142         memset(p2, 0x11, talloc_get_size(p2));
1143         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1144         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1145         memset(p2, 0x11, talloc_get_size(p2));
1146         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1147         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1148         memset(p2, 0x11, talloc_get_size(p2));
1149
1150         talloc_free(p3);
1151
1152         /* this should reclaim the memory of p4 and p3 */
1153         p2_2 = talloc_realloc_size(pool, p2, 400);
1154         torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1155         memset(p2, 0x11, talloc_get_size(p2));
1156
1157         talloc_free(p1);
1158
1159         /* this should reclaim the memory of p1 */
1160         p2_2 = talloc_realloc_size(pool, p2, 800);
1161         torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1162         p2 = p2_2;
1163         memset(p2, 0x11, talloc_get_size(p2));
1164
1165         /* this should do a malloc */
1166         p2_2 = talloc_realloc_size(pool, p2, 1800);
1167         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1168         p2 = p2_2;
1169         memset(p2, 0x11, talloc_get_size(p2));
1170
1171         /* this should reclaim the memory from the pool */
1172         p3 = talloc_size(pool, 80);
1173         torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1174         memset(p3, 0x11, talloc_get_size(p3));
1175
1176         talloc_free(p2);
1177         talloc_free(p3);
1178
1179         p1 = talloc_size(pool, 80);
1180         memset(p1, 0x11, talloc_get_size(p1));
1181         p2 = talloc_size(pool, 20);
1182         memset(p2, 0x11, talloc_get_size(p2));
1183
1184         talloc_free(p1);
1185
1186         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1187         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1188         memset(p2, 0x11, talloc_get_size(p2));
1189         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1190         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1191         memset(p2, 0x11, talloc_get_size(p2));
1192
1193         /* this should do a malloc */
1194         p2_2 = talloc_realloc_size(pool, p2, 1800);
1195         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1196         p2 = p2_2;
1197         memset(p2, 0x11, talloc_get_size(p2));
1198
1199         /* this should reclaim the memory from the pool */
1200         p3 = talloc_size(pool, 800);
1201         torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1202         memset(p3, 0x11, talloc_get_size(p3));
1203
1204 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1205
1206         talloc_free(pool);
1207
1208         return true;
1209 }
1210
1211 static bool test_pool_steal(void)
1212 {
1213         void *root;
1214         void *pool;
1215         void *p1, *p2;
1216         void *p1_2, *p2_2;
1217         size_t hdr;
1218         size_t ofs1, ofs2;
1219
1220         root = talloc_new(NULL);
1221         pool = talloc_pool(root, 1024);
1222
1223         p1 = talloc_size(pool, 4 * 16);
1224         torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1225         memset(p1, 0x11, talloc_get_size(p1));
1226         p2 = talloc_size(pool, 4 * 16);
1227         torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1228         memset(p2, 0x11, talloc_get_size(p2));
1229
1230         ofs1 = PTR_DIFF(p2, p1);
1231         hdr = ofs1 - talloc_get_size(p1);
1232
1233         talloc_steal(root, p1);
1234         talloc_steal(root, p2);
1235
1236         talloc_free(pool);
1237
1238         p1_2 = p1;
1239
1240 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1241         p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1242         torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1243         memset(p1_2, 0x11, talloc_get_size(p1_2));
1244         ofs1 = PTR_DIFF(p1_2, p2);
1245         ofs2 = talloc_get_size(p2) + hdr;
1246
1247         torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1248
1249         p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1250         torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1251         memset(p2_2, 0x11, talloc_get_size(p2_2));
1252 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1253
1254         talloc_free(p1_2);
1255
1256         p2_2 = p2;
1257
1258 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1259         /* now we should reclaim the full pool */
1260         p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1261         torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1262         p2 = p2_2;
1263         memset(p2_2, 0x11, talloc_get_size(p2_2));
1264
1265         /* now we malloc and free the full pool space */
1266         p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1267         torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1268         memset(p2_2, 0x11, talloc_get_size(p2_2));
1269
1270 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1271
1272         talloc_free(p2_2);
1273
1274         talloc_free(root);
1275
1276         return true;
1277 }
1278
1279 static bool test_free_ref_null_context(void)
1280 {
1281         void *p1, *p2, *p3;
1282         int ret;
1283
1284         talloc_disable_null_tracking();
1285         p1 = talloc_new(NULL);
1286         p2 = talloc_new(NULL);
1287
1288         p3 = talloc_reference(p2, p1);
1289         torture_assert("reference", p3 == p1, "failed: reference on null");
1290
1291         ret = talloc_free(p1);
1292         torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1293         talloc_free(p2);
1294
1295         talloc_enable_null_tracking_no_autofree();
1296         p1 = talloc_new(NULL);
1297         p2 = talloc_new(NULL);
1298
1299         p3 = talloc_reference(p2, p1);
1300         torture_assert("reference", p3 == p1, "failed: reference on null");
1301
1302         ret = talloc_free(p1);
1303         torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1304         talloc_free(p2);
1305
1306         return true;
1307 }
1308
1309 static bool test_rusty(void)
1310 {
1311         void *root;
1312         const char *p1;
1313
1314         talloc_enable_null_tracking();
1315         root = talloc_new(NULL);
1316         p1 = talloc_strdup(root, "foo");
1317         talloc_increase_ref_count(p1);
1318         talloc_report_full(root, stdout);
1319         talloc_free(root);
1320         return true;
1321 }
1322
1323
1324 static void test_reset(void)
1325 {
1326         talloc_set_log_fn(test_log_stdout);
1327         test_abort_stop();
1328         talloc_disable_null_tracking();
1329         talloc_enable_null_tracking_no_autofree();
1330 }
1331
1332 bool torture_local_talloc(struct torture_context *tctx)
1333 {
1334         bool ret = true;
1335
1336         setlinebuf(stdout);
1337
1338         test_reset();
1339         ret &= test_ref1();
1340         test_reset();
1341         ret &= test_ref2();
1342         test_reset();
1343         ret &= test_ref3();
1344         test_reset();
1345         ret &= test_ref4();
1346         test_reset();
1347         ret &= test_unlink1(); 
1348         test_reset();
1349         ret &= test_misc();
1350         test_reset();
1351         ret &= test_realloc();
1352         test_reset();
1353         ret &= test_realloc_child(); 
1354         test_reset();
1355         ret &= test_steal(); 
1356         test_reset();
1357         ret &= test_move(); 
1358         test_reset();
1359         ret &= test_unref_reparent();
1360         test_reset();
1361         ret &= test_realloc_fn(); 
1362         test_reset();
1363         ret &= test_type();
1364         test_reset();
1365         ret &= test_lifeless(); 
1366         test_reset();
1367         ret &= test_loop();
1368         test_reset();
1369         ret &= test_free_parent_deny_child(); 
1370         test_reset();
1371         ret &= test_talloc_ptrtype();
1372         test_reset();
1373         ret &= test_talloc_free_in_destructor();
1374         test_reset();
1375         ret &= test_pool();
1376         test_reset();
1377         ret &= test_pool_steal();
1378         test_reset();
1379         ret &= test_free_ref_null_context();
1380         test_reset();
1381         ret &= test_rusty();
1382
1383         if (ret) {
1384                 test_reset();
1385                 ret &= test_speed();
1386         }
1387         test_reset();
1388         ret &= test_autofree();
1389
1390         test_reset();
1391         talloc_disable_null_tracking();
1392         return ret;
1393 }