KCC: docstring for test_all_reps_from()
[Samba.git] / lib / talloc / testsuite.c
blob6d0fe94479e3b80326e4159ad94f035d20dc0db1
1 /*
2 Unix SMB/CIFS implementation.
4 local testing of talloc routines.
6 Copyright (C) Andrew Tridgell 2004
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
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.
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.
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/>.
26 #include "replace.h"
27 #include "system/time.h"
28 #include <talloc.h>
30 #ifdef HAVE_PTHREAD
31 #include <pthread.h>
32 #endif
34 #include "talloc_testsuite.h"
36 static struct timeval timeval_current(void)
38 struct timeval tv;
39 gettimeofday(&tv, NULL);
40 return tv;
43 static double timeval_elapsed(struct timeval *tv)
45 struct timeval tv2 = timeval_current();
46 return (tv2.tv_sec - tv->tv_sec) +
47 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
50 #define torture_assert(test, expr, str) if (!(expr)) { \
51 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
52 test, __location__, #expr, str); \
53 return false; \
56 #define torture_assert_str_equal(test, arg1, arg2, desc) \
57 if (arg1 == NULL && arg2 == NULL) { \
58 } else if (strcmp(arg1, arg2)) { \
59 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
60 test, __location__, arg1, arg2, desc); \
61 return false; \
64 #define CHECK_SIZE(test, ptr, tsize) do { \
65 if (talloc_total_size(ptr) != (tsize)) { \
66 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
67 test, __location__, #ptr, \
68 (unsigned)talloc_total_size(ptr), \
69 (unsigned)tsize); \
70 talloc_report_full(ptr, stdout); \
71 return false; \
72 } \
73 } while (0)
75 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
76 if (talloc_total_blocks(ptr) != (tblocks)) { \
77 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
78 test, __location__, #ptr, \
79 (unsigned)talloc_total_blocks(ptr), \
80 (unsigned)tblocks); \
81 talloc_report_full(ptr, stdout); \
82 return false; \
83 } \
84 } while (0)
86 #define CHECK_PARENT(test, ptr, parent) do { \
87 if (talloc_parent(ptr) != (parent)) { \
88 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
89 test, __location__, #ptr, \
90 talloc_parent(ptr), \
91 (parent)); \
92 talloc_report_full(ptr, stdout); \
93 talloc_report_full(parent, stdout); \
94 talloc_report_full(NULL, stdout); \
95 return false; \
96 } \
97 } while (0)
99 static unsigned int test_abort_count;
101 #if 0
102 static void test_abort_fn(const char *reason)
104 printf("# test_abort_fn(%s)\n", reason);
105 test_abort_count++;
108 static void test_abort_start(void)
110 test_abort_count = 0;
111 talloc_set_abort_fn(test_abort_fn);
113 #endif
115 static void test_abort_stop(void)
117 test_abort_count = 0;
118 talloc_set_abort_fn(NULL);
121 static void test_log_stdout(const char *message)
123 fprintf(stdout, "%s", message);
127 test references
129 static bool test_ref1(void)
131 void *root, *p1, *p2, *ref, *r1;
133 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
135 root = talloc_named_const(NULL, 0, "root");
136 p1 = talloc_named_const(root, 1, "p1");
137 p2 = talloc_named_const(p1, 1, "p2");
138 talloc_named_const(p1, 1, "x1");
139 talloc_named_const(p1, 2, "x2");
140 talloc_named_const(p1, 3, "x3");
142 r1 = talloc_named_const(root, 1, "r1");
143 ref = talloc_reference(r1, p2);
144 talloc_report_full(root, stderr);
146 CHECK_BLOCKS("ref1", p1, 5);
147 CHECK_BLOCKS("ref1", p2, 1);
148 CHECK_BLOCKS("ref1", ref, 1);
149 CHECK_BLOCKS("ref1", r1, 2);
151 fprintf(stderr, "Freeing p2\n");
152 talloc_unlink(r1, p2);
153 talloc_report_full(root, stderr);
155 CHECK_BLOCKS("ref1", p1, 5);
156 CHECK_BLOCKS("ref1", p2, 1);
157 CHECK_BLOCKS("ref1", r1, 1);
159 fprintf(stderr, "Freeing p1\n");
160 talloc_free(p1);
161 talloc_report_full(root, stderr);
163 CHECK_BLOCKS("ref1", r1, 1);
165 fprintf(stderr, "Freeing r1\n");
166 talloc_free(r1);
167 talloc_report_full(NULL, stderr);
169 fprintf(stderr, "Testing NULL\n");
170 if (talloc_reference(root, NULL)) {
171 return false;
174 CHECK_BLOCKS("ref1", root, 1);
176 CHECK_SIZE("ref1", root, 0);
178 talloc_free(root);
179 printf("success: ref1\n");
180 return true;
184 test references
186 static bool test_ref2(void)
188 void *root, *p1, *p2, *ref, *r1;
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");
198 r1 = talloc_named_const(root, 1, "r1");
199 ref = talloc_reference(r1, p2);
200 talloc_report_full(root, stderr);
202 CHECK_BLOCKS("ref2", p1, 5);
203 CHECK_BLOCKS("ref2", p2, 1);
204 CHECK_BLOCKS("ref2", r1, 2);
206 fprintf(stderr, "Freeing ref\n");
207 talloc_unlink(r1, ref);
208 talloc_report_full(root, stderr);
210 CHECK_BLOCKS("ref2", p1, 5);
211 CHECK_BLOCKS("ref2", p2, 1);
212 CHECK_BLOCKS("ref2", r1, 1);
214 fprintf(stderr, "Freeing p2\n");
215 talloc_free(p2);
216 talloc_report_full(root, stderr);
218 CHECK_BLOCKS("ref2", p1, 4);
219 CHECK_BLOCKS("ref2", r1, 1);
221 fprintf(stderr, "Freeing p1\n");
222 talloc_free(p1);
223 talloc_report_full(root, stderr);
225 CHECK_BLOCKS("ref2", r1, 1);
227 fprintf(stderr, "Freeing r1\n");
228 talloc_free(r1);
229 talloc_report_full(root, stderr);
231 CHECK_SIZE("ref2", root, 0);
233 talloc_free(root);
234 printf("success: ref2\n");
235 return true;
239 test references
241 static bool test_ref3(void)
243 void *root, *p1, *p2, *ref, *r1;
245 printf("test: ref3\n# PARENT REFERENCE FREE\n");
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);
254 CHECK_BLOCKS("ref3", p1, 2);
255 CHECK_BLOCKS("ref3", p2, 2);
256 CHECK_BLOCKS("ref3", r1, 1);
257 CHECK_BLOCKS("ref3", ref, 1);
259 fprintf(stderr, "Freeing p1\n");
260 talloc_free(p1);
261 talloc_report_full(root, stderr);
263 CHECK_BLOCKS("ref3", p2, 2);
264 CHECK_BLOCKS("ref3", r1, 1);
266 fprintf(stderr, "Freeing p2\n");
267 talloc_free(p2);
268 talloc_report_full(root, stderr);
270 CHECK_SIZE("ref3", root, 0);
272 talloc_free(root);
274 printf("success: ref3\n");
275 return true;
279 test references
281 static bool test_ref4(void)
283 void *root, *p1, *p2, *ref, *r1;
285 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
287 root = talloc_named_const(NULL, 0, "root");
288 p1 = talloc_named_const(root, 1, "p1");
289 talloc_named_const(p1, 1, "x1");
290 talloc_named_const(p1, 1, "x2");
291 talloc_named_const(p1, 1, "x3");
292 p2 = talloc_named_const(p1, 1, "p2");
294 r1 = talloc_named_const(root, 1, "r1");
295 ref = talloc_reference(r1, p2);
296 talloc_report_full(root, stderr);
298 CHECK_BLOCKS("ref4", p1, 5);
299 CHECK_BLOCKS("ref4", p2, 1);
300 CHECK_BLOCKS("ref4", ref, 1);
301 CHECK_BLOCKS("ref4", r1, 2);
303 fprintf(stderr, "Freeing r1\n");
304 talloc_free(r1);
305 talloc_report_full(root, stderr);
307 CHECK_BLOCKS("ref4", p1, 5);
308 CHECK_BLOCKS("ref4", p2, 1);
310 fprintf(stderr, "Freeing p2\n");
311 talloc_free(p2);
312 talloc_report_full(root, stderr);
314 CHECK_BLOCKS("ref4", p1, 4);
316 fprintf(stderr, "Freeing p1\n");
317 talloc_free(p1);
318 talloc_report_full(root, stderr);
320 CHECK_SIZE("ref4", root, 0);
322 talloc_free(root);
324 printf("success: ref4\n");
325 return true;
330 test references
332 static bool test_unlink1(void)
334 void *root, *p1, *p2, *ref, *r1;
336 printf("test: unlink\n# UNLINK\n");
338 root = talloc_named_const(NULL, 0, "root");
339 p1 = talloc_named_const(root, 1, "p1");
340 talloc_named_const(p1, 1, "x1");
341 talloc_named_const(p1, 1, "x2");
342 talloc_named_const(p1, 1, "x3");
343 p2 = talloc_named_const(p1, 1, "p2");
345 r1 = talloc_named_const(p1, 1, "r1");
346 ref = talloc_reference(r1, p2);
347 talloc_report_full(root, stderr);
349 CHECK_BLOCKS("unlink", p1, 7);
350 CHECK_BLOCKS("unlink", p2, 1);
351 CHECK_BLOCKS("unlink", ref, 1);
352 CHECK_BLOCKS("unlink", r1, 2);
354 fprintf(stderr, "Unreferencing r1\n");
355 talloc_unlink(r1, p2);
356 talloc_report_full(root, stderr);
358 CHECK_BLOCKS("unlink", p1, 6);
359 CHECK_BLOCKS("unlink", p2, 1);
360 CHECK_BLOCKS("unlink", r1, 1);
362 fprintf(stderr, "Freeing p1\n");
363 talloc_free(p1);
364 talloc_report_full(root, stderr);
366 CHECK_SIZE("unlink", root, 0);
368 talloc_free(root);
370 printf("success: unlink\n");
371 return true;
374 static int fail_destructor(void *ptr)
376 return -1;
380 miscellaneous tests to try to get a higher test coverage percentage
382 static bool test_misc(void)
384 void *root, *p1;
385 char *p2;
386 double *d;
387 const char *name;
389 printf("test: misc\n# MISCELLANEOUS\n");
391 root = talloc_new(NULL);
393 p1 = talloc_size(root, 0x7fffffff);
394 torture_assert("misc", !p1, "failed: large talloc allowed\n");
396 p1 = talloc_strdup(root, "foo");
397 talloc_increase_ref_count(p1);
398 talloc_increase_ref_count(p1);
399 talloc_increase_ref_count(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 talloc_unlink(NULL, p1);
406 CHECK_BLOCKS("misc", p1, 1);
407 CHECK_BLOCKS("misc", root, 2);
408 p2 = talloc_strdup(p1, "foo");
409 torture_assert("misc", talloc_unlink(root, p2) == -1,
410 "failed: talloc_unlink() of non-reference context should return -1\n");
411 torture_assert("misc", talloc_unlink(p1, p2) == 0,
412 "failed: talloc_unlink() of parent should succeed\n");
413 talloc_unlink(NULL, p1);
414 CHECK_BLOCKS("misc", p1, 1);
415 CHECK_BLOCKS("misc", root, 2);
417 name = talloc_set_name(p1, "my name is %s", "foo");
418 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
419 "failed: wrong name after talloc_set_name(my name is foo)");
420 torture_assert_str_equal("misc", talloc_get_name(p1), name,
421 "failed: wrong name after talloc_set_name(my name is foo)");
422 CHECK_BLOCKS("misc", p1, 2);
423 CHECK_BLOCKS("misc", root, 3);
425 talloc_set_name_const(p1, NULL);
426 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
427 "failed: wrong name after talloc_set_name(NULL)");
428 CHECK_BLOCKS("misc", p1, 2);
429 CHECK_BLOCKS("misc", root, 3);
431 torture_assert("misc", talloc_free(NULL) == -1,
432 "talloc_free(NULL) should give -1\n");
434 talloc_set_destructor(p1, fail_destructor);
435 torture_assert("misc", talloc_free(p1) == -1,
436 "Failed destructor should cause talloc_free to fail\n");
437 talloc_set_destructor(p1, NULL);
439 talloc_report(root, stderr);
442 p2 = (char *)talloc_zero_size(p1, 20);
443 torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
444 talloc_free(p2);
446 torture_assert("misc", talloc_strdup(root, NULL) == NULL,
447 "failed: strdup on NULL should give NULL\n");
449 p2 = talloc_strndup(p1, "foo", 2);
450 torture_assert("misc", strcmp("fo", p2) == 0,
451 "strndup doesn't work\n");
452 p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
453 torture_assert("misc", strcmp("food", p2) == 0,
454 "talloc_asprintf_append_buffer doesn't work\n");
455 CHECK_BLOCKS("misc", p2, 1);
456 CHECK_BLOCKS("misc", p1, 3);
458 p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
459 torture_assert("misc", strcmp("hello world", p2) == 0,
460 "talloc_asprintf_append_buffer doesn't work\n");
461 CHECK_BLOCKS("misc", p2, 1);
462 CHECK_BLOCKS("misc", p1, 3);
463 talloc_free(p2);
465 d = talloc_array(p1, double, 0x20000000);
466 torture_assert("misc", !d, "failed: integer overflow not detected\n");
468 d = talloc_realloc(p1, d, double, 0x20000000);
469 torture_assert("misc", !d, "failed: integer overflow not detected\n");
471 talloc_free(p1);
472 CHECK_BLOCKS("misc", root, 1);
474 p1 = talloc_named(root, 100, "%d bytes", 100);
475 CHECK_BLOCKS("misc", p1, 2);
476 CHECK_BLOCKS("misc", root, 3);
477 talloc_unlink(root, p1);
479 p1 = talloc_init("%d bytes", 200);
480 p2 = talloc_asprintf(p1, "my test '%s'", "string");
481 torture_assert_str_equal("misc", p2, "my test 'string'",
482 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
483 CHECK_BLOCKS("misc", p1, 3);
484 CHECK_SIZE("misc", p2, 17);
485 CHECK_BLOCKS("misc", root, 1);
486 talloc_unlink(NULL, p1);
488 p1 = talloc_named_const(root, 10, "p1");
489 p2 = (char *)talloc_named_const(root, 20, "p2");
490 (void)talloc_reference(p1, p2);
491 talloc_report_full(root, stderr);
492 talloc_unlink(root, p2);
493 talloc_report_full(root, stderr);
494 CHECK_BLOCKS("misc", p2, 1);
495 CHECK_BLOCKS("misc", p1, 2);
496 CHECK_BLOCKS("misc", root, 3);
497 talloc_unlink(p1, p2);
498 talloc_unlink(root, p1);
500 p1 = talloc_named_const(root, 10, "p1");
501 p2 = (char *)talloc_named_const(root, 20, "p2");
502 (void)talloc_reference(NULL, p2);
503 talloc_report_full(root, stderr);
504 talloc_unlink(root, p2);
505 talloc_report_full(root, stderr);
506 CHECK_BLOCKS("misc", p2, 1);
507 CHECK_BLOCKS("misc", p1, 1);
508 CHECK_BLOCKS("misc", root, 2);
509 talloc_unlink(NULL, p2);
510 talloc_unlink(root, p1);
512 /* Test that talloc_unlink is a no-op */
514 torture_assert("misc", talloc_unlink(root, NULL) == -1,
515 "failed: talloc_unlink(root, NULL) == -1\n");
517 talloc_report(root, stderr);
518 talloc_report(NULL, stderr);
520 CHECK_SIZE("misc", root, 0);
522 talloc_free(root);
524 CHECK_SIZE("misc", NULL, 0);
526 talloc_enable_null_tracking_no_autofree();
527 talloc_enable_leak_report();
528 talloc_enable_leak_report_full();
530 printf("success: misc\n");
532 return true;
537 test realloc
539 static bool test_realloc(void)
541 void *root, *p1, *p2;
543 printf("test: realloc\n# REALLOC\n");
545 root = talloc_new(NULL);
547 p1 = talloc_size(root, 10);
548 CHECK_SIZE("realloc", p1, 10);
550 p1 = talloc_realloc_size(NULL, p1, 20);
551 CHECK_SIZE("realloc", p1, 20);
553 talloc_new(p1);
555 p2 = talloc_realloc_size(p1, NULL, 30);
557 talloc_new(p1);
559 p2 = talloc_realloc_size(p1, p2, 40);
561 CHECK_SIZE("realloc", p2, 40);
562 CHECK_SIZE("realloc", root, 60);
563 CHECK_BLOCKS("realloc", p1, 4);
565 p1 = talloc_realloc_size(NULL, p1, 20);
566 CHECK_SIZE("realloc", p1, 60);
568 talloc_increase_ref_count(p2);
569 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
570 "failed: talloc_realloc() on a referenced pointer should fail\n");
571 CHECK_BLOCKS("realloc", p1, 4);
573 talloc_realloc_size(NULL, p2, 0);
574 talloc_realloc_size(NULL, p2, 0);
575 CHECK_BLOCKS("realloc", p1, 4);
576 talloc_realloc_size(p1, p2, 0);
577 CHECK_BLOCKS("realloc", p1, 3);
579 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
580 "failed: oversize talloc should fail\n");
582 talloc_realloc_size(NULL, p1, 0);
583 CHECK_BLOCKS("realloc", root, 4);
584 talloc_realloc_size(root, p1, 0);
585 CHECK_BLOCKS("realloc", root, 1);
587 CHECK_SIZE("realloc", root, 0);
589 talloc_free(root);
591 printf("success: realloc\n");
593 return true;
597 test realloc with a child
599 static bool test_realloc_child(void)
601 void *root;
602 struct el2 {
603 const char *name;
604 } *el2;
605 struct el1 {
606 int count;
607 struct el2 **list, **list2, **list3;
608 } *el1;
610 printf("test: REALLOC WITH CHILD\n");
612 root = talloc_new(NULL);
614 el1 = talloc(root, struct el1);
615 el1->list = talloc(el1, struct el2 *);
616 el1->list[0] = talloc(el1->list, struct el2);
617 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
619 el1->list2 = talloc(el1, struct el2 *);
620 el1->list2[0] = talloc(el1->list2, struct el2);
621 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
623 el1->list3 = talloc(el1, struct el2 *);
624 el1->list3[0] = talloc(el1->list3, struct el2);
625 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
627 el2 = talloc(el1->list, struct el2);
628 el2 = talloc(el1->list2, struct el2);
629 el2 = talloc(el1->list3, struct el2);
630 (void)el2;
632 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
633 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
634 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
636 talloc_free(root);
638 printf("success: REALLOC WITH CHILD\n");
639 return true;
643 test type checking
645 static bool test_type(void)
647 void *root;
648 struct el1 {
649 int count;
651 struct el2 {
652 int count;
654 struct el1 *el1;
656 printf("test: type\n# talloc type checking\n");
658 root = talloc_new(NULL);
660 el1 = talloc(root, struct el1);
662 el1->count = 1;
664 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
665 "type check failed on el1\n");
666 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
667 "type check failed on el1 with el2\n");
668 talloc_set_type(el1, struct el2);
669 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
670 "type set failed on el1 with el2\n");
672 talloc_free(root);
674 printf("success: type\n");
675 return true;
679 test steal
681 static bool test_steal(void)
683 void *root, *p1, *p2;
685 printf("test: steal\n# STEAL\n");
687 root = talloc_new(NULL);
689 p1 = talloc_array(root, char, 10);
690 CHECK_SIZE("steal", p1, 10);
692 p2 = talloc_realloc(root, NULL, char, 20);
693 CHECK_SIZE("steal", p1, 10);
694 CHECK_SIZE("steal", root, 30);
696 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
697 "failed: stealing NULL should give NULL\n");
699 torture_assert("steal", talloc_steal(p1, p1) == p1,
700 "failed: stealing to ourselves is a nop\n");
701 CHECK_BLOCKS("steal", root, 3);
702 CHECK_SIZE("steal", root, 30);
704 talloc_steal(NULL, p1);
705 talloc_steal(NULL, p2);
706 CHECK_BLOCKS("steal", root, 1);
707 CHECK_SIZE("steal", root, 0);
709 talloc_free(p1);
710 talloc_steal(root, p2);
711 CHECK_BLOCKS("steal", root, 2);
712 CHECK_SIZE("steal", root, 20);
714 talloc_free(p2);
716 CHECK_BLOCKS("steal", root, 1);
717 CHECK_SIZE("steal", root, 0);
719 talloc_free(root);
721 p1 = talloc_size(NULL, 3);
722 talloc_report_full(NULL, stderr);
723 CHECK_SIZE("steal", NULL, 3);
724 talloc_free(p1);
726 printf("success: steal\n");
727 return true;
731 test move
733 static bool test_move(void)
735 void *root;
736 struct t_move {
737 char *p;
738 int *x;
739 } *t1, *t2;
741 printf("test: move\n# MOVE\n");
743 root = talloc_new(NULL);
745 t1 = talloc(root, struct t_move);
746 t2 = talloc(root, struct t_move);
747 t1->p = talloc_strdup(t1, "foo");
748 t1->x = talloc(t1, int);
749 *t1->x = 42;
751 t2->p = talloc_move(t2, &t1->p);
752 t2->x = talloc_move(t2, &t1->x);
753 torture_assert("move", t1->p == NULL && t1->x == NULL &&
754 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
755 "talloc move failed");
757 talloc_free(root);
759 printf("success: move\n");
761 return true;
765 test talloc_realloc_fn
767 static bool test_realloc_fn(void)
769 void *root, *p1;
771 printf("test: realloc_fn\n# talloc_realloc_fn\n");
773 root = talloc_new(NULL);
775 p1 = talloc_realloc_fn(root, NULL, 10);
776 CHECK_BLOCKS("realloc_fn", root, 2);
777 CHECK_SIZE("realloc_fn", root, 10);
778 p1 = talloc_realloc_fn(root, p1, 20);
779 CHECK_BLOCKS("realloc_fn", root, 2);
780 CHECK_SIZE("realloc_fn", root, 20);
781 p1 = talloc_realloc_fn(root, p1, 0);
782 CHECK_BLOCKS("realloc_fn", root, 1);
783 CHECK_SIZE("realloc_fn", root, 0);
785 talloc_free(root);
787 printf("success: realloc_fn\n");
788 return true;
792 static bool test_unref_reparent(void)
794 void *root, *p1, *p2, *c1;
796 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
798 root = talloc_named_const(NULL, 0, "root");
799 p1 = talloc_named_const(root, 1, "orig parent");
800 p2 = talloc_named_const(root, 1, "parent by reference");
802 c1 = talloc_named_const(p1, 1, "child");
803 talloc_reference(p2, c1);
805 CHECK_PARENT("unref_reparent", c1, p1);
807 talloc_free(p1);
809 CHECK_PARENT("unref_reparent", c1, p2);
811 talloc_unlink(p2, c1);
813 CHECK_SIZE("unref_reparent", root, 1);
815 talloc_free(p2);
816 talloc_free(root);
818 printf("success: unref_reparent\n");
819 return true;
823 measure the speed of talloc versus malloc
825 static bool test_speed(void)
827 void *ctx = talloc_new(NULL);
828 unsigned count;
829 const int loop = 1000;
830 int i;
831 struct timeval tv;
833 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
835 tv = timeval_current();
836 count = 0;
837 do {
838 void *p1, *p2, *p3;
839 for (i=0;i<loop;i++) {
840 p1 = talloc_size(ctx, loop % 100);
841 p2 = talloc_strdup(p1, "foo bar");
842 p3 = talloc_size(p1, 300);
843 (void)p2;
844 (void)p3;
845 talloc_free(p1);
847 count += 3 * loop;
848 } while (timeval_elapsed(&tv) < 5.0);
850 fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
852 talloc_free(ctx);
854 ctx = talloc_pool(NULL, 1024);
856 tv = timeval_current();
857 count = 0;
858 do {
859 void *p1, *p2, *p3;
860 for (i=0;i<loop;i++) {
861 p1 = talloc_size(ctx, loop % 100);
862 p2 = talloc_strdup(p1, "foo bar");
863 p3 = talloc_size(p1, 300);
864 (void)p2;
865 (void)p3;
866 talloc_free(p1);
868 count += 3 * loop;
869 } while (timeval_elapsed(&tv) < 5.0);
871 talloc_free(ctx);
873 fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
875 tv = timeval_current();
876 count = 0;
877 do {
878 void *p1, *p2, *p3;
879 for (i=0;i<loop;i++) {
880 p1 = malloc(loop % 100);
881 p2 = strdup("foo bar");
882 p3 = malloc(300);
883 free(p1);
884 free(p2);
885 free(p3);
887 count += 3 * loop;
888 } while (timeval_elapsed(&tv) < 5.0);
889 fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
891 printf("success: speed\n");
893 return true;
896 static bool test_lifeless(void)
898 void *top = talloc_new(NULL);
899 char *parent, *child;
900 void *child_owner = talloc_new(NULL);
902 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
904 parent = talloc_strdup(top, "parent");
905 child = talloc_strdup(parent, "child");
906 (void)talloc_reference(child, parent);
907 (void)talloc_reference(child_owner, child);
908 talloc_report_full(top, stderr);
909 talloc_unlink(top, parent);
910 talloc_unlink(top, child);
911 talloc_report_full(top, stderr);
912 talloc_free(top);
913 talloc_free(child_owner);
914 talloc_free(child);
916 printf("success: lifeless\n");
917 return true;
920 static int loop_destructor_count;
922 static int test_loop_destructor(char *ptr)
924 loop_destructor_count++;
925 return 0;
928 static bool test_loop(void)
930 void *top = talloc_new(NULL);
931 char *parent;
932 struct req1 {
933 char *req2, *req3;
934 } *req1;
936 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
938 parent = talloc_strdup(top, "parent");
939 req1 = talloc(parent, struct req1);
940 req1->req2 = talloc_strdup(req1, "req2");
941 talloc_set_destructor(req1->req2, test_loop_destructor);
942 req1->req3 = talloc_strdup(req1, "req3");
943 (void)talloc_reference(req1->req3, req1);
944 talloc_report_full(top, stderr);
945 talloc_free(parent);
946 talloc_report_full(top, stderr);
947 talloc_report_full(NULL, stderr);
948 talloc_free(top);
950 torture_assert("loop", loop_destructor_count == 1,
951 "FAILED TO FIRE LOOP DESTRUCTOR\n");
952 loop_destructor_count = 0;
954 printf("success: loop\n");
955 return true;
958 static int fail_destructor_str(char *ptr)
960 return -1;
963 static bool test_free_parent_deny_child(void)
965 void *top = talloc_new(NULL);
966 char *level1;
967 char *level2;
968 char *level3;
970 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
972 level1 = talloc_strdup(top, "level1");
973 level2 = talloc_strdup(level1, "level2");
974 level3 = talloc_strdup(level2, "level3");
976 talloc_set_destructor(level3, fail_destructor_str);
977 talloc_free(level1);
978 talloc_set_destructor(level3, NULL);
980 CHECK_PARENT("free_parent_deny_child", level3, top);
982 talloc_free(top);
984 printf("success: free_parent_deny_child\n");
985 return true;
988 struct new_parent {
989 void *new_parent;
990 char val[20];
993 static int reparenting_destructor(struct new_parent *np)
995 talloc_set_destructor(np, NULL);
996 (void)talloc_move(np->new_parent, &np);
997 return -1;
1000 static bool test_free_parent_reparent_child(void)
1002 void *top = talloc_new(NULL);
1003 char *level1;
1004 char *alternate_level1;
1005 char *level2;
1006 struct new_parent *level3;
1008 printf("test: free_parent_reparent_child\n# "
1009 "TALLOC FREE PARENT REPARENT CHILD\n");
1011 level1 = talloc_strdup(top, "level1");
1012 alternate_level1 = talloc_strdup(top, "alternate_level1");
1013 level2 = talloc_strdup(level1, "level2");
1014 level3 = talloc(level2, struct new_parent);
1015 level3->new_parent = alternate_level1;
1016 memset(level3->val, 'x', sizeof(level3->val));
1018 talloc_set_destructor(level3, reparenting_destructor);
1019 talloc_free(level1);
1021 CHECK_PARENT("free_parent_reparent_child",
1022 level3, alternate_level1);
1024 talloc_free(top);
1026 printf("success: free_parent_reparent_child\n");
1027 return true;
1030 static bool test_free_parent_reparent_child_in_pool(void)
1032 void *top = talloc_new(NULL);
1033 char *level1;
1034 char *alternate_level1;
1035 char *level2;
1036 void *pool;
1037 struct new_parent *level3;
1039 printf("test: free_parent_reparent_child_in_pool\n# "
1040 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1042 pool = talloc_pool(top, 1024);
1043 level1 = talloc_strdup(pool, "level1");
1044 alternate_level1 = talloc_strdup(top, "alternate_level1");
1045 level2 = talloc_strdup(level1, "level2");
1046 level3 = talloc(level2, struct new_parent);
1047 level3->new_parent = alternate_level1;
1048 memset(level3->val, 'x', sizeof(level3->val));
1050 talloc_set_destructor(level3, reparenting_destructor);
1051 talloc_free(level1);
1052 talloc_set_destructor(level3, NULL);
1054 CHECK_PARENT("free_parent_reparent_child_in_pool",
1055 level3, alternate_level1);
1057 /* Even freeing alternate_level1 should leave pool alone. */
1058 talloc_free(alternate_level1);
1059 talloc_free(top);
1061 printf("success: free_parent_reparent_child_in_pool\n");
1062 return true;
1066 static bool test_talloc_ptrtype(void)
1068 void *top = talloc_new(NULL);
1069 struct struct1 {
1070 int foo;
1071 int bar;
1072 } *s1, *s2, **s3, ***s4;
1073 const char *location1;
1074 const char *location2;
1075 const char *location3;
1076 const char *location4;
1078 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1080 s1 = talloc_ptrtype(top, s1);location1 = __location__;
1082 if (talloc_get_size(s1) != sizeof(struct struct1)) {
1083 printf("failure: ptrtype [\n"
1084 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1085 "]\n", (unsigned long)talloc_get_size(s1),
1086 (unsigned long)sizeof(struct struct1));
1087 return false;
1090 if (strcmp(location1, talloc_get_name(s1)) != 0) {
1091 printf("failure: ptrtype [\n"
1092 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1093 talloc_get_name(s1), location1);
1094 return false;
1097 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1099 if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1100 printf("failure: ptrtype [\n"
1101 "talloc_array_ptrtype() allocated the wrong size "
1102 "%lu (should be %lu)\n]\n",
1103 (unsigned long)talloc_get_size(s2),
1104 (unsigned long)(sizeof(struct struct1)*10));
1105 return false;
1108 if (strcmp(location2, talloc_get_name(s2)) != 0) {
1109 printf("failure: ptrtype [\n"
1110 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1111 talloc_get_name(s2), location2);
1112 return false;
1115 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1117 if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1118 printf("failure: ptrtype [\n"
1119 "talloc_array_ptrtype() allocated the wrong size "
1120 "%lu (should be %lu)\n]\n",
1121 (unsigned long)talloc_get_size(s3),
1122 (unsigned long)(sizeof(struct struct1 *)*10));
1123 return false;
1126 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1127 "talloc_array_ptrtype() sets the wrong name");
1129 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1131 if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1132 printf("failure: ptrtype [\n"
1133 "talloc_array_ptrtype() allocated the wrong size "
1134 "%lu (should be %lu)\n]\n",
1135 (unsigned long)talloc_get_size(s4),
1136 (unsigned long)(sizeof(struct struct1 **)*10));
1137 return false;
1140 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1141 "talloc_array_ptrtype() sets the wrong name");
1143 talloc_free(top);
1145 printf("success: ptrtype\n");
1146 return true;
1149 static int _test_talloc_free_in_destructor(void **ptr)
1151 talloc_free(*ptr);
1152 return 0;
1155 static bool test_talloc_free_in_destructor(void)
1157 void *level0;
1158 void *level1;
1159 void *level2;
1160 void *level3;
1161 void *level4;
1162 void **level5;
1164 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1166 level0 = talloc_new(NULL);
1167 level1 = talloc_new(level0);
1168 level2 = talloc_new(level1);
1169 level3 = talloc_new(level2);
1170 level4 = talloc_new(level3);
1171 level5 = talloc(level4, void *);
1173 *level5 = level3;
1174 (void)talloc_reference(level0, level3);
1175 (void)talloc_reference(level3, level3);
1176 (void)talloc_reference(level5, level3);
1178 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1180 talloc_free(level1);
1182 talloc_free(level0);
1184 printf("success: free_in_destructor\n");
1185 return true;
1188 static bool test_autofree(void)
1190 #if _SAMBA_BUILD_ < 4
1191 /* autofree test would kill smbtorture */
1192 void *p;
1193 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1195 p = talloc_autofree_context();
1196 talloc_free(p);
1198 p = talloc_autofree_context();
1199 talloc_free(p);
1201 printf("success: autofree\n");
1202 #endif
1203 return true;
1206 static bool test_pool(void)
1208 void *pool;
1209 void *p1, *p2, *p3, *p4;
1210 void *p2_2;
1212 pool = talloc_pool(NULL, 1024);
1214 p1 = talloc_size(pool, 80);
1215 memset(p1, 0x11, talloc_get_size(p1));
1216 p2 = talloc_size(pool, 20);
1217 memset(p2, 0x11, talloc_get_size(p2));
1218 p3 = talloc_size(p1, 50);
1219 memset(p3, 0x11, talloc_get_size(p3));
1220 p4 = talloc_size(p3, 1000);
1221 memset(p4, 0x11, talloc_get_size(p4));
1223 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1224 p2_2 = talloc_realloc_size(pool, p2, 20+1);
1225 torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1226 memset(p2, 0x11, talloc_get_size(p2));
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));
1234 talloc_free(p3);
1236 /* this should reclaim the memory of p4 and p3 */
1237 p2_2 = talloc_realloc_size(pool, p2, 400);
1238 torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1239 memset(p2, 0x11, talloc_get_size(p2));
1241 talloc_free(p1);
1243 /* this should reclaim the memory of p1 */
1244 p2_2 = talloc_realloc_size(pool, p2, 800);
1245 torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1246 p2 = p2_2;
1247 memset(p2, 0x11, talloc_get_size(p2));
1249 /* this should do a malloc */
1250 p2_2 = talloc_realloc_size(pool, p2, 1800);
1251 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1252 p2 = p2_2;
1253 memset(p2, 0x11, talloc_get_size(p2));
1255 /* this should reclaim the memory from the pool */
1256 p3 = talloc_size(pool, 80);
1257 torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1258 memset(p3, 0x11, talloc_get_size(p3));
1260 talloc_free(p2);
1261 talloc_free(p3);
1263 p1 = talloc_size(pool, 80);
1264 memset(p1, 0x11, talloc_get_size(p1));
1265 p2 = talloc_size(pool, 20);
1266 memset(p2, 0x11, talloc_get_size(p2));
1268 talloc_free(p1);
1270 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1271 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1272 memset(p2, 0x11, talloc_get_size(p2));
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));
1277 /* this should do a malloc */
1278 p2_2 = talloc_realloc_size(pool, p2, 1800);
1279 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1280 p2 = p2_2;
1281 memset(p2, 0x11, talloc_get_size(p2));
1283 /* this should reclaim the memory from the pool */
1284 p3 = talloc_size(pool, 800);
1285 torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1286 memset(p3, 0x11, talloc_get_size(p3));
1288 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1290 talloc_free(pool);
1292 return true;
1295 static bool test_pool_steal(void)
1297 void *root;
1298 void *pool;
1299 void *p1, *p2;
1300 void *p1_2, *p2_2;
1301 size_t hdr;
1302 size_t ofs1, ofs2;
1304 root = talloc_new(NULL);
1305 pool = talloc_pool(root, 1024);
1307 p1 = talloc_size(pool, 4 * 16);
1308 torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1309 memset(p1, 0x11, talloc_get_size(p1));
1310 p2 = talloc_size(pool, 4 * 16);
1311 torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1312 memset(p2, 0x11, talloc_get_size(p2));
1314 ofs1 = PTR_DIFF(p2, p1);
1315 hdr = ofs1 - talloc_get_size(p1);
1317 talloc_steal(root, p1);
1318 talloc_steal(root, p2);
1320 talloc_free(pool);
1322 p1_2 = p1;
1324 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1325 p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1326 torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1327 memset(p1_2, 0x11, talloc_get_size(p1_2));
1328 ofs1 = PTR_DIFF(p1_2, p2);
1329 ofs2 = talloc_get_size(p2) + hdr;
1331 torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1333 p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1334 torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1335 memset(p2_2, 0x11, talloc_get_size(p2_2));
1336 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1338 talloc_free(p1_2);
1340 p2_2 = p2;
1342 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1343 /* now we should reclaim the full pool */
1344 p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1345 torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1346 p2 = p2_2;
1347 memset(p2_2, 0x11, talloc_get_size(p2_2));
1349 /* now we malloc and free the full pool space */
1350 p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1351 torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1352 memset(p2_2, 0x11, talloc_get_size(p2_2));
1354 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1356 talloc_free(p2_2);
1358 talloc_free(root);
1360 return true;
1363 static bool test_pool_nest(void)
1365 void *p1, *p2, *p3;
1366 void *e = talloc_new(NULL);
1368 p1 = talloc_pool(NULL, 1024);
1369 torture_assert("talloc_pool", p1 != NULL, "failed");
1371 p2 = talloc_pool(p1, 500);
1372 torture_assert("talloc_pool", p2 != NULL, "failed");
1374 p3 = talloc_size(p2, 10);
1376 talloc_steal(e, p3);
1378 talloc_free(p2);
1380 talloc_free(p3);
1382 talloc_free(p1);
1384 return true;
1387 struct pooled {
1388 char *s1;
1389 char *s2;
1390 char *s3;
1393 static bool test_pooled_object(void)
1395 struct pooled *p;
1396 const char *s1 = "hello";
1397 const char *s2 = "world";
1398 const char *s3 = "";
1400 p = talloc_pooled_object(NULL, struct pooled, 3,
1401 strlen(s1)+strlen(s2)+strlen(s3)+3);
1403 if (talloc_get_size(p) != sizeof(struct pooled)) {
1404 return false;
1407 p->s1 = talloc_strdup(p, s1);
1409 TALLOC_FREE(p->s1);
1410 p->s1 = talloc_strdup(p, s2);
1411 TALLOC_FREE(p->s1);
1413 p->s1 = talloc_strdup(p, s1);
1414 p->s2 = talloc_strdup(p, s2);
1415 p->s3 = talloc_strdup(p, s3);
1417 TALLOC_FREE(p);
1418 return true;
1421 static bool test_free_ref_null_context(void)
1423 void *p1, *p2, *p3;
1424 int ret;
1426 talloc_disable_null_tracking();
1427 p1 = talloc_new(NULL);
1428 p2 = talloc_new(NULL);
1430 p3 = talloc_reference(p2, p1);
1431 torture_assert("reference", p3 == p1, "failed: reference on null");
1433 ret = talloc_free(p1);
1434 torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1435 talloc_free(p2);
1437 talloc_enable_null_tracking_no_autofree();
1438 p1 = talloc_new(NULL);
1439 p2 = talloc_new(NULL);
1441 p3 = talloc_reference(p2, p1);
1442 torture_assert("reference", p3 == p1, "failed: reference on null");
1444 ret = talloc_free(p1);
1445 torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1446 talloc_free(p2);
1448 return true;
1451 static bool test_rusty(void)
1453 void *root;
1454 const char *p1;
1456 talloc_enable_null_tracking();
1457 root = talloc_new(NULL);
1458 p1 = talloc_strdup(root, "foo");
1459 talloc_increase_ref_count(p1);
1460 talloc_report_full(root, stdout);
1461 talloc_free(root);
1462 CHECK_BLOCKS("null_context", NULL, 2);
1463 return true;
1466 static bool test_free_children(void)
1468 void *root;
1469 char *p1, *p2;
1470 const char *name, *name2;
1472 talloc_enable_null_tracking();
1473 root = talloc_new(NULL);
1474 p1 = talloc_strdup(root, "foo1");
1475 p2 = talloc_strdup(p1, "foo2");
1476 (void)p2;
1478 talloc_set_name(p1, "%s", "testname");
1479 talloc_free_children(p1);
1480 /* check its still a valid talloc ptr */
1481 talloc_get_size(talloc_get_name(p1));
1482 if (strcmp(talloc_get_name(p1), "testname") != 0) {
1483 return false;
1486 talloc_set_name(p1, "%s", "testname");
1487 name = talloc_get_name(p1);
1488 talloc_free_children(p1);
1489 /* check its still a valid talloc ptr */
1490 talloc_get_size(talloc_get_name(p1));
1491 torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
1492 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
1493 "wrong name");
1494 CHECK_BLOCKS("name1", p1, 2);
1496 /* note that this does not free the old child name */
1497 talloc_set_name_const(p1, "testname2");
1498 name2 = talloc_get_name(p1);
1499 /* but this does */
1500 talloc_free_children(p1);
1501 (void)name2;
1502 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1503 "wrong name");
1504 CHECK_BLOCKS("name1", p1, 1);
1506 talloc_report_full(root, stdout);
1507 talloc_free(root);
1508 return true;
1511 static bool test_memlimit(void)
1513 void *root;
1514 char *l1, *l2, *l3, *l4, *l5, *t;
1515 char *pool;
1516 int i;
1518 printf("test: memlimit\n# MEMORY LIMITS\n");
1520 printf("==== talloc_new(NULL)\n");
1521 root = talloc_new(NULL);
1523 talloc_report_full(root, stdout);
1525 printf("==== talloc_size(root, 2048)\n");
1526 l1 = talloc_size(root, 2048);
1527 torture_assert("memlimit", l1 != NULL,
1528 "failed: alloc should not fail due to memory limit\n");
1530 talloc_report_full(root, stdout);
1532 printf("==== talloc_free(l1)\n");
1533 talloc_free(l1);
1535 talloc_report_full(root, stdout);
1537 printf("==== talloc_strdup(root, level 1)\n");
1538 l1 = talloc_strdup(root, "level 1");
1539 torture_assert("memlimit", l1 != NULL,
1540 "failed: alloc should not fail due to memory limit\n");
1542 talloc_report_full(root, stdout);
1544 printf("==== talloc_set_memlimit(l1, 2048)\n");
1545 torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
1546 "failed: setting memlimit should never fail\n");
1548 talloc_report_full(root, stdout);
1550 printf("==== talloc_size(root, 2048)\n");
1551 l2 = talloc_size(l1, 2048);
1552 torture_assert("memlimit", l2 == NULL,
1553 "failed: alloc should fail due to memory limit\n");
1555 talloc_report_full(root, stdout);
1557 printf("==== talloc_strdup(l1, level 2)\n");
1558 l2 = talloc_strdup(l1, "level 2");
1559 torture_assert("memlimit", l2 != NULL,
1560 "failed: alloc should not fail due to memory limit\n");
1562 talloc_report_full(root, stdout);
1564 printf("==== talloc_free(l2)\n");
1565 talloc_free(l2);
1567 talloc_report_full(root, stdout);
1569 printf("==== talloc_size(NULL, 2048)\n");
1570 l2 = talloc_size(NULL, 2048);
1572 talloc_report_full(root, stdout);
1574 printf("==== talloc_steal(l1, l2)\n");
1575 talloc_steal(l1, l2);
1577 talloc_report_full(root, stdout);
1579 printf("==== talloc_strdup(l2, level 3)\n");
1580 l3 = talloc_strdup(l2, "level 3");
1581 torture_assert("memlimit", l3 == NULL,
1582 "failed: alloc should fail due to memory limit\n");
1584 talloc_report_full(root, stdout);
1586 printf("==== talloc_free(l2)\n");
1587 talloc_free(l2);
1589 talloc_report_full(root, stdout);
1591 printf("==== talloc_strdup(NULL, level 2)\n");
1592 l2 = talloc_strdup(NULL, "level 2");
1593 talloc_steal(l1, l2);
1595 talloc_report_full(root, stdout);
1597 printf("==== talloc_strdup(l2, level 3)\n");
1598 l3 = talloc_strdup(l2, "level 3");
1599 torture_assert("memlimit", l3 != NULL,
1600 "failed: alloc should not fail due to memory limit\n");
1602 talloc_report_full(root, stdout);
1604 printf("==== talloc_set_memlimit(l3, 1024)\n");
1605 torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
1606 "failed: setting memlimit should never fail\n");
1608 talloc_report_full(root, stdout);
1610 printf("==== talloc_strdup(l3, level 4)\n");
1611 l4 = talloc_strdup(l3, "level 4");
1612 torture_assert("memlimit", l4 != NULL,
1613 "failed: alloc should not fail due to memory limit\n");
1615 talloc_report_full(root, stdout);
1617 printf("==== talloc_set_memlimit(l4, 512)\n");
1618 torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1619 "failed: setting memlimit should never fail\n");
1621 talloc_report_full(root, stdout);
1623 printf("==== talloc_strdup(l4, level 5)\n");
1624 l5 = talloc_strdup(l4, "level 5");
1625 torture_assert("memlimit", l5 != NULL,
1626 "failed: alloc should not fail due to memory limit\n");
1628 talloc_report_full(root, stdout);
1630 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1631 t = talloc_realloc(NULL, l5, char, 600);
1632 torture_assert("memlimit", t == NULL,
1633 "failed: alloc should fail due to memory limit\n");
1635 talloc_report_full(root, stdout);
1637 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1638 l5 = talloc_realloc(NULL, l5, char, 5);
1639 torture_assert("memlimit", l5 != NULL,
1640 "failed: alloc should not fail due to memory limit\n");
1642 talloc_report_full(root, stdout);
1644 printf("==== talloc_strdup(l3, level 4)\n");
1645 l4 = talloc_strdup(l3, "level 4");
1646 torture_assert("memlimit", l4 != NULL,
1647 "failed: alloc should not fail due to memory limit\n");
1649 talloc_report_full(root, stdout);
1651 printf("==== talloc_set_memlimit(l4, 512)\n");
1652 torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1653 "failed: setting memlimit should never fail\n");
1655 talloc_report_full(root, stdout);
1657 printf("==== talloc_strdup(l4, level 5)\n");
1658 l5 = talloc_strdup(l4, "level 5");
1659 torture_assert("memlimit", l5 != NULL,
1660 "failed: alloc should not fail due to memory limit\n");
1662 talloc_report_full(root, stdout);
1664 printf("==== Make new temp context and steal l5\n");
1665 t = talloc_new(root);
1666 talloc_steal(t, l5);
1668 talloc_report_full(root, stdout);
1670 printf("==== talloc_size(t, 2048)\n");
1671 l1 = talloc_size(t, 2048);
1672 torture_assert("memlimit", l1 != NULL,
1673 "failed: alloc should not fail due to memory limit\n");
1675 talloc_report_full(root, stdout);
1676 talloc_free(root);
1678 /* Test memlimits with pools. */
1679 pool = talloc_pool(NULL, 10*1024);
1680 torture_assert("memlimit", pool != NULL,
1681 "failed: alloc should not fail due to memory limit\n");
1682 talloc_set_memlimit(pool, 10*1024);
1683 for (i = 0; i < 9; i++) {
1684 l1 = talloc_size(pool, 1024);
1685 torture_assert("memlimit", l1 != NULL,
1686 "failed: alloc should not fail due to memory limit\n");
1688 /* The next alloc should fail. */
1689 l2 = talloc_size(pool, 1024);
1690 torture_assert("memlimit", l2 == NULL,
1691 "failed: alloc should fail due to memory limit\n");
1693 /* Moving one of the children shouldn't change the limit,
1694 as it's still inside the pool. */
1695 root = talloc_new(NULL);
1696 talloc_steal(root, l1);
1697 l2 = talloc_size(pool, 1024);
1698 torture_assert("memlimit", l2 == NULL,
1699 "failed: alloc should fail due to memory limit\n");
1701 talloc_free(pool);
1702 talloc_free(root);
1703 printf("success: memlimit\n");
1705 return true;
1708 #ifdef HAVE_PTHREAD
1710 #define NUM_THREADS 100
1712 /* Sync variables. */
1713 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1714 static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1715 static void *intermediate_ptr;
1717 /* Subthread. */
1718 static void *thread_fn(void *arg)
1720 int ret;
1721 const char *ctx_name = (const char *)arg;
1722 void *sub_ctx = NULL;
1724 * Do stuff that creates a new talloc hierarchy in
1725 * this thread.
1727 void *top_ctx = talloc_named_const(NULL, 0, "top");
1728 if (top_ctx == NULL) {
1729 return NULL;
1731 sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1732 if (sub_ctx == NULL) {
1733 return NULL;
1737 * Now transfer a pointer from our hierarchy
1738 * onto the intermediate ptr.
1740 ret = pthread_mutex_lock(&mtx);
1741 if (ret != 0) {
1742 talloc_free(top_ctx);
1743 return NULL;
1745 /* Wait for intermediate_ptr to be free. */
1746 while (intermediate_ptr != NULL) {
1747 ret = pthread_cond_wait(&condvar, &mtx);
1748 if (ret != 0) {
1749 talloc_free(top_ctx);
1750 return NULL;
1754 /* and move our memory onto it from our toplevel hierarchy. */
1755 intermediate_ptr = talloc_move(NULL, &sub_ctx);
1757 /* Tell the main thread it's ready for pickup. */
1758 pthread_cond_broadcast(&condvar);
1759 pthread_mutex_unlock(&mtx);
1761 talloc_free(top_ctx);
1762 return NULL;
1765 /* Main thread. */
1766 static bool test_pthread_talloc_passing(void)
1768 int i;
1769 int ret;
1770 char str_array[NUM_THREADS][20];
1771 pthread_t thread_id;
1772 void *mem_ctx;
1775 * Important ! Null tracking breaks threaded talloc.
1776 * It *must* be turned off.
1778 talloc_disable_null_tracking();
1780 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1782 /* Main thread toplevel context. */
1783 mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1784 if (mem_ctx == NULL) {
1785 printf("failed to create toplevel context\n");
1786 return false;
1790 * Spin off NUM_THREADS threads.
1791 * They will use their own toplevel contexts.
1793 for (i = 0; i < NUM_THREADS; i++) {
1794 (void)snprintf(str_array[i],
1796 "thread:%d",
1798 if (str_array[i] == NULL) {
1799 printf("snprintf %d failed\n", i);
1800 return false;
1802 ret = pthread_create(&thread_id,
1803 NULL,
1804 thread_fn,
1805 str_array[i]);
1806 if (ret != 0) {
1807 printf("failed to create thread %d (%d)\n", i, ret);
1808 return false;
1812 printf("Created %d threads\n", NUM_THREADS);
1814 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1815 for (i = 0; i < NUM_THREADS; i++) {
1816 ret = pthread_mutex_lock(&mtx);
1817 if (ret != 0) {
1818 printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
1819 talloc_free(mem_ctx);
1820 return false;
1823 /* Wait for intermediate_ptr to have our data. */
1824 while (intermediate_ptr == NULL) {
1825 ret = pthread_cond_wait(&condvar, &mtx);
1826 if (ret != 0) {
1827 printf("pthread_cond_wait %d failed (%d)\n", i,
1828 ret);
1829 talloc_free(mem_ctx);
1830 return false;
1834 /* and move it onto our toplevel hierarchy. */
1835 (void)talloc_move(mem_ctx, &intermediate_ptr);
1837 /* Tell the sub-threads we're ready for another. */
1838 pthread_cond_broadcast(&condvar);
1839 pthread_mutex_unlock(&mtx);
1842 CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
1843 #if 1
1844 /* Dump the hierarchy. */
1845 talloc_report(mem_ctx, stdout);
1846 #endif
1847 talloc_free(mem_ctx);
1848 printf("success: pthread_talloc_passing\n");
1849 return true;
1851 #endif
1853 static void test_reset(void)
1855 talloc_set_log_fn(test_log_stdout);
1856 test_abort_stop();
1857 talloc_disable_null_tracking();
1858 talloc_enable_null_tracking_no_autofree();
1861 bool torture_local_talloc(struct torture_context *tctx)
1863 bool ret = true;
1865 setlinebuf(stdout);
1867 test_reset();
1868 ret &= test_pooled_object();
1869 test_reset();
1870 ret &= test_pool_nest();
1871 test_reset();
1872 ret &= test_ref1();
1873 test_reset();
1874 ret &= test_ref2();
1875 test_reset();
1876 ret &= test_ref3();
1877 test_reset();
1878 ret &= test_ref4();
1879 test_reset();
1880 ret &= test_unlink1();
1881 test_reset();
1882 ret &= test_misc();
1883 test_reset();
1884 ret &= test_realloc();
1885 test_reset();
1886 ret &= test_realloc_child();
1887 test_reset();
1888 ret &= test_steal();
1889 test_reset();
1890 ret &= test_move();
1891 test_reset();
1892 ret &= test_unref_reparent();
1893 test_reset();
1894 ret &= test_realloc_fn();
1895 test_reset();
1896 ret &= test_type();
1897 test_reset();
1898 ret &= test_lifeless();
1899 test_reset();
1900 ret &= test_loop();
1901 test_reset();
1902 ret &= test_free_parent_deny_child();
1903 test_reset();
1904 ret &= test_free_parent_reparent_child();
1905 test_reset();
1906 ret &= test_free_parent_reparent_child_in_pool();
1907 test_reset();
1908 ret &= test_talloc_ptrtype();
1909 test_reset();
1910 ret &= test_talloc_free_in_destructor();
1911 test_reset();
1912 ret &= test_pool();
1913 test_reset();
1914 ret &= test_pool_steal();
1915 test_reset();
1916 ret &= test_free_ref_null_context();
1917 test_reset();
1918 ret &= test_rusty();
1919 test_reset();
1920 ret &= test_free_children();
1921 test_reset();
1922 ret &= test_memlimit();
1923 #ifdef HAVE_PTHREAD
1924 test_reset();
1925 ret &= test_pthread_talloc_passing();
1926 #endif
1929 if (ret) {
1930 test_reset();
1931 ret &= test_speed();
1933 test_reset();
1934 ret &= test_autofree();
1936 test_reset();
1937 talloc_disable_null_tracking();
1938 return ret;