r2742: - fixed a bug in talloc_unreference()
[samba.git] / source4 / torture / local / talloc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of talloc routines.
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 #define CHECK_BLOCKS(ptr, tblocks) do { \
26         if (talloc_total_blocks(ptr) != (tblocks)) { \
27                 printf("(%d) failed: wrong '%s' tree size: got %u  expected %u\n", \
28                        __LINE__, #ptr, \
29                        (unsigned)talloc_total_blocks(ptr), \
30                        (unsigned)tblocks); \
31                 talloc_report_full(ptr, stdout); \
32                 return False; \
33         } \
34 } while (0)
35
36 /*
37   test references 
38 */
39 static BOOL test_ref1(void)
40 {
41         void *root, *p1, *p2, *ref, *r1;
42
43         printf("TESTING SINGLE REFERENCE FREE\n");
44
45         root = talloc_named_const(NULL, 0, "root");
46         p1 = talloc_named_const(root, 1, "p1");
47         p2 = talloc_named_const(p1, 1, "p2");
48         talloc_named_const(p1, 1, "x1");
49         talloc_named_const(p1, 2, "x2");
50         talloc_named_const(p1, 3, "x3");
51
52         r1 = talloc_named_const(root, 1, "r1"); 
53         ref = talloc_reference(r1, p2);
54         talloc_report_full(root, stdout);
55
56         CHECK_BLOCKS(p1, 5);
57         CHECK_BLOCKS(p2, 1);
58         CHECK_BLOCKS(r1, 2);
59
60         printf("Freeing p2\n");
61         talloc_free(p2);
62         talloc_report_full(root, stdout);
63
64         CHECK_BLOCKS(p1, 5);
65         CHECK_BLOCKS(p2, 1);
66         CHECK_BLOCKS(r1, 1);
67
68         printf("Freeing p1\n");
69         talloc_free(p1);
70         talloc_report_full(root, stdout);
71
72         CHECK_BLOCKS(r1, 1);
73
74         printf("Freeing r1\n");
75         talloc_free(r1);
76         talloc_report_full(NULL, stdout);
77
78         CHECK_BLOCKS(root, 1);
79
80         if (talloc_total_size(root) != 0) {
81                 printf("failed: non-zero total size\n");
82                 return False;
83         }
84
85         talloc_free(root);
86
87         return True;
88 }
89
90 /*
91   test references 
92 */
93 static BOOL test_ref2(void)
94 {
95         void *root, *p1, *p2, *ref, *r1;
96
97         printf("TESTING DOUBLE REFERENCE FREE\n");
98
99         root = talloc_named_const(NULL, 0, "root");
100         p1 = talloc_named_const(root, 1, "p1");
101         talloc_named_const(p1, 1, "x1");
102         talloc_named_const(p1, 1, "x2");
103         talloc_named_const(p1, 1, "x3");
104         p2 = talloc_named_const(p1, 1, "p2");
105
106         r1 = talloc_named_const(root, 1, "r1"); 
107         ref = talloc_reference(r1, p2);
108         talloc_report_full(root, stdout);
109
110         CHECK_BLOCKS(p1, 5);
111         CHECK_BLOCKS(p2, 1);
112         CHECK_BLOCKS(r1, 2);
113
114         printf("Freeing ref\n");
115         talloc_free(ref);
116         talloc_report_full(root, stdout);
117
118         CHECK_BLOCKS(p1, 5);
119         CHECK_BLOCKS(p2, 1);
120         CHECK_BLOCKS(r1, 1);
121
122         printf("Freeing p2\n");
123         talloc_free(p2);
124         talloc_report_full(root, stdout);
125
126         CHECK_BLOCKS(p1, 4);
127         CHECK_BLOCKS(r1, 1);
128
129         printf("Freeing p1\n");
130         talloc_free(p1);
131         talloc_report_full(root, stdout);
132
133         CHECK_BLOCKS(r1, 1);
134
135         printf("Freeing r1\n");
136         talloc_free(r1);
137         talloc_report_full(root, stdout);
138
139         if (talloc_total_size(root) != 0) {
140                 printf("failed: non-zero total size\n");
141                 return False;
142         }
143
144         talloc_free(root);
145
146         return True;
147 }
148
149 /*
150   test references 
151 */
152 static BOOL test_ref3(void)
153 {
154         void *root, *p1, *p2, *ref, *r1;
155
156         printf("TESTING PARENT REFERENCE FREE\n");
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         talloc_report_full(root, stdout);
164
165         CHECK_BLOCKS(p1, 2);
166         CHECK_BLOCKS(p2, 2);
167         CHECK_BLOCKS(r1, 1);
168
169         printf("Freeing p1\n");
170         talloc_free(p1);
171         talloc_report_full(root, stdout);
172
173         CHECK_BLOCKS(p2, 2);
174         CHECK_BLOCKS(r1, 1);
175
176         printf("Freeing p2\n");
177         talloc_free(p2);
178         talloc_report_full(root, stdout);
179
180         if (talloc_total_size(root) != 0) {
181                 printf("failed: non-zero total size\n");
182                 return False;
183         }
184
185         talloc_free(root);
186
187         return True;
188 }
189
190 /*
191   test references 
192 */
193 static BOOL test_ref4(void)
194 {
195         void *root, *p1, *p2, *ref, *r1;
196
197         printf("TESTING REFERRER REFERENCE FREE\n");
198
199         root = talloc_named_const(NULL, 0, "root");
200         p1 = talloc_named_const(root, 1, "p1");
201         talloc_named_const(p1, 1, "x1");
202         talloc_named_const(p1, 1, "x2");
203         talloc_named_const(p1, 1, "x3");
204         p2 = talloc_named_const(p1, 1, "p2");
205
206         r1 = talloc_named_const(root, 1, "r1"); 
207         ref = talloc_reference(r1, p2);
208         talloc_report_full(root, stdout);
209
210         CHECK_BLOCKS(p1, 5);
211         CHECK_BLOCKS(p2, 1);
212         CHECK_BLOCKS(r1, 2);
213
214         printf("Freeing r1\n");
215         talloc_free(r1);
216         talloc_report_full(root, stdout);
217
218         CHECK_BLOCKS(p1, 5);
219         CHECK_BLOCKS(p2, 1);
220
221         printf("Freeing p2\n");
222         talloc_free(p2);
223         talloc_report_full(root, stdout);
224
225         CHECK_BLOCKS(p1, 4);
226
227         printf("Freeing p1\n");
228         talloc_free(p1);
229         talloc_report_full(root, stdout);
230
231         if (talloc_total_size(root) != 0) {
232                 printf("failed: non-zero total size\n");
233                 return False;
234         }
235
236         talloc_free(root);
237
238         return True;
239 }
240
241
242 /*
243   test references 
244 */
245 static BOOL test_unref1(void)
246 {
247         void *root, *p1, *p2, *ref, *r1;
248
249         printf("TESTING UNREFERENCE\n");
250
251         root = talloc_named_const(NULL, 0, "root");
252         p1 = talloc_named_const(root, 1, "p1");
253         talloc_named_const(p1, 1, "x1");
254         talloc_named_const(p1, 1, "x2");
255         talloc_named_const(p1, 1, "x3");
256         p2 = talloc_named_const(p1, 1, "p2");
257
258         r1 = talloc_named_const(p1, 1, "r1");   
259         ref = talloc_reference(r1, p2);
260         talloc_report_full(root, stdout);
261
262         CHECK_BLOCKS(p1, 7);
263         CHECK_BLOCKS(p2, 1);
264         CHECK_BLOCKS(r1, 2);
265
266         printf("Unreferencing r1\n");
267         talloc_unreference(r1, p2);
268         talloc_report_full(root, stdout);
269
270         CHECK_BLOCKS(p1, 6);
271         CHECK_BLOCKS(p2, 1);
272         CHECK_BLOCKS(r1, 1);
273
274         printf("Freeing p1\n");
275         talloc_free(p1);
276         talloc_report_full(root, stdout);
277
278         if (talloc_total_size(root) != 0) {
279                 printf("failed: non-zero total size\n");
280                 return False;
281         }
282
283         talloc_free(root);
284
285         return True;
286 }
287
288 /*
289   measure the speed of talloc versus malloc
290 */
291 static BOOL test_speed(void)
292 {
293         void *ctx = talloc(NULL, 0);
294         uint_t count;
295
296         printf("MEASURING TALLOC VS MALLOC SPEED\n");
297
298         start_timer();
299         count = 0;
300         do {
301                 void *p1, *p2, *p3;
302                 p1 = talloc(ctx, count);
303                 p2 = talloc_strdup(p1, "foo bar");
304                 p3 = talloc(p1, 300);
305                 talloc_free(p1);
306                 count += 3;
307         } while (end_timer() < 5.0);
308
309         printf("talloc: %.0f ops/sec\n", count/end_timer());
310
311         talloc_free(ctx);
312
313         start_timer();
314         count = 0;
315         do {
316                 void *p1, *p2, *p3;
317                 p1 = malloc(count);
318                 p2 = strdup("foo bar");
319                 p3 = malloc(300);
320                 free(p1);
321                 free(p2);
322                 free(p3);
323                 count += 3;
324         } while (end_timer() < 5.0);
325
326         printf("malloc: %.0f ops/sec\n", count/end_timer());
327
328         return True;    
329 }
330
331
332 BOOL torture_local_talloc(int dummy) 
333 {
334         BOOL ret = True;
335
336         init_iconv();
337
338         ret &= test_ref1();
339         ret &= test_ref2();
340         ret &= test_ref3();
341         ret &= test_ref4();
342         ret &= test_unref1();
343         ret &= test_speed();
344
345         return ret;
346 }