talloc testsuite: test (ref, free, steal) destroys reference
authorSam Liddicott <sam@liddicott.com>
Fri, 10 Jul 2009 10:45:09 +0000 (11:45 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 14 Jul 2009 09:24:33 +0000 (11:24 +0200)
references should only be removed by permission of the reference
owner and not calls to talloc_free

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

index 49070d9cbdbbd769075a60b6a2622bda22f1bdc5..ebcdac05f8ff1ba9e84d0ec8da0a4903124ceb6d 100644 (file)
@@ -884,6 +884,66 @@ static bool test_implicit_explicit_free(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
 */
@@ -1270,6 +1330,8 @@ bool torture_local_talloc(struct torture_context *tctx)
        test_reset();
        ret &= test_implicit_explicit_free();
        test_reset();
+       ret &= test_ref_free_steal();
+       test_reset();
        ret &= test_pool();
 
        if (ret) {