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
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/>.
27 #include "system/time.h"
43 #include "talloc_testsuite.h"
45 static struct timeval
private_timeval_current(void)
48 gettimeofday(&tv
, NULL
);
52 static double private_timeval_elapsed(struct timeval
*tv
)
54 struct timeval tv2
= private_timeval_current();
55 return (tv2
.tv_sec
- tv
->tv_sec
) +
56 (tv2
.tv_usec
- tv
->tv_usec
)*1.0e-6;
59 #define torture_assert(test, expr, str) if (!(expr)) { \
60 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
61 test, __location__, #expr, str); \
65 #define torture_assert_str_equal(test, arg1, arg2, desc) \
66 if (arg1 == NULL && arg2 == NULL) { \
67 } else if (strcmp(arg1, arg2)) { \
68 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
69 test, __location__, arg1, arg2, desc); \
73 #define CHECK_SIZE(test, ptr, tsize) do { \
74 if (talloc_total_size(ptr) != (tsize)) { \
75 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
76 test, __location__, #ptr, \
77 (unsigned)talloc_total_size(ptr), \
79 talloc_report_full(ptr, stdout); \
84 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
85 if (talloc_total_blocks(ptr) != (tblocks)) { \
86 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
87 test, __location__, #ptr, \
88 (unsigned)talloc_total_blocks(ptr), \
90 talloc_report_full(ptr, stdout); \
95 #define CHECK_PARENT(test, ptr, parent) do { \
96 if (talloc_parent(ptr) != (parent)) { \
97 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
98 test, __location__, #ptr, \
101 talloc_report_full(ptr, stdout); \
102 talloc_report_full(parent, stdout); \
103 talloc_report_full(NULL, stdout); \
108 static unsigned int test_abort_count
;
111 static void test_abort_fn(const char *reason
)
113 printf("# test_abort_fn(%s)\n", reason
);
117 static void test_abort_start(void)
119 test_abort_count
= 0;
120 talloc_set_abort_fn(test_abort_fn
);
124 static void test_abort_stop(void)
126 test_abort_count
= 0;
127 talloc_set_abort_fn(NULL
);
130 static void test_log_stdout(const char *message
)
132 fprintf(stdout
, "%s", message
);
138 static bool test_ref1(void)
140 void *root
, *p1
, *p2
, *ref
, *r1
;
142 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
144 root
= talloc_named_const(NULL
, 0, "root");
145 p1
= talloc_named_const(root
, 1, "p1");
146 p2
= talloc_named_const(p1
, 1, "p2");
147 talloc_named_const(p1
, 1, "x1");
148 talloc_named_const(p1
, 2, "x2");
149 talloc_named_const(p1
, 3, "x3");
151 r1
= talloc_named_const(root
, 1, "r1");
152 ref
= talloc_reference(r1
, p2
);
153 talloc_report_full(root
, stderr
);
155 CHECK_BLOCKS("ref1", p1
, 5);
156 CHECK_BLOCKS("ref1", p2
, 1);
157 CHECK_BLOCKS("ref1", ref
, 1);
158 CHECK_BLOCKS("ref1", r1
, 2);
160 fprintf(stderr
, "Freeing p2\n");
161 talloc_unlink(r1
, p2
);
162 talloc_report_full(root
, stderr
);
164 CHECK_BLOCKS("ref1", p1
, 5);
165 CHECK_BLOCKS("ref1", p2
, 1);
166 CHECK_BLOCKS("ref1", r1
, 1);
168 fprintf(stderr
, "Freeing p1\n");
170 talloc_report_full(root
, stderr
);
172 CHECK_BLOCKS("ref1", r1
, 1);
174 fprintf(stderr
, "Freeing r1\n");
176 talloc_report_full(NULL
, stderr
);
178 fprintf(stderr
, "Testing NULL\n");
179 if (talloc_reference(root
, NULL
)) {
183 CHECK_BLOCKS("ref1", root
, 1);
185 CHECK_SIZE("ref1", root
, 0);
188 printf("success: ref1\n");
195 static bool test_ref2(void)
197 void *root
, *p1
, *p2
, *ref
, *r1
;
199 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
200 root
= talloc_named_const(NULL
, 0, "root");
201 p1
= talloc_named_const(root
, 1, "p1");
202 talloc_named_const(p1
, 1, "x1");
203 talloc_named_const(p1
, 1, "x2");
204 talloc_named_const(p1
, 1, "x3");
205 p2
= talloc_named_const(p1
, 1, "p2");
207 r1
= talloc_named_const(root
, 1, "r1");
208 ref
= talloc_reference(r1
, p2
);
209 talloc_report_full(root
, stderr
);
211 CHECK_BLOCKS("ref2", p1
, 5);
212 CHECK_BLOCKS("ref2", p2
, 1);
213 CHECK_BLOCKS("ref2", r1
, 2);
215 fprintf(stderr
, "Freeing ref\n");
216 talloc_unlink(r1
, ref
);
217 talloc_report_full(root
, stderr
);
219 CHECK_BLOCKS("ref2", p1
, 5);
220 CHECK_BLOCKS("ref2", p2
, 1);
221 CHECK_BLOCKS("ref2", r1
, 1);
223 fprintf(stderr
, "Freeing p2\n");
225 talloc_report_full(root
, stderr
);
227 CHECK_BLOCKS("ref2", p1
, 4);
228 CHECK_BLOCKS("ref2", r1
, 1);
230 fprintf(stderr
, "Freeing p1\n");
232 talloc_report_full(root
, stderr
);
234 CHECK_BLOCKS("ref2", r1
, 1);
236 fprintf(stderr
, "Freeing r1\n");
238 talloc_report_full(root
, stderr
);
240 CHECK_SIZE("ref2", root
, 0);
243 printf("success: ref2\n");
250 static bool test_ref3(void)
252 void *root
, *p1
, *p2
, *ref
, *r1
;
254 printf("test: ref3\n# PARENT REFERENCE FREE\n");
256 root
= talloc_named_const(NULL
, 0, "root");
257 p1
= talloc_named_const(root
, 1, "p1");
258 p2
= talloc_named_const(root
, 1, "p2");
259 r1
= talloc_named_const(p1
, 1, "r1");
260 ref
= talloc_reference(p2
, r1
);
261 talloc_report_full(root
, stderr
);
263 CHECK_BLOCKS("ref3", p1
, 2);
264 CHECK_BLOCKS("ref3", p2
, 2);
265 CHECK_BLOCKS("ref3", r1
, 1);
266 CHECK_BLOCKS("ref3", ref
, 1);
268 fprintf(stderr
, "Freeing p1\n");
270 talloc_report_full(root
, stderr
);
272 CHECK_BLOCKS("ref3", p2
, 2);
273 CHECK_BLOCKS("ref3", r1
, 1);
275 fprintf(stderr
, "Freeing p2\n");
277 talloc_report_full(root
, stderr
);
279 CHECK_SIZE("ref3", root
, 0);
283 printf("success: ref3\n");
290 static bool test_ref4(void)
292 void *root
, *p1
, *p2
, *ref
, *r1
;
294 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
296 root
= talloc_named_const(NULL
, 0, "root");
297 p1
= talloc_named_const(root
, 1, "p1");
298 talloc_named_const(p1
, 1, "x1");
299 talloc_named_const(p1
, 1, "x2");
300 talloc_named_const(p1
, 1, "x3");
301 p2
= talloc_named_const(p1
, 1, "p2");
303 r1
= talloc_named_const(root
, 1, "r1");
304 ref
= talloc_reference(r1
, p2
);
305 talloc_report_full(root
, stderr
);
307 CHECK_BLOCKS("ref4", p1
, 5);
308 CHECK_BLOCKS("ref4", p2
, 1);
309 CHECK_BLOCKS("ref4", ref
, 1);
310 CHECK_BLOCKS("ref4", r1
, 2);
312 fprintf(stderr
, "Freeing r1\n");
314 talloc_report_full(root
, stderr
);
316 CHECK_BLOCKS("ref4", p1
, 5);
317 CHECK_BLOCKS("ref4", p2
, 1);
319 fprintf(stderr
, "Freeing p2\n");
321 talloc_report_full(root
, stderr
);
323 CHECK_BLOCKS("ref4", p1
, 4);
325 fprintf(stderr
, "Freeing p1\n");
327 talloc_report_full(root
, stderr
);
329 CHECK_SIZE("ref4", root
, 0);
333 printf("success: ref4\n");
341 static bool test_unlink1(void)
343 void *root
, *p1
, *p2
, *ref
, *r1
;
345 printf("test: unlink\n# UNLINK\n");
347 root
= talloc_named_const(NULL
, 0, "root");
348 p1
= talloc_named_const(root
, 1, "p1");
349 talloc_named_const(p1
, 1, "x1");
350 talloc_named_const(p1
, 1, "x2");
351 talloc_named_const(p1
, 1, "x3");
352 p2
= talloc_named_const(p1
, 1, "p2");
354 r1
= talloc_named_const(p1
, 1, "r1");
355 ref
= talloc_reference(r1
, p2
);
356 talloc_report_full(root
, stderr
);
358 CHECK_BLOCKS("unlink", p1
, 7);
359 CHECK_BLOCKS("unlink", p2
, 1);
360 CHECK_BLOCKS("unlink", ref
, 1);
361 CHECK_BLOCKS("unlink", r1
, 2);
363 fprintf(stderr
, "Unreferencing r1\n");
364 talloc_unlink(r1
, p2
);
365 talloc_report_full(root
, stderr
);
367 CHECK_BLOCKS("unlink", p1
, 6);
368 CHECK_BLOCKS("unlink", p2
, 1);
369 CHECK_BLOCKS("unlink", r1
, 1);
371 fprintf(stderr
, "Freeing p1\n");
373 talloc_report_full(root
, stderr
);
375 CHECK_SIZE("unlink", root
, 0);
379 printf("success: unlink\n");
383 static int fail_destructor(void *ptr
)
389 miscellaneous tests to try to get a higher test coverage percentage
391 static bool test_misc(void)
398 printf("test: misc\n# MISCELLANEOUS\n");
400 root
= talloc_new(NULL
);
402 p1
= talloc_size(root
, 0x7fffffff);
403 torture_assert("misc", !p1
, "failed: large talloc allowed\n");
405 p1
= talloc_strdup(root
, "foo");
406 talloc_increase_ref_count(p1
);
407 talloc_increase_ref_count(p1
);
408 talloc_increase_ref_count(p1
);
409 CHECK_BLOCKS("misc", p1
, 1);
410 CHECK_BLOCKS("misc", root
, 2);
411 talloc_unlink(NULL
, p1
);
412 CHECK_BLOCKS("misc", p1
, 1);
413 CHECK_BLOCKS("misc", root
, 2);
414 talloc_unlink(NULL
, p1
);
415 CHECK_BLOCKS("misc", p1
, 1);
416 CHECK_BLOCKS("misc", root
, 2);
417 p2
= talloc_strdup(p1
, "foo");
418 torture_assert("misc", talloc_unlink(root
, p2
) == -1,
419 "failed: talloc_unlink() of non-reference context should return -1\n");
420 torture_assert("misc", talloc_unlink(p1
, p2
) == 0,
421 "failed: talloc_unlink() of parent should succeed\n");
422 talloc_unlink(NULL
, p1
);
423 CHECK_BLOCKS("misc", p1
, 1);
424 CHECK_BLOCKS("misc", root
, 2);
426 name
= talloc_set_name(p1
, "my name is %s", "foo");
427 torture_assert_str_equal("misc", talloc_get_name(p1
), "my name is foo",
428 "failed: wrong name after talloc_set_name(my name is foo)");
429 torture_assert_str_equal("misc", talloc_get_name(p1
), name
,
430 "failed: wrong name after talloc_set_name(my name is foo)");
431 CHECK_BLOCKS("misc", p1
, 2);
432 CHECK_BLOCKS("misc", root
, 3);
434 talloc_set_name_const(p1
, NULL
);
435 torture_assert_str_equal ("misc", talloc_get_name(p1
), "UNNAMED",
436 "failed: wrong name after talloc_set_name(NULL)");
437 CHECK_BLOCKS("misc", p1
, 2);
438 CHECK_BLOCKS("misc", root
, 3);
440 torture_assert("misc", talloc_free(NULL
) == -1,
441 "talloc_free(NULL) should give -1\n");
443 talloc_set_destructor(p1
, fail_destructor
);
444 torture_assert("misc", talloc_free(p1
) == -1,
445 "Failed destructor should cause talloc_free to fail\n");
446 talloc_set_destructor(p1
, NULL
);
448 talloc_report(root
, stderr
);
451 p2
= (char *)talloc_zero_size(p1
, 20);
452 torture_assert("misc", p2
[19] == 0, "Failed to give zero memory\n");
455 torture_assert("misc", talloc_strdup(root
, NULL
) == NULL
,
456 "failed: strdup on NULL should give NULL\n");
458 p2
= talloc_strndup(p1
, "foo", 2);
459 torture_assert("misc", strcmp("fo", p2
) == 0,
460 "strndup doesn't work\n");
461 p2
= talloc_asprintf_append_buffer(p2
, "o%c", 'd');
462 torture_assert("misc", strcmp("food", p2
) == 0,
463 "talloc_asprintf_append_buffer doesn't work\n");
464 CHECK_BLOCKS("misc", p2
, 1);
465 CHECK_BLOCKS("misc", p1
, 3);
467 p2
= talloc_asprintf_append_buffer(NULL
, "hello %s", "world");
468 torture_assert("misc", strcmp("hello world", p2
) == 0,
469 "talloc_asprintf_append_buffer doesn't work\n");
470 CHECK_BLOCKS("misc", p2
, 1);
471 CHECK_BLOCKS("misc", p1
, 3);
474 d
= talloc_array(p1
, double, 0x20000000);
475 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
477 d
= talloc_realloc(p1
, d
, double, 0x20000000);
478 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
481 CHECK_BLOCKS("misc", root
, 1);
483 p1
= talloc_named(root
, 100, "%d bytes", 100);
484 CHECK_BLOCKS("misc", p1
, 2);
485 CHECK_BLOCKS("misc", root
, 3);
486 talloc_unlink(root
, p1
);
488 p1
= talloc_init("%d bytes", 200);
489 p2
= talloc_asprintf(p1
, "my test '%s'", "string");
490 torture_assert_str_equal("misc", p2
, "my test 'string'",
491 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
492 CHECK_BLOCKS("misc", p1
, 3);
493 CHECK_SIZE("misc", p2
, 17);
494 CHECK_BLOCKS("misc", root
, 1);
495 talloc_unlink(NULL
, p1
);
497 p1
= talloc_named_const(root
, 10, "p1");
498 p2
= (char *)talloc_named_const(root
, 20, "p2");
499 (void)talloc_reference(p1
, p2
);
500 talloc_report_full(root
, stderr
);
501 talloc_unlink(root
, p2
);
502 talloc_report_full(root
, stderr
);
503 CHECK_BLOCKS("misc", p2
, 1);
504 CHECK_BLOCKS("misc", p1
, 2);
505 CHECK_BLOCKS("misc", root
, 3);
506 talloc_unlink(p1
, p2
);
507 talloc_unlink(root
, p1
);
509 p1
= talloc_named_const(root
, 10, "p1");
510 p2
= (char *)talloc_named_const(root
, 20, "p2");
511 (void)talloc_reference(NULL
, p2
);
512 talloc_report_full(root
, stderr
);
513 talloc_unlink(root
, p2
);
514 talloc_report_full(root
, stderr
);
515 CHECK_BLOCKS("misc", p2
, 1);
516 CHECK_BLOCKS("misc", p1
, 1);
517 CHECK_BLOCKS("misc", root
, 2);
518 talloc_unlink(NULL
, p2
);
519 talloc_unlink(root
, p1
);
521 /* Test that talloc_unlink is a no-op */
523 torture_assert("misc", talloc_unlink(root
, NULL
) == -1,
524 "failed: talloc_unlink(root, NULL) == -1\n");
526 talloc_report(root
, stderr
);
527 talloc_report(NULL
, stderr
);
529 CHECK_SIZE("misc", root
, 0);
533 CHECK_SIZE("misc", NULL
, 0);
535 talloc_enable_null_tracking_no_autofree();
536 talloc_enable_leak_report();
537 talloc_enable_leak_report_full();
539 printf("success: misc\n");
548 static bool test_realloc(void)
550 void *root
, *p1
, *p2
;
552 printf("test: realloc\n# REALLOC\n");
554 root
= talloc_new(NULL
);
556 p1
= talloc_size(root
, 10);
557 CHECK_SIZE("realloc", p1
, 10);
559 p1
= talloc_realloc_size(NULL
, p1
, 20);
560 CHECK_SIZE("realloc", p1
, 20);
564 p2
= talloc_realloc_size(p1
, NULL
, 30);
568 p2
= talloc_realloc_size(p1
, p2
, 40);
570 CHECK_SIZE("realloc", p2
, 40);
571 CHECK_SIZE("realloc", root
, 60);
572 CHECK_BLOCKS("realloc", p1
, 4);
574 p1
= talloc_realloc_size(NULL
, p1
, 20);
575 CHECK_SIZE("realloc", p1
, 60);
577 talloc_increase_ref_count(p2
);
578 torture_assert("realloc", talloc_realloc_size(NULL
, p2
, 5) == NULL
,
579 "failed: talloc_realloc() on a referenced pointer should fail\n");
580 CHECK_BLOCKS("realloc", p1
, 4);
582 talloc_realloc_size(NULL
, p2
, 0);
583 talloc_realloc_size(NULL
, p2
, 0);
584 CHECK_BLOCKS("realloc", p1
, 4);
585 talloc_realloc_size(p1
, p2
, 0);
586 CHECK_BLOCKS("realloc", p1
, 3);
588 torture_assert("realloc", talloc_realloc_size(NULL
, p1
, 0x7fffffff) == NULL
,
589 "failed: oversize talloc should fail\n");
591 talloc_realloc_size(NULL
, p1
, 0);
592 CHECK_BLOCKS("realloc", root
, 4);
593 talloc_realloc_size(root
, p1
, 0);
594 CHECK_BLOCKS("realloc", root
, 1);
596 CHECK_SIZE("realloc", root
, 0);
600 printf("success: realloc\n");
606 test realloc with a child
608 static bool test_realloc_child(void)
613 } *el2
, *el2_2
, *el2_3
, **el_list_save
;
616 struct el2
**list
, **list2
, **list3
;
619 printf("test: REALLOC WITH CHILD\n");
621 root
= talloc_new(NULL
);
623 el1
= talloc(root
, struct el1
);
624 el1
->list
= talloc(el1
, struct el2
*);
625 el1
->list
[0] = talloc(el1
->list
, struct el2
);
626 el1
->list
[0]->name
= talloc_strdup(el1
->list
[0], "testing");
628 el1
->list2
= talloc(el1
, struct el2
*);
629 el1
->list2
[0] = talloc(el1
->list2
, struct el2
);
630 el1
->list2
[0]->name
= talloc_strdup(el1
->list2
[0], "testing2");
632 el1
->list3
= talloc(el1
, struct el2
*);
633 el1
->list3
[0] = talloc(el1
->list3
, struct el2
);
634 el1
->list3
[0]->name
= talloc_strdup(el1
->list3
[0], "testing2");
636 el2
= talloc(el1
->list
, struct el2
);
637 CHECK_PARENT("el2", el2
, el1
->list
);
638 el2_2
= talloc(el1
->list2
, struct el2
);
639 CHECK_PARENT("el2", el2_2
, el1
->list2
);
640 el2_3
= talloc(el1
->list3
, struct el2
);
641 CHECK_PARENT("el2", el2_3
, el1
->list3
);
643 el_list_save
= el1
->list
;
644 el1
->list
= talloc_realloc(el1
, el1
->list
, struct el2
*, 100);
645 if (el1
->list
== el_list_save
) {
646 printf("failure: talloc_realloc didn't move pointer");
650 CHECK_PARENT("el1_after_realloc", el1
->list
, el1
);
651 el1
->list2
= talloc_realloc(el1
, el1
->list2
, struct el2
*, 200);
652 CHECK_PARENT("el1_after_realloc", el1
->list2
, el1
);
653 el1
->list3
= talloc_realloc(el1
, el1
->list3
, struct el2
*, 300);
654 CHECK_PARENT("el1_after_realloc", el1
->list3
, el1
);
656 CHECK_PARENT("el2", el2
, el1
->list
);
657 CHECK_PARENT("el2", el2_2
, el1
->list2
);
658 CHECK_PARENT("el2", el2_3
, el1
->list3
);
660 /* Finally check realloc with multiple children */
661 el1
= talloc_realloc(root
, el1
, struct el1
, 100);
662 CHECK_PARENT("el1->list", el1
->list
, el1
);
663 CHECK_PARENT("el1->list2", el1
->list2
, el1
);
664 CHECK_PARENT("el1->list3", el1
->list3
, el1
);
668 printf("success: REALLOC WITH CHILD\n");
675 static bool test_type(void)
686 printf("test: type\n# talloc type checking\n");
688 root
= talloc_new(NULL
);
690 el1
= talloc(root
, struct el1
);
694 torture_assert("type", talloc_get_type(el1
, struct el1
) == el1
,
695 "type check failed on el1\n");
696 torture_assert("type", talloc_get_type(el1
, struct el2
) == NULL
,
697 "type check failed on el1 with el2\n");
698 talloc_set_type(el1
, struct el2
);
699 torture_assert("type", talloc_get_type(el1
, struct el2
) == (struct el2
*)el1
,
700 "type set failed on el1 with el2\n");
704 printf("success: type\n");
711 static bool test_steal(void)
713 void *root
, *p1
, *p2
;
715 printf("test: steal\n# STEAL\n");
717 root
= talloc_new(NULL
);
719 p1
= talloc_array(root
, char, 10);
720 CHECK_SIZE("steal", p1
, 10);
722 p2
= talloc_realloc(root
, NULL
, char, 20);
723 CHECK_SIZE("steal", p1
, 10);
724 CHECK_SIZE("steal", root
, 30);
726 torture_assert("steal", talloc_steal(p1
, NULL
) == NULL
,
727 "failed: stealing NULL should give NULL\n");
729 torture_assert("steal", talloc_steal(p1
, p1
) == p1
,
730 "failed: stealing to ourselves is a nop\n");
731 CHECK_BLOCKS("steal", root
, 3);
732 CHECK_SIZE("steal", root
, 30);
734 talloc_steal(NULL
, p1
);
735 talloc_steal(NULL
, p2
);
736 CHECK_BLOCKS("steal", root
, 1);
737 CHECK_SIZE("steal", root
, 0);
740 talloc_steal(root
, p2
);
741 CHECK_BLOCKS("steal", root
, 2);
742 CHECK_SIZE("steal", root
, 20);
746 CHECK_BLOCKS("steal", root
, 1);
747 CHECK_SIZE("steal", root
, 0);
751 p1
= talloc_size(NULL
, 3);
752 talloc_report_full(NULL
, stderr
);
753 CHECK_SIZE("steal", NULL
, 3);
756 printf("success: steal\n");
763 static bool test_move(void)
771 printf("test: move\n# MOVE\n");
773 root
= talloc_new(NULL
);
775 t1
= talloc(root
, struct t_move
);
776 t2
= talloc(root
, struct t_move
);
777 t1
->p
= talloc_strdup(t1
, "foo");
778 t1
->x
= talloc(t1
, int);
781 t2
->p
= talloc_move(t2
, &t1
->p
);
782 t2
->x
= talloc_move(t2
, &t1
->x
);
783 torture_assert("move", t1
->p
== NULL
&& t1
->x
== NULL
&&
784 strcmp(t2
->p
, "foo") == 0 && *t2
->x
== 42,
785 "talloc move failed");
789 printf("success: move\n");
795 test talloc_realloc_fn
797 static bool test_realloc_fn(void)
801 printf("test: realloc_fn\n# talloc_realloc_fn\n");
803 root
= talloc_new(NULL
);
805 p1
= talloc_realloc_fn(root
, NULL
, 10);
806 CHECK_BLOCKS("realloc_fn", root
, 2);
807 CHECK_SIZE("realloc_fn", root
, 10);
808 p1
= talloc_realloc_fn(root
, p1
, 20);
809 CHECK_BLOCKS("realloc_fn", root
, 2);
810 CHECK_SIZE("realloc_fn", root
, 20);
811 p1
= talloc_realloc_fn(root
, p1
, 0);
812 CHECK_BLOCKS("realloc_fn", root
, 1);
813 CHECK_SIZE("realloc_fn", root
, 0);
817 printf("success: realloc_fn\n");
822 static bool test_unref_reparent(void)
824 void *root
, *p1
, *p2
, *c1
;
826 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
828 root
= talloc_named_const(NULL
, 0, "root");
829 p1
= talloc_named_const(root
, 1, "orig parent");
830 p2
= talloc_named_const(root
, 1, "parent by reference");
832 c1
= talloc_named_const(p1
, 1, "child");
833 talloc_reference(p2
, c1
);
835 CHECK_PARENT("unref_reparent", c1
, p1
);
839 CHECK_PARENT("unref_reparent", c1
, p2
);
841 talloc_unlink(p2
, c1
);
843 CHECK_SIZE("unref_reparent", root
, 1);
848 printf("success: unref_reparent\n");
853 measure the speed of talloc versus malloc
855 static bool test_speed(void)
857 void *ctx
= talloc_new(NULL
);
859 const int loop
= 1000;
863 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
865 tv
= private_timeval_current();
869 for (i
=0;i
<loop
;i
++) {
870 p1
= talloc_size(ctx
, loop
% 100);
871 p2
= talloc_strdup(p1
, "foo bar");
872 p3
= talloc_size(p1
, 300);
878 } while (private_timeval_elapsed(&tv
) < 5.0);
880 fprintf(stderr
, "talloc: %.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
884 ctx
= talloc_pool(NULL
, 1024);
886 tv
= private_timeval_current();
890 for (i
=0;i
<loop
;i
++) {
891 p1
= talloc_size(ctx
, loop
% 100);
892 p2
= talloc_strdup(p1
, "foo bar");
893 p3
= talloc_size(p1
, 300);
899 } while (private_timeval_elapsed(&tv
) < 5.0);
903 fprintf(stderr
, "talloc_pool: %.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
905 tv
= private_timeval_current();
909 for (i
=0;i
<loop
;i
++) {
910 p1
= malloc(loop
% 100);
911 p2
= strdup("foo bar");
918 } while (private_timeval_elapsed(&tv
) < 5.0);
919 fprintf(stderr
, "malloc: %.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
921 printf("success: speed\n");
926 static bool test_lifeless(void)
928 void *top
= talloc_new(NULL
);
929 char *parent
, *child
;
930 void *child_owner
= talloc_new(NULL
);
932 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
934 parent
= talloc_strdup(top
, "parent");
935 child
= talloc_strdup(parent
, "child");
936 (void)talloc_reference(child
, parent
);
937 (void)talloc_reference(child_owner
, child
);
938 talloc_report_full(top
, stderr
);
939 talloc_unlink(top
, parent
);
940 talloc_unlink(top
, child
);
941 talloc_report_full(top
, stderr
);
943 talloc_free(child_owner
);
946 printf("success: lifeless\n");
950 static int loop_destructor_count
;
952 static int test_loop_destructor(char *ptr
)
954 loop_destructor_count
++;
958 static bool test_loop(void)
960 void *top
= talloc_new(NULL
);
966 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
968 parent
= talloc_strdup(top
, "parent");
969 req1
= talloc(parent
, struct req1
);
970 req1
->req2
= talloc_strdup(req1
, "req2");
971 talloc_set_destructor(req1
->req2
, test_loop_destructor
);
972 req1
->req3
= talloc_strdup(req1
, "req3");
973 (void)talloc_reference(req1
->req3
, req1
);
974 talloc_report_full(top
, stderr
);
976 talloc_report_full(top
, stderr
);
977 talloc_report_full(NULL
, stderr
);
980 torture_assert("loop", loop_destructor_count
== 1,
981 "FAILED TO FIRE LOOP DESTRUCTOR\n");
982 loop_destructor_count
= 0;
984 printf("success: loop\n");
988 static int realloc_parent_destructor_count
;
990 static int test_realloc_parent_destructor(char *ptr
)
992 realloc_parent_destructor_count
++;
996 static bool test_realloc_on_destructor_parent(void)
998 void *top
= talloc_new(NULL
);
1000 char *a
, *b
, *C
, *D
;
1001 realloc_parent_destructor_count
= 0;
1003 printf("test: free_for_exit\n# TALLOC FREE FOR EXIT\n");
1005 parent
= talloc_strdup(top
, "parent");
1006 a
= talloc_strdup(parent
, "a");
1007 b
= talloc_strdup(a
, "b");
1008 C
= talloc_strdup(a
, "C");
1009 D
= talloc_strdup(b
, "D");
1010 talloc_set_destructor(D
, test_realloc_parent_destructor
);
1011 /* Capitalised ones have destructors.
1013 * parent --> a -> b -> D
1017 a
= talloc_realloc(parent
, a
, char, 2048);
1019 torture_assert("check talloc_realloc", a
!= NULL
, "talloc_realloc failed");
1021 talloc_set_destructor(C
, test_realloc_parent_destructor
);
1023 * parent --> a[2048] -> b -> D
1028 talloc_free(parent
);
1030 torture_assert("check destructor realloc_parent_destructor",
1031 realloc_parent_destructor_count
== 2,
1032 "FAILED TO FIRE free_for_exit_destructor\n");
1035 printf("success: free_for_exit\n");
1039 static int fail_destructor_str(char *ptr
)
1044 static bool test_free_parent_deny_child(void)
1046 void *top
= talloc_new(NULL
);
1051 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1053 level1
= talloc_strdup(top
, "level1");
1054 level2
= talloc_strdup(level1
, "level2");
1055 level3
= talloc_strdup(level2
, "level3");
1057 talloc_set_destructor(level3
, fail_destructor_str
);
1058 talloc_free(level1
);
1059 talloc_set_destructor(level3
, NULL
);
1061 CHECK_PARENT("free_parent_deny_child", level3
, top
);
1065 printf("success: free_parent_deny_child\n");
1074 static int reparenting_destructor(struct new_parent
*np
)
1076 talloc_set_destructor(np
, NULL
);
1077 (void)talloc_move(np
->new_parent
, &np
);
1081 static bool test_free_parent_reparent_child(void)
1083 void *top
= talloc_new(NULL
);
1085 char *alternate_level1
;
1087 struct new_parent
*level3
;
1089 printf("test: free_parent_reparent_child\n# "
1090 "TALLOC FREE PARENT REPARENT CHILD\n");
1092 level1
= talloc_strdup(top
, "level1");
1093 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1094 level2
= talloc_strdup(level1
, "level2");
1095 level3
= talloc(level2
, struct new_parent
);
1096 level3
->new_parent
= alternate_level1
;
1097 memset(level3
->val
, 'x', sizeof(level3
->val
));
1099 talloc_set_destructor(level3
, reparenting_destructor
);
1100 talloc_free(level1
);
1102 CHECK_PARENT("free_parent_reparent_child",
1103 level3
, alternate_level1
);
1107 printf("success: free_parent_reparent_child\n");
1111 static bool test_free_parent_reparent_child_in_pool(void)
1113 void *top
= talloc_new(NULL
);
1115 char *alternate_level1
;
1118 struct new_parent
*level3
;
1120 printf("test: free_parent_reparent_child_in_pool\n# "
1121 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1123 pool
= talloc_pool(top
, 1024);
1124 level1
= talloc_strdup(pool
, "level1");
1125 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1126 level2
= talloc_strdup(level1
, "level2");
1127 level3
= talloc(level2
, struct new_parent
);
1128 level3
->new_parent
= alternate_level1
;
1129 memset(level3
->val
, 'x', sizeof(level3
->val
));
1131 talloc_set_destructor(level3
, reparenting_destructor
);
1132 talloc_free(level1
);
1133 talloc_set_destructor(level3
, NULL
);
1135 CHECK_PARENT("free_parent_reparent_child_in_pool",
1136 level3
, alternate_level1
);
1138 /* Even freeing alternate_level1 should leave pool alone. */
1139 talloc_free(alternate_level1
);
1142 printf("success: free_parent_reparent_child_in_pool\n");
1147 static bool test_talloc_ptrtype(void)
1149 void *top
= talloc_new(NULL
);
1153 } *s1
, *s2
, **s3
, ***s4
;
1154 const char *location1
;
1155 const char *location2
;
1156 const char *location3
;
1157 const char *location4
;
1159 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1161 s1
= talloc_ptrtype(top
, s1
);location1
= __location__
;
1163 if (talloc_get_size(s1
) != sizeof(struct struct1
)) {
1164 printf("failure: ptrtype [\n"
1165 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1166 "]\n", (unsigned long)talloc_get_size(s1
),
1167 (unsigned long)sizeof(struct struct1
));
1171 if (strcmp(location1
, talloc_get_name(s1
)) != 0) {
1172 printf("failure: ptrtype [\n"
1173 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1174 talloc_get_name(s1
), location1
);
1178 s2
= talloc_array_ptrtype(top
, s2
, 10);location2
= __location__
;
1180 if (talloc_get_size(s2
) != (sizeof(struct struct1
) * 10)) {
1181 printf("failure: ptrtype [\n"
1182 "talloc_array_ptrtype() allocated the wrong size "
1183 "%lu (should be %lu)\n]\n",
1184 (unsigned long)talloc_get_size(s2
),
1185 (unsigned long)(sizeof(struct struct1
)*10));
1189 if (strcmp(location2
, talloc_get_name(s2
)) != 0) {
1190 printf("failure: ptrtype [\n"
1191 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1192 talloc_get_name(s2
), location2
);
1196 s3
= talloc_array_ptrtype(top
, s3
, 10);location3
= __location__
;
1198 if (talloc_get_size(s3
) != (sizeof(struct struct1
*) * 10)) {
1199 printf("failure: ptrtype [\n"
1200 "talloc_array_ptrtype() allocated the wrong size "
1201 "%lu (should be %lu)\n]\n",
1202 (unsigned long)talloc_get_size(s3
),
1203 (unsigned long)(sizeof(struct struct1
*)*10));
1207 torture_assert_str_equal("ptrtype", location3
, talloc_get_name(s3
),
1208 "talloc_array_ptrtype() sets the wrong name");
1210 s4
= talloc_array_ptrtype(top
, s4
, 10);location4
= __location__
;
1212 if (talloc_get_size(s4
) != (sizeof(struct struct1
**) * 10)) {
1213 printf("failure: ptrtype [\n"
1214 "talloc_array_ptrtype() allocated the wrong size "
1215 "%lu (should be %lu)\n]\n",
1216 (unsigned long)talloc_get_size(s4
),
1217 (unsigned long)(sizeof(struct struct1
**)*10));
1221 torture_assert_str_equal("ptrtype", location4
, talloc_get_name(s4
),
1222 "talloc_array_ptrtype() sets the wrong name");
1226 printf("success: ptrtype\n");
1230 static int _test_talloc_free_in_destructor(void **ptr
)
1236 static bool test_talloc_free_in_destructor(void)
1245 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1247 level0
= talloc_new(NULL
);
1248 level1
= talloc_new(level0
);
1249 level2
= talloc_new(level1
);
1250 level3
= talloc_new(level2
);
1251 level4
= talloc_new(level3
);
1252 level5
= talloc(level4
, void *);
1255 (void)talloc_reference(level0
, level3
);
1256 (void)talloc_reference(level3
, level3
);
1257 (void)talloc_reference(level5
, level3
);
1259 talloc_set_destructor(level5
, _test_talloc_free_in_destructor
);
1261 talloc_free(level1
);
1263 talloc_free(level0
);
1265 printf("success: free_in_destructor\n");
1269 static bool test_autofree(void)
1271 #if _SAMBA_BUILD_ < 4
1272 /* autofree test would kill smbtorture */
1274 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1276 p
= talloc_autofree_context();
1279 p
= talloc_autofree_context();
1282 printf("success: autofree\n");
1287 static bool test_pool(void)
1290 void *p1
, *p2
, *p3
, *p4
;
1293 pool
= talloc_pool(NULL
, 1024);
1295 p1
= talloc_size(pool
, 80);
1296 memset(p1
, 0x11, talloc_get_size(p1
));
1297 p2
= talloc_size(pool
, 20);
1298 memset(p2
, 0x11, talloc_get_size(p2
));
1299 p3
= talloc_size(p1
, 50);
1300 memset(p3
, 0x11, talloc_get_size(p3
));
1301 p4
= talloc_size(p3
, 1000);
1302 memset(p4
, 0x11, talloc_get_size(p4
));
1304 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1305 p2_2
= talloc_realloc_size(pool
, p2
, 20+1);
1306 torture_assert("pool realloc 20+1", p2_2
== p2
, "failed: pointer changed");
1307 memset(p2
, 0x11, talloc_get_size(p2
));
1308 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1309 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1310 memset(p2
, 0x11, talloc_get_size(p2
));
1311 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1312 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1313 memset(p2
, 0x11, talloc_get_size(p2
));
1317 /* this should reclaim the memory of p4 and p3 */
1318 p2_2
= talloc_realloc_size(pool
, p2
, 400);
1319 torture_assert("pool realloc 400", p2_2
== p2
, "failed: pointer changed");
1320 memset(p2
, 0x11, talloc_get_size(p2
));
1324 /* this should reclaim the memory of p1 */
1325 p2_2
= talloc_realloc_size(pool
, p2
, 800);
1326 torture_assert("pool realloc 800", p2_2
== p1
, "failed: pointer not changed");
1328 memset(p2
, 0x11, talloc_get_size(p2
));
1330 /* this should do a malloc */
1331 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1332 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1334 memset(p2
, 0x11, talloc_get_size(p2
));
1336 /* this should reclaim the memory from the pool */
1337 p3
= talloc_size(pool
, 80);
1338 torture_assert("pool alloc 80", p3
== p1
, "failed: pointer changed");
1339 memset(p3
, 0x11, talloc_get_size(p3
));
1344 p1
= talloc_size(pool
, 80);
1345 memset(p1
, 0x11, talloc_get_size(p1
));
1346 p2
= talloc_size(pool
, 20);
1347 memset(p2
, 0x11, talloc_get_size(p2
));
1351 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1352 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1353 memset(p2
, 0x11, talloc_get_size(p2
));
1354 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1355 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1356 memset(p2
, 0x11, talloc_get_size(p2
));
1358 /* this should do a malloc */
1359 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1360 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1362 memset(p2
, 0x11, talloc_get_size(p2
));
1364 /* this should reclaim the memory from the pool */
1365 p3
= talloc_size(pool
, 800);
1366 torture_assert("pool alloc 800", p3
== p1
, "failed: pointer changed");
1367 memset(p3
, 0x11, talloc_get_size(p3
));
1369 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1376 static bool test_pool_steal(void)
1385 root
= talloc_new(NULL
);
1386 pool
= talloc_pool(root
, 1024);
1388 p1
= talloc_size(pool
, 4 * 16);
1389 torture_assert("pool allocate 4 * 16", p1
!= NULL
, "failed ");
1390 memset(p1
, 0x11, talloc_get_size(p1
));
1391 p2
= talloc_size(pool
, 4 * 16);
1392 torture_assert("pool allocate 4 * 16", p2
> p1
, "failed: !(p2 > p1) ");
1393 memset(p2
, 0x11, talloc_get_size(p2
));
1395 ofs1
= PTR_DIFF(p2
, p1
);
1396 hdr
= ofs1
- talloc_get_size(p1
);
1398 talloc_steal(root
, p1
);
1399 talloc_steal(root
, p2
);
1405 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1406 p1_2
= talloc_realloc_size(root
, p1
, 5 * 16);
1407 torture_assert("pool realloc 5 * 16", p1_2
> p2
, "failed: pointer not changed");
1408 memset(p1_2
, 0x11, talloc_get_size(p1_2
));
1409 ofs1
= PTR_DIFF(p1_2
, p2
);
1410 ofs2
= talloc_get_size(p2
) + hdr
;
1412 torture_assert("pool realloc ", ofs1
== ofs2
, "failed: pointer offset unexpected");
1414 p2_2
= talloc_realloc_size(root
, p2
, 3 * 16);
1415 torture_assert("pool realloc 5 * 16", p2_2
== p2
, "failed: pointer changed");
1416 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1417 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1423 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1424 /* now we should reclaim the full pool */
1425 p2_2
= talloc_realloc_size(root
, p2
, 8 * 16);
1426 torture_assert("pool realloc 8 * 16", p2_2
== p1
, "failed: pointer not expected");
1428 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1430 /* now we malloc and free the full pool space */
1431 p2_2
= talloc_realloc_size(root
, p2
, 2 * 1024);
1432 torture_assert("pool realloc 2 * 1024", p2_2
!= p1
, "failed: pointer not expected");
1433 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1435 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1444 static bool test_pool_nest(void)
1447 void *e
= talloc_new(NULL
);
1449 p1
= talloc_pool(NULL
, 1024);
1450 torture_assert("talloc_pool", p1
!= NULL
, "failed");
1452 p2
= talloc_pool(p1
, 500);
1453 torture_assert("talloc_pool", p2
!= NULL
, "failed");
1455 p3
= talloc_size(p2
, 10);
1457 talloc_steal(e
, p3
);
1474 static bool test_pooled_object(void)
1477 const char *s1
= "hello";
1478 const char *s2
= "world";
1479 const char *s3
= "";
1481 p
= talloc_pooled_object(NULL
, struct pooled
, 3,
1482 strlen(s1
)+strlen(s2
)+strlen(s3
)+3);
1484 if (talloc_get_size(p
) != sizeof(struct pooled
)) {
1488 p
->s1
= talloc_strdup(p
, s1
);
1491 p
->s1
= talloc_strdup(p
, s2
);
1494 p
->s1
= talloc_strdup(p
, s1
);
1495 p
->s2
= talloc_strdup(p
, s2
);
1496 p
->s3
= talloc_strdup(p
, s3
);
1502 static bool test_free_ref_null_context(void)
1507 talloc_disable_null_tracking();
1508 p1
= talloc_new(NULL
);
1509 p2
= talloc_new(NULL
);
1511 p3
= talloc_reference(p2
, p1
);
1512 torture_assert("reference", p3
== p1
, "failed: reference on null");
1514 ret
= talloc_free(p1
);
1515 torture_assert("ref free with null parent", ret
== 0, "failed: free with null parent");
1518 talloc_enable_null_tracking_no_autofree();
1519 p1
= talloc_new(NULL
);
1520 p2
= talloc_new(NULL
);
1522 p3
= talloc_reference(p2
, p1
);
1523 torture_assert("reference", p3
== p1
, "failed: reference on null");
1525 ret
= talloc_free(p1
);
1526 torture_assert("ref free with null tracked parent", ret
== 0, "failed: free with null parent");
1532 static bool test_rusty(void)
1537 talloc_enable_null_tracking();
1538 root
= talloc_new(NULL
);
1539 p1
= talloc_strdup(root
, "foo");
1540 talloc_increase_ref_count(p1
);
1541 talloc_report_full(root
, stdout
);
1543 CHECK_BLOCKS("null_context", NULL
, 2);
1547 static bool test_free_children(void)
1551 const char *name
, *name2
;
1553 talloc_enable_null_tracking();
1554 root
= talloc_new(NULL
);
1555 p1
= talloc_strdup(root
, "foo1");
1556 p2
= talloc_strdup(p1
, "foo2");
1559 talloc_set_name(p1
, "%s", "testname");
1560 talloc_free_children(p1
);
1561 /* check its still a valid talloc ptr */
1562 talloc_get_size(talloc_get_name(p1
));
1563 if (strcmp(talloc_get_name(p1
), "testname") != 0) {
1567 talloc_set_name(p1
, "%s", "testname");
1568 name
= talloc_get_name(p1
);
1569 talloc_free_children(p1
);
1570 /* check its still a valid talloc ptr */
1571 talloc_get_size(talloc_get_name(p1
));
1572 torture_assert("name", name
== talloc_get_name(p1
), "name ptr changed");
1573 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname") == 0,
1575 CHECK_BLOCKS("name1", p1
, 2);
1577 /* note that this does not free the old child name */
1578 talloc_set_name_const(p1
, "testname2");
1579 name2
= talloc_get_name(p1
);
1581 talloc_free_children(p1
);
1583 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname2") == 0,
1585 CHECK_BLOCKS("name1", p1
, 1);
1587 talloc_report_full(root
, stdout
);
1592 static bool test_memlimit(void)
1595 char *l1
, *l2
, *l3
, *l4
, *l5
, *t
;
1599 printf("test: memlimit\n# MEMORY LIMITS\n");
1601 printf("==== talloc_new(NULL)\n");
1602 root
= talloc_new(NULL
);
1604 talloc_report_full(root
, stdout
);
1606 printf("==== talloc_size(root, 2048)\n");
1607 l1
= talloc_size(root
, 2048);
1608 torture_assert("memlimit", l1
!= NULL
,
1609 "failed: alloc should not fail due to memory limit\n");
1611 talloc_report_full(root
, stdout
);
1613 printf("==== talloc_free(l1)\n");
1616 talloc_report_full(root
, stdout
);
1618 printf("==== talloc_strdup(root, level 1)\n");
1619 l1
= talloc_strdup(root
, "level 1");
1620 torture_assert("memlimit", l1
!= NULL
,
1621 "failed: alloc should not fail due to memory limit\n");
1623 talloc_report_full(root
, stdout
);
1625 printf("==== talloc_set_memlimit(l1, 2048)\n");
1626 torture_assert("memlimit", talloc_set_memlimit(l1
, 2048) == 0,
1627 "failed: setting memlimit should never fail\n");
1629 talloc_report_full(root
, stdout
);
1631 printf("==== talloc_size(root, 2048)\n");
1632 l2
= talloc_size(l1
, 2048);
1633 torture_assert("memlimit", l2
== NULL
,
1634 "failed: alloc should fail due to memory limit\n");
1636 talloc_report_full(root
, stdout
);
1638 printf("==== talloc_strdup(l1, level 2)\n");
1639 l2
= talloc_strdup(l1
, "level 2");
1640 torture_assert("memlimit", l2
!= NULL
,
1641 "failed: alloc should not fail due to memory limit\n");
1643 talloc_report_full(root
, stdout
);
1645 printf("==== talloc_free(l2)\n");
1648 talloc_report_full(root
, stdout
);
1650 printf("==== talloc_size(NULL, 2048)\n");
1651 l2
= talloc_size(NULL
, 2048);
1653 talloc_report_full(root
, stdout
);
1655 printf("==== talloc_steal(l1, l2)\n");
1656 talloc_steal(l1
, l2
);
1658 talloc_report_full(root
, stdout
);
1660 printf("==== talloc_strdup(l2, level 3)\n");
1661 l3
= talloc_strdup(l2
, "level 3");
1662 torture_assert("memlimit", l3
== NULL
,
1663 "failed: alloc should fail due to memory limit\n");
1665 talloc_report_full(root
, stdout
);
1667 printf("==== talloc_free(l2)\n");
1670 talloc_report_full(root
, stdout
);
1672 printf("==== talloc_strdup(NULL, level 2)\n");
1673 l2
= talloc_strdup(NULL
, "level 2");
1674 talloc_steal(l1
, l2
);
1676 talloc_report_full(root
, stdout
);
1678 printf("==== talloc_strdup(l2, level 3)\n");
1679 l3
= talloc_strdup(l2
, "level 3");
1680 torture_assert("memlimit", l3
!= NULL
,
1681 "failed: alloc should not fail due to memory limit\n");
1683 talloc_report_full(root
, stdout
);
1685 printf("==== talloc_set_memlimit(l3, 1024)\n");
1686 torture_assert("memlimit", talloc_set_memlimit(l3
, 1024) == 0,
1687 "failed: setting memlimit should never fail\n");
1689 talloc_report_full(root
, stdout
);
1691 printf("==== talloc_strdup(l3, level 4)\n");
1692 l4
= talloc_strdup(l3
, "level 4");
1693 torture_assert("memlimit", l4
!= NULL
,
1694 "failed: alloc should not fail due to memory limit\n");
1696 talloc_report_full(root
, stdout
);
1698 printf("==== talloc_set_memlimit(l4, 512)\n");
1699 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1700 "failed: setting memlimit should never fail\n");
1702 talloc_report_full(root
, stdout
);
1704 printf("==== talloc_strdup(l4, level 5)\n");
1705 l5
= talloc_strdup(l4
, "level 5");
1706 torture_assert("memlimit", l5
!= NULL
,
1707 "failed: alloc should not fail due to memory limit\n");
1709 talloc_report_full(root
, stdout
);
1711 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1712 t
= talloc_realloc(NULL
, l5
, char, 600);
1713 torture_assert("memlimit", t
== NULL
,
1714 "failed: alloc should fail due to memory limit\n");
1716 talloc_report_full(root
, stdout
);
1718 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1719 l5
= talloc_realloc(NULL
, l5
, char, 5);
1720 torture_assert("memlimit", l5
!= NULL
,
1721 "failed: alloc should not fail due to memory limit\n");
1723 talloc_report_full(root
, stdout
);
1725 printf("==== talloc_strdup(l3, level 4)\n");
1726 l4
= talloc_strdup(l3
, "level 4");
1727 torture_assert("memlimit", l4
!= NULL
,
1728 "failed: alloc should not fail due to memory limit\n");
1730 talloc_report_full(root
, stdout
);
1732 printf("==== talloc_set_memlimit(l4, 512)\n");
1733 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1734 "failed: setting memlimit should never fail\n");
1736 talloc_report_full(root
, stdout
);
1738 printf("==== talloc_strdup(l4, level 5)\n");
1739 l5
= talloc_strdup(l4
, "level 5");
1740 torture_assert("memlimit", l5
!= NULL
,
1741 "failed: alloc should not fail due to memory limit\n");
1743 talloc_report_full(root
, stdout
);
1745 printf("==== Make new temp context and steal l5\n");
1746 t
= talloc_new(root
);
1747 talloc_steal(t
, l5
);
1749 talloc_report_full(root
, stdout
);
1751 printf("==== talloc_size(t, 2048)\n");
1752 l1
= talloc_size(t
, 2048);
1753 torture_assert("memlimit", l1
!= NULL
,
1754 "failed: alloc should not fail due to memory limit\n");
1756 talloc_report_full(root
, stdout
);
1759 /* Test memlimits with pools. */
1760 pool
= talloc_pool(NULL
, 10*1024);
1761 torture_assert("memlimit", pool
!= NULL
,
1762 "failed: alloc should not fail due to memory limit\n");
1763 talloc_set_memlimit(pool
, 10*1024);
1764 for (i
= 0; i
< 9; i
++) {
1765 l1
= talloc_size(pool
, 1024);
1766 torture_assert("memlimit", l1
!= NULL
,
1767 "failed: alloc should not fail due to memory limit\n");
1769 /* The next alloc should fail. */
1770 l2
= talloc_size(pool
, 1024);
1771 torture_assert("memlimit", l2
== NULL
,
1772 "failed: alloc should fail due to memory limit\n");
1774 /* Moving one of the children shouldn't change the limit,
1775 as it's still inside the pool. */
1776 root
= talloc_new(NULL
);
1777 talloc_steal(root
, l1
);
1778 l2
= talloc_size(pool
, 1024);
1779 torture_assert("memlimit", l2
== NULL
,
1780 "failed: alloc should fail due to memory limit\n");
1784 printf("success: memlimit\n");
1791 #define NUM_THREADS 100
1793 /* Sync variables. */
1794 static pthread_mutex_t mtx
= PTHREAD_MUTEX_INITIALIZER
;
1795 static pthread_cond_t condvar
= PTHREAD_COND_INITIALIZER
;
1796 static void *intermediate_ptr
;
1799 static void *thread_fn(void *arg
)
1802 const char *ctx_name
= (const char *)arg
;
1803 void *sub_ctx
= NULL
;
1805 * Do stuff that creates a new talloc hierarchy in
1808 void *top_ctx
= talloc_named_const(NULL
, 0, "top");
1809 if (top_ctx
== NULL
) {
1812 sub_ctx
= talloc_named_const(top_ctx
, 100, ctx_name
);
1813 if (sub_ctx
== NULL
) {
1818 * Now transfer a pointer from our hierarchy
1819 * onto the intermediate ptr.
1821 ret
= pthread_mutex_lock(&mtx
);
1823 talloc_free(top_ctx
);
1826 /* Wait for intermediate_ptr to be free. */
1827 while (intermediate_ptr
!= NULL
) {
1828 ret
= pthread_cond_wait(&condvar
, &mtx
);
1830 talloc_free(top_ctx
);
1831 ret
= pthread_mutex_unlock(&mtx
);
1837 /* and move our memory onto it from our toplevel hierarchy. */
1838 intermediate_ptr
= talloc_move(NULL
, &sub_ctx
);
1840 /* Tell the main thread it's ready for pickup. */
1841 pthread_cond_broadcast(&condvar
);
1842 ret
= pthread_mutex_unlock(&mtx
);
1845 talloc_free(top_ctx
);
1850 static bool test_pthread_talloc_passing(void)
1854 char str_array
[NUM_THREADS
][20];
1855 pthread_t thread_id
;
1859 * Important ! Null tracking breaks threaded talloc.
1860 * It *must* be turned off.
1862 talloc_disable_null_tracking();
1864 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1866 /* Main thread toplevel context. */
1867 mem_ctx
= talloc_named_const(NULL
, 0, "toplevel");
1868 if (mem_ctx
== NULL
) {
1869 printf("failed to create toplevel context\n");
1874 * Spin off NUM_THREADS threads.
1875 * They will use their own toplevel contexts.
1877 for (i
= 0; i
< NUM_THREADS
; i
++) {
1878 ret
= snprintf(str_array
[i
],
1883 printf("snprintf %d failed\n", i
);
1886 ret
= pthread_create(&thread_id
,
1891 printf("failed to create thread %d (%d)\n", i
, ret
);
1896 printf("Created %d threads\n", NUM_THREADS
);
1898 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1899 for (i
= 0; i
< NUM_THREADS
; i
++) {
1900 ret
= pthread_mutex_lock(&mtx
);
1902 printf("pthread_mutex_lock %d failed (%d)\n", i
, ret
);
1903 talloc_free(mem_ctx
);
1907 /* Wait for intermediate_ptr to have our data. */
1908 while (intermediate_ptr
== NULL
) {
1909 ret
= pthread_cond_wait(&condvar
, &mtx
);
1911 printf("pthread_cond_wait %d failed (%d)\n", i
,
1913 talloc_free(mem_ctx
);
1914 ret
= pthread_mutex_unlock(&mtx
);
1919 /* and move it onto our toplevel hierarchy. */
1920 (void)talloc_move(mem_ctx
, &intermediate_ptr
);
1922 /* Tell the sub-threads we're ready for another. */
1923 pthread_cond_broadcast(&condvar
);
1924 ret
= pthread_mutex_unlock(&mtx
);
1928 CHECK_SIZE("pthread_talloc_passing", mem_ctx
, NUM_THREADS
* 100);
1930 /* Dump the hierarchy. */
1931 talloc_report(mem_ctx
, stdout
);
1933 talloc_free(mem_ctx
);
1934 printf("success: pthread_talloc_passing\n");
1939 static void test_magic_protection_abort(const char *reason
)
1941 /* exit with errcode 42 to communicate successful test to the parent process */
1942 if (strcmp(reason
, "Bad talloc magic value - unknown value") == 0) {
1945 printf("talloc aborted for an unexpected reason\n");
1949 static int test_magic_protection_destructor(int *ptr
)
1951 _exit(404); /* Not 42 */
1954 static bool test_magic_protection(void)
1956 void *pool
= talloc_pool(NULL
, 1024);
1961 printf("test: magic_protection\n");
1962 p1
= talloc(pool
, int);
1963 p2
= talloc(pool
, int);
1965 /* To avoid complaints from the compiler assign values to the p1 & p2. */
1971 talloc_set_abort_fn(test_magic_protection_abort
);
1972 talloc_set_destructor(p2
, test_magic_protection_destructor
);
1975 * Simulate a security attack
1976 * by triggering a buffer overflow in memset to overwrite the
1977 * constructor in the next pool chunk.
1979 * Real attacks would attempt to set a real destructor.
1981 memset(p1
, '\0', 32);
1983 /* Then the attack takes effect when the memory's freed. */
1986 /* Never reached. Make compilers happy */
1990 while (wait(&exit_status
) != pid
);
1992 if (!WIFEXITED(exit_status
)) {
1993 printf("Child exited through unexpected abnormal means\n");
1996 if (WEXITSTATUS(exit_status
) != 42) {
1997 printf("Child exited with wrong exit status\n");
2000 if (WIFSIGNALED(exit_status
)) {
2001 printf("Child recieved unexpected signal\n");
2005 printf("success: magic_protection\n");
2009 static void test_reset(void)
2011 talloc_set_log_fn(test_log_stdout
);
2013 talloc_disable_null_tracking();
2014 talloc_enable_null_tracking_no_autofree();
2017 bool torture_local_talloc(struct torture_context
*tctx
)
2024 ret
&= test_pooled_object();
2026 ret
&= test_pool_nest();
2036 ret
&= test_unlink1();
2040 ret
&= test_realloc();
2042 ret
&= test_realloc_child();
2044 ret
&= test_steal();
2048 ret
&= test_unref_reparent();
2050 ret
&= test_realloc_fn();
2054 ret
&= test_lifeless();
2058 ret
&= test_free_parent_deny_child();
2060 ret
&= test_realloc_on_destructor_parent();
2062 ret
&= test_free_parent_reparent_child();
2064 ret
&= test_free_parent_reparent_child_in_pool();
2066 ret
&= test_talloc_ptrtype();
2068 ret
&= test_talloc_free_in_destructor();
2072 ret
&= test_pool_steal();
2074 ret
&= test_free_ref_null_context();
2076 ret
&= test_rusty();
2078 ret
&= test_free_children();
2080 ret
&= test_memlimit();
2083 ret
&= test_pthread_talloc_passing();
2089 ret
&= test_speed();
2092 ret
&= test_autofree();
2094 ret
&= test_magic_protection();
2097 talloc_disable_null_tracking();