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