talloc testsuite: test (ref, free, steal) destroys reference
authorSam Liddicott <sam@liddicott.com>
Mon, 2 Feb 2009 12:12:08 +0000 (12:12 +0000)
committerStefan Metzmacher <metze@samba.org>
Thu, 9 Jul 2009 08:36:00 +0000 (10:36 +0200)
ref, free, steal destroys the reference (as it became the new owner
on free) and stops the reference from keeping the object alive.

references should only be removed by permission of the reference owner.

Current behaviour may be according to design, but it's very awkward.

Signed-off-by: Sam Liddicott <sam@liddicott.com>
lib/talloc/testsuite.c

index 5c720cb427529fe3f988542f78d03b6d43b76321..65742f2194f5a1b22161d2096e1c642d48501c25 100644 (file)
@@ -1125,6 +1125,66 @@ static bool test_dangling_loop(void)
        return true;
 }
 
+/* If take r1 reference to p2 and then free p2's owner p1
+   p2 should still be around by virtue of the reference.
+   steal p2 to p3 and free p3.
+   In current talloc p2 will be freed despite the reference.
+   In proposed talloc r1 will be the reference with no parent for p2*/
+static bool test_ref_free_steal(void)
+{
+       void *root, *p1, *p2, *p3, *ref, *r1;
+
+       printf("test: ref_free_self\n# SINGLE REFERENCE FREE SELF FREE\n");
+       talloc_erase_no_owner_context();
+
+       root = talloc_named_const(NULL, 0, "root");
+       p1 = talloc_named_const(root, 1, "p1");
+       p2 = talloc_named_const(p1, 1, "p2");
+       p3 = talloc_named_const(root, 1, "p3");
+       /* Now root owns p1, and p1 owns p2 */
+
+       r1 = talloc_named_const(root, 1, "r1");
+       ref = talloc_reference(r1, p2);
+       /* now r1 has ref reference to p2 */
+       talloc_report_full(NULL, stderr);
+
+       CHECK_BLOCKS(__FUNCTION__, p1, 2);
+       CHECK_BLOCKS(__FUNCTION__, p2, 1);
+       CHECK_BLOCKS(__FUNCTION__, p3, 1);
+       CHECK_BLOCKS(__FUNCTION__, r1, 2);
+
+       fprintf(stderr, "Freeing p1\n");
+       talloc_free(p1);
+       /* r1 should have ref reference to p2 still */
+       talloc_report_full(NULL, stderr);
+       CHECK_BLOCKS(__FUNCTION__, r1, 2);
+
+       /* if we talloc_steal p2 to p3, r1 should still have a reference
+          (unless it had been made the parent like in old talloc */
+       fprintf(stderr, "Steal p2 to p3\n");
+       talloc_steal(p3, p2);
+       talloc_report_full(NULL, stderr);
+       //CHECK_BLOCKS(__FUNCTION__, r1, 2);
+
+       /* now we free p3 and r1 should still have a reference */
+       fprintf(stderr, "free p3\n");
+       talloc_free(p3);
+       talloc_report_full(NULL, stderr);
+       CHECK_BLOCKS(__FUNCTION__, p2, 1);
+       CHECK_BLOCKS(__FUNCTION__, r1, 2);
+
+       /* if we free r1 then p2 should also vanish */
+       fprintf(stderr, "Freeing r1\n");
+       talloc_free(r1);
+
+       talloc_report_full(NULL, stderr);
+       CHECK_BLOCKS(__FUNCTION__, root, 1);
+
+       talloc_free(root);
+       printf("success: ref1\n");
+       return true;
+}
+
 /*
   measure the speed of talloc versus malloc
 */
@@ -1495,6 +1555,7 @@ bool torture_local_talloc(struct torture_context *tctx)
        ret &= test_talloc_free_in_destructor();
        ret &= test_implicit_explicit_free();
        ret &= test_dangling_loop();
+       ret &= test_ref_free_steal();
        ret &= test_ref_free_owner();
        ret &= test_ref_free_self();
        ret &= test_ref_free();