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) { /* OK, both NULL == equal */ \
67 } else if (arg1 == NULL || arg2 == NULL) { \
69 } else if (strcmp(arg1, arg2)) { \
70 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
71 test, __location__, arg1, arg2, desc); \
75 #define CHECK_SIZE(test, ptr, tsize) do { \
76 if (talloc_total_size(ptr) != (tsize)) { \
77 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
78 test, __location__, #ptr, \
79 (unsigned)talloc_total_size(ptr), \
81 talloc_report_full(ptr, stdout); \
86 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
87 if (talloc_total_blocks(ptr) != (tblocks)) { \
88 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
89 test, __location__, #ptr, \
90 (unsigned)talloc_total_blocks(ptr), \
92 talloc_report_full(ptr, stdout); \
97 #define CHECK_PARENT(test, ptr, parent) do { \
98 if (talloc_parent(ptr) != (parent)) { \
99 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
100 test, __location__, #ptr, \
101 talloc_parent(ptr), \
103 talloc_report_full(ptr, stdout); \
104 talloc_report_full(parent, stdout); \
105 talloc_report_full(NULL, stdout); \
110 static unsigned int test_abort_count
;
113 static void test_abort_fn(const char *reason
)
115 printf("# test_abort_fn(%s)\n", reason
);
119 static void test_abort_start(void)
121 test_abort_count
= 0;
122 talloc_set_abort_fn(test_abort_fn
);
126 static void test_abort_stop(void)
128 test_abort_count
= 0;
129 talloc_set_abort_fn(NULL
);
132 static void test_log_stdout(const char *message
)
134 fprintf(stdout
, "%s", message
);
140 static bool test_ref1(void)
142 void *root
, *p1
, *p2
, *ref
, *r1
;
144 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
146 root
= talloc_named_const(NULL
, 0, "root");
147 p1
= talloc_named_const(root
, 1, "p1");
148 p2
= talloc_named_const(p1
, 1, "p2");
149 talloc_named_const(p1
, 1, "x1");
150 talloc_named_const(p1
, 2, "x2");
151 talloc_named_const(p1
, 3, "x3");
153 r1
= talloc_named_const(root
, 1, "r1");
154 ref
= talloc_reference(r1
, p2
);
155 talloc_report_full(root
, stderr
);
157 CHECK_BLOCKS("ref1", p1
, 5);
158 CHECK_BLOCKS("ref1", p2
, 1);
159 CHECK_BLOCKS("ref1", ref
, 1);
160 CHECK_BLOCKS("ref1", r1
, 2);
162 fprintf(stderr
, "Freeing p2\n");
163 talloc_unlink(r1
, p2
);
164 talloc_report_full(root
, stderr
);
166 CHECK_BLOCKS("ref1", p1
, 5);
167 CHECK_BLOCKS("ref1", p2
, 1);
168 CHECK_BLOCKS("ref1", r1
, 1);
170 fprintf(stderr
, "Freeing p1\n");
172 talloc_report_full(root
, stderr
);
174 CHECK_BLOCKS("ref1", r1
, 1);
176 fprintf(stderr
, "Freeing r1\n");
178 talloc_report_full(NULL
, stderr
);
180 fprintf(stderr
, "Testing NULL\n");
181 if (talloc_reference(root
, NULL
)) {
185 CHECK_BLOCKS("ref1", root
, 1);
187 CHECK_SIZE("ref1", root
, 0);
190 printf("success: ref1\n");
197 static bool test_ref2(void)
199 void *root
, *p1
, *p2
, *ref
, *r1
;
201 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
202 root
= talloc_named_const(NULL
, 0, "root");
203 p1
= talloc_named_const(root
, 1, "p1");
204 talloc_named_const(p1
, 1, "x1");
205 talloc_named_const(p1
, 1, "x2");
206 talloc_named_const(p1
, 1, "x3");
207 p2
= talloc_named_const(p1
, 1, "p2");
209 r1
= talloc_named_const(root
, 1, "r1");
210 ref
= talloc_reference(r1
, p2
);
211 talloc_report_full(root
, stderr
);
213 CHECK_BLOCKS("ref2", p1
, 5);
214 CHECK_BLOCKS("ref2", p2
, 1);
215 CHECK_BLOCKS("ref2", r1
, 2);
217 fprintf(stderr
, "Freeing ref\n");
218 talloc_unlink(r1
, ref
);
219 talloc_report_full(root
, stderr
);
221 CHECK_BLOCKS("ref2", p1
, 5);
222 CHECK_BLOCKS("ref2", p2
, 1);
223 CHECK_BLOCKS("ref2", r1
, 1);
225 fprintf(stderr
, "Freeing p2\n");
227 talloc_report_full(root
, stderr
);
229 CHECK_BLOCKS("ref2", p1
, 4);
230 CHECK_BLOCKS("ref2", r1
, 1);
232 fprintf(stderr
, "Freeing p1\n");
234 talloc_report_full(root
, stderr
);
236 CHECK_BLOCKS("ref2", r1
, 1);
238 fprintf(stderr
, "Freeing r1\n");
240 talloc_report_full(root
, stderr
);
242 CHECK_SIZE("ref2", root
, 0);
245 printf("success: ref2\n");
252 static bool test_ref3(void)
254 void *root
, *p1
, *p2
, *ref
, *r1
;
256 printf("test: ref3\n# PARENT REFERENCE FREE\n");
258 root
= talloc_named_const(NULL
, 0, "root");
259 p1
= talloc_named_const(root
, 1, "p1");
260 p2
= talloc_named_const(root
, 1, "p2");
261 r1
= talloc_named_const(p1
, 1, "r1");
262 ref
= talloc_reference(p2
, r1
);
263 talloc_report_full(root
, stderr
);
265 CHECK_BLOCKS("ref3", p1
, 2);
266 CHECK_BLOCKS("ref3", p2
, 2);
267 CHECK_BLOCKS("ref3", r1
, 1);
268 CHECK_BLOCKS("ref3", ref
, 1);
270 fprintf(stderr
, "Freeing p1\n");
272 talloc_report_full(root
, stderr
);
274 CHECK_BLOCKS("ref3", p2
, 2);
275 CHECK_BLOCKS("ref3", r1
, 1);
277 fprintf(stderr
, "Freeing p2\n");
279 talloc_report_full(root
, stderr
);
281 CHECK_SIZE("ref3", root
, 0);
285 printf("success: ref3\n");
292 static bool test_ref4(void)
294 void *root
, *p1
, *p2
, *ref
, *r1
;
296 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
298 root
= talloc_named_const(NULL
, 0, "root");
299 p1
= talloc_named_const(root
, 1, "p1");
300 talloc_named_const(p1
, 1, "x1");
301 talloc_named_const(p1
, 1, "x2");
302 talloc_named_const(p1
, 1, "x3");
303 p2
= talloc_named_const(p1
, 1, "p2");
305 r1
= talloc_named_const(root
, 1, "r1");
306 ref
= talloc_reference(r1
, p2
);
307 talloc_report_full(root
, stderr
);
309 CHECK_BLOCKS("ref4", p1
, 5);
310 CHECK_BLOCKS("ref4", p2
, 1);
311 CHECK_BLOCKS("ref4", ref
, 1);
312 CHECK_BLOCKS("ref4", r1
, 2);
314 fprintf(stderr
, "Freeing r1\n");
316 talloc_report_full(root
, stderr
);
318 CHECK_BLOCKS("ref4", p1
, 5);
319 CHECK_BLOCKS("ref4", p2
, 1);
321 fprintf(stderr
, "Freeing p2\n");
323 talloc_report_full(root
, stderr
);
325 CHECK_BLOCKS("ref4", p1
, 4);
327 fprintf(stderr
, "Freeing p1\n");
329 talloc_report_full(root
, stderr
);
331 CHECK_SIZE("ref4", root
, 0);
335 printf("success: ref4\n");
343 static bool test_unlink1(void)
345 void *root
, *p1
, *p2
, *ref
, *r1
;
347 printf("test: unlink\n# UNLINK\n");
349 root
= talloc_named_const(NULL
, 0, "root");
350 p1
= talloc_named_const(root
, 1, "p1");
351 talloc_named_const(p1
, 1, "x1");
352 talloc_named_const(p1
, 1, "x2");
353 talloc_named_const(p1
, 1, "x3");
354 p2
= talloc_named_const(p1
, 1, "p2");
356 r1
= talloc_named_const(p1
, 1, "r1");
357 ref
= talloc_reference(r1
, p2
);
358 talloc_report_full(root
, stderr
);
360 CHECK_BLOCKS("unlink", p1
, 7);
361 CHECK_BLOCKS("unlink", p2
, 1);
362 CHECK_BLOCKS("unlink", ref
, 1);
363 CHECK_BLOCKS("unlink", r1
, 2);
365 fprintf(stderr
, "Unreferencing r1\n");
366 talloc_unlink(r1
, p2
);
367 talloc_report_full(root
, stderr
);
369 CHECK_BLOCKS("unlink", p1
, 6);
370 CHECK_BLOCKS("unlink", p2
, 1);
371 CHECK_BLOCKS("unlink", r1
, 1);
373 fprintf(stderr
, "Freeing p1\n");
375 talloc_report_full(root
, stderr
);
377 CHECK_SIZE("unlink", root
, 0);
381 printf("success: unlink\n");
385 static int fail_destructor(void *ptr
)
391 miscellaneous tests to try to get a higher test coverage percentage
393 static bool test_misc(void)
400 printf("test: misc\n# MISCELLANEOUS\n");
402 root
= talloc_new(NULL
);
404 p1
= talloc_size(root
, 0x7fffffff);
405 torture_assert("misc", !p1
, "failed: large talloc allowed\n");
407 p1
= talloc_strdup(root
, "foo");
408 talloc_increase_ref_count(p1
);
409 talloc_increase_ref_count(p1
);
410 talloc_increase_ref_count(p1
);
411 CHECK_BLOCKS("misc", p1
, 1);
412 CHECK_BLOCKS("misc", root
, 2);
413 talloc_unlink(NULL
, p1
);
414 CHECK_BLOCKS("misc", p1
, 1);
415 CHECK_BLOCKS("misc", root
, 2);
416 talloc_unlink(NULL
, p1
);
417 CHECK_BLOCKS("misc", p1
, 1);
418 CHECK_BLOCKS("misc", root
, 2);
419 p2
= talloc_strdup(p1
, "foo");
420 torture_assert("misc", talloc_unlink(root
, p2
) == -1,
421 "failed: talloc_unlink() of non-reference context should return -1\n");
422 torture_assert("misc", talloc_unlink(p1
, p2
) == 0,
423 "failed: talloc_unlink() of parent should succeed\n");
424 talloc_unlink(NULL
, p1
);
425 CHECK_BLOCKS("misc", p1
, 1);
426 CHECK_BLOCKS("misc", root
, 2);
428 name
= talloc_set_name(p1
, "my name is %s", "foo");
429 torture_assert_str_equal("misc", talloc_get_name(p1
), "my name is foo",
430 "failed: wrong name after talloc_set_name(my name is foo)");
431 torture_assert_str_equal("misc", talloc_get_name(p1
), name
,
432 "failed: wrong name after talloc_set_name(my name is foo)");
433 CHECK_BLOCKS("misc", p1
, 2);
434 CHECK_BLOCKS("misc", root
, 3);
436 talloc_set_name_const(p1
, NULL
);
437 torture_assert_str_equal ("misc", talloc_get_name(p1
), "UNNAMED",
438 "failed: wrong name after talloc_set_name(NULL)");
439 CHECK_BLOCKS("misc", p1
, 2);
440 CHECK_BLOCKS("misc", root
, 3);
442 torture_assert("misc", talloc_free(NULL
) == -1,
443 "talloc_free(NULL) should give -1\n");
445 talloc_set_destructor(p1
, fail_destructor
);
446 torture_assert("misc", talloc_free(p1
) == -1,
447 "Failed destructor should cause talloc_free to fail\n");
448 talloc_set_destructor(p1
, NULL
);
450 talloc_report(root
, stderr
);
453 p2
= (char *)talloc_zero_size(p1
, 20);
454 torture_assert("misc", p2
[19] == 0, "Failed to give zero memory\n");
457 torture_assert("misc", talloc_strdup(root
, NULL
) == NULL
,
458 "failed: strdup on NULL should give NULL\n");
460 p2
= talloc_strndup(p1
, "foo", 2);
461 torture_assert("misc", strcmp("fo", p2
) == 0,
462 "strndup doesn't work\n");
463 p2
= talloc_asprintf_append_buffer(p2
, "o%c", 'd');
464 torture_assert("misc", strcmp("food", p2
) == 0,
465 "talloc_asprintf_append_buffer doesn't work\n");
466 CHECK_BLOCKS("misc", p2
, 1);
467 CHECK_BLOCKS("misc", p1
, 3);
469 p2
= talloc_asprintf_append_buffer(NULL
, "hello %s", "world");
470 torture_assert("misc", strcmp("hello world", p2
) == 0,
471 "talloc_asprintf_append_buffer doesn't work\n");
472 CHECK_BLOCKS("misc", p2
, 1);
473 CHECK_BLOCKS("misc", p1
, 3);
476 d
= talloc_array(p1
, double, 0x20000000);
477 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
479 d
= talloc_realloc(p1
, d
, double, 0x20000000);
480 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
483 CHECK_BLOCKS("misc", root
, 1);
485 p1
= talloc_named(root
, 100, "%d bytes", 100);
486 CHECK_BLOCKS("misc", p1
, 2);
487 CHECK_BLOCKS("misc", root
, 3);
488 talloc_unlink(root
, p1
);
490 p1
= talloc_init("%d bytes", 200);
491 p2
= talloc_asprintf(p1
, "my test '%s'", "string");
492 torture_assert_str_equal("misc", p2
, "my test 'string'",
493 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
494 CHECK_BLOCKS("misc", p1
, 3);
495 CHECK_SIZE("misc", p2
, 17);
496 CHECK_BLOCKS("misc", root
, 1);
497 talloc_unlink(NULL
, p1
);
499 p1
= talloc_named_const(root
, 10, "p1");
500 p2
= (char *)talloc_named_const(root
, 20, "p2");
501 (void)talloc_reference(p1
, p2
);
502 talloc_report_full(root
, stderr
);
503 talloc_unlink(root
, p2
);
504 talloc_report_full(root
, stderr
);
505 CHECK_BLOCKS("misc", p2
, 1);
506 CHECK_BLOCKS("misc", p1
, 2);
507 CHECK_BLOCKS("misc", root
, 3);
508 talloc_unlink(p1
, p2
);
509 talloc_unlink(root
, p1
);
511 p1
= talloc_named_const(root
, 10, "p1");
512 p2
= (char *)talloc_named_const(root
, 20, "p2");
513 (void)talloc_reference(NULL
, p2
);
514 talloc_report_full(root
, stderr
);
515 talloc_unlink(root
, p2
);
516 talloc_report_full(root
, stderr
);
517 CHECK_BLOCKS("misc", p2
, 1);
518 CHECK_BLOCKS("misc", p1
, 1);
519 CHECK_BLOCKS("misc", root
, 2);
520 talloc_unlink(NULL
, p2
);
521 talloc_unlink(root
, p1
);
523 /* Test that talloc_unlink is a no-op */
525 torture_assert("misc", talloc_unlink(root
, NULL
) == -1,
526 "failed: talloc_unlink(root, NULL) == -1\n");
528 talloc_report(root
, stderr
);
529 talloc_report(NULL
, stderr
);
531 CHECK_SIZE("misc", root
, 0);
535 CHECK_SIZE("misc", NULL
, 0);
537 talloc_enable_null_tracking_no_autofree();
538 talloc_enable_leak_report();
539 talloc_enable_leak_report_full();
541 printf("success: misc\n");
550 static bool test_realloc(void)
552 void *root
, *p1
, *p2
;
554 printf("test: realloc\n# REALLOC\n");
556 root
= talloc_new(NULL
);
558 p1
= talloc_size(root
, 10);
559 CHECK_SIZE("realloc", p1
, 10);
561 p1
= talloc_realloc_size(NULL
, p1
, 20);
562 CHECK_SIZE("realloc", p1
, 20);
566 p2
= talloc_realloc_size(p1
, NULL
, 30);
570 p2
= talloc_realloc_size(p1
, p2
, 40);
572 CHECK_SIZE("realloc", p2
, 40);
573 CHECK_SIZE("realloc", root
, 60);
574 CHECK_BLOCKS("realloc", p1
, 4);
576 p1
= talloc_realloc_size(NULL
, p1
, 20);
577 CHECK_SIZE("realloc", p1
, 60);
579 talloc_increase_ref_count(p2
);
580 torture_assert("realloc", talloc_realloc_size(NULL
, p2
, 5) == NULL
,
581 "failed: talloc_realloc() on a referenced pointer should fail\n");
582 CHECK_BLOCKS("realloc", p1
, 4);
584 talloc_realloc_size(NULL
, p2
, 0);
585 talloc_realloc_size(NULL
, p2
, 0);
586 CHECK_BLOCKS("realloc", p1
, 4);
587 talloc_realloc_size(p1
, p2
, 0);
588 CHECK_BLOCKS("realloc", p1
, 3);
590 torture_assert("realloc", talloc_realloc_size(NULL
, p1
, 0x7fffffff) == NULL
,
591 "failed: oversize talloc should fail\n");
593 talloc_realloc_size(NULL
, p1
, 0);
594 CHECK_BLOCKS("realloc", root
, 4);
595 talloc_realloc_size(root
, p1
, 0);
596 CHECK_BLOCKS("realloc", root
, 1);
598 CHECK_SIZE("realloc", root
, 0);
602 printf("success: realloc\n");
608 test realloc with a child
610 static bool test_realloc_child(void)
615 } *el2
, *el2_2
, *el2_3
, **el_list_save
;
618 struct el2
**list
, **list2
, **list3
;
621 printf("test: REALLOC WITH CHILD\n");
623 root
= talloc_new(NULL
);
625 el1
= talloc(root
, struct el1
);
626 el1
->list
= talloc(el1
, struct el2
*);
627 el1
->list
[0] = talloc(el1
->list
, struct el2
);
628 el1
->list
[0]->name
= talloc_strdup(el1
->list
[0], "testing");
630 el1
->list2
= talloc(el1
, struct el2
*);
631 el1
->list2
[0] = talloc(el1
->list2
, struct el2
);
632 el1
->list2
[0]->name
= talloc_strdup(el1
->list2
[0], "testing2");
634 el1
->list3
= talloc(el1
, struct el2
*);
635 el1
->list3
[0] = talloc(el1
->list3
, struct el2
);
636 el1
->list3
[0]->name
= talloc_strdup(el1
->list3
[0], "testing2");
638 el2
= talloc(el1
->list
, struct el2
);
639 CHECK_PARENT("el2", el2
, el1
->list
);
640 el2_2
= talloc(el1
->list2
, struct el2
);
641 CHECK_PARENT("el2", el2_2
, el1
->list2
);
642 el2_3
= talloc(el1
->list3
, struct el2
);
643 CHECK_PARENT("el2", el2_3
, el1
->list3
);
645 el_list_save
= el1
->list
;
646 el1
->list
= talloc_realloc(el1
, el1
->list
, struct el2
*, 100);
647 if (el1
->list
== el_list_save
) {
648 printf("failure: talloc_realloc didn't move pointer");
652 CHECK_PARENT("el1_after_realloc", el1
->list
, el1
);
653 el1
->list2
= talloc_realloc(el1
, el1
->list2
, struct el2
*, 200);
654 CHECK_PARENT("el1_after_realloc", el1
->list2
, el1
);
655 el1
->list3
= talloc_realloc(el1
, el1
->list3
, struct el2
*, 300);
656 CHECK_PARENT("el1_after_realloc", el1
->list3
, el1
);
658 CHECK_PARENT("el2", el2
, el1
->list
);
659 CHECK_PARENT("el2", el2_2
, el1
->list2
);
660 CHECK_PARENT("el2", el2_3
, el1
->list3
);
662 /* Finally check realloc with multiple children */
663 el1
= talloc_realloc(root
, el1
, struct el1
, 100);
664 CHECK_PARENT("el1->list", el1
->list
, el1
);
665 CHECK_PARENT("el1->list2", el1
->list2
, el1
);
666 CHECK_PARENT("el1->list3", el1
->list3
, el1
);
670 printf("success: REALLOC WITH CHILD\n");
677 static bool test_type(void)
688 printf("test: type\n# talloc type checking\n");
690 root
= talloc_new(NULL
);
692 el1
= talloc(root
, struct el1
);
696 torture_assert("type", talloc_get_type(el1
, struct el1
) == el1
,
697 "type check failed on el1\n");
698 torture_assert("type", talloc_get_type(el1
, struct el2
) == NULL
,
699 "type check failed on el1 with el2\n");
700 talloc_set_type(el1
, struct el2
);
701 torture_assert("type", talloc_get_type(el1
, struct el2
) == (struct el2
*)el1
,
702 "type set failed on el1 with el2\n");
706 printf("success: type\n");
713 static bool test_steal(void)
715 void *root
, *p1
, *p2
;
717 printf("test: steal\n# STEAL\n");
719 root
= talloc_new(NULL
);
721 p1
= talloc_array(root
, char, 10);
722 CHECK_SIZE("steal", p1
, 10);
724 p2
= talloc_realloc(root
, NULL
, char, 20);
725 CHECK_SIZE("steal", p1
, 10);
726 CHECK_SIZE("steal", root
, 30);
728 torture_assert("steal", talloc_steal(p1
, NULL
) == NULL
,
729 "failed: stealing NULL should give NULL\n");
731 torture_assert("steal", talloc_steal(p1
, p1
) == p1
,
732 "failed: stealing to ourselves is a nop\n");
733 CHECK_BLOCKS("steal", root
, 3);
734 CHECK_SIZE("steal", root
, 30);
736 talloc_steal(NULL
, p1
);
737 talloc_steal(NULL
, p2
);
738 CHECK_BLOCKS("steal", root
, 1);
739 CHECK_SIZE("steal", root
, 0);
742 talloc_steal(root
, p2
);
743 CHECK_BLOCKS("steal", root
, 2);
744 CHECK_SIZE("steal", root
, 20);
748 CHECK_BLOCKS("steal", root
, 1);
749 CHECK_SIZE("steal", root
, 0);
753 p1
= talloc_size(NULL
, 3);
754 talloc_report_full(NULL
, stderr
);
755 CHECK_SIZE("steal", NULL
, 3);
758 printf("success: steal\n");
765 static bool test_move(void)
773 printf("test: move\n# MOVE\n");
775 root
= talloc_new(NULL
);
777 t1
= talloc(root
, struct t_move
);
778 t2
= talloc(root
, struct t_move
);
779 t1
->p
= talloc_strdup(t1
, "foo");
780 t1
->x
= talloc(t1
, int);
783 t2
->p
= talloc_move(t2
, &t1
->p
);
784 t2
->x
= talloc_move(t2
, &t1
->x
);
785 torture_assert("move", t1
->p
== NULL
&& t1
->x
== NULL
&&
786 strcmp(t2
->p
, "foo") == 0 && *t2
->x
== 42,
787 "talloc move failed");
791 printf("success: move\n");
797 test talloc_realloc_fn
799 static bool test_realloc_fn(void)
803 printf("test: realloc_fn\n# talloc_realloc_fn\n");
805 root
= talloc_new(NULL
);
807 p1
= talloc_realloc_fn(root
, NULL
, 10);
808 CHECK_BLOCKS("realloc_fn", root
, 2);
809 CHECK_SIZE("realloc_fn", root
, 10);
810 p1
= talloc_realloc_fn(root
, p1
, 20);
811 CHECK_BLOCKS("realloc_fn", root
, 2);
812 CHECK_SIZE("realloc_fn", root
, 20);
813 p1
= talloc_realloc_fn(root
, p1
, 0);
814 CHECK_BLOCKS("realloc_fn", root
, 1);
815 CHECK_SIZE("realloc_fn", root
, 0);
819 printf("success: realloc_fn\n");
824 static bool test_unref_reparent(void)
826 void *root
, *p1
, *p2
, *c1
;
828 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
830 root
= talloc_named_const(NULL
, 0, "root");
831 p1
= talloc_named_const(root
, 1, "orig parent");
832 p2
= talloc_named_const(root
, 1, "parent by reference");
834 c1
= talloc_named_const(p1
, 1, "child");
835 talloc_reference(p2
, c1
);
837 CHECK_PARENT("unref_reparent", c1
, p1
);
841 CHECK_PARENT("unref_reparent", c1
, p2
);
843 talloc_unlink(p2
, c1
);
845 CHECK_SIZE("unref_reparent", root
, 1);
850 printf("success: unref_reparent\n");
855 measure the speed of talloc versus malloc
857 static bool test_speed(void)
859 void *ctx
= talloc_new(NULL
);
861 const int loop
= 1000;
865 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
867 tv
= private_timeval_current();
871 for (i
=0;i
<loop
;i
++) {
872 p1
= talloc_size(ctx
, loop
% 100);
873 p2
= talloc_strdup(p1
, "foo bar");
874 p3
= talloc_size(p1
, 300);
880 } while (private_timeval_elapsed(&tv
) < 5.0);
882 fprintf(stderr
, "talloc: %.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
886 ctx
= talloc_pool(NULL
, 1024);
888 tv
= private_timeval_current();
892 for (i
=0;i
<loop
;i
++) {
893 p1
= talloc_size(ctx
, loop
% 100);
894 p2
= talloc_strdup(p1
, "foo bar");
895 p3
= talloc_size(p1
, 300);
901 } while (private_timeval_elapsed(&tv
) < 5.0);
905 fprintf(stderr
, "talloc_pool: %.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
907 tv
= private_timeval_current();
911 for (i
=0;i
<loop
;i
++) {
912 p1
= malloc(loop
% 100);
913 p2
= strdup("foo bar");
920 } while (private_timeval_elapsed(&tv
) < 5.0);
921 fprintf(stderr
, "malloc: %.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
923 printf("success: speed\n");
928 static bool test_lifeless(void)
930 void *top
= talloc_new(NULL
);
931 char *parent
, *child
;
932 void *child_owner
= talloc_new(NULL
);
934 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
936 parent
= talloc_strdup(top
, "parent");
937 child
= talloc_strdup(parent
, "child");
938 (void)talloc_reference(child
, parent
);
939 (void)talloc_reference(child_owner
, child
);
940 talloc_report_full(top
, stderr
);
941 talloc_unlink(top
, parent
);
942 talloc_unlink(top
, child
);
943 talloc_report_full(top
, stderr
);
945 talloc_free(child_owner
);
948 printf("success: lifeless\n");
952 static int loop_destructor_count
;
954 static int test_loop_destructor(char *ptr
)
956 loop_destructor_count
++;
960 static bool test_loop(void)
962 void *top
= talloc_new(NULL
);
968 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
970 parent
= talloc_strdup(top
, "parent");
971 req1
= talloc(parent
, struct req1
);
972 req1
->req2
= talloc_strdup(req1
, "req2");
973 talloc_set_destructor(req1
->req2
, test_loop_destructor
);
974 req1
->req3
= talloc_strdup(req1
, "req3");
975 (void)talloc_reference(req1
->req3
, req1
);
976 talloc_report_full(top
, stderr
);
978 talloc_report_full(top
, stderr
);
979 talloc_report_full(NULL
, stderr
);
982 torture_assert("loop", loop_destructor_count
== 1,
983 "FAILED TO FIRE LOOP DESTRUCTOR\n");
984 loop_destructor_count
= 0;
986 printf("success: loop\n");
990 static int realloc_parent_destructor_count
;
992 static int test_realloc_parent_destructor(char *ptr
)
994 realloc_parent_destructor_count
++;
998 static bool test_realloc_on_destructor_parent(void)
1000 void *top
= talloc_new(NULL
);
1002 char *a
, *b
, *C
, *D
;
1003 realloc_parent_destructor_count
= 0;
1005 printf("test: free_for_exit\n# TALLOC FREE FOR EXIT\n");
1007 parent
= talloc_strdup(top
, "parent");
1008 a
= talloc_strdup(parent
, "a");
1009 b
= talloc_strdup(a
, "b");
1010 C
= talloc_strdup(a
, "C");
1011 D
= talloc_strdup(b
, "D");
1012 talloc_set_destructor(D
, test_realloc_parent_destructor
);
1013 /* Capitalised ones have destructors.
1015 * parent --> a -> b -> D
1019 a
= talloc_realloc(parent
, a
, char, 2048);
1021 torture_assert("check talloc_realloc", a
!= NULL
, "talloc_realloc failed");
1023 talloc_set_destructor(C
, test_realloc_parent_destructor
);
1025 * parent --> a[2048] -> b -> D
1030 talloc_free(parent
);
1032 torture_assert("check destructor realloc_parent_destructor",
1033 realloc_parent_destructor_count
== 2,
1034 "FAILED TO FIRE free_for_exit_destructor\n");
1037 printf("success: free_for_exit\n");
1038 talloc_free(top
); /* make ASAN happy */
1043 static int fail_destructor_str(char *ptr
)
1048 static bool test_free_parent_deny_child(void)
1050 void *top
= talloc_new(NULL
);
1055 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1057 level1
= talloc_strdup(top
, "level1");
1058 level2
= talloc_strdup(level1
, "level2");
1059 level3
= talloc_strdup(level2
, "level3");
1061 talloc_set_destructor(level3
, fail_destructor_str
);
1062 talloc_free(level1
);
1063 talloc_set_destructor(level3
, NULL
);
1065 CHECK_PARENT("free_parent_deny_child", level3
, top
);
1069 printf("success: free_parent_deny_child\n");
1078 static int reparenting_destructor(struct new_parent
*np
)
1080 talloc_set_destructor(np
, NULL
);
1081 (void)talloc_move(np
->new_parent
, &np
);
1085 static bool test_free_parent_reparent_child(void)
1087 void *top
= talloc_new(NULL
);
1089 char *alternate_level1
;
1091 struct new_parent
*level3
;
1093 printf("test: free_parent_reparent_child\n# "
1094 "TALLOC FREE PARENT REPARENT CHILD\n");
1096 level1
= talloc_strdup(top
, "level1");
1097 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1098 level2
= talloc_strdup(level1
, "level2");
1099 level3
= talloc(level2
, struct new_parent
);
1100 level3
->new_parent
= alternate_level1
;
1101 memset(level3
->val
, 'x', sizeof(level3
->val
));
1103 talloc_set_destructor(level3
, reparenting_destructor
);
1104 talloc_free(level1
);
1106 CHECK_PARENT("free_parent_reparent_child",
1107 level3
, alternate_level1
);
1111 printf("success: free_parent_reparent_child\n");
1115 static bool test_free_parent_reparent_child_in_pool(void)
1117 void *top
= talloc_new(NULL
);
1119 char *alternate_level1
;
1122 struct new_parent
*level3
;
1124 printf("test: free_parent_reparent_child_in_pool\n# "
1125 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1127 pool
= talloc_pool(top
, 1024);
1128 level1
= talloc_strdup(pool
, "level1");
1129 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1130 level2
= talloc_strdup(level1
, "level2");
1131 level3
= talloc(level2
, struct new_parent
);
1132 level3
->new_parent
= alternate_level1
;
1133 memset(level3
->val
, 'x', sizeof(level3
->val
));
1135 talloc_set_destructor(level3
, reparenting_destructor
);
1136 talloc_free(level1
);
1137 talloc_set_destructor(level3
, NULL
);
1139 CHECK_PARENT("free_parent_reparent_child_in_pool",
1140 level3
, alternate_level1
);
1142 /* Even freeing alternate_level1 should leave pool alone. */
1143 talloc_free(alternate_level1
);
1146 printf("success: free_parent_reparent_child_in_pool\n");
1151 static bool test_talloc_ptrtype(void)
1153 void *top
= talloc_new(NULL
);
1157 } *s1
, *s2
, **s3
, ***s4
;
1158 const char *location1
;
1159 const char *location2
;
1160 const char *location3
;
1161 const char *location4
;
1163 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1165 s1
= talloc_ptrtype(top
, s1
);location1
= __location__
;
1167 if (talloc_get_size(s1
) != sizeof(struct struct1
)) {
1168 printf("failure: ptrtype [\n"
1169 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1170 "]\n", (unsigned long)talloc_get_size(s1
),
1171 (unsigned long)sizeof(struct struct1
));
1175 if (strcmp(location1
, talloc_get_name(s1
)) != 0) {
1176 printf("failure: ptrtype [\n"
1177 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1178 talloc_get_name(s1
), location1
);
1182 s2
= talloc_array_ptrtype(top
, s2
, 10);location2
= __location__
;
1184 if (talloc_get_size(s2
) != (sizeof(struct struct1
) * 10)) {
1185 printf("failure: ptrtype [\n"
1186 "talloc_array_ptrtype() allocated the wrong size "
1187 "%lu (should be %lu)\n]\n",
1188 (unsigned long)talloc_get_size(s2
),
1189 (unsigned long)(sizeof(struct struct1
)*10));
1193 if (strcmp(location2
, talloc_get_name(s2
)) != 0) {
1194 printf("failure: ptrtype [\n"
1195 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1196 talloc_get_name(s2
), location2
);
1200 s3
= talloc_array_ptrtype(top
, s3
, 10);location3
= __location__
;
1202 if (talloc_get_size(s3
) != (sizeof(struct struct1
*) * 10)) {
1203 printf("failure: ptrtype [\n"
1204 "talloc_array_ptrtype() allocated the wrong size "
1205 "%lu (should be %lu)\n]\n",
1206 (unsigned long)talloc_get_size(s3
),
1207 (unsigned long)(sizeof(struct struct1
*)*10));
1211 torture_assert_str_equal("ptrtype", location3
, talloc_get_name(s3
),
1212 "talloc_array_ptrtype() sets the wrong name");
1214 s4
= talloc_array_ptrtype(top
, s4
, 10);location4
= __location__
;
1216 if (talloc_get_size(s4
) != (sizeof(struct struct1
**) * 10)) {
1217 printf("failure: ptrtype [\n"
1218 "talloc_array_ptrtype() allocated the wrong size "
1219 "%lu (should be %lu)\n]\n",
1220 (unsigned long)talloc_get_size(s4
),
1221 (unsigned long)(sizeof(struct struct1
**)*10));
1225 torture_assert_str_equal("ptrtype", location4
, talloc_get_name(s4
),
1226 "talloc_array_ptrtype() sets the wrong name");
1230 printf("success: ptrtype\n");
1234 static int _test_talloc_free_in_destructor(void **ptr
)
1240 static bool test_talloc_free_in_destructor(void)
1249 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1251 level0
= talloc_new(NULL
);
1252 level1
= talloc_new(level0
);
1253 level2
= talloc_new(level1
);
1254 level3
= talloc_new(level2
);
1255 level4
= talloc_new(level3
);
1256 level5
= talloc(level4
, void *);
1259 (void)talloc_reference(level0
, level3
);
1260 (void)talloc_reference(level3
, level3
);
1261 (void)talloc_reference(level5
, level3
);
1263 talloc_set_destructor(level5
, _test_talloc_free_in_destructor
);
1265 talloc_free(level1
);
1267 talloc_free(level0
);
1269 talloc_free(level3
); /* make ASAN happy */
1271 printf("success: free_in_destructor\n");
1275 static bool test_autofree(void)
1277 #if _SAMBA_BUILD_ < 4
1278 /* autofree test would kill smbtorture */
1280 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1282 p
= talloc_autofree_context();
1285 p
= talloc_autofree_context();
1288 printf("success: autofree\n");
1293 static bool test_pool(void)
1296 void *p1
, *p2
, *p3
, *p4
;
1299 pool
= talloc_pool(NULL
, 1024);
1301 p1
= talloc_size(pool
, 80);
1302 memset(p1
, 0x11, talloc_get_size(p1
));
1303 p2
= talloc_size(pool
, 20);
1304 memset(p2
, 0x11, talloc_get_size(p2
));
1305 p3
= talloc_size(p1
, 50);
1306 memset(p3
, 0x11, talloc_get_size(p3
));
1307 p4
= talloc_size(p3
, 1000);
1308 memset(p4
, 0x11, talloc_get_size(p4
));
1310 p2_2
= talloc_realloc_size(pool
, p2
, 20+1);
1311 torture_assert("pool realloc 20+1", p2_2
== p2
, "failed: pointer changed");
1312 memset(p2
, 0x11, talloc_get_size(p2
));
1313 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1314 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1315 memset(p2
, 0x11, talloc_get_size(p2
));
1316 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1317 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1318 memset(p2
, 0x11, talloc_get_size(p2
));
1322 /* this should reclaim the memory of p4 and p3 */
1323 p2_2
= talloc_realloc_size(pool
, p2
, 400);
1324 torture_assert("pool realloc 400", p2_2
== p2
, "failed: pointer changed");
1325 memset(p2
, 0x11, talloc_get_size(p2
));
1329 /* this should reclaim the memory of p1 */
1330 p2_2
= talloc_realloc_size(pool
, p2
, 800);
1331 torture_assert("pool realloc 800", p2_2
== p1
, "failed: pointer not changed");
1333 memset(p2
, 0x11, talloc_get_size(p2
));
1335 /* this should do a malloc */
1336 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1337 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1339 memset(p2
, 0x11, talloc_get_size(p2
));
1341 /* this should reclaim the memory from the pool */
1342 p3
= talloc_size(pool
, 80);
1343 torture_assert("pool alloc 80", p3
== p1
, "failed: pointer changed");
1344 memset(p3
, 0x11, talloc_get_size(p3
));
1349 p1
= talloc_size(pool
, 80);
1350 memset(p1
, 0x11, talloc_get_size(p1
));
1351 p2
= talloc_size(pool
, 20);
1352 memset(p2
, 0x11, talloc_get_size(p2
));
1356 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1357 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1358 memset(p2
, 0x11, talloc_get_size(p2
));
1359 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1360 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1361 memset(p2
, 0x11, talloc_get_size(p2
));
1363 /* this should do a malloc */
1364 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1365 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1367 memset(p2
, 0x11, talloc_get_size(p2
));
1369 /* this should reclaim the memory from the pool */
1370 p3
= talloc_size(pool
, 800);
1371 torture_assert("pool alloc 800", p3
== p1
, "failed: pointer changed");
1372 memset(p3
, 0x11, talloc_get_size(p3
));
1379 static bool test_pool_steal(void)
1388 root
= talloc_new(NULL
);
1389 pool
= talloc_pool(root
, 1024);
1391 p1
= talloc_size(pool
, 4 * 16);
1392 torture_assert("pool allocate 4 * 16", p1
!= NULL
, "failed ");
1393 memset(p1
, 0x11, talloc_get_size(p1
));
1394 p2
= talloc_size(pool
, 4 * 16);
1395 torture_assert("pool allocate 4 * 16", p2
> p1
, "failed: !(p2 > p1) ");
1396 memset(p2
, 0x11, talloc_get_size(p2
));
1398 ofs1
= PTR_DIFF(p2
, p1
);
1399 hdr
= ofs1
- talloc_get_size(p1
);
1401 talloc_steal(root
, p1
);
1402 talloc_steal(root
, p2
);
1408 p1_2
= talloc_realloc_size(root
, p1
, 5 * 16);
1409 torture_assert("pool realloc 5 * 16", p1_2
> p2
, "failed: pointer not changed");
1410 memset(p1_2
, 0x11, talloc_get_size(p1_2
));
1411 ofs1
= PTR_DIFF(p1_2
, p2
);
1412 ofs2
= talloc_get_size(p2
) + hdr
;
1414 torture_assert("pool realloc ", ofs1
== ofs2
, "failed: pointer offset unexpected");
1416 p2_2
= talloc_realloc_size(root
, p2
, 3 * 16);
1417 torture_assert("pool realloc 5 * 16", p2_2
== p2
, "failed: pointer changed");
1418 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
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
));
1442 static bool test_pool_nest(void)
1445 void *e
= talloc_new(NULL
);
1447 p1
= talloc_pool(NULL
, 1024);
1448 torture_assert("talloc_pool", p1
!= NULL
, "failed");
1450 p2
= talloc_pool(p1
, 500);
1451 torture_assert("talloc_pool", p2
!= NULL
, "failed");
1453 p3
= talloc_size(p2
, 10);
1455 talloc_steal(e
, p3
);
1463 talloc_free(e
); /* make ASAN happy */
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);
1544 talloc_free(p1
); /* make ASAN happy */
1549 static bool test_free_children(void)
1553 const char *name
, *name2
;
1555 talloc_enable_null_tracking();
1556 root
= talloc_new(NULL
);
1557 p1
= talloc_strdup(root
, "foo1");
1558 p2
= talloc_strdup(p1
, "foo2");
1561 talloc_set_name(p1
, "%s", "testname");
1562 talloc_free_children(p1
);
1563 /* check its still a valid talloc ptr */
1564 talloc_get_size(talloc_get_name(p1
));
1565 if (strcmp(talloc_get_name(p1
), "testname") != 0) {
1569 talloc_set_name(p1
, "%s", "testname");
1570 name
= talloc_get_name(p1
);
1571 talloc_free_children(p1
);
1572 /* check its still a valid talloc ptr */
1573 talloc_get_size(talloc_get_name(p1
));
1574 torture_assert("name", name
== talloc_get_name(p1
), "name ptr changed");
1575 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname") == 0,
1577 CHECK_BLOCKS("name1", p1
, 2);
1579 /* note that this does not free the old child name */
1580 talloc_set_name_const(p1
, "testname2");
1581 name2
= talloc_get_name(p1
);
1583 talloc_free_children(p1
);
1585 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname2") == 0,
1587 CHECK_BLOCKS("name1", p1
, 1);
1589 talloc_report_full(root
, stdout
);
1594 static bool test_memlimit(void)
1597 char *l1
, *l2
, *l3
, *l4
, *l5
, *t
;
1601 printf("test: memlimit\n# MEMORY LIMITS\n");
1603 printf("==== talloc_new(NULL)\n");
1604 root
= talloc_new(NULL
);
1606 talloc_report_full(root
, stdout
);
1608 printf("==== talloc_size(root, 2048)\n");
1609 l1
= talloc_size(root
, 2048);
1610 torture_assert("memlimit", l1
!= NULL
,
1611 "failed: alloc should not fail due to memory limit\n");
1613 talloc_report_full(root
, stdout
);
1615 printf("==== talloc_free(l1)\n");
1618 talloc_report_full(root
, stdout
);
1620 printf("==== talloc_strdup(root, level 1)\n");
1621 l1
= talloc_strdup(root
, "level 1");
1622 torture_assert("memlimit", l1
!= NULL
,
1623 "failed: alloc should not fail due to memory limit\n");
1625 talloc_report_full(root
, stdout
);
1627 printf("==== talloc_set_memlimit(l1, 2048)\n");
1628 torture_assert("memlimit", talloc_set_memlimit(l1
, 2048) == 0,
1629 "failed: setting memlimit should never fail\n");
1631 talloc_report_full(root
, stdout
);
1633 printf("==== talloc_size(root, 2048)\n");
1634 l2
= talloc_size(l1
, 2048);
1635 torture_assert("memlimit", l2
== NULL
,
1636 "failed: alloc should fail due to memory limit\n");
1638 talloc_report_full(root
, stdout
);
1640 printf("==== talloc_strdup(l1, level 2)\n");
1641 l2
= talloc_strdup(l1
, "level 2");
1642 torture_assert("memlimit", l2
!= NULL
,
1643 "failed: alloc should not fail due to memory limit\n");
1645 talloc_report_full(root
, stdout
);
1647 printf("==== talloc_free(l2)\n");
1650 talloc_report_full(root
, stdout
);
1652 printf("==== talloc_size(NULL, 2048)\n");
1653 l2
= talloc_size(NULL
, 2048);
1655 talloc_report_full(root
, stdout
);
1657 printf("==== talloc_steal(l1, l2)\n");
1658 talloc_steal(l1
, l2
);
1660 talloc_report_full(root
, stdout
);
1662 printf("==== talloc_strdup(l2, level 3)\n");
1663 l3
= talloc_strdup(l2
, "level 3");
1664 torture_assert("memlimit", l3
== NULL
,
1665 "failed: alloc should fail due to memory limit\n");
1667 talloc_report_full(root
, stdout
);
1669 printf("==== talloc_free(l2)\n");
1672 talloc_report_full(root
, stdout
);
1674 printf("==== talloc_strdup(NULL, level 2)\n");
1675 l2
= talloc_strdup(NULL
, "level 2");
1676 talloc_steal(l1
, l2
);
1678 talloc_report_full(root
, stdout
);
1680 printf("==== talloc_strdup(l2, level 3)\n");
1681 l3
= talloc_strdup(l2
, "level 3");
1682 torture_assert("memlimit", l3
!= NULL
,
1683 "failed: alloc should not fail due to memory limit\n");
1685 talloc_report_full(root
, stdout
);
1687 printf("==== talloc_set_memlimit(l3, 1024)\n");
1688 torture_assert("memlimit", talloc_set_memlimit(l3
, 1024) == 0,
1689 "failed: setting memlimit should never fail\n");
1691 talloc_report_full(root
, stdout
);
1693 printf("==== talloc_strdup(l3, level 4)\n");
1694 l4
= talloc_strdup(l3
, "level 4");
1695 torture_assert("memlimit", l4
!= NULL
,
1696 "failed: alloc should not fail due to memory limit\n");
1698 talloc_report_full(root
, stdout
);
1700 printf("==== talloc_set_memlimit(l4, 512)\n");
1701 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1702 "failed: setting memlimit should never fail\n");
1704 talloc_report_full(root
, stdout
);
1706 printf("==== talloc_strdup(l4, level 5)\n");
1707 l5
= talloc_strdup(l4
, "level 5");
1708 torture_assert("memlimit", l5
!= NULL
,
1709 "failed: alloc should not fail due to memory limit\n");
1711 talloc_report_full(root
, stdout
);
1713 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1714 t
= talloc_realloc(NULL
, l5
, char, 600);
1715 torture_assert("memlimit", t
== NULL
,
1716 "failed: alloc should fail due to memory limit\n");
1718 talloc_report_full(root
, stdout
);
1720 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1721 l5
= talloc_realloc(NULL
, l5
, char, 5);
1722 torture_assert("memlimit", l5
!= NULL
,
1723 "failed: alloc should not fail due to memory limit\n");
1725 talloc_report_full(root
, stdout
);
1727 printf("==== talloc_strdup(l3, level 4)\n");
1728 l4
= talloc_strdup(l3
, "level 4");
1729 torture_assert("memlimit", l4
!= NULL
,
1730 "failed: alloc should not fail due to memory limit\n");
1732 talloc_report_full(root
, stdout
);
1734 printf("==== talloc_set_memlimit(l4, 512)\n");
1735 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1736 "failed: setting memlimit should never fail\n");
1738 talloc_report_full(root
, stdout
);
1740 printf("==== talloc_strdup(l4, level 5)\n");
1741 l5
= talloc_strdup(l4
, "level 5");
1742 torture_assert("memlimit", l5
!= NULL
,
1743 "failed: alloc should not fail due to memory limit\n");
1745 talloc_report_full(root
, stdout
);
1747 printf("==== Make new temp context and steal l5\n");
1748 t
= talloc_new(root
);
1749 talloc_steal(t
, l5
);
1751 talloc_report_full(root
, stdout
);
1753 printf("==== talloc_size(t, 2048)\n");
1754 l1
= talloc_size(t
, 2048);
1755 torture_assert("memlimit", l1
!= NULL
,
1756 "failed: alloc should not fail due to memory limit\n");
1758 talloc_report_full(root
, stdout
);
1761 /* Test memlimits with pools. */
1762 printf("==== talloc_pool(NULL, 10*1024)\n");
1763 pool
= talloc_pool(NULL
, 10*1024);
1764 torture_assert("memlimit", pool
!= NULL
,
1765 "failed: alloc should not fail due to memory limit\n");
1767 printf("==== talloc_set_memlimit(pool, 10*1024)\n");
1768 talloc_set_memlimit(pool
, 10*1024);
1769 for (i
= 0; i
< 9; i
++) {
1770 printf("==== talloc_size(pool, 1024) %i/10\n", i
+ 1);
1771 l1
= talloc_size(pool
, 1024);
1772 torture_assert("memlimit", l1
!= NULL
,
1773 "failed: alloc should not fail due to memory limit\n");
1774 talloc_report_full(pool
, stdout
);
1776 /* The next alloc should fail. */
1777 printf("==== talloc_size(pool, 1024) 10/10\n");
1778 l2
= talloc_size(pool
, 1024);
1779 torture_assert("memlimit", l2
== NULL
,
1780 "failed: alloc should fail due to memory limit\n");
1782 talloc_report_full(pool
, stdout
);
1784 /* Moving one of the children shouldn't change the limit,
1785 as it's still inside the pool. */
1787 printf("==== talloc_new(NULL)\n");
1788 root
= talloc_new(NULL
);
1790 printf("==== talloc_steal(root, l1)\n");
1791 talloc_steal(root
, l1
);
1793 printf("==== talloc_size(pool, 1024)\n");
1794 l2
= talloc_size(pool
, 1024);
1795 torture_assert("memlimit", l2
== NULL
,
1796 "failed: alloc should fail due to memory limit\n");
1798 printf("==== talloc_free_children(pool)\n");
1800 talloc_free_children(pool
);
1802 printf("==== talloc_size(pool, 1024)\n");
1803 l1
= talloc_size(pool
, 1024);
1805 /* try reallocs of increasing size */
1806 for (i
= 1; i
< 9; i
++) {
1807 printf("==== talloc_realloc_size(NULL, l1, %i*1024) %i/10\n", i
, i
+ 1);
1808 l1
= talloc_realloc_size(NULL
, l1
, i
*1024);
1809 torture_assert("memlimit", l1
!= NULL
,
1810 "failed: realloc should not fail due to memory limit\n");
1811 talloc_report_full(pool
, stdout
);
1813 /* The next alloc should fail. */
1814 printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1815 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1816 torture_assert("memlimit", l2
== NULL
,
1817 "failed: realloc should fail due to memory limit\n");
1819 /* Increase the memlimit */
1820 printf("==== talloc_set_memlimit(pool, 11*1024)\n");
1821 talloc_set_memlimit(pool
, 11*1024);
1823 /* The final realloc should still fail
1824 as the entire realloced chunk needs to be moved out of the pool */
1825 printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1826 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1827 torture_assert("memlimit", l2
== NULL
,
1828 "failed: realloc should fail due to memory limit\n");
1830 talloc_report_full(pool
, stdout
);
1832 printf("==== talloc_set_memlimit(pool, 21*1024)\n");
1833 talloc_set_memlimit(pool
, 21*1024);
1835 /* There's now sufficient space to move the chunk out of the pool */
1836 printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1837 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1838 torture_assert("memlimit", l2
!= NULL
,
1839 "failed: realloc should not fail due to memory limit\n");
1841 talloc_report_full(pool
, stdout
);
1843 /* ...which should mean smaller allocations can now occur within the pool */
1844 printf("==== talloc_size(pool, 9*1024)\n");
1845 l1
= talloc_size(pool
, 9*1024);
1846 torture_assert("memlimit", l1
!= NULL
,
1847 "failed: new allocations should be allowed in the pool\n");
1849 talloc_report_full(pool
, stdout
);
1851 /* But reallocs bigger than the pool will still fail */
1852 printf("==== talloc_realloc_size(NULL, l1, 10*1024)\n");
1853 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1854 torture_assert("memlimit", l2
== NULL
,
1855 "failed: realloc should fail due to memory limit\n");
1857 talloc_report_full(pool
, stdout
);
1859 /* ..as well as allocs */
1860 printf("==== talloc_size(pool, 1024)\n");
1861 l1
= talloc_size(pool
, 1024);
1862 torture_assert("memlimit", l1
== NULL
,
1863 "failed: alloc should fail due to memory limit\n");
1865 talloc_report_full(pool
, stdout
);
1867 printf("==== talloc_free_children(pool)\n");
1868 talloc_free_children(pool
);
1870 printf("==== talloc_set_memlimit(pool, 1024)\n");
1871 talloc_set_memlimit(pool
, 1024);
1873 /* We should still be able to allocate up to the pool limit
1874 because the memlimit only applies to new heap allocations */
1875 printf("==== talloc_size(pool, 9*1024)\n");
1876 l1
= talloc_size(pool
, 9*1024);
1877 torture_assert("memlimit", l1
!= NULL
,
1878 "failed: alloc should not fail due to memory limit\n");
1880 talloc_report_full(pool
, stdout
);
1882 l1
= talloc_size(pool
, 1024);
1883 torture_assert("memlimit", l1
== NULL
,
1884 "failed: alloc should fail due to memory limit\n");
1886 talloc_report_full(pool
, stdout
);
1888 printf("==== talloc_free_children(pool)\n");
1889 talloc_free_children(pool
);
1891 printf("==== talloc_set_memlimit(pool, 10*1024)\n");
1892 talloc_set_memlimit(pool
, 10*1024);
1894 printf("==== talloc_size(pool, 1024)\n");
1895 l1
= talloc_size(pool
, 1024);
1896 torture_assert("memlimit", l1
!= NULL
,
1897 "failed: alloc should not fail due to memory limit\n");
1899 talloc_report_full(pool
, stdout
);
1903 printf("success: memlimit\n");
1910 #define NUM_THREADS 100
1912 /* Sync variables. */
1913 static pthread_mutex_t mtx
= PTHREAD_MUTEX_INITIALIZER
;
1914 static pthread_cond_t condvar
= PTHREAD_COND_INITIALIZER
;
1915 static void *intermediate_ptr
;
1918 static void *thread_fn(void *arg
)
1921 const char *ctx_name
= (const char *)arg
;
1922 void *sub_ctx
= NULL
;
1924 * Do stuff that creates a new talloc hierarchy in
1927 void *top_ctx
= talloc_named_const(NULL
, 0, "top");
1928 if (top_ctx
== NULL
) {
1931 sub_ctx
= talloc_named_const(top_ctx
, 100, ctx_name
);
1932 if (sub_ctx
== NULL
) {
1937 * Now transfer a pointer from our hierarchy
1938 * onto the intermediate ptr.
1940 ret
= pthread_mutex_lock(&mtx
);
1942 talloc_free(top_ctx
);
1945 /* Wait for intermediate_ptr to be free. */
1946 while (intermediate_ptr
!= NULL
) {
1947 ret
= pthread_cond_wait(&condvar
, &mtx
);
1949 talloc_free(top_ctx
);
1950 ret
= pthread_mutex_unlock(&mtx
);
1956 /* and move our memory onto it from our toplevel hierarchy. */
1957 intermediate_ptr
= talloc_move(NULL
, &sub_ctx
);
1959 /* Tell the main thread it's ready for pickup. */
1960 pthread_cond_broadcast(&condvar
);
1961 ret
= pthread_mutex_unlock(&mtx
);
1964 talloc_free(top_ctx
);
1969 static bool test_pthread_talloc_passing(void)
1973 char str_array
[NUM_THREADS
][20];
1974 pthread_t thread_id
;
1978 * Important ! Null tracking breaks threaded talloc.
1979 * It *must* be turned off.
1981 talloc_disable_null_tracking();
1983 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1985 /* Main thread toplevel context. */
1986 mem_ctx
= talloc_named_const(NULL
, 0, "toplevel");
1987 if (mem_ctx
== NULL
) {
1988 printf("failed to create toplevel context\n");
1993 * Spin off NUM_THREADS threads.
1994 * They will use their own toplevel contexts.
1996 for (i
= 0; i
< NUM_THREADS
; i
++) {
1997 ret
= snprintf(str_array
[i
],
2002 printf("snprintf %d failed\n", i
);
2005 ret
= pthread_create(&thread_id
,
2010 printf("failed to create thread %d (%d)\n", i
, ret
);
2015 printf("Created %d threads\n", NUM_THREADS
);
2017 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
2018 for (i
= 0; i
< NUM_THREADS
; i
++) {
2019 ret
= pthread_mutex_lock(&mtx
);
2021 printf("pthread_mutex_lock %d failed (%d)\n", i
, ret
);
2022 talloc_free(mem_ctx
);
2026 /* Wait for intermediate_ptr to have our data. */
2027 while (intermediate_ptr
== NULL
) {
2028 ret
= pthread_cond_wait(&condvar
, &mtx
);
2030 printf("pthread_cond_wait %d failed (%d)\n", i
,
2032 talloc_free(mem_ctx
);
2033 ret
= pthread_mutex_unlock(&mtx
);
2038 /* and move it onto our toplevel hierarchy. */
2039 (void)talloc_move(mem_ctx
, &intermediate_ptr
);
2041 /* Tell the sub-threads we're ready for another. */
2042 pthread_cond_broadcast(&condvar
);
2043 ret
= pthread_mutex_unlock(&mtx
);
2047 CHECK_SIZE("pthread_talloc_passing", mem_ctx
, NUM_THREADS
* 100);
2049 /* Dump the hierarchy. */
2050 talloc_report(mem_ctx
, stdout
);
2052 talloc_free(mem_ctx
);
2053 printf("success: pthread_talloc_passing\n");
2058 static void test_magic_protection_abort(const char *reason
)
2060 /* exit with errcode 42 to communicate successful test to the parent process */
2061 if (strcmp(reason
, "Bad talloc magic value - unknown value") == 0) {
2064 printf("talloc aborted for an unexpected reason\n");
2068 static int test_magic_protection_destructor(int *ptr
)
2070 _exit(404); /* Not 42 */
2073 static bool test_magic_protection(void)
2075 void *pool
= talloc_pool(NULL
, 1024);
2080 printf("test: magic_protection\n");
2081 p1
= talloc(pool
, int);
2082 p2
= talloc(pool
, int);
2084 /* To avoid complaints from the compiler assign values to the p1 & p2. */
2090 talloc_set_abort_fn(test_magic_protection_abort
);
2091 talloc_set_destructor(p2
, test_magic_protection_destructor
);
2094 * Simulate a security attack
2095 * by triggering a buffer overflow in memset to overwrite the
2096 * constructor in the next pool chunk.
2098 * Real attacks would attempt to set a real destructor.
2100 memset(p1
, '\0', 32);
2102 /* Then the attack takes effect when the memory's freed. */
2105 /* Never reached. Make compilers happy */
2109 while (wait(&exit_status
) != pid
);
2111 talloc_free(pool
); /* make ASAN happy */
2113 if (!WIFEXITED(exit_status
)) {
2114 printf("Child exited through unexpected abnormal means\n");
2117 if (WEXITSTATUS(exit_status
) != 42) {
2118 printf("Child exited with wrong exit status\n");
2121 if (WIFSIGNALED(exit_status
)) {
2122 printf("Child received unexpected signal\n");
2126 printf("success: magic_protection\n");
2130 static void test_magic_free_protection_abort(const char *reason
)
2132 /* exit with errcode 42 to communicate successful test to the parent process */
2133 if (strcmp(reason
, "Bad talloc magic value - access after free") == 0) {
2140 static bool test_magic_free_protection(void)
2142 void *pool
= talloc_pool(NULL
, 1024);
2147 printf("test: magic_free_protection\n");
2148 p1
= talloc(pool
, int);
2149 p2
= talloc(pool
, int);
2151 /* To avoid complaints from the compiler assign values to the p1 & p2. */
2155 p3
= talloc_realloc(pool
, p2
, int, 2048);
2156 torture_assert("pool realloc 2048",
2158 "failed: pointer not changed");
2161 * Now access the memory in the pool after the realloc(). It
2162 * should be marked as free, so use of the old pointer should
2163 * trigger the abort function
2167 talloc_set_abort_fn(test_magic_free_protection_abort
);
2169 talloc_get_name(p2
);
2171 /* Never reached. Make compilers happy */
2175 while (wait(&exit_status
) != pid
);
2177 if (!WIFEXITED(exit_status
)) {
2178 printf("Child exited through unexpected abnormal means\n");
2181 if (WEXITSTATUS(exit_status
) != 42) {
2182 printf("Child exited with wrong exit status\n");
2185 if (WIFSIGNALED(exit_status
)) {
2186 printf("Child received unexpected signal\n");
2192 printf("success: magic_free_protection\n");
2196 static void test_reset(void)
2198 talloc_set_log_fn(test_log_stdout
);
2200 talloc_disable_null_tracking();
2201 talloc_enable_null_tracking_no_autofree();
2204 bool torture_local_talloc(struct torture_context
*tctx
)
2211 ret
&= test_pooled_object();
2213 ret
&= test_pool_nest();
2223 ret
&= test_unlink1();
2227 ret
&= test_realloc();
2229 ret
&= test_realloc_child();
2231 ret
&= test_steal();
2235 ret
&= test_unref_reparent();
2237 ret
&= test_realloc_fn();
2241 ret
&= test_lifeless();
2245 ret
&= test_free_parent_deny_child();
2247 ret
&= test_realloc_on_destructor_parent();
2249 ret
&= test_free_parent_reparent_child();
2251 ret
&= test_free_parent_reparent_child_in_pool();
2253 ret
&= test_talloc_ptrtype();
2255 ret
&= test_talloc_free_in_destructor();
2259 ret
&= test_pool_steal();
2261 ret
&= test_free_ref_null_context();
2263 ret
&= test_rusty();
2265 ret
&= test_free_children();
2267 ret
&= test_memlimit();
2270 ret
&= test_pthread_talloc_passing();
2276 ret
&= test_speed();
2279 ret
&= test_autofree();
2281 ret
&= test_magic_protection();
2283 ret
&= test_magic_free_protection();
2286 talloc_disable_null_tracking();