2 Unix SMB/CIFS implementation.
4 local testing of talloc routines.
6 Copyright (C) Andrew Tridgell 2004
7 Converted to ccan tests by Rusty Russell 2008
9 ** NOTE! The following LGPL license applies to the talloc
10 ** library. This does NOT imply that all of Samba is released
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <ccan/talloc/talloc.c>
30 #include <ccan/tap/tap.h>
32 #define torture_assert(test, expr, str) \
33 ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \
34 test, __location__, #expr, str)
36 #define torture_assert_str_equal(test, arg1, arg2, desc) \
37 ok(strcmp(arg1, arg2) == 0, \
38 "%s [\n%s: Expected %s, got %s: %s\n]\n", \
39 test, __location__, arg1, arg2, desc)
41 #define CHECK_SIZE(test, ptr, tsize) \
42 ok(talloc_total_size(ptr) == (tsize), \
43 "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \
45 (unsigned)talloc_total_size(ptr), \
48 #define CHECK_BLOCKS(test, ptr, tblocks) \
49 ok(talloc_total_blocks(ptr) == (tblocks), \
50 "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \
52 (unsigned)talloc_total_blocks(ptr), \
55 #define CHECK_PARENT(test, ptr, parent) \
56 ok(talloc_parent(ptr) == (parent), \
57 "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \
62 struct torture_context;
67 static bool test_ref1(const struct torture_context *ctx)
69 void *root, *p1, *p2, *ref, *r1;
71 root = talloc_named_const(ctx, 0, "root");
72 p1 = talloc_named_const(root, 1, "p1");
73 p2 = talloc_named_const(p1, 1, "p2");
74 talloc_named_const(p1, 1, "x1");
75 talloc_named_const(p1, 2, "x2");
76 talloc_named_const(p1, 3, "x3");
78 r1 = talloc_named_const(root, 1, "r1");
79 ref = talloc_reference(r1, p2);
81 CHECK_BLOCKS("ref1", p1, 5);
82 CHECK_BLOCKS("ref1", p2, 1);
83 CHECK_BLOCKS("ref1", r1, 2);
87 CHECK_BLOCKS("ref1", p1, 5);
88 CHECK_BLOCKS("ref1", p2, 1);
89 CHECK_BLOCKS("ref1", r1, 1);
93 CHECK_BLOCKS("ref1", r1, 1);
97 if (talloc_reference(root, NULL)) {
101 CHECK_BLOCKS("ref1", root, 1);
103 CHECK_SIZE("ref1", root, 0);
112 static bool test_ref2(const struct torture_context *ctx)
114 void *root, *p1, *p2, *ref, *r1;
116 root = talloc_named_const(ctx, 0, "root");
117 p1 = talloc_named_const(root, 1, "p1");
118 talloc_named_const(p1, 1, "x1");
119 talloc_named_const(p1, 1, "x2");
120 talloc_named_const(p1, 1, "x3");
121 p2 = talloc_named_const(p1, 1, "p2");
123 r1 = talloc_named_const(root, 1, "r1");
124 ref = talloc_reference(r1, p2);
126 CHECK_BLOCKS("ref2", p1, 5);
127 CHECK_BLOCKS("ref2", p2, 1);
128 CHECK_BLOCKS("ref2", r1, 2);
132 CHECK_BLOCKS("ref2", p1, 5);
133 CHECK_BLOCKS("ref2", p2, 1);
134 CHECK_BLOCKS("ref2", r1, 1);
138 CHECK_BLOCKS("ref2", p1, 4);
139 CHECK_BLOCKS("ref2", r1, 1);
143 CHECK_BLOCKS("ref2", r1, 1);
147 CHECK_SIZE("ref2", root, 0);
156 static bool test_ref3(const struct torture_context *ctx)
158 void *root, *p1, *p2, *ref, *r1;
160 root = talloc_named_const(ctx, 0, "root");
161 p1 = talloc_named_const(root, 1, "p1");
162 p2 = talloc_named_const(root, 1, "p2");
163 r1 = talloc_named_const(p1, 1, "r1");
164 ref = talloc_reference(p2, r1);
166 CHECK_BLOCKS("ref3", p1, 2);
167 CHECK_BLOCKS("ref3", p2, 2);
168 CHECK_BLOCKS("ref3", r1, 1);
172 CHECK_BLOCKS("ref3", p2, 2);
173 CHECK_BLOCKS("ref3", r1, 1);
177 CHECK_SIZE("ref3", root, 0);
187 static bool test_ref4(const struct torture_context *ctx)
189 void *root, *p1, *p2, *ref, *r1;
191 root = talloc_named_const(ctx, 0, "root");
192 p1 = talloc_named_const(root, 1, "p1");
193 talloc_named_const(p1, 1, "x1");
194 talloc_named_const(p1, 1, "x2");
195 talloc_named_const(p1, 1, "x3");
196 p2 = talloc_named_const(p1, 1, "p2");
198 r1 = talloc_named_const(root, 1, "r1");
199 ref = talloc_reference(r1, p2);
201 CHECK_BLOCKS("ref4", p1, 5);
202 CHECK_BLOCKS("ref4", p2, 1);
203 CHECK_BLOCKS("ref4", r1, 2);
207 CHECK_BLOCKS("ref4", p1, 5);
208 CHECK_BLOCKS("ref4", p2, 1);
212 CHECK_BLOCKS("ref4", p1, 4);
216 CHECK_SIZE("ref4", root, 0);
227 static bool test_unlink1(const struct torture_context *ctx)
229 void *root, *p1, *p2, *ref, *r1;
231 root = talloc_named_const(ctx, 0, "root");
232 p1 = talloc_named_const(root, 1, "p1");
233 talloc_named_const(p1, 1, "x1");
234 talloc_named_const(p1, 1, "x2");
235 talloc_named_const(p1, 1, "x3");
236 p2 = talloc_named_const(p1, 1, "p2");
238 r1 = talloc_named_const(p1, 1, "r1");
239 ref = talloc_reference(r1, p2);
241 CHECK_BLOCKS("unlink", p1, 7);
242 CHECK_BLOCKS("unlink", p2, 1);
243 CHECK_BLOCKS("unlink", r1, 2);
245 talloc_unlink(r1, p2);
247 CHECK_BLOCKS("unlink", p1, 6);
248 CHECK_BLOCKS("unlink", p2, 1);
249 CHECK_BLOCKS("unlink", r1, 1);
253 CHECK_SIZE("unlink", root, 0);
260 static int fail_destructor(void *ptr)
266 miscellaneous tests to try to get a higher test coverage percentage
268 static bool test_misc(const struct torture_context *ctx)
275 root = talloc_new(ctx);
277 p1 = talloc_size(root, 0x7fffffff);
278 torture_assert("misc", !p1, "failed: large talloc allowed\n");
280 p1 = talloc_strdup(root, "foo");
281 talloc_increase_ref_count(p1);
282 talloc_increase_ref_count(p1);
283 talloc_increase_ref_count(p1);
284 CHECK_BLOCKS("misc", p1, 1);
285 CHECK_BLOCKS("misc", root, 2);
287 CHECK_BLOCKS("misc", p1, 1);
288 CHECK_BLOCKS("misc", root, 2);
289 talloc_unlink(NULL, p1);
290 CHECK_BLOCKS("misc", p1, 1);
291 CHECK_BLOCKS("misc", root, 2);
292 p2 = talloc_strdup(p1, "foo");
293 torture_assert("misc", talloc_unlink(root, p2) == -1,
294 "failed: talloc_unlink() of non-reference context should return -1\n");
295 torture_assert("misc", talloc_unlink(p1, p2) == 0,
296 "failed: talloc_unlink() of parent should succeed\n");
298 CHECK_BLOCKS("misc", p1, 1);
299 CHECK_BLOCKS("misc", root, 2);
301 name = talloc_set_name(p1, "my name is %s", "foo");
302 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
303 "failed: wrong name after talloc_set_name(my name is foo)");
304 CHECK_BLOCKS("misc", p1, 2);
305 CHECK_BLOCKS("misc", root, 3);
307 talloc_set_name_const(p1, NULL);
308 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
309 "failed: wrong name after talloc_set_name(NULL)");
310 CHECK_BLOCKS("misc", p1, 2);
311 CHECK_BLOCKS("misc", root, 3);
313 torture_assert("misc", talloc_free(NULL) == -1,
314 "talloc_free(NULL) should give -1\n");
316 talloc_set_destructor(p1, fail_destructor);
317 torture_assert("misc", talloc_free(p1) == -1,
318 "Failed destructor should cause talloc_free to fail\n");
319 talloc_set_destructor(p1, NULL);
322 p2 = (char *)talloc_zero_size(p1, 20);
323 torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
326 torture_assert("misc", talloc_strdup(root, NULL) == NULL,
327 "failed: strdup on NULL should give NULL\n");
329 p2 = talloc_strndup(p1, "foo", 2);
330 torture_assert("misc", strcmp("fo", p2) == 0,
331 "strndup doesn't work\n");
332 p2 = talloc_asprintf_append(p2, "o%c", 'd');
333 torture_assert("misc", strcmp("food", p2) == 0,
334 "talloc_asprintf_append doesn't work\n");
335 CHECK_BLOCKS("misc", p2, 1);
336 CHECK_BLOCKS("misc", p1, 3);
338 p2 = talloc_asprintf_append(NULL, "hello %s", "world");
339 torture_assert("misc", strcmp("hello world", p2) == 0,
340 "talloc_asprintf_append doesn't work\n");
341 CHECK_BLOCKS("misc", p2, 1);
342 CHECK_BLOCKS("misc", p1, 3);
345 d = talloc_array(p1, double, 0x20000000);
346 torture_assert("misc", !d, "failed: integer overflow not detected\n");
348 d = talloc_realloc(p1, d, double, 0x20000000);
349 torture_assert("misc", !d, "failed: integer overflow not detected\n");
352 CHECK_BLOCKS("misc", root, 1);
354 p1 = talloc_named(root, 100, "%d bytes", 100);
355 CHECK_BLOCKS("misc", p1, 2);
356 CHECK_BLOCKS("misc", root, 3);
357 talloc_unlink(root, p1);
359 p1 = talloc_init("%d bytes", 200);
360 p2 = talloc_asprintf(p1, "my test '%s'", "string");
361 torture_assert_str_equal("misc", p2, "my test 'string'",
362 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
363 CHECK_BLOCKS("misc", p1, 3);
364 CHECK_SIZE("misc", p2, 17);
365 CHECK_BLOCKS("misc", root, 1);
366 talloc_unlink(NULL, p1);
368 p1 = talloc_named_const(root, 10, "p1");
369 p2 = (char *)talloc_named_const(root, 20, "p2");
370 (void)talloc_reference(p1, p2);
371 talloc_unlink(root, p2);
372 CHECK_BLOCKS("misc", p2, 1);
373 CHECK_BLOCKS("misc", p1, 2);
374 CHECK_BLOCKS("misc", root, 3);
375 talloc_unlink(p1, p2);
376 talloc_unlink(root, p1);
378 p1 = talloc_named_const(root, 10, "p1");
379 p2 = (char *)talloc_named_const(root, 20, "p2");
380 (void)talloc_reference(NULL, p2);
381 talloc_unlink(root, p2);
382 CHECK_BLOCKS("misc", p2, 1);
383 CHECK_BLOCKS("misc", p1, 1);
384 CHECK_BLOCKS("misc", root, 2);
385 talloc_unlink(NULL, p2);
386 talloc_unlink(root, p1);
388 /* Test that talloc_unlink is a no-op */
390 torture_assert("misc", talloc_unlink(root, NULL) == -1,
391 "failed: talloc_unlink(root, NULL) == -1\n");
393 CHECK_SIZE("misc", root, 0);
397 CHECK_SIZE("misc", NULL, 0);
399 talloc_enable_leak_report();
400 talloc_enable_leak_report_full();
409 static bool test_realloc(const struct torture_context *ctx)
411 void *root, *p1, *p2;
413 root = talloc_new(ctx);
415 p1 = talloc_size(root, 10);
416 CHECK_SIZE("realloc", p1, 10);
418 p1 = talloc_realloc_size(NULL, p1, 20);
419 CHECK_SIZE("realloc", p1, 20);
423 p2 = talloc_realloc_size(p1, NULL, 30);
427 p2 = talloc_realloc_size(p1, p2, 40);
429 CHECK_SIZE("realloc", p2, 40);
430 CHECK_SIZE("realloc", root, 60);
431 CHECK_BLOCKS("realloc", p1, 4);
433 p1 = talloc_realloc_size(NULL, p1, 20);
434 CHECK_SIZE("realloc", p1, 60);
436 talloc_increase_ref_count(p2);
437 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
438 "failed: talloc_realloc() on a referenced pointer should fail\n");
439 CHECK_BLOCKS("realloc", p1, 4);
441 talloc_realloc_size(NULL, p2, 0);
442 talloc_realloc_size(NULL, p2, 0);
443 CHECK_BLOCKS("realloc", p1, 3);
445 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
446 "failed: oversize talloc should fail\n");
448 talloc_realloc_size(NULL, p1, 0);
450 CHECK_BLOCKS("realloc", root, 1);
451 CHECK_SIZE("realloc", root, 0);
459 test realloc with a child
461 static bool test_realloc_child(const struct torture_context *ctx)
469 struct el2 **list, **list2, **list3;
472 root = talloc_new(ctx);
474 el1 = talloc(root, struct el1);
475 el1->list = talloc(el1, struct el2 *);
476 el1->list[0] = talloc(el1->list, struct el2);
477 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
479 el1->list2 = talloc(el1, struct el2 *);
480 el1->list2[0] = talloc(el1->list2, struct el2);
481 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
483 el1->list3 = talloc(el1, struct el2 *);
484 el1->list3[0] = talloc(el1->list3, struct el2);
485 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
487 el2 = talloc(el1->list, struct el2);
488 el2 = talloc(el1->list2, struct el2);
489 el2 = talloc(el1->list3, struct el2);
491 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
492 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
493 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
503 static bool test_type(const struct torture_context *ctx)
514 root = talloc_new(ctx);
516 el1 = talloc(root, struct el1);
520 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
521 "type check failed on el1\n");
522 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
523 "type check failed on el1 with el2\n");
524 talloc_set_type(el1, struct el2);
525 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
526 "type set failed on el1 with el2\n");
536 static bool test_steal(const struct torture_context *ctx)
538 void *root, *p1, *p2;
540 root = talloc_new(ctx);
542 p1 = talloc_array(root, char, 10);
543 CHECK_SIZE("steal", p1, 10);
545 p2 = talloc_realloc(root, NULL, char, 20);
546 CHECK_SIZE("steal", p1, 10);
547 CHECK_SIZE("steal", root, 30);
549 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
550 "failed: stealing NULL should give NULL\n");
552 torture_assert("steal", talloc_steal(p1, p1) == p1,
553 "failed: stealing to ourselves is a nop\n");
554 CHECK_BLOCKS("steal", root, 3);
555 CHECK_SIZE("steal", root, 30);
557 talloc_steal(NULL, p1);
558 talloc_steal(NULL, p2);
559 CHECK_BLOCKS("steal", root, 1);
560 CHECK_SIZE("steal", root, 0);
563 talloc_steal(root, p2);
564 CHECK_BLOCKS("steal", root, 2);
565 CHECK_SIZE("steal", root, 20);
569 CHECK_BLOCKS("steal", root, 1);
570 CHECK_SIZE("steal", root, 0);
574 p1 = talloc_size(NULL, 3);
575 CHECK_SIZE("steal", NULL, 3);
584 static bool test_move(const struct torture_context *ctx)
592 root = talloc_new(ctx);
594 t1 = talloc(root, struct t_move);
595 t2 = talloc(root, struct t_move);
596 t1->p = talloc_strdup(t1, "foo");
597 t1->x = talloc(t1, int);
600 t2->p = talloc_move(t2, &t1->p);
601 t2->x = talloc_move(t2, &t1->x);
602 torture_assert("move", t1->p == NULL && t1->x == NULL &&
603 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
604 "talloc move failed");
612 test talloc_realloc_fn
614 static bool test_realloc_fn(const struct torture_context *ctx)
618 root = talloc_new(ctx);
620 p1 = talloc_realloc_fn(root, NULL, 10);
621 CHECK_BLOCKS("realloc_fn", root, 2);
622 CHECK_SIZE("realloc_fn", root, 10);
623 p1 = talloc_realloc_fn(root, p1, 20);
624 CHECK_BLOCKS("realloc_fn", root, 2);
625 CHECK_SIZE("realloc_fn", root, 20);
626 p1 = talloc_realloc_fn(root, p1, 0);
627 CHECK_BLOCKS("realloc_fn", root, 1);
628 CHECK_SIZE("realloc_fn", root, 0);
636 static bool test_unref_reparent(const struct torture_context *ctx)
638 void *root, *p1, *p2, *c1;
640 root = talloc_named_const(ctx, 0, "root");
641 p1 = talloc_named_const(root, 1, "orig parent");
642 p2 = talloc_named_const(root, 1, "parent by reference");
644 c1 = talloc_named_const(p1, 1, "child");
645 talloc_reference(p2, c1);
647 CHECK_PARENT("unref_reparent", c1, p1);
651 CHECK_PARENT("unref_reparent", c1, p2);
653 talloc_unlink(p2, c1);
655 CHECK_SIZE("unref_reparent", root, 1);
663 static bool test_lifeless(const struct torture_context *ctx)
665 void *top = talloc_new(ctx);
666 char *parent, *child;
667 void *child_owner = talloc_new(ctx);
669 parent = talloc_strdup(top, "parent");
670 child = talloc_strdup(parent, "child");
671 (void)talloc_reference(child, parent);
672 (void)talloc_reference(child_owner, child);
673 talloc_unlink(top, parent);
676 talloc_free(child_owner);
682 static int loop_destructor_count;
684 static int test_loop_destructor(char *ptr)
686 loop_destructor_count++;
690 static bool test_loop(const struct torture_context *ctx)
692 void *top = talloc_new(ctx);
698 parent = talloc_strdup(top, "parent");
699 req1 = talloc(parent, struct req1);
700 req1->req2 = talloc_strdup(req1, "req2");
701 talloc_set_destructor(req1->req2, test_loop_destructor);
702 req1->req3 = talloc_strdup(req1, "req3");
703 (void)talloc_reference(req1->req3, req1);
707 torture_assert("loop", loop_destructor_count == 1,
708 "FAILED TO FIRE LOOP DESTRUCTOR\n");
709 loop_destructor_count = 0;
714 static int fail_destructor_str(char *ptr)
719 static bool test_free_parent_deny_child(const struct torture_context *ctx)
721 void *top = talloc_new(ctx);
726 level1 = talloc_strdup(top, "level1");
727 level2 = talloc_strdup(level1, "level2");
728 level3 = talloc_strdup(level2, "level3");
730 talloc_set_destructor(level3, fail_destructor_str);
732 talloc_set_destructor(level3, NULL);
734 CHECK_PARENT("free_parent_deny_child", level3, top);
741 static bool test_talloc_ptrtype(const struct torture_context *ctx)
743 void *top = talloc_new(ctx);
747 } *s1, *s2, **s3, ***s4;
748 const char *location1;
749 const char *location2;
750 const char *location3;
751 const char *location4;
753 s1 = talloc_ptrtype(top, s1);location1 = __location__;
755 ok1(talloc_get_size(s1) == sizeof(struct struct1));
757 ok1(strcmp(location1, talloc_get_name(s1)) == 0);
759 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
761 ok1(talloc_get_size(s2) == (sizeof(struct struct1) * 10));
763 ok1(strcmp(location2, talloc_get_name(s2)) == 0);
765 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
767 ok1(talloc_get_size(s3) == (sizeof(struct struct1 *) * 10));
769 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
770 "talloc_array_ptrtype() sets the wrong name");
772 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
774 ok1(talloc_get_size(s4) == (sizeof(struct struct1 **) * 10));
776 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
777 "talloc_array_ptrtype() sets the wrong name");
784 static bool test_talloc_free_in_destructor_run;
785 static int _test_talloc_free_in_destructor(void **ptr)
788 test_talloc_free_in_destructor_run = true;
792 static bool test_talloc_free_in_destructor(const struct torture_context *ctx)
801 /* FIXME: Can't do nested destruction with locking, sorry. */
805 level0 = talloc_new(ctx);
806 level1 = talloc_new(level0);
807 level2 = talloc_new(level1);
808 level3 = talloc_new(level2);
809 level4 = talloc_new(level3);
810 level5 = talloc(level4, void *);
812 *level5 = talloc_reference(NULL, level3);
814 test_talloc_free_in_destructor_run = false;
815 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
821 ok1(test_talloc_free_in_destructor_run);
826 static bool test_autofree(const struct torture_context *ctx)
828 /* autofree test would kill smbtorture */
830 p = talloc_autofree_context();
833 p = talloc_autofree_context();
839 static bool torture_local_talloc(const struct torture_context *tctx)
845 talloc_disable_null_tracking();
846 talloc_enable_null_tracking();
848 ret &= test_ref1(tctx);
849 ret &= test_ref2(tctx);
850 ret &= test_ref3(tctx);
851 ret &= test_ref4(tctx);
852 ret &= test_unlink1(tctx);
853 ret &= test_misc(tctx);
854 ret &= test_realloc(tctx);
855 ret &= test_realloc_child(tctx);
856 ret &= test_steal(tctx);
857 ret &= test_move(tctx);
858 ret &= test_unref_reparent(tctx);
859 ret &= test_realloc_fn(tctx);
860 ret &= test_type(tctx);
861 ret &= test_lifeless(tctx);
862 ret &= test_loop(tctx);
863 ret &= test_free_parent_deny_child(tctx);
864 ret &= test_talloc_ptrtype(tctx);
865 ret &= test_talloc_free_in_destructor(tctx);
866 ret &= test_autofree(tctx);
871 static int lock_failed = 0, unlock_failed = 0, lock_bad = 0;
874 #define MAX_ALLOCATIONS 100
875 static void *allocations[MAX_ALLOCATIONS];
876 static int num_allocs, num_frees, num_reallocs;
878 static unsigned int find_ptr(const void *p)
882 for (i = 0; i < MAX_ALLOCATIONS; i++)
883 if (allocations[i] == p)
888 static unsigned int allocations_used(void)
890 unsigned int i, ret = 0;
892 for (i = 0; i < MAX_ALLOCATIONS; i++)
898 static void test_lock(const void *ctx)
900 if (find_ptr(ctx) == MAX_ALLOCATIONS)
908 static void test_unlock(void)
915 static int realloc_called, realloc_bad;
917 static void *normal_realloc(const void *parent, void *ptr, size_t size)
919 unsigned int i = find_ptr(ptr);
931 if (i == MAX_ALLOCATIONS) {
939 allocations[i] = realloc(ptr, size);
940 /* Not guarenteed by realloc. */
942 allocations[i] = NULL;
944 return allocations[i];
949 struct torture_context *ctx;
952 ctx = talloc_add_external(NULL, normal_realloc, test_lock, test_unlock);
954 torture_local_talloc(NULL);
955 ok(!lock_bad, "%u locks on bad pointer", lock_bad);
956 ok(!lock_failed, "lock_failed count %u should be zero", lock_failed);
957 ok(!unlock_failed, "unlock_failed count %u should be zero",
959 ok(realloc_called == 1, "our realloc should not be called again");
961 torture_local_talloc(ctx);
962 ok(!lock_bad, "%u locks on bad pointer", lock_bad);
963 ok(!lock_failed, "lock_failed count %u should be zero", lock_failed);
964 ok(!unlock_failed, "unlock_failed count %u should be zero",
966 ok(realloc_called, "our realloc should be called");
967 ok(!realloc_bad, "our realloc given unknown pointer %u times",
971 ok(!lock_bad, "%u locks on bad pointer", lock_bad);
972 ok(!lock_failed, "lock_failed count %u should be zero", lock_failed);
973 ok(!unlock_failed, "unlock_failed count %u should be zero",
975 ok(realloc_called, "our realloc should be called");
976 ok(!realloc_bad, "our realloc given unknown pointer %u times",
979 ok(allocations_used() == 0, "%u allocations still used?",
982 return exit_status();