Simple locking for talloc.
[ccan] / ccan / talloc / test / run.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of talloc routines.
5
6    Copyright (C) Andrew Tridgell 2004
7    Converted to ccan tests by Rusty Russell 2008
8    
9      ** NOTE! The following LGPL license applies to the talloc
10      ** library. This does NOT imply that all of Samba is released
11      ** under the LGPL
12    
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 */
27
28 #include "talloc/talloc.c"
29 #include <stdbool.h>
30 #include "tap/tap.h"
31
32 #define torture_assert(test, expr, str)                                 \
33         ok(expr, "failure: %s [\n%s: Expression %s failed: %s\n]\n",    \
34            test, __location__, #expr, str)
35
36 #define torture_assert_str_equal(test, arg1, arg2, desc)        \
37         ok(strcmp(arg1, arg2) == 0,                             \
38            "failure: %s [\n%s: Expected %s, got %s: %s\n]\n",   \
39            test, __location__, arg1, arg2, desc)
40
41 #define CHECK_SIZE(test, ptr, tsize)                                    \
42         ok(talloc_total_size(ptr) == (tsize),                           \
43            "failed: %s [\nwrong '%s' tree size: got %u  expected %u\n]\n", \
44            test, #ptr,                                                  \
45            (unsigned)talloc_total_size(ptr),                            \
46            (unsigned)tsize)
47
48 #define CHECK_BLOCKS(test, ptr, tblocks)                                \
49         ok(talloc_total_blocks(ptr) == (tblocks),                       \
50            "failed: %s [\nwrong '%s' tree blocks: got %u  expected %u\n]\n", \
51            test, #ptr,                                                  \
52            (unsigned)talloc_total_blocks(ptr),                          \
53            (unsigned)tblocks)
54
55 #define CHECK_PARENT(test, ptr, parent)                                 \
56         ok(talloc_parent(ptr) == (parent),                              \
57            "failed: %s [\n'%s' has wrong parent: got %p  expected %p\n]\n", \
58            test, #ptr,                                                  \
59            talloc_parent(ptr),                                          \
60            (parent))
61
62 /*
63   test references 
64 */
65 static bool test_ref1(void)
66 {
67         void *root, *p1, *p2, *ref, *r1;
68
69         root = talloc_named_const(NULL, 0, "root");
70         p1 = talloc_named_const(root, 1, "p1");
71         p2 = talloc_named_const(p1, 1, "p2");
72         talloc_named_const(p1, 1, "x1");
73         talloc_named_const(p1, 2, "x2");
74         talloc_named_const(p1, 3, "x3");
75
76         r1 = talloc_named_const(root, 1, "r1"); 
77         ref = talloc_reference(r1, p2);
78
79         CHECK_BLOCKS("ref1", p1, 5);
80         CHECK_BLOCKS("ref1", p2, 1);
81         CHECK_BLOCKS("ref1", r1, 2);
82
83         talloc_free(p2);
84
85         CHECK_BLOCKS("ref1", p1, 5);
86         CHECK_BLOCKS("ref1", p2, 1);
87         CHECK_BLOCKS("ref1", r1, 1);
88
89         talloc_free(p1);
90
91         CHECK_BLOCKS("ref1", r1, 1);
92
93         talloc_free(r1);
94
95         if (talloc_reference(root, NULL)) {
96                 return false;
97         }
98
99         CHECK_BLOCKS("ref1", root, 1);
100
101         CHECK_SIZE("ref1", root, 0);
102
103         talloc_free(root);
104         return true;
105 }
106
107 /*
108   test references 
109 */
110 static bool test_ref2(void)
111 {
112         void *root, *p1, *p2, *ref, *r1;
113
114         root = talloc_named_const(NULL, 0, "root");
115         p1 = talloc_named_const(root, 1, "p1");
116         talloc_named_const(p1, 1, "x1");
117         talloc_named_const(p1, 1, "x2");
118         talloc_named_const(p1, 1, "x3");
119         p2 = talloc_named_const(p1, 1, "p2");
120
121         r1 = talloc_named_const(root, 1, "r1"); 
122         ref = talloc_reference(r1, p2);
123
124         CHECK_BLOCKS("ref2", p1, 5);
125         CHECK_BLOCKS("ref2", p2, 1);
126         CHECK_BLOCKS("ref2", r1, 2);
127
128         talloc_free(ref);
129
130         CHECK_BLOCKS("ref2", p1, 5);
131         CHECK_BLOCKS("ref2", p2, 1);
132         CHECK_BLOCKS("ref2", r1, 1);
133
134         talloc_free(p2);
135
136         CHECK_BLOCKS("ref2", p1, 4);
137         CHECK_BLOCKS("ref2", r1, 1);
138
139         talloc_free(p1);
140
141         CHECK_BLOCKS("ref2", r1, 1);
142
143         talloc_free(r1);
144
145         CHECK_SIZE("ref2", root, 0);
146
147         talloc_free(root);
148         return true;
149 }
150
151 /*
152   test references 
153 */
154 static bool test_ref3(void)
155 {
156         void *root, *p1, *p2, *ref, *r1;
157
158         root = talloc_named_const(NULL, 0, "root");
159         p1 = talloc_named_const(root, 1, "p1");
160         p2 = talloc_named_const(root, 1, "p2");
161         r1 = talloc_named_const(p1, 1, "r1");
162         ref = talloc_reference(p2, r1);
163
164         CHECK_BLOCKS("ref3", p1, 2);
165         CHECK_BLOCKS("ref3", p2, 2);
166         CHECK_BLOCKS("ref3", r1, 1);
167
168         talloc_free(p1);
169
170         CHECK_BLOCKS("ref3", p2, 2);
171         CHECK_BLOCKS("ref3", r1, 1);
172
173         talloc_free(p2);
174
175         CHECK_SIZE("ref3", root, 0);
176
177         talloc_free(root);
178
179         return true;
180 }
181
182 /*
183   test references 
184 */
185 static bool test_ref4(void)
186 {
187         void *root, *p1, *p2, *ref, *r1;
188
189         root = talloc_named_const(NULL, 0, "root");
190         p1 = talloc_named_const(root, 1, "p1");
191         talloc_named_const(p1, 1, "x1");
192         talloc_named_const(p1, 1, "x2");
193         talloc_named_const(p1, 1, "x3");
194         p2 = talloc_named_const(p1, 1, "p2");
195
196         r1 = talloc_named_const(root, 1, "r1"); 
197         ref = talloc_reference(r1, p2);
198
199         CHECK_BLOCKS("ref4", p1, 5);
200         CHECK_BLOCKS("ref4", p2, 1);
201         CHECK_BLOCKS("ref4", r1, 2);
202
203         talloc_free(r1);
204
205         CHECK_BLOCKS("ref4", p1, 5);
206         CHECK_BLOCKS("ref4", p2, 1);
207
208         talloc_free(p2);
209
210         CHECK_BLOCKS("ref4", p1, 4);
211
212         talloc_free(p1);
213
214         CHECK_SIZE("ref4", root, 0);
215
216         talloc_free(root);
217
218         return true;
219 }
220
221
222 /*
223   test references 
224 */
225 static bool test_unlink1(void)
226 {
227         void *root, *p1, *p2, *ref, *r1;
228
229         root = talloc_named_const(NULL, 0, "root");
230         p1 = talloc_named_const(root, 1, "p1");
231         talloc_named_const(p1, 1, "x1");
232         talloc_named_const(p1, 1, "x2");
233         talloc_named_const(p1, 1, "x3");
234         p2 = talloc_named_const(p1, 1, "p2");
235
236         r1 = talloc_named_const(p1, 1, "r1");   
237         ref = talloc_reference(r1, p2);
238
239         CHECK_BLOCKS("unlink", p1, 7);
240         CHECK_BLOCKS("unlink", p2, 1);
241         CHECK_BLOCKS("unlink", r1, 2);
242
243         talloc_unlink(r1, p2);
244
245         CHECK_BLOCKS("unlink", p1, 6);
246         CHECK_BLOCKS("unlink", p2, 1);
247         CHECK_BLOCKS("unlink", r1, 1);
248
249         talloc_free(p1);
250
251         CHECK_SIZE("unlink", root, 0);
252
253         talloc_free(root);
254
255         return true;
256 }
257
258 static int fail_destructor(void *ptr)
259 {
260         return -1;
261 }
262
263 /*
264   miscellaneous tests to try to get a higher test coverage percentage
265 */
266 static bool test_misc(void)
267 {
268         void *root, *p1;
269         char *p2;
270         double *d;
271         const char *name;
272
273         root = talloc_new(NULL);
274
275         p1 = talloc_size(root, 0x7fffffff);
276         torture_assert("misc", !p1, "failed: large talloc allowed\n");
277
278         p1 = talloc_strdup(root, "foo");
279         talloc_increase_ref_count(p1);
280         talloc_increase_ref_count(p1);
281         talloc_increase_ref_count(p1);
282         CHECK_BLOCKS("misc", p1, 1);
283         CHECK_BLOCKS("misc", root, 2);
284         talloc_free(p1);
285         CHECK_BLOCKS("misc", p1, 1);
286         CHECK_BLOCKS("misc", root, 2);
287         talloc_unlink(NULL, p1);
288         CHECK_BLOCKS("misc", p1, 1);
289         CHECK_BLOCKS("misc", root, 2);
290         p2 = talloc_strdup(p1, "foo");
291         torture_assert("misc", talloc_unlink(root, p2) == -1,
292                                    "failed: talloc_unlink() of non-reference context should return -1\n");
293         torture_assert("misc", talloc_unlink(p1, p2) == 0,
294                 "failed: talloc_unlink() of parent should succeed\n");
295         talloc_free(p1);
296         CHECK_BLOCKS("misc", p1, 1);
297         CHECK_BLOCKS("misc", root, 2);
298
299         name = talloc_set_name(p1, "my name is %s", "foo");
300         torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
301                 "failed: wrong name after talloc_set_name(my name is foo)");
302         CHECK_BLOCKS("misc", p1, 2);
303         CHECK_BLOCKS("misc", root, 3);
304
305         talloc_set_name_const(p1, NULL);
306         torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
307                 "failed: wrong name after talloc_set_name(NULL)");
308         CHECK_BLOCKS("misc", p1, 2);
309         CHECK_BLOCKS("misc", root, 3);
310
311         torture_assert("misc", talloc_free(NULL) == -1, 
312                                    "talloc_free(NULL) should give -1\n");
313
314         talloc_set_destructor(p1, fail_destructor);
315         torture_assert("misc", talloc_free(p1) == -1, 
316                 "Failed destructor should cause talloc_free to fail\n");
317         talloc_set_destructor(p1, NULL);
318
319
320         p2 = (char *)talloc_zero_size(p1, 20);
321         torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
322         talloc_free(p2);
323
324         torture_assert("misc", talloc_strdup(root, NULL) == NULL,
325                 "failed: strdup on NULL should give NULL\n");
326
327         p2 = talloc_strndup(p1, "foo", 2);
328         torture_assert("misc", strcmp("fo", p2) == 0, 
329                                    "strndup doesn't work\n");
330         p2 = talloc_asprintf_append(p2, "o%c", 'd');
331         torture_assert("misc", strcmp("food", p2) == 0, 
332                                    "talloc_asprintf_append doesn't work\n");
333         CHECK_BLOCKS("misc", p2, 1);
334         CHECK_BLOCKS("misc", p1, 3);
335
336         p2 = talloc_asprintf_append(NULL, "hello %s", "world");
337         torture_assert("misc", strcmp("hello world", p2) == 0,
338                 "talloc_asprintf_append doesn't work\n");
339         CHECK_BLOCKS("misc", p2, 1);
340         CHECK_BLOCKS("misc", p1, 3);
341         talloc_free(p2);
342
343         d = talloc_array(p1, double, 0x20000000);
344         torture_assert("misc", !d, "failed: integer overflow not detected\n");
345
346         d = talloc_realloc(p1, d, double, 0x20000000);
347         torture_assert("misc", !d, "failed: integer overflow not detected\n");
348
349         talloc_free(p1);
350         CHECK_BLOCKS("misc", root, 1);
351
352         p1 = talloc_named(root, 100, "%d bytes", 100);
353         CHECK_BLOCKS("misc", p1, 2);
354         CHECK_BLOCKS("misc", root, 3);
355         talloc_unlink(root, p1);
356
357         p1 = talloc_init("%d bytes", 200);
358         p2 = talloc_asprintf(p1, "my test '%s'", "string");
359         torture_assert_str_equal("misc", p2, "my test 'string'",
360                 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
361         CHECK_BLOCKS("misc", p1, 3);
362         CHECK_SIZE("misc", p2, 17);
363         CHECK_BLOCKS("misc", root, 1);
364         talloc_unlink(NULL, p1);
365
366         p1 = talloc_named_const(root, 10, "p1");
367         p2 = (char *)talloc_named_const(root, 20, "p2");
368         (void)talloc_reference(p1, p2);
369         talloc_unlink(root, p2);
370         CHECK_BLOCKS("misc", p2, 1);
371         CHECK_BLOCKS("misc", p1, 2);
372         CHECK_BLOCKS("misc", root, 3);
373         talloc_unlink(p1, p2);
374         talloc_unlink(root, p1);
375
376         p1 = talloc_named_const(root, 10, "p1");
377         p2 = (char *)talloc_named_const(root, 20, "p2");
378         (void)talloc_reference(NULL, p2);
379         talloc_unlink(root, p2);
380         CHECK_BLOCKS("misc", p2, 1);
381         CHECK_BLOCKS("misc", p1, 1);
382         CHECK_BLOCKS("misc", root, 2);
383         talloc_unlink(NULL, p2);
384         talloc_unlink(root, p1);
385
386         /* Test that talloc_unlink is a no-op */
387
388         torture_assert("misc", talloc_unlink(root, NULL) == -1,
389                 "failed: talloc_unlink(root, NULL) == -1\n");
390
391         CHECK_SIZE("misc", root, 0);
392
393         talloc_free(root);
394
395         CHECK_SIZE("misc", NULL, 0);
396
397         talloc_enable_leak_report();
398         talloc_enable_leak_report_full();
399
400         return true;
401 }
402
403
404 /*
405   test realloc
406 */
407 static bool test_realloc(void)
408 {
409         void *root, *p1, *p2;
410
411         root = talloc_new(NULL);
412
413         p1 = talloc_size(root, 10);
414         CHECK_SIZE("realloc", p1, 10);
415
416         p1 = talloc_realloc_size(NULL, p1, 20);
417         CHECK_SIZE("realloc", p1, 20);
418
419         talloc_new(p1);
420
421         p2 = talloc_realloc_size(p1, NULL, 30);
422
423         talloc_new(p1);
424
425         p2 = talloc_realloc_size(p1, p2, 40);
426
427         CHECK_SIZE("realloc", p2, 40);
428         CHECK_SIZE("realloc", root, 60);
429         CHECK_BLOCKS("realloc", p1, 4);
430
431         p1 = talloc_realloc_size(NULL, p1, 20);
432         CHECK_SIZE("realloc", p1, 60);
433
434         talloc_increase_ref_count(p2);
435         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
436                 "failed: talloc_realloc() on a referenced pointer should fail\n");
437         CHECK_BLOCKS("realloc", p1, 4);
438
439         talloc_realloc_size(NULL, p2, 0);
440         talloc_realloc_size(NULL, p2, 0);
441         CHECK_BLOCKS("realloc", p1, 3);
442
443         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
444                 "failed: oversize talloc should fail\n");
445
446         talloc_realloc_size(NULL, p1, 0);
447
448         CHECK_BLOCKS("realloc", root, 1);
449         CHECK_SIZE("realloc", root, 0);
450
451         talloc_free(root);
452
453         return true;
454 }
455
456 /*
457   test realloc with a child
458 */
459 static bool test_realloc_child(void)
460 {
461         void *root;
462         struct el2 {
463                 const char *name;
464         } *el2; 
465         struct el1 {
466                 int count;
467                 struct el2 **list, **list2, **list3;
468         } *el1;
469
470         root = talloc_new(NULL);
471
472         el1 = talloc(root, struct el1);
473         el1->list = talloc(el1, struct el2 *);
474         el1->list[0] = talloc(el1->list, struct el2);
475         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
476
477         el1->list2 = talloc(el1, struct el2 *);
478         el1->list2[0] = talloc(el1->list2, struct el2);
479         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
480
481         el1->list3 = talloc(el1, struct el2 *);
482         el1->list3[0] = talloc(el1->list3, struct el2);
483         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
484         
485         el2 = talloc(el1->list, struct el2);
486         el2 = talloc(el1->list2, struct el2);
487         el2 = talloc(el1->list3, struct el2);
488
489         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
490         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
491         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
492
493         talloc_free(root);
494
495         return true;
496 }
497
498 /*
499   test type checking
500 */
501 static bool test_type(void)
502 {
503         void *root;
504         struct el1 {
505                 int count;
506         };
507         struct el2 {
508                 int count;
509         };
510         struct el1 *el1;
511
512         root = talloc_new(NULL);
513
514         el1 = talloc(root, struct el1);
515
516         el1->count = 1;
517
518         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
519                 "type check failed on el1\n");
520         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
521                 "type check failed on el1 with el2\n");
522         talloc_set_type(el1, struct el2);
523         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
524                 "type set failed on el1 with el2\n");
525
526         talloc_free(root);
527
528         return true;
529 }
530
531 /*
532   test steal
533 */
534 static bool test_steal(void)
535 {
536         void *root, *p1, *p2;
537
538         root = talloc_new(NULL);
539
540         p1 = talloc_array(root, char, 10);
541         CHECK_SIZE("steal", p1, 10);
542
543         p2 = talloc_realloc(root, NULL, char, 20);
544         CHECK_SIZE("steal", p1, 10);
545         CHECK_SIZE("steal", root, 30);
546
547         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
548                 "failed: stealing NULL should give NULL\n");
549
550         torture_assert("steal", talloc_steal(p1, p1) == p1,
551                 "failed: stealing to ourselves is a nop\n");
552         CHECK_BLOCKS("steal", root, 3);
553         CHECK_SIZE("steal", root, 30);
554
555         talloc_steal(NULL, p1);
556         talloc_steal(NULL, p2);
557         CHECK_BLOCKS("steal", root, 1);
558         CHECK_SIZE("steal", root, 0);
559
560         talloc_free(p1);
561         talloc_steal(root, p2);
562         CHECK_BLOCKS("steal", root, 2);
563         CHECK_SIZE("steal", root, 20);
564         
565         talloc_free(p2);
566
567         CHECK_BLOCKS("steal", root, 1);
568         CHECK_SIZE("steal", root, 0);
569
570         talloc_free(root);
571
572         p1 = talloc_size(NULL, 3);
573         CHECK_SIZE("steal", NULL, 3);
574         talloc_free(p1);
575
576         return true;
577 }
578
579 /*
580   test move
581 */
582 static bool test_move(void)
583 {
584         void *root;
585         struct t_move {
586                 char *p;
587                 int *x;
588         } *t1, *t2;
589
590         root = talloc_new(NULL);
591
592         t1 = talloc(root, struct t_move);
593         t2 = talloc(root, struct t_move);
594         t1->p = talloc_strdup(t1, "foo");
595         t1->x = talloc(t1, int);
596         *t1->x = 42;
597
598         t2->p = talloc_move(t2, &t1->p);
599         t2->x = talloc_move(t2, &t1->x);
600         torture_assert("move", t1->p == NULL && t1->x == NULL &&
601             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
602                 "talloc move failed");
603
604         talloc_free(root);
605
606         return true;
607 }
608
609 /*
610   test talloc_realloc_fn
611 */
612 static bool test_realloc_fn(void)
613 {
614         void *root, *p1;
615
616         root = talloc_new(NULL);
617
618         p1 = talloc_realloc_fn(root, NULL, 10);
619         CHECK_BLOCKS("realloc_fn", root, 2);
620         CHECK_SIZE("realloc_fn", root, 10);
621         p1 = talloc_realloc_fn(root, p1, 20);
622         CHECK_BLOCKS("realloc_fn", root, 2);
623         CHECK_SIZE("realloc_fn", root, 20);
624         p1 = talloc_realloc_fn(root, p1, 0);
625         CHECK_BLOCKS("realloc_fn", root, 1);
626         CHECK_SIZE("realloc_fn", root, 0);
627
628         talloc_free(root);
629
630         return true;
631 }
632
633
634 static bool test_unref_reparent(void)
635 {
636         void *root, *p1, *p2, *c1;
637
638         root = talloc_named_const(NULL, 0, "root");
639         p1 = talloc_named_const(root, 1, "orig parent");
640         p2 = talloc_named_const(root, 1, "parent by reference");
641
642         c1 = talloc_named_const(p1, 1, "child");
643         talloc_reference(p2, c1);
644
645         CHECK_PARENT("unref_reparent", c1, p1);
646
647         talloc_free(p1);
648
649         CHECK_PARENT("unref_reparent", c1, p2);
650
651         talloc_unlink(p2, c1);
652
653         CHECK_SIZE("unref_reparent", root, 1);
654
655         talloc_free(p2);
656         talloc_free(root);
657
658         return true;
659 }
660
661 static bool test_lifeless(void)
662 {
663         void *top = talloc_new(NULL);
664         char *parent, *child; 
665         void *child_owner = talloc_new(NULL);
666
667         parent = talloc_strdup(top, "parent");
668         child = talloc_strdup(parent, "child");  
669         (void)talloc_reference(child, parent);
670         (void)talloc_reference(child_owner, child); 
671         talloc_unlink(top, parent);
672         talloc_free(child);
673         talloc_free(top);
674         talloc_free(child_owner);
675         talloc_free(child);
676
677         return true;
678 }
679
680 static int loop_destructor_count;
681
682 static int test_loop_destructor(char *ptr)
683 {
684         loop_destructor_count++;
685         return 0;
686 }
687
688 static bool test_loop(void)
689 {
690         void *top = talloc_new(NULL);
691         char *parent;
692         struct req1 {
693                 char *req2, *req3;
694         } *req1;
695
696         parent = talloc_strdup(top, "parent");
697         req1 = talloc(parent, struct req1);
698         req1->req2 = talloc_strdup(req1, "req2");  
699         talloc_set_destructor(req1->req2, test_loop_destructor);
700         req1->req3 = talloc_strdup(req1, "req3");
701         (void)talloc_reference(req1->req3, req1);
702         talloc_free(parent);
703         talloc_free(top);
704
705         torture_assert("loop", loop_destructor_count == 1, 
706                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
707         loop_destructor_count = 0;
708
709         return true;
710 }
711
712 static int fail_destructor_str(char *ptr)
713 {
714         return -1;
715 }
716
717 static bool test_free_parent_deny_child(void)
718 {
719         void *top = talloc_new(NULL);
720         char *level1;
721         char *level2;
722         char *level3;
723
724         level1 = talloc_strdup(top, "level1");
725         level2 = talloc_strdup(level1, "level2");
726         level3 = talloc_strdup(level2, "level3");
727
728         talloc_set_destructor(level3, fail_destructor_str);
729         talloc_free(level1);
730         talloc_set_destructor(level3, NULL);
731
732         CHECK_PARENT("free_parent_deny_child", level3, top);
733
734         talloc_free(top);
735
736         return true;
737 }
738
739 static bool test_talloc_ptrtype(void)
740 {
741         void *top = talloc_new(NULL);
742         struct struct1 {
743                 int foo;
744                 int bar;
745         } *s1, *s2, **s3, ***s4;
746         const char *location1;
747         const char *location2;
748         const char *location3;
749         const char *location4;
750
751         s1 = talloc_ptrtype(top, s1);location1 = __location__;
752
753         ok1(talloc_get_size(s1) == sizeof(struct struct1));
754
755         ok1(strcmp(location1, talloc_get_name(s1)) == 0);
756
757         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
758
759         ok1(talloc_get_size(s2) == (sizeof(struct struct1) * 10));
760
761         ok1(strcmp(location2, talloc_get_name(s2)) == 0);
762
763         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
764
765         ok1(talloc_get_size(s3) == (sizeof(struct struct1 *) * 10));
766
767         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
768                 "talloc_array_ptrtype() sets the wrong name");
769
770         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
771
772         ok1(talloc_get_size(s4) == (sizeof(struct struct1 **) * 10));
773
774         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
775                 "talloc_array_ptrtype() sets the wrong name");
776
777         talloc_free(top);
778
779         return true;
780 }
781
782 static int _test_talloc_free_in_destructor(void **ptr)
783 {
784         talloc_free(*ptr);
785         return 0;
786 }
787
788 static bool test_talloc_free_in_destructor(void)
789 {
790         void *level0;
791         void *level1;
792         void *level2;
793         void *level3;
794         void *level4;
795         void **level5;
796
797         level0 = talloc_new(NULL);
798         level1 = talloc_new(level0);
799         level2 = talloc_new(level1);
800         level3 = talloc_new(level2);
801         level4 = talloc_new(level3);
802         level5 = talloc(level4, void *);
803
804         *level5 = level3;
805         (void)talloc_reference(level0, level3);
806         (void)talloc_reference(level3, level3);
807         (void)talloc_reference(level5, level3);
808
809         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
810
811         talloc_free(level1);
812
813         talloc_free(level0);
814
815         return true;
816 }
817
818 static bool test_autofree(void)
819 {
820         /* autofree test would kill smbtorture */
821         void *p;
822         p = talloc_autofree_context();
823         talloc_free(p);
824
825         p = talloc_autofree_context();
826         talloc_free(p);
827
828         return true;
829 }
830
831 struct torture_context;
832 static bool torture_local_talloc(struct torture_context *tctx)
833 {
834         bool ret = true;
835
836         setlinebuf(stdout);
837
838         talloc_disable_null_tracking();
839         talloc_enable_null_tracking();
840
841         ret &= test_ref1();
842         ret &= test_ref2();
843         ret &= test_ref3();
844         ret &= test_ref4();
845         ret &= test_unlink1(); 
846         ret &= test_misc();
847         ret &= test_realloc();
848         ret &= test_realloc_child(); 
849         ret &= test_steal(); 
850         ret &= test_move(); 
851         ret &= test_unref_reparent();
852         ret &= test_realloc_fn(); 
853         ret &= test_type();
854         ret &= test_lifeless(); 
855         ret &= test_loop();
856         ret &= test_free_parent_deny_child(); 
857         ret &= test_talloc_ptrtype();
858         ret &= test_talloc_free_in_destructor();
859         ret &= test_autofree();
860
861         return ret;
862 }
863
864 static int lock_failed = 0, unlock_failed = 0;
865 static void test_lock(int *locked)
866 {
867         if (*locked)
868                 lock_failed++;
869         *locked = 1;
870 }
871
872 static void test_unlock(int *locked)
873 {
874         if (!*locked)
875                 unlock_failed++;
876         *locked = 0;
877 }
878
879 int main(void)
880 {
881         int locked = 0;
882
883         plan_tests(136);
884         talloc_locksafe(test_lock, test_unlock, &locked);
885
886         torture_local_talloc(NULL);
887         ok(!lock_failed, "lock_failed count %u should be zero", lock_failed);
888         ok(!unlock_failed, "unlock_failed count %u should be zero", unlock_failed);
889         return exit_status();
890 }
891