f33805d6b07bb95f202323f69df5b9d7b71852a7
[samba.git] / lib / talloc / testsuite.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of talloc routines.
5
6    Copyright (C) Andrew Tridgell 2004
7    
8      ** NOTE! The following LGPL license applies to the talloc
9      ** library. This does NOT imply that all of Samba is released
10      ** under the LGPL
11    
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 3 of the License, or (at your option) any later version.
16
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Lesser General Public License for more details.
21
22    You should have received a copy of the GNU Lesser General Public
23    License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "replace.h"
27 #include "system/time.h"
28 #include <talloc.h>
29
30 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_null_tracking_no_autofree();
522         talloc_enable_leak_report();
523         talloc_enable_leak_report_full();
524
525         printf("success: misc\n");
526
527         return true;
528 }
529
530
531 /*
532   test realloc
533 */
534 static bool test_realloc(void)
535 {
536         void *root, *p1, *p2;
537
538         printf("test: realloc\n# REALLOC\n");
539
540         root = talloc_new(NULL);
541
542         p1 = talloc_size(root, 10);
543         CHECK_SIZE("realloc", p1, 10);
544
545         p1 = talloc_realloc_size(NULL, p1, 20);
546         CHECK_SIZE("realloc", p1, 20);
547
548         talloc_new(p1);
549
550         p2 = talloc_realloc_size(p1, NULL, 30);
551
552         talloc_new(p1);
553
554         p2 = talloc_realloc_size(p1, p2, 40);
555
556         CHECK_SIZE("realloc", p2, 40);
557         CHECK_SIZE("realloc", root, 60);
558         CHECK_BLOCKS("realloc", p1, 4);
559
560         p1 = talloc_realloc_size(NULL, p1, 20);
561         CHECK_SIZE("realloc", p1, 60);
562
563         talloc_increase_ref_count(p2);
564         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
565                 "failed: talloc_realloc() on a referenced pointer should fail\n");
566         CHECK_BLOCKS("realloc", p1, 4);
567
568         talloc_realloc_size(NULL, p2, 0);
569         talloc_realloc_size(NULL, p2, 0);
570         CHECK_BLOCKS("realloc", p1, 4);
571         talloc_realloc_size(p1, p2, 0);
572         CHECK_BLOCKS("realloc", p1, 3);
573
574         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
575                 "failed: oversize talloc should fail\n");
576
577         talloc_realloc_size(NULL, p1, 0);
578         CHECK_BLOCKS("realloc", root, 4);
579         talloc_realloc_size(root, p1, 0);
580         CHECK_BLOCKS("realloc", root, 1);
581
582         CHECK_SIZE("realloc", root, 0);
583
584         talloc_free(root);
585
586         printf("success: realloc\n");
587
588         return true;
589 }
590
591 /*
592   test realloc with a child
593 */
594 static bool test_realloc_child(void)
595 {
596         void *root;
597         struct el2 {
598                 const char *name;
599         } *el2; 
600         struct el1 {
601                 int count;
602                 struct el2 **list, **list2, **list3;
603         } *el1;
604
605         printf("test: REALLOC WITH CHILD\n");
606
607         root = talloc_new(NULL);
608
609         el1 = talloc(root, struct el1);
610         el1->list = talloc(el1, struct el2 *);
611         el1->list[0] = talloc(el1->list, struct el2);
612         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
613
614         el1->list2 = talloc(el1, struct el2 *);
615         el1->list2[0] = talloc(el1->list2, struct el2);
616         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
617
618         el1->list3 = talloc(el1, struct el2 *);
619         el1->list3[0] = talloc(el1->list3, struct el2);
620         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
621         
622         el2 = talloc(el1->list, struct el2);
623         el2 = talloc(el1->list2, struct el2);
624         el2 = talloc(el1->list3, struct el2);
625
626         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
627         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
628         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
629
630         talloc_free(root);
631
632         printf("success: REALLOC WITH CHILD\n");
633         return true;
634 }
635
636 /*
637   test type checking
638 */
639 static bool test_type(void)
640 {
641         void *root;
642         struct el1 {
643                 int count;
644         };
645         struct el2 {
646                 int count;
647         };
648         struct el1 *el1;
649
650         printf("test: type\n# talloc type checking\n");
651
652         root = talloc_new(NULL);
653
654         el1 = talloc(root, struct el1);
655
656         el1->count = 1;
657
658         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
659                 "type check failed on el1\n");
660         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
661                 "type check failed on el1 with el2\n");
662         talloc_set_type(el1, struct el2);
663         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
664                 "type set failed on el1 with el2\n");
665
666         talloc_free(root);
667
668         printf("success: type\n");
669         return true;
670 }
671
672 /*
673   test steal
674 */
675 static bool test_steal(void)
676 {
677         void *root, *p1, *p2;
678
679         printf("test: steal\n# STEAL\n");
680
681         root = talloc_new(NULL);
682
683         p1 = talloc_array(root, char, 10);
684         CHECK_SIZE("steal", p1, 10);
685
686         p2 = talloc_realloc(root, NULL, char, 20);
687         CHECK_SIZE("steal", p1, 10);
688         CHECK_SIZE("steal", root, 30);
689
690         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
691                 "failed: stealing NULL should give NULL\n");
692
693         torture_assert("steal", talloc_steal(p1, p1) == p1,
694                 "failed: stealing to ourselves is a nop\n");
695         CHECK_BLOCKS("steal", root, 3);
696         CHECK_SIZE("steal", root, 30);
697
698         talloc_steal(NULL, p1);
699         talloc_steal(NULL, p2);
700         CHECK_BLOCKS("steal", root, 1);
701         CHECK_SIZE("steal", root, 0);
702
703         talloc_free(p1);
704         talloc_steal(root, p2);
705         CHECK_BLOCKS("steal", root, 2);
706         CHECK_SIZE("steal", root, 20);
707         
708         talloc_free(p2);
709
710         CHECK_BLOCKS("steal", root, 1);
711         CHECK_SIZE("steal", root, 0);
712
713         talloc_free(root);
714
715         p1 = talloc_size(NULL, 3);
716         talloc_report_full(NULL, stderr);
717         CHECK_SIZE("steal", NULL, 3);
718         talloc_free(p1);
719
720         printf("success: steal\n");
721         return true;
722 }
723
724 /*
725   test move
726 */
727 static bool test_move(void)
728 {
729         void *root;
730         struct t_move {
731                 char *p;
732                 int *x;
733         } *t1, *t2;
734
735         printf("test: move\n# MOVE\n");
736
737         root = talloc_new(NULL);
738
739         t1 = talloc(root, struct t_move);
740         t2 = talloc(root, struct t_move);
741         t1->p = talloc_strdup(t1, "foo");
742         t1->x = talloc(t1, int);
743         *t1->x = 42;
744
745         t2->p = talloc_move(t2, &t1->p);
746         t2->x = talloc_move(t2, &t1->x);
747         torture_assert("move", t1->p == NULL && t1->x == NULL &&
748             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
749                 "talloc move failed");
750
751         talloc_free(root);
752
753         printf("success: move\n");
754
755         return true;
756 }
757
758 /*
759   test talloc_realloc_fn
760 */
761 static bool test_realloc_fn(void)
762 {
763         void *root, *p1;
764
765         printf("test: realloc_fn\n# talloc_realloc_fn\n");
766
767         root = talloc_new(NULL);
768
769         p1 = talloc_realloc_fn(root, NULL, 10);
770         CHECK_BLOCKS("realloc_fn", root, 2);
771         CHECK_SIZE("realloc_fn", root, 10);
772         p1 = talloc_realloc_fn(root, p1, 20);
773         CHECK_BLOCKS("realloc_fn", root, 2);
774         CHECK_SIZE("realloc_fn", root, 20);
775         p1 = talloc_realloc_fn(root, p1, 0);
776         CHECK_BLOCKS("realloc_fn", root, 1);
777         CHECK_SIZE("realloc_fn", root, 0);
778
779         talloc_free(root);
780
781         printf("success: realloc_fn\n");
782         return true;
783 }
784
785
786 static bool test_unref_reparent(void)
787 {
788         void *root, *p1, *p2, *c1;
789
790         printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
791
792         root = talloc_named_const(NULL, 0, "root");
793         p1 = talloc_named_const(root, 1, "orig parent");
794         p2 = talloc_named_const(root, 1, "parent by reference");
795
796         c1 = talloc_named_const(p1, 1, "child");
797         talloc_reference(p2, c1);
798
799         CHECK_PARENT("unref_reparent", c1, p1);
800
801         talloc_free(p1);
802
803         CHECK_PARENT("unref_reparent", c1, p2);
804
805         talloc_unlink(p2, c1);
806
807         CHECK_SIZE("unref_reparent", root, 1);
808
809         talloc_free(p2);
810         talloc_free(root);
811
812         printf("success: unref_reparent\n");
813         return true;
814 }
815
816 /*
817   measure the speed of talloc versus malloc
818 */
819 static bool test_speed(void)
820 {
821         void *ctx = talloc_new(NULL);
822         unsigned count;
823         const int loop = 1000;
824         int i;
825         struct timeval tv;
826
827         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
828
829         tv = timeval_current();
830         count = 0;
831         do {
832                 void *p1, *p2, *p3;
833                 for (i=0;i<loop;i++) {
834                         p1 = talloc_size(ctx, loop % 100);
835                         p2 = talloc_strdup(p1, "foo bar");
836                         p3 = talloc_size(p1, 300);
837                         talloc_free(p1);
838                 }
839                 count += 3 * loop;
840         } while (timeval_elapsed(&tv) < 5.0);
841
842         fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
843
844         talloc_free(ctx);
845
846         ctx = talloc_pool(NULL, 1024);
847
848         tv = timeval_current();
849         count = 0;
850         do {
851                 void *p1, *p2, *p3;
852                 for (i=0;i<loop;i++) {
853                         p1 = talloc_size(ctx, loop % 100);
854                         p2 = talloc_strdup(p1, "foo bar");
855                         p3 = talloc_size(p1, 300);
856                         talloc_free_children(ctx);
857                 }
858                 count += 3 * loop;
859         } while (timeval_elapsed(&tv) < 5.0);
860
861         talloc_free(ctx);
862
863         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
864
865         tv = timeval_current();
866         count = 0;
867         do {
868                 void *p1, *p2, *p3;
869                 for (i=0;i<loop;i++) {
870                         p1 = malloc(loop % 100);
871                         p2 = strdup("foo bar");
872                         p3 = malloc(300);
873                         free(p1);
874                         free(p2);
875                         free(p3);
876                 }
877                 count += 3 * loop;
878         } while (timeval_elapsed(&tv) < 5.0);
879         fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
880
881         printf("success: speed\n");
882
883         return true;
884 }
885
886 static bool test_lifeless(void)
887 {
888         void *top = talloc_new(NULL);
889         char *parent, *child; 
890         void *child_owner = talloc_new(NULL);
891
892         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
893
894         parent = talloc_strdup(top, "parent");
895         child = talloc_strdup(parent, "child");  
896         (void)talloc_reference(child, parent);
897         (void)talloc_reference(child_owner, child); 
898         talloc_report_full(top, stderr);
899         talloc_unlink(top, parent);
900         talloc_unlink(top, child);
901         talloc_report_full(top, stderr);
902         talloc_free(top);
903         talloc_free(child_owner);
904         talloc_free(child);
905
906         printf("success: lifeless\n");
907         return true;
908 }
909
910 static int loop_destructor_count;
911
912 static int test_loop_destructor(char *ptr)
913 {
914         loop_destructor_count++;
915         return 0;
916 }
917
918 static bool test_loop(void)
919 {
920         void *top = talloc_new(NULL);
921         char *parent;
922         struct req1 {
923                 char *req2, *req3;
924         } *req1;
925
926         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
927
928         parent = talloc_strdup(top, "parent");
929         req1 = talloc(parent, struct req1);
930         req1->req2 = talloc_strdup(req1, "req2");  
931         talloc_set_destructor(req1->req2, test_loop_destructor);
932         req1->req3 = talloc_strdup(req1, "req3");
933         (void)talloc_reference(req1->req3, req1);
934         talloc_report_full(top, stderr);
935         talloc_free(parent);
936         talloc_report_full(top, stderr);
937         talloc_report_full(NULL, stderr);
938         talloc_free(top);
939
940         torture_assert("loop", loop_destructor_count == 1, 
941                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
942         loop_destructor_count = 0;
943
944         printf("success: loop\n");
945         return true;
946 }
947
948 static int fail_destructor_str(char *ptr)
949 {
950         return -1;
951 }
952
953 static bool test_free_parent_deny_child(void)
954 {
955         void *top = talloc_new(NULL);
956         char *level1;
957         char *level2;
958         char *level3;
959
960         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
961
962         level1 = talloc_strdup(top, "level1");
963         level2 = talloc_strdup(level1, "level2");
964         level3 = talloc_strdup(level2, "level3");
965
966         talloc_set_destructor(level3, fail_destructor_str);
967         talloc_free(level1);
968         talloc_set_destructor(level3, NULL);
969
970         CHECK_PARENT("free_parent_deny_child", level3, top);
971
972         talloc_free(top);
973
974         printf("success: free_parent_deny_child\n");
975         return true;
976 }
977
978 static bool test_talloc_ptrtype(void)
979 {
980         void *top = talloc_new(NULL);
981         struct struct1 {
982                 int foo;
983                 int bar;
984         } *s1, *s2, **s3, ***s4;
985         const char *location1;
986         const char *location2;
987         const char *location3;
988         const char *location4;
989
990         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
991
992         s1 = talloc_ptrtype(top, s1);location1 = __location__;
993
994         if (talloc_get_size(s1) != sizeof(struct struct1)) {
995                 printf("failure: ptrtype [\n"
996                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
997                   "]\n", (unsigned long)talloc_get_size(s1),
998                            (unsigned long)sizeof(struct struct1));
999                 return false;
1000         }
1001
1002         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1003                 printf("failure: ptrtype [\n"
1004                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1005                         talloc_get_name(s1), location1);
1006                 return false;
1007         }
1008
1009         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1010
1011         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1012                 printf("failure: ptrtype [\n"
1013                            "talloc_array_ptrtype() allocated the wrong size "
1014                        "%lu (should be %lu)\n]\n",
1015                         (unsigned long)talloc_get_size(s2),
1016                     (unsigned long)(sizeof(struct struct1)*10));
1017                 return false;
1018         }
1019
1020         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1021                 printf("failure: ptrtype [\n"
1022                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1023                         talloc_get_name(s2), location2);
1024                 return false;
1025         }
1026
1027         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1028
1029         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1030                 printf("failure: ptrtype [\n"
1031                            "talloc_array_ptrtype() allocated the wrong size "
1032                        "%lu (should be %lu)\n]\n",
1033                            (unsigned long)talloc_get_size(s3),
1034                        (unsigned long)(sizeof(struct struct1 *)*10));
1035                 return false;
1036         }
1037
1038         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1039                 "talloc_array_ptrtype() sets the wrong name");
1040
1041         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1042
1043         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1044                 printf("failure: ptrtype [\n"
1045                       "talloc_array_ptrtype() allocated the wrong size "
1046                        "%lu (should be %lu)\n]\n",
1047                            (unsigned long)talloc_get_size(s4),
1048                        (unsigned long)(sizeof(struct struct1 **)*10));
1049                 return false;
1050         }
1051
1052         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1053                 "talloc_array_ptrtype() sets the wrong name");
1054
1055         talloc_free(top);
1056
1057         printf("success: ptrtype\n");
1058         return true;
1059 }
1060
1061 static int _test_talloc_free_in_destructor(void **ptr)
1062 {
1063         talloc_free(*ptr);
1064         return 0;
1065 }
1066
1067 static bool test_talloc_free_in_destructor(void)
1068 {
1069         void *level0;
1070         void *level1;
1071         void *level2;
1072         void *level3;
1073         void *level4;
1074         void **level5;
1075
1076         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1077
1078         level0 = talloc_new(NULL);
1079         level1 = talloc_new(level0);
1080         level2 = talloc_new(level1);
1081         level3 = talloc_new(level2);
1082         level4 = talloc_new(level3);
1083         level5 = talloc(level4, void *);
1084
1085         *level5 = level3;
1086         (void)talloc_reference(level0, level3);
1087         (void)talloc_reference(level3, level3);
1088         (void)talloc_reference(level5, level3);
1089
1090         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1091
1092         talloc_free(level1);
1093
1094         talloc_free(level0);
1095
1096         printf("success: free_in_destructor\n");
1097         return true;
1098 }
1099
1100 static bool test_autofree(void)
1101 {
1102 #if _SAMBA_BUILD_ < 4
1103         /* autofree test would kill smbtorture */
1104         void *p;
1105         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1106
1107         p = talloc_autofree_context();
1108         talloc_free(p);
1109
1110         p = talloc_autofree_context();
1111         talloc_free(p);
1112
1113         printf("success: autofree\n");
1114 #endif
1115         return true;
1116 }
1117
1118 static bool test_pool(void)
1119 {
1120         void *pool;
1121         void *p1, *p2, *p3, *p4;
1122
1123         pool = talloc_pool(NULL, 1024);
1124
1125         p1 = talloc_size(pool, 80);
1126         p2 = talloc_size(pool, 20);
1127         p3 = talloc_size(p1, 50);
1128         p4 = talloc_size(p3, 1000);
1129
1130         talloc_free(pool);
1131
1132         return true;
1133 }
1134
1135 static void test_reset(void)
1136 {
1137         talloc_set_log_fn(test_log_stdout);
1138         test_abort_stop();
1139         talloc_disable_null_tracking();
1140         talloc_enable_null_tracking_no_autofree();
1141 }
1142
1143 struct torture_context;
1144 bool torture_local_talloc(struct torture_context *tctx)
1145 {
1146         bool ret = true;
1147
1148         setlinebuf(stdout);
1149
1150         test_reset();
1151         ret &= test_ref1();
1152         test_reset();
1153         ret &= test_ref2();
1154         test_reset();
1155         ret &= test_ref3();
1156         test_reset();
1157         ret &= test_ref4();
1158         test_reset();
1159         ret &= test_unlink1(); 
1160         test_reset();
1161         ret &= test_misc();
1162         test_reset();
1163         ret &= test_realloc();
1164         test_reset();
1165         ret &= test_realloc_child(); 
1166         test_reset();
1167         ret &= test_steal(); 
1168         test_reset();
1169         ret &= test_move(); 
1170         test_reset();
1171         ret &= test_unref_reparent();
1172         test_reset();
1173         ret &= test_realloc_fn(); 
1174         test_reset();
1175         ret &= test_type();
1176         test_reset();
1177         ret &= test_lifeless(); 
1178         test_reset();
1179         ret &= test_loop();
1180         test_reset();
1181         ret &= test_free_parent_deny_child(); 
1182         test_reset();
1183         ret &= test_talloc_ptrtype();
1184         test_reset();
1185         ret &= test_talloc_free_in_destructor();
1186         test_reset();
1187         ret &= test_pool();
1188
1189         if (ret) {
1190                 test_reset();
1191                 ret &= test_speed();
1192         }
1193         test_reset();
1194         ret &= test_autofree();
1195
1196         test_reset();
1197
1198         return ret;
1199 }