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