Changelog for previous commit
[abartlet/talloc-debian.git] / 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 #ifdef HAVE_PTHREAD
31 #include <pthread.h>
32 #endif
33
34 #include <unistd.h>
35 #include <sys/wait.h>
36
37 #include "talloc_testsuite.h"
38
39 static struct timeval timeval_current(void)
40 {
41         struct timeval tv;
42         gettimeofday(&tv, NULL);
43         return tv;
44 }
45
46 static double timeval_elapsed(struct timeval *tv)
47 {
48         struct timeval tv2 = timeval_current();
49         return (tv2.tv_sec - tv->tv_sec) + 
50                (tv2.tv_usec - tv->tv_usec)*1.0e-6;
51 }
52
53 #define torture_assert(test, expr, str) if (!(expr)) { \
54         printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
55                 test, __location__, #expr, str); \
56         return false; \
57 }
58
59 #define torture_assert_str_equal(test, arg1, arg2, desc) \
60         if (arg1 == NULL && arg2 == NULL) {                             \
61         } else if (strcmp(arg1, arg2)) {                        \
62                 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
63                    test, __location__, arg1, arg2, desc); \
64                 return false; \
65         }
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 #if 0
105 static void test_abort_fn(const char *reason)
106 {
107         printf("# test_abort_fn(%s)\n", reason);
108         test_abort_count++;
109 }
110
111 static void test_abort_start(void)
112 {
113         test_abort_count = 0;
114         talloc_set_abort_fn(test_abort_fn);
115 }
116 #endif
117
118 static void test_abort_stop(void)
119 {
120         test_abort_count = 0;
121         talloc_set_abort_fn(NULL);
122 }
123
124 static void test_log_stdout(const char *message)
125 {
126         fprintf(stdout, "%s", message);
127 }
128
129 /*
130   test references 
131 */
132 static bool test_ref1(void)
133 {
134         void *root, *p1, *p2, *ref, *r1;
135
136         printf("test: ref1\n# SINGLE REFERENCE FREE\n");
137
138         root = talloc_named_const(NULL, 0, "root");
139         p1 = talloc_named_const(root, 1, "p1");
140         p2 = talloc_named_const(p1, 1, "p2");
141         talloc_named_const(p1, 1, "x1");
142         talloc_named_const(p1, 2, "x2");
143         talloc_named_const(p1, 3, "x3");
144
145         r1 = talloc_named_const(root, 1, "r1"); 
146         ref = talloc_reference(r1, p2);
147         talloc_report_full(root, stderr);
148
149         CHECK_BLOCKS("ref1", p1, 5);
150         CHECK_BLOCKS("ref1", p2, 1);
151         CHECK_BLOCKS("ref1", ref, 1);
152         CHECK_BLOCKS("ref1", r1, 2);
153
154         fprintf(stderr, "Freeing p2\n");
155         talloc_unlink(r1, p2);
156         talloc_report_full(root, stderr);
157
158         CHECK_BLOCKS("ref1", p1, 5);
159         CHECK_BLOCKS("ref1", p2, 1);
160         CHECK_BLOCKS("ref1", r1, 1);
161
162         fprintf(stderr, "Freeing p1\n");
163         talloc_free(p1);
164         talloc_report_full(root, stderr);
165
166         CHECK_BLOCKS("ref1", r1, 1);
167
168         fprintf(stderr, "Freeing r1\n");
169         talloc_free(r1);
170         talloc_report_full(NULL, stderr);
171
172         fprintf(stderr, "Testing NULL\n");
173         if (talloc_reference(root, NULL)) {
174                 return false;
175         }
176
177         CHECK_BLOCKS("ref1", root, 1);
178
179         CHECK_SIZE("ref1", root, 0);
180
181         talloc_free(root);
182         printf("success: ref1\n");
183         return true;
184 }
185
186 /*
187   test references 
188 */
189 static bool test_ref2(void)
190 {
191         void *root, *p1, *p2, *ref, *r1;
192
193         printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
194         root = talloc_named_const(NULL, 0, "root");
195         p1 = talloc_named_const(root, 1, "p1");
196         talloc_named_const(p1, 1, "x1");
197         talloc_named_const(p1, 1, "x2");
198         talloc_named_const(p1, 1, "x3");
199         p2 = talloc_named_const(p1, 1, "p2");
200
201         r1 = talloc_named_const(root, 1, "r1"); 
202         ref = talloc_reference(r1, p2);
203         talloc_report_full(root, stderr);
204
205         CHECK_BLOCKS("ref2", p1, 5);
206         CHECK_BLOCKS("ref2", p2, 1);
207         CHECK_BLOCKS("ref2", r1, 2);
208
209         fprintf(stderr, "Freeing ref\n");
210         talloc_unlink(r1, ref);
211         talloc_report_full(root, stderr);
212
213         CHECK_BLOCKS("ref2", p1, 5);
214         CHECK_BLOCKS("ref2", p2, 1);
215         CHECK_BLOCKS("ref2", r1, 1);
216
217         fprintf(stderr, "Freeing p2\n");
218         talloc_free(p2);
219         talloc_report_full(root, stderr);
220
221         CHECK_BLOCKS("ref2", p1, 4);
222         CHECK_BLOCKS("ref2", r1, 1);
223
224         fprintf(stderr, "Freeing p1\n");
225         talloc_free(p1);
226         talloc_report_full(root, stderr);
227
228         CHECK_BLOCKS("ref2", r1, 1);
229
230         fprintf(stderr, "Freeing r1\n");
231         talloc_free(r1);
232         talloc_report_full(root, stderr);
233
234         CHECK_SIZE("ref2", root, 0);
235
236         talloc_free(root);
237         printf("success: ref2\n");
238         return true;
239 }
240
241 /*
242   test references 
243 */
244 static bool test_ref3(void)
245 {
246         void *root, *p1, *p2, *ref, *r1;
247
248         printf("test: ref3\n# PARENT REFERENCE FREE\n");
249
250         root = talloc_named_const(NULL, 0, "root");
251         p1 = talloc_named_const(root, 1, "p1");
252         p2 = talloc_named_const(root, 1, "p2");
253         r1 = talloc_named_const(p1, 1, "r1");
254         ref = talloc_reference(p2, r1);
255         talloc_report_full(root, stderr);
256
257         CHECK_BLOCKS("ref3", p1, 2);
258         CHECK_BLOCKS("ref3", p2, 2);
259         CHECK_BLOCKS("ref3", r1, 1);
260         CHECK_BLOCKS("ref3", ref, 1);
261
262         fprintf(stderr, "Freeing p1\n");
263         talloc_free(p1);
264         talloc_report_full(root, stderr);
265
266         CHECK_BLOCKS("ref3", p2, 2);
267         CHECK_BLOCKS("ref3", r1, 1);
268
269         fprintf(stderr, "Freeing p2\n");
270         talloc_free(p2);
271         talloc_report_full(root, stderr);
272
273         CHECK_SIZE("ref3", root, 0);
274
275         talloc_free(root);
276
277         printf("success: ref3\n");
278         return true;
279 }
280
281 /*
282   test references 
283 */
284 static bool test_ref4(void)
285 {
286         void *root, *p1, *p2, *ref, *r1;
287
288         printf("test: ref4\n# REFERRER REFERENCE FREE\n");
289
290         root = talloc_named_const(NULL, 0, "root");
291         p1 = talloc_named_const(root, 1, "p1");
292         talloc_named_const(p1, 1, "x1");
293         talloc_named_const(p1, 1, "x2");
294         talloc_named_const(p1, 1, "x3");
295         p2 = talloc_named_const(p1, 1, "p2");
296
297         r1 = talloc_named_const(root, 1, "r1"); 
298         ref = talloc_reference(r1, p2);
299         talloc_report_full(root, stderr);
300
301         CHECK_BLOCKS("ref4", p1, 5);
302         CHECK_BLOCKS("ref4", p2, 1);
303         CHECK_BLOCKS("ref4", ref, 1);
304         CHECK_BLOCKS("ref4", r1, 2);
305
306         fprintf(stderr, "Freeing r1\n");
307         talloc_free(r1);
308         talloc_report_full(root, stderr);
309
310         CHECK_BLOCKS("ref4", p1, 5);
311         CHECK_BLOCKS("ref4", p2, 1);
312
313         fprintf(stderr, "Freeing p2\n");
314         talloc_free(p2);
315         talloc_report_full(root, stderr);
316
317         CHECK_BLOCKS("ref4", p1, 4);
318
319         fprintf(stderr, "Freeing p1\n");
320         talloc_free(p1);
321         talloc_report_full(root, stderr);
322
323         CHECK_SIZE("ref4", root, 0);
324
325         talloc_free(root);
326
327         printf("success: ref4\n");
328         return true;
329 }
330
331
332 /*
333   test references 
334 */
335 static bool test_unlink1(void)
336 {
337         void *root, *p1, *p2, *ref, *r1;
338
339         printf("test: unlink\n# UNLINK\n");
340
341         root = talloc_named_const(NULL, 0, "root");
342         p1 = talloc_named_const(root, 1, "p1");
343         talloc_named_const(p1, 1, "x1");
344         talloc_named_const(p1, 1, "x2");
345         talloc_named_const(p1, 1, "x3");
346         p2 = talloc_named_const(p1, 1, "p2");
347
348         r1 = talloc_named_const(p1, 1, "r1");   
349         ref = talloc_reference(r1, p2);
350         talloc_report_full(root, stderr);
351
352         CHECK_BLOCKS("unlink", p1, 7);
353         CHECK_BLOCKS("unlink", p2, 1);
354         CHECK_BLOCKS("unlink", ref, 1);
355         CHECK_BLOCKS("unlink", r1, 2);
356
357         fprintf(stderr, "Unreferencing r1\n");
358         talloc_unlink(r1, p2);
359         talloc_report_full(root, stderr);
360
361         CHECK_BLOCKS("unlink", p1, 6);
362         CHECK_BLOCKS("unlink", p2, 1);
363         CHECK_BLOCKS("unlink", r1, 1);
364
365         fprintf(stderr, "Freeing p1\n");
366         talloc_free(p1);
367         talloc_report_full(root, stderr);
368
369         CHECK_SIZE("unlink", root, 0);
370
371         talloc_free(root);
372
373         printf("success: unlink\n");
374         return true;
375 }
376
377 static int fail_destructor(void *ptr)
378 {
379         return -1;
380 }
381
382 /*
383   miscellaneous tests to try to get a higher test coverage percentage
384 */
385 static bool test_misc(void)
386 {
387         void *root, *p1;
388         char *p2;
389         double *d;
390         const char *name;
391
392         printf("test: misc\n# MISCELLANEOUS\n");
393
394         root = talloc_new(NULL);
395
396         p1 = talloc_size(root, 0x7fffffff);
397         torture_assert("misc", !p1, "failed: large talloc allowed\n");
398
399         p1 = talloc_strdup(root, "foo");
400         talloc_increase_ref_count(p1);
401         talloc_increase_ref_count(p1);
402         talloc_increase_ref_count(p1);
403         CHECK_BLOCKS("misc", p1, 1);
404         CHECK_BLOCKS("misc", root, 2);
405         talloc_unlink(NULL, p1);
406         CHECK_BLOCKS("misc", p1, 1);
407         CHECK_BLOCKS("misc", root, 2);
408         talloc_unlink(NULL, p1);
409         CHECK_BLOCKS("misc", p1, 1);
410         CHECK_BLOCKS("misc", root, 2);
411         p2 = talloc_strdup(p1, "foo");
412         torture_assert("misc", talloc_unlink(root, p2) == -1,
413                                    "failed: talloc_unlink() of non-reference context should return -1\n");
414         torture_assert("misc", talloc_unlink(p1, p2) == 0,
415                 "failed: talloc_unlink() of parent should succeed\n");
416         talloc_unlink(NULL, p1);
417         CHECK_BLOCKS("misc", p1, 1);
418         CHECK_BLOCKS("misc", root, 2);
419
420         name = talloc_set_name(p1, "my name is %s", "foo");
421         torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
422                 "failed: wrong name after talloc_set_name(my name is foo)");
423         torture_assert_str_equal("misc", talloc_get_name(p1), name,
424                 "failed: wrong name after talloc_set_name(my name is foo)");
425         CHECK_BLOCKS("misc", p1, 2);
426         CHECK_BLOCKS("misc", root, 3);
427
428         talloc_set_name_const(p1, NULL);
429         torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
430                 "failed: wrong name after talloc_set_name(NULL)");
431         CHECK_BLOCKS("misc", p1, 2);
432         CHECK_BLOCKS("misc", root, 3);
433
434         torture_assert("misc", talloc_free(NULL) == -1, 
435                                    "talloc_free(NULL) should give -1\n");
436
437         talloc_set_destructor(p1, fail_destructor);
438         torture_assert("misc", talloc_free(p1) == -1, 
439                 "Failed destructor should cause talloc_free to fail\n");
440         talloc_set_destructor(p1, NULL);
441
442         talloc_report(root, stderr);
443
444
445         p2 = (char *)talloc_zero_size(p1, 20);
446         torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
447         talloc_free(p2);
448
449         torture_assert("misc", talloc_strdup(root, NULL) == NULL,
450                 "failed: strdup on NULL should give NULL\n");
451
452         p2 = talloc_strndup(p1, "foo", 2);
453         torture_assert("misc", strcmp("fo", p2) == 0, 
454                                    "strndup doesn't work\n");
455         p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
456         torture_assert("misc", strcmp("food", p2) == 0, 
457                                    "talloc_asprintf_append_buffer doesn't work\n");
458         CHECK_BLOCKS("misc", p2, 1);
459         CHECK_BLOCKS("misc", p1, 3);
460
461         p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
462         torture_assert("misc", strcmp("hello world", p2) == 0,
463                 "talloc_asprintf_append_buffer doesn't work\n");
464         CHECK_BLOCKS("misc", p2, 1);
465         CHECK_BLOCKS("misc", p1, 3);
466         talloc_free(p2);
467
468         d = talloc_array(p1, double, 0x20000000);
469         torture_assert("misc", !d, "failed: integer overflow not detected\n");
470
471         d = talloc_realloc(p1, d, double, 0x20000000);
472         torture_assert("misc", !d, "failed: integer overflow not detected\n");
473
474         talloc_free(p1);
475         CHECK_BLOCKS("misc", root, 1);
476
477         p1 = talloc_named(root, 100, "%d bytes", 100);
478         CHECK_BLOCKS("misc", p1, 2);
479         CHECK_BLOCKS("misc", root, 3);
480         talloc_unlink(root, p1);
481
482         p1 = talloc_init("%d bytes", 200);
483         p2 = talloc_asprintf(p1, "my test '%s'", "string");
484         torture_assert_str_equal("misc", p2, "my test 'string'",
485                 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
486         CHECK_BLOCKS("misc", p1, 3);
487         CHECK_SIZE("misc", p2, 17);
488         CHECK_BLOCKS("misc", root, 1);
489         talloc_unlink(NULL, p1);
490
491         p1 = talloc_named_const(root, 10, "p1");
492         p2 = (char *)talloc_named_const(root, 20, "p2");
493         (void)talloc_reference(p1, p2);
494         talloc_report_full(root, stderr);
495         talloc_unlink(root, p2);
496         talloc_report_full(root, stderr);
497         CHECK_BLOCKS("misc", p2, 1);
498         CHECK_BLOCKS("misc", p1, 2);
499         CHECK_BLOCKS("misc", root, 3);
500         talloc_unlink(p1, p2);
501         talloc_unlink(root, p1);
502
503         p1 = talloc_named_const(root, 10, "p1");
504         p2 = (char *)talloc_named_const(root, 20, "p2");
505         (void)talloc_reference(NULL, p2);
506         talloc_report_full(root, stderr);
507         talloc_unlink(root, p2);
508         talloc_report_full(root, stderr);
509         CHECK_BLOCKS("misc", p2, 1);
510         CHECK_BLOCKS("misc", p1, 1);
511         CHECK_BLOCKS("misc", root, 2);
512         talloc_unlink(NULL, p2);
513         talloc_unlink(root, p1);
514
515         /* Test that talloc_unlink is a no-op */
516
517         torture_assert("misc", talloc_unlink(root, NULL) == -1,
518                 "failed: talloc_unlink(root, NULL) == -1\n");
519
520         talloc_report(root, stderr);
521         talloc_report(NULL, stderr);
522
523         CHECK_SIZE("misc", root, 0);
524
525         talloc_free(root);
526
527         CHECK_SIZE("misc", NULL, 0);
528
529         talloc_enable_null_tracking_no_autofree();
530         talloc_enable_leak_report();
531         talloc_enable_leak_report_full();
532
533         printf("success: misc\n");
534
535         return true;
536 }
537
538
539 /*
540   test realloc
541 */
542 static bool test_realloc(void)
543 {
544         void *root, *p1, *p2;
545
546         printf("test: realloc\n# REALLOC\n");
547
548         root = talloc_new(NULL);
549
550         p1 = talloc_size(root, 10);
551         CHECK_SIZE("realloc", p1, 10);
552
553         p1 = talloc_realloc_size(NULL, p1, 20);
554         CHECK_SIZE("realloc", p1, 20);
555
556         talloc_new(p1);
557
558         p2 = talloc_realloc_size(p1, NULL, 30);
559
560         talloc_new(p1);
561
562         p2 = talloc_realloc_size(p1, p2, 40);
563
564         CHECK_SIZE("realloc", p2, 40);
565         CHECK_SIZE("realloc", root, 60);
566         CHECK_BLOCKS("realloc", p1, 4);
567
568         p1 = talloc_realloc_size(NULL, p1, 20);
569         CHECK_SIZE("realloc", p1, 60);
570
571         talloc_increase_ref_count(p2);
572         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
573                 "failed: talloc_realloc() on a referenced pointer should fail\n");
574         CHECK_BLOCKS("realloc", p1, 4);
575
576         talloc_realloc_size(NULL, p2, 0);
577         talloc_realloc_size(NULL, p2, 0);
578         CHECK_BLOCKS("realloc", p1, 4);
579         talloc_realloc_size(p1, p2, 0);
580         CHECK_BLOCKS("realloc", p1, 3);
581
582         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
583                 "failed: oversize talloc should fail\n");
584
585         talloc_realloc_size(NULL, p1, 0);
586         CHECK_BLOCKS("realloc", root, 4);
587         talloc_realloc_size(root, p1, 0);
588         CHECK_BLOCKS("realloc", root, 1);
589
590         CHECK_SIZE("realloc", root, 0);
591
592         talloc_free(root);
593
594         printf("success: realloc\n");
595
596         return true;
597 }
598
599 /*
600   test realloc with a child
601 */
602 static bool test_realloc_child(void)
603 {
604         void *root;
605         struct el2 {
606                 const char *name;
607         } *el2; 
608         struct el1 {
609                 int count;
610                 struct el2 **list, **list2, **list3;
611         } *el1;
612
613         printf("test: REALLOC WITH CHILD\n");
614
615         root = talloc_new(NULL);
616
617         el1 = talloc(root, struct el1);
618         el1->list = talloc(el1, struct el2 *);
619         el1->list[0] = talloc(el1->list, struct el2);
620         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
621
622         el1->list2 = talloc(el1, struct el2 *);
623         el1->list2[0] = talloc(el1->list2, struct el2);
624         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
625
626         el1->list3 = talloc(el1, struct el2 *);
627         el1->list3[0] = talloc(el1->list3, struct el2);
628         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
629         
630         el2 = talloc(el1->list, struct el2);
631         el2 = talloc(el1->list2, struct el2);
632         el2 = talloc(el1->list3, struct el2);
633         (void)el2;
634
635         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
636         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
637         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
638
639         talloc_free(root);
640
641         printf("success: REALLOC WITH CHILD\n");
642         return true;
643 }
644
645 /*
646   test type checking
647 */
648 static bool test_type(void)
649 {
650         void *root;
651         struct el1 {
652                 int count;
653         };
654         struct el2 {
655                 int count;
656         };
657         struct el1 *el1;
658
659         printf("test: type\n# talloc type checking\n");
660
661         root = talloc_new(NULL);
662
663         el1 = talloc(root, struct el1);
664
665         el1->count = 1;
666
667         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
668                 "type check failed on el1\n");
669         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
670                 "type check failed on el1 with el2\n");
671         talloc_set_type(el1, struct el2);
672         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
673                 "type set failed on el1 with el2\n");
674
675         talloc_free(root);
676
677         printf("success: type\n");
678         return true;
679 }
680
681 /*
682   test steal
683 */
684 static bool test_steal(void)
685 {
686         void *root, *p1, *p2;
687
688         printf("test: steal\n# STEAL\n");
689
690         root = talloc_new(NULL);
691
692         p1 = talloc_array(root, char, 10);
693         CHECK_SIZE("steal", p1, 10);
694
695         p2 = talloc_realloc(root, NULL, char, 20);
696         CHECK_SIZE("steal", p1, 10);
697         CHECK_SIZE("steal", root, 30);
698
699         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
700                 "failed: stealing NULL should give NULL\n");
701
702         torture_assert("steal", talloc_steal(p1, p1) == p1,
703                 "failed: stealing to ourselves is a nop\n");
704         CHECK_BLOCKS("steal", root, 3);
705         CHECK_SIZE("steal", root, 30);
706
707         talloc_steal(NULL, p1);
708         talloc_steal(NULL, p2);
709         CHECK_BLOCKS("steal", root, 1);
710         CHECK_SIZE("steal", root, 0);
711
712         talloc_free(p1);
713         talloc_steal(root, p2);
714         CHECK_BLOCKS("steal", root, 2);
715         CHECK_SIZE("steal", root, 20);
716         
717         talloc_free(p2);
718
719         CHECK_BLOCKS("steal", root, 1);
720         CHECK_SIZE("steal", root, 0);
721
722         talloc_free(root);
723
724         p1 = talloc_size(NULL, 3);
725         talloc_report_full(NULL, stderr);
726         CHECK_SIZE("steal", NULL, 3);
727         talloc_free(p1);
728
729         printf("success: steal\n");
730         return true;
731 }
732
733 /*
734   test move
735 */
736 static bool test_move(void)
737 {
738         void *root;
739         struct t_move {
740                 char *p;
741                 int *x;
742         } *t1, *t2;
743
744         printf("test: move\n# MOVE\n");
745
746         root = talloc_new(NULL);
747
748         t1 = talloc(root, struct t_move);
749         t2 = talloc(root, struct t_move);
750         t1->p = talloc_strdup(t1, "foo");
751         t1->x = talloc(t1, int);
752         *t1->x = 42;
753
754         t2->p = talloc_move(t2, &t1->p);
755         t2->x = talloc_move(t2, &t1->x);
756         torture_assert("move", t1->p == NULL && t1->x == NULL &&
757             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
758                 "talloc move failed");
759
760         talloc_free(root);
761
762         printf("success: move\n");
763
764         return true;
765 }
766
767 /*
768   test talloc_realloc_fn
769 */
770 static bool test_realloc_fn(void)
771 {
772         void *root, *p1;
773
774         printf("test: realloc_fn\n# talloc_realloc_fn\n");
775
776         root = talloc_new(NULL);
777
778         p1 = talloc_realloc_fn(root, NULL, 10);
779         CHECK_BLOCKS("realloc_fn", root, 2);
780         CHECK_SIZE("realloc_fn", root, 10);
781         p1 = talloc_realloc_fn(root, p1, 20);
782         CHECK_BLOCKS("realloc_fn", root, 2);
783         CHECK_SIZE("realloc_fn", root, 20);
784         p1 = talloc_realloc_fn(root, p1, 0);
785         CHECK_BLOCKS("realloc_fn", root, 1);
786         CHECK_SIZE("realloc_fn", root, 0);
787
788         talloc_free(root);
789
790         printf("success: realloc_fn\n");
791         return true;
792 }
793
794
795 static bool test_unref_reparent(void)
796 {
797         void *root, *p1, *p2, *c1;
798
799         printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
800
801         root = talloc_named_const(NULL, 0, "root");
802         p1 = talloc_named_const(root, 1, "orig parent");
803         p2 = talloc_named_const(root, 1, "parent by reference");
804
805         c1 = talloc_named_const(p1, 1, "child");
806         talloc_reference(p2, c1);
807
808         CHECK_PARENT("unref_reparent", c1, p1);
809
810         talloc_free(p1);
811
812         CHECK_PARENT("unref_reparent", c1, p2);
813
814         talloc_unlink(p2, c1);
815
816         CHECK_SIZE("unref_reparent", root, 1);
817
818         talloc_free(p2);
819         talloc_free(root);
820
821         printf("success: unref_reparent\n");
822         return true;
823 }
824
825 /*
826   measure the speed of talloc versus malloc
827 */
828 static bool test_speed(void)
829 {
830         void *ctx = talloc_new(NULL);
831         unsigned count;
832         const int loop = 1000;
833         int i;
834         struct timeval tv;
835
836         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
837
838         tv = timeval_current();
839         count = 0;
840         do {
841                 void *p1, *p2, *p3;
842                 for (i=0;i<loop;i++) {
843                         p1 = talloc_size(ctx, loop % 100);
844                         p2 = talloc_strdup(p1, "foo bar");
845                         p3 = talloc_size(p1, 300);
846                         (void)p2;
847                         (void)p3;
848                         talloc_free(p1);
849                 }
850                 count += 3 * loop;
851         } while (timeval_elapsed(&tv) < 5.0);
852
853         fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
854
855         talloc_free(ctx);
856
857         ctx = talloc_pool(NULL, 1024);
858
859         tv = timeval_current();
860         count = 0;
861         do {
862                 void *p1, *p2, *p3;
863                 for (i=0;i<loop;i++) {
864                         p1 = talloc_size(ctx, loop % 100);
865                         p2 = talloc_strdup(p1, "foo bar");
866                         p3 = talloc_size(p1, 300);
867                         (void)p2;
868                         (void)p3;
869                         talloc_free(p1);
870                 }
871                 count += 3 * loop;
872         } while (timeval_elapsed(&tv) < 5.0);
873
874         talloc_free(ctx);
875
876         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
877
878         tv = timeval_current();
879         count = 0;
880         do {
881                 void *p1, *p2, *p3;
882                 for (i=0;i<loop;i++) {
883                         p1 = malloc(loop % 100);
884                         p2 = strdup("foo bar");
885                         p3 = malloc(300);
886                         free(p1);
887                         free(p2);
888                         free(p3);
889                 }
890                 count += 3 * loop;
891         } while (timeval_elapsed(&tv) < 5.0);
892         fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
893
894         printf("success: speed\n");
895
896         return true;
897 }
898
899 static bool test_lifeless(void)
900 {
901         void *top = talloc_new(NULL);
902         char *parent, *child; 
903         void *child_owner = talloc_new(NULL);
904
905         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
906
907         parent = talloc_strdup(top, "parent");
908         child = talloc_strdup(parent, "child");  
909         (void)talloc_reference(child, parent);
910         (void)talloc_reference(child_owner, child); 
911         talloc_report_full(top, stderr);
912         talloc_unlink(top, parent);
913         talloc_unlink(top, child);
914         talloc_report_full(top, stderr);
915         talloc_free(top);
916         talloc_free(child_owner);
917         talloc_free(child);
918
919         printf("success: lifeless\n");
920         return true;
921 }
922
923 static int loop_destructor_count;
924
925 static int test_loop_destructor(char *ptr)
926 {
927         loop_destructor_count++;
928         return 0;
929 }
930
931 static bool test_loop(void)
932 {
933         void *top = talloc_new(NULL);
934         char *parent;
935         struct req1 {
936                 char *req2, *req3;
937         } *req1;
938
939         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
940
941         parent = talloc_strdup(top, "parent");
942         req1 = talloc(parent, struct req1);
943         req1->req2 = talloc_strdup(req1, "req2");  
944         talloc_set_destructor(req1->req2, test_loop_destructor);
945         req1->req3 = talloc_strdup(req1, "req3");
946         (void)talloc_reference(req1->req3, req1);
947         talloc_report_full(top, stderr);
948         talloc_free(parent);
949         talloc_report_full(top, stderr);
950         talloc_report_full(NULL, stderr);
951         talloc_free(top);
952
953         torture_assert("loop", loop_destructor_count == 1, 
954                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
955         loop_destructor_count = 0;
956
957         printf("success: loop\n");
958         return true;
959 }
960
961 static int fail_destructor_str(char *ptr)
962 {
963         return -1;
964 }
965
966 static bool test_free_parent_deny_child(void)
967 {
968         void *top = talloc_new(NULL);
969         char *level1;
970         char *level2;
971         char *level3;
972
973         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
974
975         level1 = talloc_strdup(top, "level1");
976         level2 = talloc_strdup(level1, "level2");
977         level3 = talloc_strdup(level2, "level3");
978
979         talloc_set_destructor(level3, fail_destructor_str);
980         talloc_free(level1);
981         talloc_set_destructor(level3, NULL);
982
983         CHECK_PARENT("free_parent_deny_child", level3, top);
984
985         talloc_free(top);
986
987         printf("success: free_parent_deny_child\n");
988         return true;
989 }
990
991 struct new_parent {
992         void *new_parent;
993         char val[20];
994 };
995
996 static int reparenting_destructor(struct new_parent *np)
997 {
998         talloc_set_destructor(np, NULL);
999         (void)talloc_move(np->new_parent, &np);
1000         return -1;
1001 }
1002
1003 static bool test_free_parent_reparent_child(void)
1004 {
1005         void *top = talloc_new(NULL);
1006         char *level1;
1007         char *alternate_level1;
1008         char *level2;
1009         struct new_parent *level3;
1010
1011         printf("test: free_parent_reparent_child\n# "
1012                 "TALLOC FREE PARENT REPARENT CHILD\n");
1013
1014         level1 = talloc_strdup(top, "level1");
1015         alternate_level1 = talloc_strdup(top, "alternate_level1");
1016         level2 = talloc_strdup(level1, "level2");
1017         level3 = talloc(level2, struct new_parent);
1018         level3->new_parent = alternate_level1;
1019         memset(level3->val, 'x', sizeof(level3->val));
1020
1021         talloc_set_destructor(level3, reparenting_destructor);
1022         talloc_free(level1);
1023
1024         CHECK_PARENT("free_parent_reparent_child",
1025                 level3, alternate_level1);
1026
1027         talloc_free(top);
1028
1029         printf("success: free_parent_reparent_child\n");
1030         return true;
1031 }
1032
1033 static bool test_free_parent_reparent_child_in_pool(void)
1034 {
1035         void *top = talloc_new(NULL);
1036         char *level1;
1037         char *alternate_level1;
1038         char *level2;
1039         void *pool;
1040         struct new_parent *level3;
1041
1042         printf("test: free_parent_reparent_child_in_pool\n# "
1043                 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1044
1045         pool = talloc_pool(top, 1024);
1046         level1 = talloc_strdup(pool, "level1");
1047         alternate_level1 = talloc_strdup(top, "alternate_level1");
1048         level2 = talloc_strdup(level1, "level2");
1049         level3 = talloc(level2, struct new_parent);
1050         level3->new_parent = alternate_level1;
1051         memset(level3->val, 'x', sizeof(level3->val));
1052
1053         talloc_set_destructor(level3, reparenting_destructor);
1054         talloc_free(level1);
1055         talloc_set_destructor(level3, NULL);
1056
1057         CHECK_PARENT("free_parent_reparent_child_in_pool",
1058                 level3, alternate_level1);
1059
1060         /* Even freeing alternate_level1 should leave pool alone. */
1061         talloc_free(alternate_level1);
1062         talloc_free(top);
1063
1064         printf("success: free_parent_reparent_child_in_pool\n");
1065         return true;
1066 }
1067
1068
1069 static bool test_talloc_ptrtype(void)
1070 {
1071         void *top = talloc_new(NULL);
1072         struct struct1 {
1073                 int foo;
1074                 int bar;
1075         } *s1, *s2, **s3, ***s4;
1076         const char *location1;
1077         const char *location2;
1078         const char *location3;
1079         const char *location4;
1080
1081         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1082
1083         s1 = talloc_ptrtype(top, s1);location1 = __location__;
1084
1085         if (talloc_get_size(s1) != sizeof(struct struct1)) {
1086                 printf("failure: ptrtype [\n"
1087                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1088                   "]\n", (unsigned long)talloc_get_size(s1),
1089                            (unsigned long)sizeof(struct struct1));
1090                 return false;
1091         }
1092
1093         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1094                 printf("failure: ptrtype [\n"
1095                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1096                         talloc_get_name(s1), location1);
1097                 return false;
1098         }
1099
1100         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1101
1102         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1103                 printf("failure: ptrtype [\n"
1104                            "talloc_array_ptrtype() allocated the wrong size "
1105                        "%lu (should be %lu)\n]\n",
1106                         (unsigned long)talloc_get_size(s2),
1107                     (unsigned long)(sizeof(struct struct1)*10));
1108                 return false;
1109         }
1110
1111         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1112                 printf("failure: ptrtype [\n"
1113                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1114                         talloc_get_name(s2), location2);
1115                 return false;
1116         }
1117
1118         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1119
1120         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1121                 printf("failure: ptrtype [\n"
1122                            "talloc_array_ptrtype() allocated the wrong size "
1123                        "%lu (should be %lu)\n]\n",
1124                            (unsigned long)talloc_get_size(s3),
1125                        (unsigned long)(sizeof(struct struct1 *)*10));
1126                 return false;
1127         }
1128
1129         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1130                 "talloc_array_ptrtype() sets the wrong name");
1131
1132         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1133
1134         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1135                 printf("failure: ptrtype [\n"
1136                       "talloc_array_ptrtype() allocated the wrong size "
1137                        "%lu (should be %lu)\n]\n",
1138                            (unsigned long)talloc_get_size(s4),
1139                        (unsigned long)(sizeof(struct struct1 **)*10));
1140                 return false;
1141         }
1142
1143         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1144                 "talloc_array_ptrtype() sets the wrong name");
1145
1146         talloc_free(top);
1147
1148         printf("success: ptrtype\n");
1149         return true;
1150 }
1151
1152 static int _test_talloc_free_in_destructor(void **ptr)
1153 {
1154         talloc_free(*ptr);
1155         return 0;
1156 }
1157
1158 static bool test_talloc_free_in_destructor(void)
1159 {
1160         void *level0;
1161         void *level1;
1162         void *level2;
1163         void *level3;
1164         void *level4;
1165         void **level5;
1166
1167         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1168
1169         level0 = talloc_new(NULL);
1170         level1 = talloc_new(level0);
1171         level2 = talloc_new(level1);
1172         level3 = talloc_new(level2);
1173         level4 = talloc_new(level3);
1174         level5 = talloc(level4, void *);
1175
1176         *level5 = level3;
1177         (void)talloc_reference(level0, level3);
1178         (void)talloc_reference(level3, level3);
1179         (void)talloc_reference(level5, level3);
1180
1181         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1182
1183         talloc_free(level1);
1184
1185         talloc_free(level0);
1186
1187         printf("success: free_in_destructor\n");
1188         return true;
1189 }
1190
1191 static bool test_autofree(void)
1192 {
1193 #if _SAMBA_BUILD_ < 4
1194         /* autofree test would kill smbtorture */
1195         void *p;
1196         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1197
1198         p = talloc_autofree_context();
1199         talloc_free(p);
1200
1201         p = talloc_autofree_context();
1202         talloc_free(p);
1203
1204         printf("success: autofree\n");
1205 #endif
1206         return true;
1207 }
1208
1209 static bool test_pool(void)
1210 {
1211         void *pool;
1212         void *p1, *p2, *p3, *p4;
1213         void *p2_2;
1214
1215         pool = talloc_pool(NULL, 1024);
1216
1217         p1 = talloc_size(pool, 80);
1218         memset(p1, 0x11, talloc_get_size(p1));
1219         p2 = talloc_size(pool, 20);
1220         memset(p2, 0x11, talloc_get_size(p2));
1221         p3 = talloc_size(p1, 50);
1222         memset(p3, 0x11, talloc_get_size(p3));
1223         p4 = talloc_size(p3, 1000);
1224         memset(p4, 0x11, talloc_get_size(p4));
1225
1226 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1227         p2_2 = talloc_realloc_size(pool, p2, 20+1);
1228         torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1229         memset(p2, 0x11, talloc_get_size(p2));
1230         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1231         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1232         memset(p2, 0x11, talloc_get_size(p2));
1233         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1234         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1235         memset(p2, 0x11, talloc_get_size(p2));
1236
1237         talloc_free(p3);
1238
1239         /* this should reclaim the memory of p4 and p3 */
1240         p2_2 = talloc_realloc_size(pool, p2, 400);
1241         torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1242         memset(p2, 0x11, talloc_get_size(p2));
1243
1244         talloc_free(p1);
1245
1246         /* this should reclaim the memory of p1 */
1247         p2_2 = talloc_realloc_size(pool, p2, 800);
1248         torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1249         p2 = p2_2;
1250         memset(p2, 0x11, talloc_get_size(p2));
1251
1252         /* this should do a malloc */
1253         p2_2 = talloc_realloc_size(pool, p2, 1800);
1254         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1255         p2 = p2_2;
1256         memset(p2, 0x11, talloc_get_size(p2));
1257
1258         /* this should reclaim the memory from the pool */
1259         p3 = talloc_size(pool, 80);
1260         torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1261         memset(p3, 0x11, talloc_get_size(p3));
1262
1263         talloc_free(p2);
1264         talloc_free(p3);
1265
1266         p1 = talloc_size(pool, 80);
1267         memset(p1, 0x11, talloc_get_size(p1));
1268         p2 = talloc_size(pool, 20);
1269         memset(p2, 0x11, talloc_get_size(p2));
1270
1271         talloc_free(p1);
1272
1273         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1274         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1275         memset(p2, 0x11, talloc_get_size(p2));
1276         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1277         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1278         memset(p2, 0x11, talloc_get_size(p2));
1279
1280         /* this should do a malloc */
1281         p2_2 = talloc_realloc_size(pool, p2, 1800);
1282         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1283         p2 = p2_2;
1284         memset(p2, 0x11, talloc_get_size(p2));
1285
1286         /* this should reclaim the memory from the pool */
1287         p3 = talloc_size(pool, 800);
1288         torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1289         memset(p3, 0x11, talloc_get_size(p3));
1290
1291 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1292
1293         talloc_free(pool);
1294
1295         return true;
1296 }
1297
1298 static bool test_pool_steal(void)
1299 {
1300         void *root;
1301         void *pool;
1302         void *p1, *p2;
1303         void *p1_2, *p2_2;
1304         size_t hdr;
1305         size_t ofs1, ofs2;
1306
1307         root = talloc_new(NULL);
1308         pool = talloc_pool(root, 1024);
1309
1310         p1 = talloc_size(pool, 4 * 16);
1311         torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1312         memset(p1, 0x11, talloc_get_size(p1));
1313         p2 = talloc_size(pool, 4 * 16);
1314         torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1315         memset(p2, 0x11, talloc_get_size(p2));
1316
1317         ofs1 = PTR_DIFF(p2, p1);
1318         hdr = ofs1 - talloc_get_size(p1);
1319
1320         talloc_steal(root, p1);
1321         talloc_steal(root, p2);
1322
1323         talloc_free(pool);
1324
1325         p1_2 = p1;
1326
1327 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1328         p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1329         torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1330         memset(p1_2, 0x11, talloc_get_size(p1_2));
1331         ofs1 = PTR_DIFF(p1_2, p2);
1332         ofs2 = talloc_get_size(p2) + hdr;
1333
1334         torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1335
1336         p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1337         torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1338         memset(p2_2, 0x11, talloc_get_size(p2_2));
1339 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1340
1341         talloc_free(p1_2);
1342
1343         p2_2 = p2;
1344
1345 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1346         /* now we should reclaim the full pool */
1347         p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1348         torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1349         p2 = p2_2;
1350         memset(p2_2, 0x11, talloc_get_size(p2_2));
1351
1352         /* now we malloc and free the full pool space */
1353         p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1354         torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1355         memset(p2_2, 0x11, talloc_get_size(p2_2));
1356
1357 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1358
1359         talloc_free(p2_2);
1360
1361         talloc_free(root);
1362
1363         return true;
1364 }
1365
1366 static bool test_pool_nest(void)
1367 {
1368         void *p1, *p2, *p3;
1369         void *e = talloc_new(NULL);
1370
1371         p1 = talloc_pool(NULL, 1024);
1372         torture_assert("talloc_pool", p1 != NULL, "failed");
1373
1374         p2 = talloc_pool(p1, 500);
1375         torture_assert("talloc_pool", p2 != NULL, "failed");
1376
1377         p3 = talloc_size(p2, 10);
1378
1379         talloc_steal(e, p3);
1380
1381         talloc_free(p2);
1382
1383         talloc_free(p3);
1384
1385         talloc_free(p1);
1386
1387         return true;
1388 }
1389
1390 struct pooled {
1391         char *s1;
1392         char *s2;
1393         char *s3;
1394 };
1395
1396 static bool test_pooled_object(void)
1397 {
1398         struct pooled *p;
1399         const char *s1 = "hello";
1400         const char *s2 = "world";
1401         const char *s3 = "";
1402
1403         p = talloc_pooled_object(NULL, struct pooled, 3,
1404                         strlen(s1)+strlen(s2)+strlen(s3)+3);
1405
1406         if (talloc_get_size(p) != sizeof(struct pooled)) {
1407                 return false;
1408         }
1409
1410         p->s1 = talloc_strdup(p, s1);
1411
1412         TALLOC_FREE(p->s1);
1413         p->s1 = talloc_strdup(p, s2);
1414         TALLOC_FREE(p->s1);
1415
1416         p->s1 = talloc_strdup(p, s1);
1417         p->s2 = talloc_strdup(p, s2);
1418         p->s3 = talloc_strdup(p, s3);
1419
1420         TALLOC_FREE(p);
1421         return true;
1422 }
1423
1424 static bool test_free_ref_null_context(void)
1425 {
1426         void *p1, *p2, *p3;
1427         int ret;
1428
1429         talloc_disable_null_tracking();
1430         p1 = talloc_new(NULL);
1431         p2 = talloc_new(NULL);
1432
1433         p3 = talloc_reference(p2, p1);
1434         torture_assert("reference", p3 == p1, "failed: reference on null");
1435
1436         ret = talloc_free(p1);
1437         torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1438         talloc_free(p2);
1439
1440         talloc_enable_null_tracking_no_autofree();
1441         p1 = talloc_new(NULL);
1442         p2 = talloc_new(NULL);
1443
1444         p3 = talloc_reference(p2, p1);
1445         torture_assert("reference", p3 == p1, "failed: reference on null");
1446
1447         ret = talloc_free(p1);
1448         torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1449         talloc_free(p2);
1450
1451         return true;
1452 }
1453
1454 static bool test_rusty(void)
1455 {
1456         void *root;
1457         const char *p1;
1458
1459         talloc_enable_null_tracking();
1460         root = talloc_new(NULL);
1461         p1 = talloc_strdup(root, "foo");
1462         talloc_increase_ref_count(p1);
1463         talloc_report_full(root, stdout);
1464         talloc_free(root);
1465         CHECK_BLOCKS("null_context", NULL, 2);
1466         return true;
1467 }
1468
1469 static bool test_free_children(void)
1470 {
1471         void *root;
1472         char *p1, *p2;
1473         const char *name, *name2;
1474
1475         talloc_enable_null_tracking();
1476         root = talloc_new(NULL);
1477         p1 = talloc_strdup(root, "foo1");
1478         p2 = talloc_strdup(p1, "foo2");
1479         (void)p2;
1480
1481         talloc_set_name(p1, "%s", "testname");
1482         talloc_free_children(p1);
1483         /* check its still a valid talloc ptr */
1484         talloc_get_size(talloc_get_name(p1));
1485         if (strcmp(talloc_get_name(p1), "testname") != 0) {
1486                 return false;
1487         }
1488
1489         talloc_set_name(p1, "%s", "testname");
1490         name = talloc_get_name(p1);
1491         talloc_free_children(p1);
1492         /* check its still a valid talloc ptr */
1493         talloc_get_size(talloc_get_name(p1));
1494         torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
1495         torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
1496                        "wrong name");
1497         CHECK_BLOCKS("name1", p1, 2);
1498
1499         /* note that this does not free the old child name */
1500         talloc_set_name_const(p1, "testname2");
1501         name2 = talloc_get_name(p1);
1502         /* but this does */
1503         talloc_free_children(p1);
1504         (void)name2;
1505         torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1506                        "wrong name");
1507         CHECK_BLOCKS("name1", p1, 1);
1508
1509         talloc_report_full(root, stdout);
1510         talloc_free(root);
1511         return true;
1512 }
1513
1514 static bool test_memlimit(void)
1515 {
1516         void *root;
1517         char *l1, *l2, *l3, *l4, *l5, *t;
1518         char *pool;
1519         int i;
1520
1521         printf("test: memlimit\n# MEMORY LIMITS\n");
1522
1523         printf("==== talloc_new(NULL)\n");
1524         root = talloc_new(NULL);
1525
1526         talloc_report_full(root, stdout);
1527
1528         printf("==== talloc_size(root, 2048)\n");
1529         l1 = talloc_size(root, 2048);
1530         torture_assert("memlimit", l1 != NULL,
1531                 "failed: alloc should not fail due to memory limit\n");
1532
1533         talloc_report_full(root, stdout);
1534
1535         printf("==== talloc_free(l1)\n");
1536         talloc_free(l1);
1537
1538         talloc_report_full(root, stdout);
1539
1540         printf("==== talloc_strdup(root, level 1)\n");
1541         l1 = talloc_strdup(root, "level 1");
1542         torture_assert("memlimit", l1 != NULL,
1543                 "failed: alloc should not fail due to memory limit\n");
1544
1545         talloc_report_full(root, stdout);
1546
1547         printf("==== talloc_set_memlimit(l1, 2048)\n");
1548         torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
1549                 "failed: setting memlimit should never fail\n");
1550
1551         talloc_report_full(root, stdout);
1552
1553         printf("==== talloc_size(root, 2048)\n");
1554         l2 = talloc_size(l1, 2048);
1555         torture_assert("memlimit", l2 == NULL,
1556                 "failed: alloc should fail due to memory limit\n");
1557
1558         talloc_report_full(root, stdout);
1559
1560         printf("==== talloc_strdup(l1, level 2)\n");
1561         l2 = talloc_strdup(l1, "level 2");
1562         torture_assert("memlimit", l2 != NULL,
1563                 "failed: alloc should not fail due to memory limit\n");
1564
1565         talloc_report_full(root, stdout);
1566
1567         printf("==== talloc_free(l2)\n");
1568         talloc_free(l2);
1569
1570         talloc_report_full(root, stdout);
1571
1572         printf("==== talloc_size(NULL, 2048)\n");
1573         l2 = talloc_size(NULL, 2048);
1574
1575         talloc_report_full(root, stdout);
1576
1577         printf("==== talloc_steal(l1, l2)\n");
1578         talloc_steal(l1, l2);
1579
1580         talloc_report_full(root, stdout);
1581
1582         printf("==== talloc_strdup(l2, level 3)\n");
1583         l3 = talloc_strdup(l2, "level 3");
1584         torture_assert("memlimit", l3 == NULL,
1585                 "failed: alloc should fail due to memory limit\n");
1586
1587         talloc_report_full(root, stdout);
1588
1589         printf("==== talloc_free(l2)\n");
1590         talloc_free(l2);
1591
1592         talloc_report_full(root, stdout);
1593
1594         printf("==== talloc_strdup(NULL, level 2)\n");
1595         l2 = talloc_strdup(NULL, "level 2");
1596         talloc_steal(l1, l2);
1597
1598         talloc_report_full(root, stdout);
1599
1600         printf("==== talloc_strdup(l2, level 3)\n");
1601         l3 = talloc_strdup(l2, "level 3");
1602         torture_assert("memlimit", l3 != NULL,
1603                 "failed: alloc should not fail due to memory limit\n");
1604
1605         talloc_report_full(root, stdout);
1606
1607         printf("==== talloc_set_memlimit(l3, 1024)\n");
1608         torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
1609                 "failed: setting memlimit should never fail\n");
1610
1611         talloc_report_full(root, stdout);
1612
1613         printf("==== talloc_strdup(l3, level 4)\n");
1614         l4 = talloc_strdup(l3, "level 4");
1615         torture_assert("memlimit", l4 != NULL,
1616                 "failed: alloc should not fail due to memory limit\n");
1617
1618         talloc_report_full(root, stdout);
1619
1620         printf("==== talloc_set_memlimit(l4, 512)\n");
1621         torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1622                 "failed: setting memlimit should never fail\n");
1623
1624         talloc_report_full(root, stdout);
1625
1626         printf("==== talloc_strdup(l4, level 5)\n");
1627         l5 = talloc_strdup(l4, "level 5");
1628         torture_assert("memlimit", l5 != NULL,
1629                 "failed: alloc should not fail due to memory limit\n");
1630
1631         talloc_report_full(root, stdout);
1632
1633         printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1634         t = talloc_realloc(NULL, l5, char, 600);
1635         torture_assert("memlimit", t == NULL,
1636                 "failed: alloc should fail due to memory limit\n");
1637
1638         talloc_report_full(root, stdout);
1639
1640         printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1641         l5 = talloc_realloc(NULL, l5, char, 5);
1642         torture_assert("memlimit", l5 != NULL,
1643                 "failed: alloc should not fail due to memory limit\n");
1644
1645         talloc_report_full(root, stdout);
1646
1647         printf("==== talloc_strdup(l3, level 4)\n");
1648         l4 = talloc_strdup(l3, "level 4");
1649         torture_assert("memlimit", l4 != NULL,
1650                 "failed: alloc should not fail due to memory limit\n");
1651
1652         talloc_report_full(root, stdout);
1653
1654         printf("==== talloc_set_memlimit(l4, 512)\n");
1655         torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1656                 "failed: setting memlimit should never fail\n");
1657
1658         talloc_report_full(root, stdout);
1659
1660         printf("==== talloc_strdup(l4, level 5)\n");
1661         l5 = talloc_strdup(l4, "level 5");
1662         torture_assert("memlimit", l5 != NULL,
1663                 "failed: alloc should not fail due to memory limit\n");
1664
1665         talloc_report_full(root, stdout);
1666
1667         printf("==== Make new temp context and steal l5\n");
1668         t = talloc_new(root);
1669         talloc_steal(t, l5);
1670
1671         talloc_report_full(root, stdout);
1672
1673         printf("==== talloc_size(t, 2048)\n");
1674         l1 = talloc_size(t, 2048);
1675         torture_assert("memlimit", l1 != NULL,
1676                 "failed: alloc should not fail due to memory limit\n");
1677
1678         talloc_report_full(root, stdout);
1679         talloc_free(root);
1680
1681         /* Test memlimits with pools. */
1682         pool = talloc_pool(NULL, 10*1024);
1683         torture_assert("memlimit", pool != NULL,
1684                 "failed: alloc should not fail due to memory limit\n");
1685         talloc_set_memlimit(pool, 10*1024);
1686         for (i = 0; i < 9; i++) {
1687                 l1 = talloc_size(pool, 1024);
1688                 torture_assert("memlimit", l1 != NULL,
1689                         "failed: alloc should not fail due to memory limit\n");
1690         }
1691         /* The next alloc should fail. */
1692         l2 = talloc_size(pool, 1024);
1693         torture_assert("memlimit", l2 == NULL,
1694                         "failed: alloc should fail due to memory limit\n");
1695
1696         /* Moving one of the children shouldn't change the limit,
1697            as it's still inside the pool. */
1698         root = talloc_new(NULL);
1699         talloc_steal(root, l1);
1700         l2 = talloc_size(pool, 1024);
1701         torture_assert("memlimit", l2 == NULL,
1702                         "failed: alloc should fail due to memory limit\n");
1703
1704         talloc_free(pool);
1705         talloc_free(root);
1706         printf("success: memlimit\n");
1707
1708         return true;
1709 }
1710
1711 #ifdef HAVE_PTHREAD
1712
1713 #define NUM_THREADS 100
1714
1715 /* Sync variables. */
1716 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1717 static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1718 static void *intermediate_ptr;
1719
1720 /* Subthread. */
1721 static void *thread_fn(void *arg)
1722 {
1723         int ret;
1724         const char *ctx_name = (const char *)arg;
1725         void *sub_ctx = NULL;
1726         /*
1727          * Do stuff that creates a new talloc hierarchy in
1728          * this thread.
1729          */
1730         void *top_ctx = talloc_named_const(NULL, 0, "top");
1731         if (top_ctx == NULL) {
1732                 return NULL;
1733         }
1734         sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1735         if (sub_ctx == NULL) {
1736                 return NULL;
1737         }
1738
1739         /*
1740          * Now transfer a pointer from our hierarchy
1741          * onto the intermediate ptr.
1742          */
1743         ret = pthread_mutex_lock(&mtx);
1744         if (ret != 0) {
1745                 talloc_free(top_ctx);
1746                 return NULL;
1747         }
1748         /* Wait for intermediate_ptr to be free. */
1749         while (intermediate_ptr != NULL) {
1750                 ret = pthread_cond_wait(&condvar, &mtx);
1751                 if (ret != 0) {
1752                         talloc_free(top_ctx);
1753                         pthread_mutex_unlock(&mtx);
1754                         return NULL;
1755                 }
1756         }
1757
1758         /* and move our memory onto it from our toplevel hierarchy. */
1759         intermediate_ptr = talloc_move(NULL, &sub_ctx);
1760
1761         /* Tell the main thread it's ready for pickup. */
1762         pthread_cond_broadcast(&condvar);
1763         pthread_mutex_unlock(&mtx);
1764
1765         talloc_free(top_ctx);
1766         return NULL;
1767 }
1768
1769 /* Main thread. */
1770 static bool test_pthread_talloc_passing(void)
1771 {
1772         int i;
1773         int ret;
1774         char str_array[NUM_THREADS][20];
1775         pthread_t thread_id;
1776         void *mem_ctx;
1777
1778         /*
1779          * Important ! Null tracking breaks threaded talloc.
1780          * It *must* be turned off.
1781          */
1782         talloc_disable_null_tracking();
1783
1784         printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1785
1786         /* Main thread toplevel context. */
1787         mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1788         if (mem_ctx == NULL) {
1789                 printf("failed to create toplevel context\n");
1790                 return false;
1791         }
1792
1793         /*
1794          * Spin off NUM_THREADS threads.
1795          * They will use their own toplevel contexts.
1796          */
1797         for (i = 0; i < NUM_THREADS; i++) {
1798                 (void)snprintf(str_array[i],
1799                                 20,
1800                                 "thread:%d",
1801                                 i);
1802                 if (str_array[i] == NULL) {
1803                         printf("snprintf %d failed\n", i);
1804                         return false;
1805                 }
1806                 ret = pthread_create(&thread_id,
1807                                 NULL,
1808                                 thread_fn,
1809                                 str_array[i]);
1810                 if (ret != 0) {
1811                         printf("failed to create thread %d (%d)\n", i, ret);
1812                         return false;
1813                 }
1814         }
1815
1816         printf("Created %d threads\n", NUM_THREADS);
1817
1818         /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1819         for (i = 0; i < NUM_THREADS; i++) {
1820                 ret = pthread_mutex_lock(&mtx);
1821                 if (ret != 0) {
1822                         printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
1823                         talloc_free(mem_ctx);
1824                         return false;
1825                 }
1826
1827                 /* Wait for intermediate_ptr to have our data. */
1828                 while (intermediate_ptr == NULL) {
1829                         ret = pthread_cond_wait(&condvar, &mtx);
1830                         if (ret != 0) {
1831                                 printf("pthread_cond_wait %d failed (%d)\n", i,
1832                                         ret);
1833                                 talloc_free(mem_ctx);
1834                                 pthread_mutex_unlock(&mtx);
1835                                 return false;
1836                         }
1837                 }
1838
1839                 /* and move it onto our toplevel hierarchy. */
1840                 (void)talloc_move(mem_ctx, &intermediate_ptr);
1841
1842                 /* Tell the sub-threads we're ready for another. */
1843                 pthread_cond_broadcast(&condvar);
1844                 pthread_mutex_unlock(&mtx);
1845         }
1846
1847         CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
1848 #if 1
1849         /* Dump the hierarchy. */
1850         talloc_report(mem_ctx, stdout);
1851 #endif
1852         talloc_free(mem_ctx);
1853         printf("success: pthread_talloc_passing\n");
1854         return true;
1855 }
1856 #endif
1857
1858 static void test_magic_protection_abort(const char *reason)
1859 {
1860         /* exit with errcode 42 to communicate successful test to the parent process */
1861         if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
1862                 _exit(42);
1863         } else {
1864                 printf("talloc aborted for an unexpected reason\n");
1865         }
1866 }
1867
1868 static bool test_magic_protection(void)
1869 {
1870         void *pool = talloc_pool(NULL, 1024);
1871         int *p1, *p2;
1872         pid_t pid;
1873         int exit_status;
1874
1875         printf("test: magic_protection\n");
1876         p1 = talloc(pool, int);
1877         p2 = talloc(pool, int);
1878
1879         /* To avoid complaints from the compiler assign values to the p1 & p2. */
1880         *p1 = 6;
1881         *p2 = 9;
1882
1883         pid = fork();
1884         if (pid == 0) {
1885                 talloc_set_abort_fn(test_magic_protection_abort);
1886
1887                 /*
1888                  * Simulate a security attack
1889                  * by triggering a buffer overflow in memset to overwrite the
1890                  * constructor in the next pool chunk.
1891                  *
1892                  * Real attacks would attempt to set a real destructor.
1893                  */
1894                 memset(p1, '\0', 32);
1895
1896                 /* Then the attack takes effect when the memory's freed. */
1897                 talloc_free(pool);
1898
1899                 /* Never reached. Make compilers happy */
1900                 return true;
1901         }
1902
1903         while (wait(&exit_status) != pid);
1904
1905         if (!WIFEXITED(exit_status)) {
1906                 printf("Child exited through unexpected abnormal means\n");
1907                 return false;
1908         }
1909         if (WEXITSTATUS(exit_status) != 42) {
1910                 printf("Child exited with wrong exit status\n");
1911                 return false;
1912         }
1913         if (WIFSIGNALED(exit_status)) {
1914                 printf("Child recieved unexpected signal\n");
1915                 return false;
1916         }
1917
1918         printf("success: magic_protection\n");
1919         return true;
1920 }
1921
1922 static void test_reset(void)
1923 {
1924         talloc_set_log_fn(test_log_stdout);
1925         test_abort_stop();
1926         talloc_disable_null_tracking();
1927         talloc_enable_null_tracking_no_autofree();
1928 }
1929
1930 bool torture_local_talloc(struct torture_context *tctx)
1931 {
1932         bool ret = true;
1933
1934         setlinebuf(stdout);
1935
1936         test_reset();
1937         ret &= test_pooled_object();
1938         test_reset();
1939         ret &= test_pool_nest();
1940         test_reset();
1941         ret &= test_ref1();
1942         test_reset();
1943         ret &= test_ref2();
1944         test_reset();
1945         ret &= test_ref3();
1946         test_reset();
1947         ret &= test_ref4();
1948         test_reset();
1949         ret &= test_unlink1(); 
1950         test_reset();
1951         ret &= test_misc();
1952         test_reset();
1953         ret &= test_realloc();
1954         test_reset();
1955         ret &= test_realloc_child(); 
1956         test_reset();
1957         ret &= test_steal(); 
1958         test_reset();
1959         ret &= test_move(); 
1960         test_reset();
1961         ret &= test_unref_reparent();
1962         test_reset();
1963         ret &= test_realloc_fn(); 
1964         test_reset();
1965         ret &= test_type();
1966         test_reset();
1967         ret &= test_lifeless(); 
1968         test_reset();
1969         ret &= test_loop();
1970         test_reset();
1971         ret &= test_free_parent_deny_child(); 
1972         test_reset();
1973         ret &= test_free_parent_reparent_child();
1974         test_reset();
1975         ret &= test_free_parent_reparent_child_in_pool();
1976         test_reset();
1977         ret &= test_talloc_ptrtype();
1978         test_reset();
1979         ret &= test_talloc_free_in_destructor();
1980         test_reset();
1981         ret &= test_pool();
1982         test_reset();
1983         ret &= test_pool_steal();
1984         test_reset();
1985         ret &= test_free_ref_null_context();
1986         test_reset();
1987         ret &= test_rusty();
1988         test_reset();
1989         ret &= test_free_children();
1990         test_reset();
1991         ret &= test_memlimit();
1992 #ifdef HAVE_PTHREAD
1993         test_reset();
1994         ret &= test_pthread_talloc_passing();
1995 #endif
1996
1997
1998         if (ret) {
1999                 test_reset();
2000                 ret &= test_speed();
2001         }
2002         test_reset();
2003         ret &= test_autofree();
2004         test_reset();
2005         ret &= test_magic_protection();
2006
2007         test_reset();
2008         talloc_disable_null_tracking();
2009         return ret;
2010 }