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