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"
30 static struct timeval timeval_current(void)
33 gettimeofday(&tv, NULL);
37 static double timeval_elapsed(struct timeval *tv)
39 struct timeval tv2 = timeval_current();
40 return (tv2.tv_sec - tv->tv_sec) +
41 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
44 #define torture_assert(test, expr, str) if (!(expr)) { \
45 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
46 test, __location__, #expr, str); \
50 #define torture_assert_str_equal(test, arg1, arg2, desc) \
51 if (arg1 == NULL && arg2 == NULL) { \
52 } else if (strcmp(arg1, arg2)) { \
53 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
54 test, __location__, arg1, arg2, desc); \
67 #define CHECK_SIZE(test, ptr, tsize) do { \
68 if (talloc_total_size(ptr) != (tsize)) { \
69 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
70 test, __location__, #ptr, \
71 (unsigned)talloc_total_size(ptr), \
73 talloc_report_full(ptr, stdout); \
78 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
79 if (talloc_total_blocks(ptr) != (tblocks)) { \
80 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
81 test, __location__, #ptr, \
82 (unsigned)talloc_total_blocks(ptr), \
84 talloc_report_full(ptr, stdout); \
89 #define CHECK_PARENT(test, ptr, parent) do { \
90 if (talloc_parent(ptr) != (parent)) { \
91 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
92 test, __location__, #ptr, \
95 talloc_report_full(ptr, stdout); \
96 talloc_report_full(parent, stdout); \
97 talloc_report_full(NULL, stdout); \
102 #define CHECK_NOT_PARENT(test, ptr, parent) do { \
103 if (talloc_parent(ptr) == (parent)) { \
104 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected a difference\n]\n", \
105 test, __location__, #ptr, \
107 talloc_report_full(ptr, stdout); \
108 talloc_report_full(parent, stdout); \
109 talloc_report_full(NULL, stdout); \
114 static unsigned int test_abort_count;
116 static void test_abort_fn(const char *reason)
118 printf("# test_abort_fn(%s)\n", reason);
122 static void test_abort_start(void)
124 test_abort_count = 0;
125 talloc_set_abort_fn(test_abort_fn);
128 static void test_abort_stop(void)
130 test_abort_count = 0;
131 talloc_set_abort_fn(NULL);
137 static bool test_ref1(void)
139 void *root, *p1, *p2, *ref, *r1;
141 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
143 root = talloc_named_const(NULL, 0, "root");
144 p1 = talloc_named_const(root, 1, "p1");
145 p2 = talloc_named_const(p1, 1, "p2");
146 talloc_named_const(p1, 1, "x1");
147 talloc_named_const(p1, 2, "x2");
148 talloc_named_const(p1, 3, "x3");
150 r1 = talloc_named_const(root, 1, "r1");
151 ref = talloc_reference(r1, p2);
152 talloc_report_full(root, stderr);
154 CHECK_BLOCKS("ref1", p1, 5);
155 CHECK_BLOCKS("ref1", p2, 1);
156 CHECK_BLOCKS("ref1", r1, 2);
158 fprintf(stderr, "Freeing p2\n");
160 talloc_report_full(root, stderr);
162 CHECK_BLOCKS("ref1", p1, 4);
163 CHECK_BLOCKS("ref1", p2, 1);
164 CHECK_BLOCKS("ref1", r1, 2);
166 fprintf(stderr, "Freeing p1\n");
168 talloc_report_full(root, stderr);
170 CHECK_BLOCKS("ref1", r1, 2);
172 fprintf(stderr, "Freeing r1\n");
174 talloc_report_full(NULL, stderr);
176 fprintf(stderr, "Testing NULL\n");
177 if (talloc_reference(root, NULL)) {
181 CHECK_BLOCKS("ref1", root, 1);
183 CHECK_SIZE("ref1", root, 0);
186 printf("success: ref1\n");
193 static bool test_ref2(void)
195 void *root, *p1, *p2, *ref, *r1;
197 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
198 root = talloc_named_const(NULL, 0, "root");
199 p1 = talloc_named_const(root, 1, "p1");
200 talloc_named_const(p1, 1, "x1");
201 talloc_named_const(p1, 1, "x2");
202 talloc_named_const(p1, 1, "x3");
203 p2 = talloc_named_const(p1, 1, "p2");
205 r1 = talloc_named_const(root, 1, "r1");
206 ref = talloc_reference(r1, p2);
207 talloc_report_full(root, stderr);
209 CHECK_BLOCKS("ref2", p1, 5);
210 CHECK_BLOCKS("ref2", p2, 1);
211 CHECK_BLOCKS("ref2", r1, 2);
213 fprintf(stderr, "Freeing ref\n");
214 talloc_unlink(r1, ref);
215 talloc_report_full(root, stderr);
217 CHECK_BLOCKS("ref2", p1, 5);
218 CHECK_BLOCKS("ref2", p2, 1);
219 CHECK_BLOCKS("ref2", r1, 1);
221 fprintf(stderr, "Freeing p2\n");
223 talloc_report_full(root, stderr);
225 CHECK_BLOCKS("ref2", p1, 4);
226 CHECK_BLOCKS("ref2", r1, 1);
228 fprintf(stderr, "Freeing p1\n");
230 talloc_report_full(root, stderr);
232 CHECK_BLOCKS("ref2", r1, 1);
234 fprintf(stderr, "Freeing r1\n");
236 talloc_report_full(root, stderr);
238 CHECK_SIZE("ref2", root, 0);
241 printf("success: ref2\n");
248 static bool test_ref3(void)
250 void *root, *p1, *p2, *ref, *r1;
252 printf("test: ref3\n# PARENT REFERENCE FREE\n");
254 root = talloc_named_const(NULL, 0, "root");
255 p1 = talloc_named_const(root, 1, "p1");
256 p2 = talloc_named_const(root, 1, "p2");
257 r1 = talloc_named_const(p1, 1, "r1");
258 ref = talloc_reference(p2, r1);
259 talloc_report_full(root, stderr);
261 CHECK_BLOCKS("ref3", p1, 2);
262 CHECK_BLOCKS("ref3", p2, 2);
263 CHECK_BLOCKS("ref3", r1, 1);
265 fprintf(stderr, "Freeing p1\n");
267 talloc_report_full(root, stderr);
269 CHECK_BLOCKS("ref3", p2, 2);
270 CHECK_BLOCKS("ref3", r1, 1);
272 fprintf(stderr, "Freeing p2\n");
274 talloc_report_full(root, stderr);
276 CHECK_SIZE("ref3", root, 0);
280 printf("success: ref3\n");
287 static bool test_ref4(void)
289 void *root, *p1, *p2, *ref, *r1;
291 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
293 root = talloc_named_const(NULL, 0, "root");
294 p1 = talloc_named_const(root, 1, "p1");
295 talloc_named_const(p1, 1, "x1");
296 talloc_named_const(p1, 1, "x2");
297 talloc_named_const(p1, 1, "x3");
298 p2 = talloc_named_const(p1, 1, "p2");
300 r1 = talloc_named_const(root, 1, "r1");
301 ref = talloc_reference(r1, p2);
302 talloc_report_full(root, stderr);
304 CHECK_BLOCKS("ref4", p1, 5);
305 CHECK_BLOCKS("ref4", p2, 1);
306 CHECK_BLOCKS("ref4", r1, 2);
308 fprintf(stderr, "Freeing r1\n");
310 talloc_report_full(root, stderr);
312 CHECK_BLOCKS("ref4", p1, 5);
313 CHECK_BLOCKS("ref4", p2, 1);
315 fprintf(stderr, "Freeing p2\n");
317 talloc_report_full(root, stderr);
319 CHECK_BLOCKS("ref4", p1, 4);
321 fprintf(stderr, "Freeing p1\n");
323 talloc_report_full(root, stderr);
325 CHECK_SIZE("ref4", root, 0);
329 printf("success: ref4\n");
337 static bool test_unlink1(void)
339 void *root, *p1, *p2, *ref, *r1;
341 printf("test: unlink\n# UNLINK\n");
343 root = talloc_named_const(NULL, 0, "root");
344 p1 = talloc_named_const(root, 1, "p1");
345 talloc_named_const(p1, 1, "x1");
346 talloc_named_const(p1, 1, "x2");
347 talloc_named_const(p1, 1, "x3");
348 p2 = talloc_named_const(p1, 1, "p2");
350 r1 = talloc_named_const(p1, 1, "r1");
351 ref = talloc_reference(r1, p2);
352 talloc_report_full(root, stderr);
354 CHECK_BLOCKS("unlink", p1, 7);
355 CHECK_BLOCKS("unlink", p2, 1);
356 CHECK_BLOCKS("unlink", r1, 2);
358 fprintf(stderr, "Unreferencing r1\n");
359 talloc_unlink(r1, p2);
360 talloc_report_full(root, stderr);
362 CHECK_BLOCKS("unlink", p1, 6);
363 CHECK_BLOCKS("unlink", p2, 1);
364 CHECK_BLOCKS("unlink", r1, 1);
366 fprintf(stderr, "Freeing p1\n");
368 talloc_report_full(root, stderr);
370 CHECK_SIZE("unlink", root, 0);
374 printf("success: unlink\n");
378 static int fail_destructor(void *ptr)
384 miscellaneous tests to try to get a higher test coverage percentage
386 static bool test_misc(void)
393 printf("test: misc\n# MISCELLANEOUS\n");
395 root = talloc_new(NULL);
397 p1 = talloc_size(root, 0x7fffffff);
398 torture_assert("misc", !p1, "failed: large talloc allowed\n");
400 p1 = talloc_strdup(root, "foo");
401 talloc_increase_ref_count(p1);
402 talloc_increase_ref_count(p1);
403 talloc_increase_ref_count(p1);
404 CHECK_BLOCKS("misc", NULL, 7);
405 CHECK_BLOCKS("misc", p1, 1);
406 CHECK_BLOCKS("misc", root, 2);
407 talloc_unlink(NULL, p1);
408 CHECK_BLOCKS("misc", NULL, 6);
409 CHECK_BLOCKS("misc", p1, 1);
410 CHECK_BLOCKS("misc", root, 2);
411 p2 = talloc_strdup(p1, "foo");
412 torture_assert("misc", talloc_unlink(root, p2) == -1,
413 "failed: talloc_unlink() of non-reference context should return -1\n");
414 torture_assert("misc", talloc_unlink(p1, p2) == 0,
415 "failed: talloc_unlink() of parent should succeed\n");
417 CHECK_BLOCKS("misc", NULL, 6);
418 CHECK_BLOCKS("misc", p1, 1);
419 CHECK_BLOCKS("misc", root, 1);
420 talloc_unlink(NULL, p1);
421 CHECK_BLOCKS("misc", NULL, 5);
422 CHECK_BLOCKS("misc", p1, 1);
423 CHECK_BLOCKS("misc", root, 1);
425 name = talloc_set_name(p1, "my name is %s", "foo");
426 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
427 "failed: wrong name after talloc_set_name(my name is foo)");
428 CHECK_BLOCKS("misc", NULL, 6);
429 CHECK_BLOCKS("misc", p1, 2);
430 CHECK_BLOCKS("misc", root, 1);
432 talloc_set_name_const(p1, NULL);
433 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
434 "failed: wrong name after talloc_set_name(NULL)");
435 CHECK_BLOCKS("misc", NULL, 6);
436 CHECK_BLOCKS("misc", p1, 2);
437 CHECK_BLOCKS("misc", root, 1);
439 torture_assert("misc", talloc_free(NULL) == -1,
440 "talloc_free(NULL) should give -1\n");
442 talloc_set_destructor(p1, fail_destructor);
443 torture_assert("misc", talloc_unlink(NULL, p1) == -1,
444 "Failed destructor should cause talloc_unlink to fail\n");
445 talloc_set_destructor(p1, NULL);
446 CHECK_BLOCKS("misc", NULL, 6);
447 CHECK_BLOCKS("misc", p1, 2);
448 CHECK_BLOCKS("misc", root, 1);
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");
482 CHECK_BLOCKS("misc", NULL, 7);
483 talloc_unlink(NULL, p1);
484 CHECK_BLOCKS("misc", NULL, 3);
485 CHECK_BLOCKS("misc", root, 1);
487 p1 = talloc_named(root, 100, "%d bytes", 100);
488 CHECK_BLOCKS("misc", NULL, 5);
489 CHECK_BLOCKS("misc", p1, 2);
490 CHECK_BLOCKS("misc", root, 3);
491 talloc_unlink(root, p1);
492 CHECK_BLOCKS("misc", NULL, 3);
493 CHECK_BLOCKS("misc", root, 1);
495 p1 = talloc_init("%d bytes", 200);
496 p2 = talloc_asprintf(p1, "my test '%s'", "string");
497 torture_assert_str_equal("misc", p2, "my test 'string'",
498 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
499 CHECK_BLOCKS("misc", p1, 3);
500 CHECK_SIZE("misc", p2, 17);
501 CHECK_BLOCKS("misc", root, 1);
502 talloc_unlink(NULL, p1);
504 p1 = talloc_named_const(root, 10, "p1");
505 p2 = (char *)talloc_named_const(root, 20, "p2");
506 (void)talloc_reference(p1, p2);
507 talloc_report_full(root, stderr);
508 talloc_unlink(root, p2);
509 talloc_report_full(root, stderr);
510 CHECK_BLOCKS("misc", p2, 1);
511 CHECK_BLOCKS("misc", p1, 2);
512 CHECK_BLOCKS("misc", root, 3);
513 talloc_unlink(p1, p2);
514 talloc_unlink(root, p1);
516 p1 = talloc_named_const(root, 10, "p1");
517 p2 = (char *)talloc_named_const(root, 20, "p2");
518 (void)talloc_reference(NULL, p2);
519 talloc_report_full(root, stderr);
520 talloc_unlink(root, p2);
521 talloc_report_full(root, stderr);
522 CHECK_BLOCKS("misc", p2, 1);
523 CHECK_BLOCKS("misc", p1, 1);
524 CHECK_BLOCKS("misc", root, 2);
525 talloc_unlink(NULL, p2);
526 talloc_unlink(root, p1);
528 /* Test that talloc_unlink is a no-op */
530 torture_assert("misc", talloc_unlink(root, NULL) == -1,
531 "failed: talloc_unlink(root, NULL) == -1\n");
533 talloc_report(root, stderr);
534 talloc_report(NULL, stderr);
536 CHECK_SIZE("misc", root, 0);
540 CHECK_SIZE("misc", NULL, 0);
542 talloc_enable_leak_report();
543 talloc_enable_leak_report_full();
545 printf("success: misc\n");
554 static bool test_realloc(void)
556 void *root, *p1, *p2;
558 printf("test: realloc\n# REALLOC\n");
560 root = talloc_new(NULL);
562 p1 = talloc_size(root, 10);
563 CHECK_SIZE("realloc", p1, 10);
565 p1 = talloc_realloc_size(NULL, p1, 20);
566 CHECK_SIZE("realloc", p1, 20);
570 p2 = talloc_realloc_size(p1, NULL, 30);
574 p2 = talloc_realloc_size(p1, p2, 40);
576 CHECK_SIZE("realloc", p2, 40);
577 CHECK_SIZE("realloc", root, 60);
578 CHECK_BLOCKS("realloc", p1, 4);
580 p1 = talloc_realloc_size(NULL, p1, 20);
581 CHECK_SIZE("realloc", p1, 60);
583 talloc_increase_ref_count(p2);
584 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
585 "failed: talloc_realloc() on a referenced pointer should fail\n");
586 CHECK_BLOCKS("realloc", p1, 4);
588 talloc_realloc_size(NULL, p2, 0);
589 talloc_realloc_size(NULL, p2, 0);
590 CHECK_BLOCKS("realloc", p1, 3);
592 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
593 "failed: oversize talloc should fail\n");
595 talloc_realloc_size(NULL, p1, 0);
597 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)
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 el2 = talloc(el1->list2, struct el2);
640 el2 = talloc(el1->list3, struct el2);
642 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
643 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
644 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
648 printf("success: REALLOC WITH CHILD\n");
655 static bool test_type(void)
666 printf("test: type\n# talloc type checking\n");
668 root = talloc_new(NULL);
670 el1 = talloc(root, struct el1);
674 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
675 "type check failed on el1\n");
676 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
677 "type check failed on el1 with el2\n");
678 talloc_set_type(el1, struct el2);
679 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
680 "type set failed on el1 with el2\n");
684 printf("success: type\n");
691 static bool test_steal(void)
693 void *root, *p1, *p2;
695 printf("test: steal\n# STEAL\n");
697 root = talloc_new(NULL);
699 p1 = talloc_array(root, char, 10);
700 CHECK_SIZE("steal", p1, 10);
702 p2 = talloc_realloc(root, NULL, char, 20);
703 CHECK_SIZE("steal", p1, 10);
704 CHECK_SIZE("steal", root, 30);
706 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
707 "failed: stealing NULL should give NULL\n");
709 torture_assert("steal", talloc_steal(p1, p1) == p1,
710 "failed: stealing to ourselves is a nop\n");
711 CHECK_BLOCKS("steal", root, 3);
712 CHECK_SIZE("steal", root, 30);
714 talloc_steal(NULL, p1);
715 talloc_steal(NULL, p2);
716 CHECK_BLOCKS("steal", root, 1);
717 CHECK_SIZE("steal", root, 0);
720 talloc_steal(root, p2);
721 CHECK_BLOCKS("steal", root, 2);
722 CHECK_SIZE("steal", root, 20);
726 CHECK_BLOCKS("steal", root, 1);
727 CHECK_SIZE("steal", root, 0);
731 p1 = talloc_size(NULL, 3);
732 talloc_report_full(NULL, stderr);
733 CHECK_SIZE("steal", NULL, 3);
736 printf("success: steal\n");
743 static bool test_move(void)
751 printf("test: move\n# MOVE\n");
753 root = talloc_new(NULL);
755 t1 = talloc(root, struct t_move);
756 t2 = talloc(root, struct t_move);
757 t1->p = talloc_strdup(t1, "foo");
758 t1->x = talloc(t1, int);
761 t2->p = talloc_move(t2, &t1->p);
762 t2->x = talloc_move(t2, &t1->x);
763 torture_assert("move", t1->p == NULL && t1->x == NULL &&
764 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
765 "talloc move failed");
769 printf("success: move\n");
775 test talloc_realloc_fn
777 static bool test_realloc_fn(void)
781 printf("test: realloc_fn\n# talloc_realloc_fn\n");
783 root = talloc_new(NULL);
785 p1 = talloc_realloc_fn(root, NULL, 10);
786 CHECK_BLOCKS("realloc_fn", root, 2);
787 CHECK_SIZE("realloc_fn", root, 10);
788 p1 = talloc_realloc_fn(root, p1, 20);
789 CHECK_BLOCKS("realloc_fn", root, 2);
790 CHECK_SIZE("realloc_fn", root, 20);
791 p1 = talloc_realloc_fn(root, p1, 0);
792 CHECK_BLOCKS("realloc_fn", root, 1);
793 CHECK_SIZE("realloc_fn", root, 0);
797 printf("success: realloc_fn\n");
802 static bool test_unref_reparent(void)
804 void *root, *p1, *p2, *c1;
806 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
808 root = talloc_named_const(NULL, 0, "root");
809 p1 = talloc_named_const(root, 1, "orig parent");
810 p2 = talloc_named_const(root, 1, "parent by reference");
812 c1 = talloc_named_const(p1, 1, "child");
813 CHECK_BLOCKS("unref_reparent", root, 4);
814 CHECK_SIZE("unref_reparent", root, 3);
815 talloc_reference(p2, c1);
816 CHECK_BLOCKS("unref_reparent", root, 5);
817 CHECK_SIZE("unref_reparent", root, 3);
819 CHECK_BLOCKS("unref_reparent", root, 5);
820 CHECK_SIZE("unref_reparent", root, 3);
821 CHECK_PARENT("unref_reparent", c1, p1);
825 CHECK_BLOCKS("unref_reparent", root, 3);
826 CHECK_SIZE("unref_reparent", root, 1);
827 CHECK_NOT_PARENT("unref_reparent", c1, p2);
829 talloc_unlink(p2, c1);
831 CHECK_BLOCKS("unref_reparent", root, 2);
832 CHECK_SIZE("unref_reparent", root, 1);
837 printf("success: unref_reparent\n");
841 /* If a referenced allocation is explicitly freed the new owner
842 should be the same as if the same allocation is implicitly freed
843 (because it's owner was freed).
844 Traditionally in talloc an explicit free will free the top non-child reference
845 but an implicit free will move the top (any) reference to be the new owner */
846 static bool test_implicit_explicit_free(void)
848 void *root, *p1, *p2, *p3, *ref, *r1;
851 printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE IMPLICIT FREE\n");
853 root = talloc_named_const(NULL, 0, "root");
854 p1 = talloc_named_const(root, 1, "p1");
855 p2 = talloc_named_const(p1, 1, "p2");
856 /* Now root owns p1, and p1 owns p2 */
858 r1 = talloc_named_const(root, 1, "r1");
859 ref = talloc_reference(r1, p2);
860 /* now r1 has ref reference to p2 */
861 talloc_report_full(root, stderr);
863 CHECK_BLOCKS(__FUNCTION__, p1, 2);
864 CHECK_BLOCKS(__FUNCTION__, p2, 1);
865 CHECK_BLOCKS(__FUNCTION__, r1, 2);
867 fprintf(stderr, "Freeing p2\n");
869 /* how many blocks is r1 taking against p2 ? */
870 e=talloc_total_blocks(r1);
872 talloc_report_full(root, stderr);
875 /* now repeat, but this time free p1 */
876 printf("# SINGLE REFERENCE EXPLICIT FREE\n");
878 root = talloc_named_const(NULL, 0, "root");
879 p1 = talloc_named_const(root, 1, "p1");
880 p2 = talloc_named_const(p1, 1, "p2");
881 /* Now root owns p1, and p1 owns p2 */
883 r1 = talloc_named_const(root, 1, "r1");
884 ref = talloc_reference(r1, p2);
885 /* now r1 has ref reference to p2 */
886 talloc_report_full(NULL, stderr);
888 CHECK_BLOCKS(__FUNCTION__, p1, 2);
889 CHECK_BLOCKS(__FUNCTION__, p2, 1);
890 CHECK_BLOCKS(__FUNCTION__, r1, 2);
892 fprintf(stderr, "Freeing p1\n");
894 /* how many blocks is r1 taking against p2 ? */
895 i=talloc_total_blocks(r1);
896 talloc_report_full(NULL, stderr);
898 CHECK_BLOCKS(__FUNCTION__,r1, e);
902 printf("success: test_implicit_explicit_free\n");
906 /* If take r1 reference to p2 and then free p2's parent
907 p2 should still be around by virtue of the reference.
908 In current talloc r1 will be the parent
909 In proposed talloc r1 will be the reference with no parent */
910 static bool test_ref_free_owner(void)
912 void *root, *p1, *p2, *ref, *r1;
914 printf("test: ref_free_owner\n# SINGLE REFERENCE FREE OWNER FREE\n");
916 root = talloc_named_const(NULL, 0, "root");
917 p1 = talloc_named_const(root, 1, "p1");
918 p2 = talloc_named_const(p1, 1, "p2");
919 /* Now root owns p1 ,and p2 owns p2 */
921 r1 = talloc_named_const(root, 1, "r1");
922 ref = talloc_reference(r1, p2);
923 /* now r1 has ref reference to p2 */
924 talloc_report_full(root, stderr);
926 CHECK_BLOCKS(__FUNCTION__, NULL, 7);
927 CHECK_BLOCKS(__FUNCTION__, p1, 2);
928 CHECK_BLOCKS(__FUNCTION__, p2, 1);
929 CHECK_BLOCKS(__FUNCTION__, r1, 2);
931 fprintf(stderr, "Freeing p1\n");
933 /* r1 should have ref reference to p2 still */
934 talloc_report_full(NULL, stderr);
935 CHECK_BLOCKS(__FUNCTION__, NULL, 6);
936 CHECK_BLOCKS(__FUNCTION__, r1, 2);
937 CHECK_BLOCKS(__FUNCTION__, p2, 1);
939 /* if we free r1 then p2 should vanish */
940 fprintf(stderr, "Freeing r1\n");
943 talloc_report_full(NULL, stderr);
944 CHECK_BLOCKS(__FUNCTION__, NULL, 3);
945 CHECK_BLOCKS(__FUNCTION__, root, 1);
948 printf("success: ref_free_owner\n");
952 /* If take r1 reference to p2 and then free p2
953 p2 should still be around by virtue of the reference.
954 In current talloc r1 will be the parent
955 In proposed talloc r1 will be the reference with no parent */
956 static bool test_ref_free_self(void)
958 void *root, *p1, *p2, *ref, *r1;
960 printf("test: ref_free_self\n# SINGLE REFERENCE FREE SELF FREE\n");
962 root = talloc_named_const(NULL, 0, "root");
963 p1 = talloc_named_const(root, 1, "p1");
964 p2 = talloc_named_const(p1, 1, "p2");
965 /* Now root owns p1, and p1 owns p2 */
967 r1 = talloc_named_const(root, 1, "r1");
968 ref = talloc_reference(r1, p2);
969 /* now r1 has ref reference to p2 */
970 talloc_report_full(NULL, stderr);
972 CHECK_BLOCKS(__FUNCTION__, NULL, 7);
973 CHECK_BLOCKS(__FUNCTION__, p1, 2);
974 CHECK_BLOCKS(__FUNCTION__, p2, 1);
975 CHECK_BLOCKS(__FUNCTION__, r1, 2);
977 fprintf(stderr, "Freeing p2\n");
979 /* r1 should have ref reference to p2 still */
980 talloc_report_full(NULL, stderr);
981 CHECK_BLOCKS(__FUNCTION__, NULL, 7);
982 CHECK_BLOCKS(__FUNCTION__, p1, 1);
983 CHECK_BLOCKS(__FUNCTION__, p2, 1);
984 CHECK_BLOCKS(__FUNCTION__, r1, 2);
986 /* if we free r1 then p2 should also vanish */
987 fprintf(stderr, "Freeing r1\n");
990 fprintf(stderr, "Checking that p1 is empty and freeing p1\n");
991 CHECK_BLOCKS(__FUNCTION__, NULL, 4);
992 CHECK_BLOCKS(__FUNCTION__, p1, 1);
995 talloc_report_full(NULL, stderr);
996 CHECK_BLOCKS(__FUNCTION__, NULL, 3);
997 CHECK_BLOCKS(__FUNCTION__, root, 1);
1000 CHECK_BLOCKS(__FUNCTION__, NULL, 2);
1001 printf("success: ref_free_self\n");
1005 /* check that an allocation that is freed while also referenced finally goes
1006 away when the reference is released */
1007 static bool test_ref_free(void)
1009 void *root, *p1, *p2, *ref, *r1;
1011 printf("test: test_ref_free\n# FREE ON SINGLE REFERENCE FREE\n");
1013 root = talloc_named_const(NULL, 0, "root");
1014 p1 = talloc_named_const(root, 1, "p1");
1015 p2 = talloc_named_const(p1, 1, "p2");
1016 /* Now root owns p1, and p1 owns p2 */
1018 r1 = talloc_named_const(root, 1, "r1");
1019 ref = talloc_reference(r1, p2);
1020 /* now r1 has ref reference to p2 */
1021 talloc_report_full(root, stderr);
1023 CHECK_BLOCKS(__FUNCTION__, p1, 2);
1024 CHECK_BLOCKS(__FUNCTION__, p2, 1);
1025 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1027 fprintf(stderr, "Freeing p2\n");
1029 /* r1 should have ref reference to p2 still */
1030 talloc_report_full(root, stderr);
1032 CHECK_BLOCKS(__FUNCTION__, p1, 1);
1033 CHECK_BLOCKS(__FUNCTION__, root, 4);
1034 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1036 /* if we free r1 then p2 should also vanish */
1037 fprintf(stderr, "Freeing r1\n");
1039 /* p2 should have gone away */
1040 talloc_report_full(NULL, stderr);
1041 CHECK_BLOCKS(__FUNCTION__, root, 2);
1042 CHECK_BLOCKS(__FUNCTION__, p1, 1);
1045 printf("success: test_ref_free\n");
1049 /* If an object having references from children that are also referenced is
1050 freed, the child reference will be removed, but the child will survive
1051 (because of it's reference) and the object will still be freed leaving
1052 a dangling reference */
1053 static bool test_dangling_loop(void)
1055 void *root, *p1, *p2, *ref, *r1, *r2;
1057 printf("test: %s\n# FREE ON SINGLE REFERENCE FREE\n",__FUNCTION__);
1059 root = talloc_named_const(NULL, 0, "root");
1060 p1 = talloc_named_const(root, 1, "p1");
1061 p2 = talloc_named_const(p1, 1, "p2");
1062 /* Now root owns p1, and p1 owns p2 */
1064 /* someone takes a ref on p2 */
1065 r1 = talloc_named_const(root, 1, "r1");
1066 ref = talloc_reference(r1, p2);
1068 /* p2 takes a ref on p1 */
1069 talloc_reference(p2, p1);
1071 talloc_report_full(NULL, stderr);
1073 CHECK_BLOCKS(__FUNCTION__, root, 6);
1074 CHECK_BLOCKS(__FUNCTION__, p1, 3);
1075 CHECK_BLOCKS(__FUNCTION__, p2, 2);
1076 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1078 /* talloc will wrongly spot a loop and free p2's ref, and then p1
1079 leaving a dangling pointer */
1080 fprintf(stderr, "Freeing p1\n");
1082 /* p1 should not get freed as it is referenced from something (a child) that won't free */
1083 /* r1 should have ref reference to p2 still */
1084 talloc_report_full(NULL, stderr);
1086 CHECK_BLOCKS(__FUNCTION__, root, 3);
1087 /* The ugly talloc de-child-looping code will delete p2's reference
1088 leaving p2 having a dangling pointer. p2's reference should remain */
1089 /* TODO change this back to 2 when the loop detection is working */
1090 CHECK_BLOCKS(__FUNCTION__, p2, 1);
1091 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1093 /* if we free r1 then p2 should also vanish as it is owned by something that
1094 is not owned, but we can't track that yet. Once p2 vanishes it's reference
1095 to p1 should vanish letting p1 vanish.
1096 We can often make sub-tree's from no-owner-context, by checking when references
1097 of things child-of no-owner-context die
1099 fprintf(stderr, "Freeing r1\n");
1101 talloc_report_full(NULL, stderr);
1102 CHECK_BLOCKS(__FUNCTION__, root, 1);
1105 printf("success: %s\n", __FUNCTION__);
1107 talloc_report_full(NULL, stderr);
1111 /* If take r1 reference to p2 and then free p2's owner p1
1112 p2 should still be around by virtue of the reference.
1113 steal p2 to p3 and free p3.
1114 In current talloc p2 will be freed despite the reference.
1115 In proposed talloc r1 will be the reference with no parent for p2*/
1116 static bool test_ref_free_steal(void)
1118 void *root, *p1, *p2, *p3, *ref, *r1;
1120 printf("test: ref_free_steal\n# SINGLE REFERENCE FREE SELF FREE\n");
1122 root = talloc_named_const(NULL, 0, "root");
1123 p1 = talloc_named_const(root, 1, "p1");
1124 p2 = talloc_named_const(p1, 1, "p2");
1125 p3 = talloc_named_const(root, 1, "p3");
1126 /* Now root owns p1, and p1 owns p2 */
1128 r1 = talloc_named_const(root, 1, "r1");
1129 ref = talloc_reference(r1, p2);
1130 /* now r1 has ref reference to p2 */
1131 talloc_report_full(NULL, stderr);
1133 CHECK_BLOCKS(__FUNCTION__, p1, 2);
1134 CHECK_BLOCKS(__FUNCTION__, p2, 1);
1135 CHECK_BLOCKS(__FUNCTION__, p3, 1);
1136 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1138 fprintf(stderr, "Freeing p1\n");
1140 /* r1 should have ref reference to p2 still */
1141 talloc_report_full(NULL, stderr);
1142 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1143 CHECK_BLOCKS(__FUNCTION__, p3, 1);
1145 /* if we talloc_steal p2 to p3, we should get an abort() */
1146 fprintf(stderr, "Steal p2 to p3\n");
1148 talloc_steal(p3, p2);
1149 torture_assert(__FUNCTION__,
1150 test_abort_count == 1,
1151 "talloc_steal() didn't abort");
1154 talloc_report_full(NULL, stderr);
1155 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1156 CHECK_BLOCKS(__FUNCTION__, p3, 1);
1158 /* but we can reference p2 to p3 */
1159 fprintf(stderr, "Steal p2 to p3\n");
1160 talloc_reference(p3, p2);
1162 talloc_report_full(NULL, stderr);
1163 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1164 CHECK_BLOCKS(__FUNCTION__, p3, 2);
1166 /* now we free p3 and r1 should still have a reference */
1167 fprintf(stderr, "free p3\n");
1169 talloc_report_full(NULL, stderr);
1170 CHECK_BLOCKS(__FUNCTION__, p2, 1);
1171 CHECK_BLOCKS(__FUNCTION__, r1, 2);
1173 /* if we free r1 then p2 should also vanish */
1174 fprintf(stderr, "Freeing r1\n");
1177 talloc_report_full(NULL, stderr);
1178 CHECK_BLOCKS(__FUNCTION__, NULL, 3);
1179 CHECK_BLOCKS(__FUNCTION__, root, 1);
1182 CHECK_BLOCKS(__FUNCTION__, NULL, 2);
1183 printf("success: ref_free_steal\n");
1188 measure the speed of talloc versus malloc
1190 static bool test_speed(void)
1192 void *ctx = talloc_new(NULL);
1194 const int loop = 1000;
1198 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
1200 tv = timeval_current();
1204 for (i=0;i<loop;i++) {
1205 p1 = talloc_size(ctx, loop % 100);
1206 p2 = talloc_strdup(p1, "foo bar");
1207 p3 = talloc_size(p1, 300);
1211 } while (timeval_elapsed(&tv) < 5.0);
1213 fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1217 ctx = talloc_pool(NULL, 1024);
1219 tv = timeval_current();
1223 for (i=0;i<loop;i++) {
1224 p1 = talloc_size(ctx, loop % 100);
1225 p2 = talloc_strdup(p1, "foo bar");
1226 p3 = talloc_size(p1, 300);
1227 talloc_free_children(ctx);
1230 } while (timeval_elapsed(&tv) < 5.0);
1234 fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1236 tv = timeval_current();
1240 for (i=0;i<loop;i++) {
1241 p1 = malloc(loop % 100);
1242 p2 = strdup("foo bar");
1249 } while (timeval_elapsed(&tv) < 5.0);
1250 fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
1252 printf("success: speed\n");
1257 static bool test_lifeless(void)
1259 void *top = talloc_named_const(NULL, 0, "top");
1260 char *parent, *child;
1261 void *child_owner = talloc_named_const(NULL, 0, "child_owner");
1263 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
1265 parent = talloc_strdup(top, "parent");
1266 CHECK_BLOCKS("lifeless", NULL, 5);
1267 child = talloc_strdup(parent, "child");
1268 CHECK_BLOCKS("lifeless", NULL, 6);
1269 (void)talloc_reference(child, parent);
1270 CHECK_BLOCKS("lifeless", NULL, 7);
1271 (void)talloc_reference(child_owner, child);
1272 CHECK_BLOCKS("lifeless", NULL, 8);
1273 CHECK_BLOCKS("lifeless", top, 4);
1274 CHECK_BLOCKS("lifeless", child_owner, 2);
1275 talloc_unlink(top, parent);
1276 CHECK_BLOCKS("lifeless", NULL, 8);
1277 CHECK_BLOCKS("lifeless", top, 1);
1278 CHECK_BLOCKS("lifeless", child_owner, 2);
1279 CHECK_BLOCKS("lifeless", child, 2);
1281 CHECK_BLOCKS("lifeless", NULL, 8);
1282 CHECK_BLOCKS("lifeless", top, 1);
1283 CHECK_BLOCKS("lifeless", child_owner, 2);
1284 CHECK_BLOCKS("lifeless", child, 2);
1286 CHECK_BLOCKS("lifeless", NULL, 7);
1287 CHECK_BLOCKS("lifeless", child_owner, 2);
1288 CHECK_BLOCKS("lifeless", child, 2);
1289 talloc_free(child_owner);
1290 CHECK_BLOCKS("lifeless", NULL, 2);
1292 printf("success: lifeless\n");
1296 static int loop_destructor_count;
1298 static int test_loop_destructor(char *ptr)
1300 loop_destructor_count++;
1304 static bool test_loop(void)
1306 void *top = talloc_new(NULL);
1312 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
1314 parent = talloc_strdup(top, "parent");
1315 req1 = talloc(parent, struct req1);
1316 req1->req2 = talloc_strdup(req1, "req2");
1317 talloc_set_destructor(req1->req2, test_loop_destructor);
1318 req1->req3 = talloc_strdup(req1, "req3");
1319 (void)talloc_reference(req1->req3, req1);
1320 talloc_report_full(top, stderr);
1321 talloc_free(parent);
1322 talloc_report_full(top, stderr);
1323 talloc_report_full(NULL, stderr);
1326 torture_assert("loop", loop_destructor_count == 1,
1327 "FAILED TO FIRE LOOP DESTRUCTOR\n");
1328 loop_destructor_count = 0;
1330 printf("success: loop\n");
1334 static int fail_destructor_str(char *ptr)
1339 static bool test_free_parent_deny_child(void)
1341 void *top = talloc_new(NULL);
1346 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1348 level1 = talloc_strdup(top, "level1");
1349 level2 = talloc_strdup(level1, "level2");
1350 level3 = talloc_strdup(level2, "level3");
1352 talloc_set_destructor(level3, fail_destructor_str);
1353 talloc_free(level1);
1354 talloc_set_destructor(level3, NULL);
1356 CHECK_PARENT("free_parent_deny_child", level3, top);
1360 printf("success: free_parent_deny_child\n");
1364 static bool test_talloc_ptrtype(void)
1366 void *top = talloc_new(NULL);
1370 } *s1, *s2, **s3, ***s4;
1371 const char *location1;
1372 const char *location2;
1373 const char *location3;
1374 const char *location4;
1376 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1378 s1 = talloc_ptrtype(top, s1);location1 = __location__;
1380 if (talloc_get_size(s1) != sizeof(struct struct1)) {
1381 printf("failure: ptrtype [\n"
1382 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1383 "]\n", (unsigned long)talloc_get_size(s1),
1384 (unsigned long)sizeof(struct struct1));
1388 if (strcmp(location1, talloc_get_name(s1)) != 0) {
1389 printf("failure: ptrtype [\n"
1390 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1391 talloc_get_name(s1), location1);
1395 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1397 if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1398 printf("failure: ptrtype [\n"
1399 "talloc_array_ptrtype() allocated the wrong size "
1400 "%lu (should be %lu)\n]\n",
1401 (unsigned long)talloc_get_size(s2),
1402 (unsigned long)(sizeof(struct struct1)*10));
1406 if (strcmp(location2, talloc_get_name(s2)) != 0) {
1407 printf("failure: ptrtype [\n"
1408 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1409 talloc_get_name(s2), location2);
1413 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1415 if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1416 printf("failure: ptrtype [\n"
1417 "talloc_array_ptrtype() allocated the wrong size "
1418 "%lu (should be %lu)\n]\n",
1419 (unsigned long)talloc_get_size(s3),
1420 (unsigned long)(sizeof(struct struct1 *)*10));
1424 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1425 "talloc_array_ptrtype() sets the wrong name");
1427 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1429 if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1430 printf("failure: ptrtype [\n"
1431 "talloc_array_ptrtype() allocated the wrong size "
1432 "%lu (should be %lu)\n]\n",
1433 (unsigned long)talloc_get_size(s4),
1434 (unsigned long)(sizeof(struct struct1 **)*10));
1438 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1439 "talloc_array_ptrtype() sets the wrong name");
1443 printf("success: ptrtype\n");
1447 static int _test_talloc_free_in_destructor(void **ptr)
1453 static bool test_talloc_free_in_destructor(void)
1462 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1464 level0 = talloc_new(NULL);
1465 level1 = talloc_new(level0);
1466 level2 = talloc_new(level1);
1467 level3 = talloc_new(level2);
1468 level4 = talloc_new(level3);
1469 level5 = talloc(level4, void *);
1472 (void)talloc_reference(level0, level3);
1473 (void)talloc_reference(level3, level3);
1474 (void)talloc_reference(level5, level3);
1476 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1478 talloc_free(level1);
1480 talloc_free(level0);
1482 printf("success: free_in_destructor\n");
1486 static bool test_autofree(void)
1488 #if _SAMBA_BUILD_ < 4
1489 /* autofree test would kill smbtorture */
1491 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1493 p = talloc_autofree_context();
1496 p = talloc_autofree_context();
1499 printf("success: autofree\n");
1504 static bool test_pool(void)
1507 void *p1, *p2, *p3, *p4;
1509 pool = talloc_pool(NULL, 1024);
1511 p1 = talloc_size(pool, 80);
1512 p2 = talloc_size(pool, 20);
1513 p3 = talloc_size(p1, 50);
1514 p4 = talloc_size(p3, 1000);
1521 static void test_reset(void)
1524 talloc_disable_null_tracking();
1525 talloc_enable_null_tracking();
1528 struct torture_context;
1529 bool torture_local_talloc(struct torture_context *tctx)
1544 ret &= test_unlink1();
1548 ret &= test_realloc();
1550 ret &= test_realloc_child();
1552 ret &= test_steal();
1556 ret &= test_unref_reparent();
1558 ret &= test_realloc_fn();
1562 ret &= test_lifeless();
1566 ret &= test_free_parent_deny_child();
1568 ret &= test_talloc_ptrtype();
1570 ret &= test_talloc_free_in_destructor();
1572 ret &= test_implicit_explicit_free();
1574 ret &= test_ref_free_steal();
1576 ret &= test_dangling_loop();
1578 ret &= test_ref_free_owner();
1580 ret &= test_ref_free_self();
1582 ret &= test_ref_free();
1588 ret &= test_speed();
1591 ret &= test_autofree();