From 87aba1fa2abc28ff06f82e30cde3fa3d991e8e18 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 10 Jan 2011 14:01:47 +1030 Subject: [PATCH 1/1] talloc: use failtest to test failure paths. --- ccan/talloc/_info | 1 + ccan/talloc/test/run-corruption1.c | 24 ++ ccan/talloc/test/run-external-alloc.c | 6 +- ccan/talloc/test/run-test_autofree.c | 25 ++ .../talloc/test/run-test_free_in_destructor.c | 132 ++++++++ .../test/run-test_free_parent_deny_child.c | 119 +++++++ ccan/talloc/test/run-test_loop.c | 129 ++++++++ ccan/talloc/test/run-test_misc.c | 258 +++++++++++++++ ccan/talloc/test/run-test_move.c | 123 +++++++ ccan/talloc/test/run-test_realloc.c | 229 +++++++++++++ ccan/talloc/test/run-test_realloc_fn.c | 112 +++++++ ccan/talloc/test/run-test_ref.c | 302 ++++++++++++++++++ ccan/talloc/test/run-test_steal.c | 141 ++++++++ ccan/talloc/test/run-test_talloc_ptrtype.c | 137 ++++++++ ccan/talloc/test/run-test_type.c | 116 +++++++ ccan/talloc/test/run-test_unlink.c | 129 ++++++++ ccan/talloc/test/run-test_unref_reparent.c | 153 +++++++++ ccan/talloc/test/run.c | 6 +- 18 files changed, 2140 insertions(+), 2 deletions(-) create mode 100644 ccan/talloc/test/run-corruption1.c create mode 100644 ccan/talloc/test/run-test_autofree.c create mode 100644 ccan/talloc/test/run-test_free_in_destructor.c create mode 100644 ccan/talloc/test/run-test_free_parent_deny_child.c create mode 100644 ccan/talloc/test/run-test_loop.c create mode 100644 ccan/talloc/test/run-test_misc.c create mode 100644 ccan/talloc/test/run-test_move.c create mode 100644 ccan/talloc/test/run-test_realloc.c create mode 100644 ccan/talloc/test/run-test_realloc_fn.c create mode 100644 ccan/talloc/test/run-test_ref.c create mode 100644 ccan/talloc/test/run-test_steal.c create mode 100644 ccan/talloc/test/run-test_talloc_ptrtype.c create mode 100644 ccan/talloc/test/run-test_type.c create mode 100644 ccan/talloc/test/run-test_unlink.c create mode 100644 ccan/talloc/test/run-test_unref_reparent.c diff --git a/ccan/talloc/_info b/ccan/talloc/_info index cf2ea7d1..46173d96 100644 --- a/ccan/talloc/_info +++ b/ccan/talloc/_info @@ -99,6 +99,7 @@ int main(int argc, char *argv[]) if (strcmp(argv[1], "depends") == 0) { printf("ccan/compiler\n"); printf("ccan/typesafe_cb\n"); + printf("ccan/failtest\n"); return 0; } diff --git a/ccan/talloc/test/run-corruption1.c b/ccan/talloc/test/run-corruption1.c new file mode 100644 index 00000000..d6ac7da5 --- /dev/null +++ b/ccan/talloc/test/run-corruption1.c @@ -0,0 +1,24 @@ +/* failtest with valgrind caught this read-after-free. */ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + void *root, *p1; + + plan_tests(2); + talloc_enable_null_tracking(); + root = talloc_new(NULL); + p1 = talloc_strdup(root, "foo"); + talloc_increase_ref_count(p1); + talloc_free(root); + ok1(strcmp(p1, "foo") == 0); + talloc_unlink(NULL, p1); + + /* This closes the leak, but make sure we're not freeing unexpected. */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + + return exit_status(); +} diff --git a/ccan/talloc/test/run-external-alloc.c b/ccan/talloc/test/run-external-alloc.c index 013041fe..0dc93460 100644 --- a/ccan/talloc/test/run-external-alloc.c +++ b/ccan/talloc/test/run-external-alloc.c @@ -32,7 +32,7 @@ static void ext_unlock(void) int main(void) { char *p, *p2, *head; - plan_tests(13); + plan_tests(15); expected_parent = NULL; head = talloc_add_external(NULL, ext_realloc, ext_lock, ext_unlock); @@ -62,6 +62,10 @@ int main(void) talloc_free(p); ok1(ext_free_count == 2); + expected_parent = NULL; + talloc_free(head); + ok1(ext_free_count == 3); + ok1(lock_count == unlock_count); return exit_status(); diff --git a/ccan/talloc/test/run-test_autofree.c b/ccan/talloc/test/run-test_autofree.c new file mode 100644 index 00000000..0aa0c172 --- /dev/null +++ b/ccan/talloc/test/run-test_autofree.c @@ -0,0 +1,25 @@ +#include +#include +#include + +static int destroy_int(int *p) +{ + ok1(*p == 7); + _exit(0); +} + +int main(int argc, char *argv[]) +{ + int *p; + + /* If autofree context doesn't work, we won't run all tests! */ + plan_tests(1); + + p = talloc(talloc_autofree_context(), int); + *p = 7; + talloc_set_destructor(p, destroy_int); + + /* Note! We fail here, unless destructor called! */ + exit(1); +} + diff --git a/ccan/talloc/test/run-test_free_in_destructor.c b/ccan/talloc/test/run-test_free_in_destructor.c new file mode 100644 index 00000000..644fcac2 --- /dev/null +++ b/ccan/talloc/test/run-test_free_in_destructor.c @@ -0,0 +1,132 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +static bool test_talloc_free_in_destructor_run; +static int _test_talloc_free_in_destructor(void **ptr) +{ + talloc_free(*ptr); + test_talloc_free_in_destructor_run = true; + return 0; +} + +static bool test_talloc_free_in_destructor(const struct torture_context *ctx) +{ + void *level0; + void *level1; + void *level2; + void *level3; + void *level4; + void **level5; + bool ret = false; + + level0 = talloc_new(ctx); + if (!level0) + goto out; + level1 = talloc_new(level0); + if (!level1) + goto out; + level2 = talloc_new(level1); + if (!level2) + goto out; + level3 = talloc_new(level2); + if (!level3) + goto out; + level4 = talloc_new(level3); + if (!level4) + goto out; + level5 = talloc(level4, void *); + if (!level5) + goto out; + + *level5 = talloc_reference(NULL, level3); + + test_talloc_free_in_destructor_run = false; + talloc_set_destructor(level5, _test_talloc_free_in_destructor); + + talloc_free(level1); + ret = true; +out: + talloc_free(level0); + + ok1(test_talloc_free_in_destructor_run); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(3); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_talloc_free_in_destructor(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_free_parent_deny_child.c b/ccan/talloc/test/run-test_free_parent_deny_child.c new file mode 100644 index 00000000..f173d5cd --- /dev/null +++ b/ccan/talloc/test/run-test_free_parent_deny_child.c @@ -0,0 +1,119 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +static int fail_destructor_str(char *ptr) +{ + return -1; +} + +static bool test_free_parent_deny_child(const struct torture_context *ctx) +{ + void *top = talloc_new(ctx); + char *level1; + char *level2; + char *level3; + bool ret = false; + + if (!top) + goto out; + + level1 = talloc_strdup(top, "level1"); + if (!level1) + goto out; + level2 = talloc_strdup(level1, "level2"); + if (!level2) + goto out; + level3 = talloc_strdup(level2, "level3"); + if (!level3) + goto out; + + talloc_set_destructor(level3, fail_destructor_str); + talloc_free(level1); + talloc_set_destructor(level3, NULL); + + CHECK_PARENT("free_parent_deny_child", level3, top); + ret = true; + +out: + talloc_free(top); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(3); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_free_parent_deny_child(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_loop.c b/ccan/talloc/test/run-test_loop.c new file mode 100644 index 00000000..0fdc081d --- /dev/null +++ b/ccan/talloc/test/run-test_loop.c @@ -0,0 +1,129 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +static int loop_destructor_count; + +static int test_loop_destructor(char *ptr) +{ + loop_destructor_count++; + return 0; +} + +static bool test_loop(const struct torture_context *ctx) +{ + void *top = talloc_new(ctx); + char *parent; + struct req1 { + char *req2, *req3; + } *req1; + bool ret = false; + + if (!top) + goto out; + + parent = talloc_strdup(top, "parent"); + if (!parent) + goto out; + + req1 = talloc(parent, struct req1); + if (!req1) + goto out; + + req1->req2 = talloc_strdup(req1, "req2"); + if (!req1->req2) + goto out; + + talloc_set_destructor(req1->req2, test_loop_destructor); + req1->req3 = talloc_strdup(req1, "req3"); + if (!req1->req3) + goto out; + (void)talloc_reference(req1->req3, req1); + talloc_free(parent); + + torture_assert("loop", loop_destructor_count == 1, + "FAILED TO FIRE LOOP DESTRUCTOR\n"); + loop_destructor_count = 0; + ret = true; +out: + talloc_free(top); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(3); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_loop(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_misc.c b/ccan/talloc/test/run-test_misc.c new file mode 100644 index 00000000..d446578e --- /dev/null +++ b/ccan/talloc/test/run-test_misc.c @@ -0,0 +1,258 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +static int fail_destructor(void *ptr) +{ + return -1; +} + +/* + miscellaneous tests to try to get a higher test coverage percentage +*/ +static bool test_misc(const struct torture_context *ctx) +{ + void *root, *p1; + char *p2; + double *d; + const char *name; + bool ret = false; + + root = talloc_new(ctx); + if (!root) + goto out; + + p1 = talloc_size(root, 0x7fffffff); + torture_assert("misc", !p1, "failed: large talloc allowed\n"); + + p1 = talloc_strdup(root, "foo"); + if (!p1) + goto out; + + if (talloc_increase_ref_count(p1) != 0) + goto out; + if (talloc_increase_ref_count(p1) != 0) + goto out; + if (talloc_increase_ref_count(p1) != 0) + goto out; + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_free(p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + p2 = talloc_strdup(p1, "foo"); + if (!p2) + goto out; + torture_assert("misc", talloc_unlink(root, p2) == -1, + "failed: talloc_unlink() of non-reference context should return -1\n"); + torture_assert("misc", talloc_unlink(p1, p2) == 0, + "failed: talloc_unlink() of parent should succeed\n"); + talloc_free(p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + + name = talloc_set_name(p1, "my name is %s", "foo"); + if (!name) + goto out; + torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo", + "failed: wrong name after talloc_set_name(my name is foo)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + + talloc_set_name_const(p1, NULL); + torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED", + "failed: wrong name after talloc_set_name(NULL)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + + torture_assert("misc", talloc_free(NULL) == -1, + "talloc_free(NULL) should give -1\n"); + + talloc_set_destructor(p1, fail_destructor); + torture_assert("misc", talloc_free(p1) == -1, + "Failed destructor should cause talloc_free to fail\n"); + talloc_set_destructor(p1, NULL); + + p2 = (char *)talloc_zero_size(p1, 20); + if (!p2) + goto out; + torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n"); + talloc_free(p2); + + torture_assert("misc", talloc_strdup(root, NULL) == NULL, + "failed: strdup on NULL should give NULL\n"); + + p2 = talloc_strndup(p1, "foo", 2); + if (!p2) + goto out; + torture_assert("misc", strcmp("fo", p2) == 0, + "strndup doesn't work\n"); + p2 = talloc_asprintf_append(p2, "o%c", 'd'); + if (!p2) + goto out; + torture_assert("misc", strcmp("food", p2) == 0, + "talloc_asprintf_append doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); + + p2 = talloc_asprintf_append(NULL, "hello %s", "world"); + if (!p2) + goto out; + torture_assert("misc", strcmp("hello world", p2) == 0, + "talloc_asprintf_append doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); + talloc_free(p2); + + d = talloc_array(p1, double, 0x20000000); + torture_assert("misc", !d, "failed: integer overflow not detected\n"); + + d = talloc_realloc(p1, d, double, 0x20000000); + torture_assert("misc", !d, "failed: integer overflow not detected\n"); + + talloc_free(p1); + CHECK_BLOCKS("misc", root, 1); + + p1 = talloc_named(root, 100, "%d bytes", 100); + if (!p1) + goto out; + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + talloc_unlink(root, p1); + + p1 = talloc_init("%d bytes", 200); + if (!p1) + goto out; + p2 = talloc_asprintf(p1, "my test '%s'", "string"); + if (!p2) + goto out; + torture_assert_str_equal("misc", p2, "my test 'string'", + "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\""); + CHECK_BLOCKS("misc", p1, 3); + CHECK_SIZE("misc", p2, 17); + CHECK_BLOCKS("misc", root, 1); + talloc_unlink(NULL, p1); + + p1 = talloc_named_const(root, 10, "p1"); + if (!p1) + goto out; + p2 = (char *)talloc_named_const(root, 20, "p2"); + if (!p2) + goto out; + if (!talloc_reference(p1, p2)) + goto out; + talloc_unlink(root, p2); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + talloc_unlink(p1, p2); + talloc_unlink(root, p1); + + p1 = talloc_named_const(root, 10, "p1"); + if (!p1) + goto out; + p2 = (char *)talloc_named_const(root, 20, "p2"); + if (!p2) + goto out; + if (!talloc_reference(NULL, p2)) + goto out; + talloc_unlink(root, p2); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p2); + talloc_unlink(root, p1); + + /* Test that talloc_unlink is a no-op */ + + torture_assert("misc", talloc_unlink(root, NULL) == -1, + "failed: talloc_unlink(root, NULL) == -1\n"); + + CHECK_SIZE("misc", root, 0); + + talloc_enable_leak_report(); + talloc_enable_leak_report_full(); + ret = true; +out: + talloc_free(root); + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(47); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_misc(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} diff --git a/ccan/talloc/test/run-test_move.c b/ccan/talloc/test/run-test_move.c new file mode 100644 index 00000000..4662e984 --- /dev/null +++ b/ccan/talloc/test/run-test_move.c @@ -0,0 +1,123 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test move +*/ +static bool test_move(const struct torture_context *ctx) +{ + void *root; + struct t_move { + char *p; + int *x; + } *t1, *t2; + bool ret = false; + + root = talloc_new(ctx); + if (!root) + goto out; + + t1 = talloc(root, struct t_move); + if (!t1) + goto out; + t2 = talloc(root, struct t_move); + if (!t2) + goto out; + t1->p = talloc_strdup(t1, "foo"); + if (!t1->p) + goto out; + t1->x = talloc(t1, int); + if (!t1->x) + goto out; + *t1->x = 42; + + t2->p = talloc_move(t2, &t1->p); + t2->x = talloc_move(t2, &t1->x); + torture_assert("move", t1->p == NULL && t1->x == NULL && + strcmp(t2->p, "foo") == 0 && *t2->x == 42, + "talloc move failed"); + + ret = true; +out: + talloc_free(root); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(3); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_move(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_realloc.c b/ccan/talloc/test/run-test_realloc.c new file mode 100644 index 00000000..e7998a3a --- /dev/null +++ b/ccan/talloc/test/run-test_realloc.c @@ -0,0 +1,229 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test realloc +*/ +static bool test_realloc(const struct torture_context *ctx) +{ + void *root, *p1, *p2; + bool ret = false; + + root = talloc_new(ctx); + if (!root) + goto out; + + p1 = talloc_size(root, 10); + if (!p1) + goto out; + CHECK_SIZE("realloc", p1, 10); + + p1 = talloc_realloc_size(NULL, p1, 20); + if (!p1) + goto out; + CHECK_SIZE("realloc", p1, 20); + + if (!talloc_new(p1)) + goto out; + + p2 = talloc_realloc_size(p1, NULL, 30); + if (!p2) + goto out; + + if (!talloc_new(p1)) + goto out; + + p2 = talloc_realloc_size(p1, p2, 40); + if (!p2) + goto out; + + CHECK_SIZE("realloc", p2, 40); + CHECK_SIZE("realloc", root, 60); + CHECK_BLOCKS("realloc", p1, 4); + + p1 = talloc_realloc_size(NULL, p1, 20); + if (!p1) + goto out; + CHECK_SIZE("realloc", p1, 60); + + if (talloc_increase_ref_count(p2) != 0) + goto out; + torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL, + "failed: talloc_realloc() on a referenced pointer should fail\n"); + CHECK_BLOCKS("realloc", p1, 4); + + ok1(talloc_realloc_size(NULL, p2, 0) == NULL); + ok1(talloc_realloc_size(NULL, p2, 0) == NULL); + CHECK_BLOCKS("realloc", p1, 3); + + torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL, + "failed: oversize talloc should fail\n"); + + ok1(talloc_realloc_size(NULL, p1, 0) == NULL); + + CHECK_BLOCKS("realloc", root, 1); + CHECK_SIZE("realloc", root, 0); + ret = true; + +out: + talloc_free(root); + + return ret; +} + +/* + test realloc with a child +*/ +static bool test_realloc_child(const struct torture_context *ctx) +{ + void *root; + struct el2 { + const char *name; + } *el2; + struct el1 { + int count; + struct el2 **list, **list2, **list3; + } *el1; + bool ret = false; + + root = talloc_new(ctx); + if (!root) + goto out; + + el1 = talloc(root, struct el1); + if (!el1) + goto out; + el1->list = talloc(el1, struct el2 *); + if (!el1->list) + goto out; + el1->list[0] = talloc(el1->list, struct el2); + if (!el1->list[0]) + goto out; + el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); + if (!el1->list[0]->name) + goto out; + + el1->list2 = talloc(el1, struct el2 *); + if (!el1->list2) + goto out; + el1->list2[0] = talloc(el1->list2, struct el2); + if (!el1->list2[0]) + goto out; + el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2"); + if (!el1->list2[0]->name) + goto out; + + el1->list3 = talloc(el1, struct el2 *); + if (!el1->list3) + goto out; + el1->list3[0] = talloc(el1->list3, struct el2); + if (!el1->list3[0]) + goto out; + el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2"); + if (!el1->list3[0]->name) + goto out; + + el2 = talloc(el1->list, struct el2); + if (!el2) + goto out; + el2 = talloc(el1->list2, struct el2); + if (!el2) + goto out; + el2 = talloc(el1->list3, struct el2); + if (!el2) + goto out; + + el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100); + if (!el1->list) + goto out; + el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200); + if (!el1->list2) + goto out; + el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300); + if (!el1->list3) + goto out; + + ret = true; +out: + talloc_free(root); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(17); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_realloc(NULL) && test_realloc_child(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_realloc_fn.c b/ccan/talloc/test/run-test_realloc_fn.c new file mode 100644 index 00000000..368e5841 --- /dev/null +++ b/ccan/talloc/test/run-test_realloc_fn.c @@ -0,0 +1,112 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test talloc_realloc_fn +*/ +static bool test_realloc_fn(const struct torture_context *ctx) +{ + void *root, *p1; + bool ret = false; + + root = talloc_new(ctx); + if (!root) + goto out; + + p1 = talloc_realloc_fn(root, NULL, 10); + if (!p1) + goto out; + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 10); + p1 = talloc_realloc_fn(root, p1, 20); + if (!p1) + goto out; + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 20); + p1 = talloc_realloc_fn(root, p1, 0); + CHECK_BLOCKS("realloc_fn", root, 1); + CHECK_SIZE("realloc_fn", root, 0); + ret = true; + +out: + talloc_free(root); + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(8); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_realloc_fn(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_ref.c b/ccan/talloc/test/run-test_ref.c new file mode 100644 index 00000000..872487ef --- /dev/null +++ b/ccan/talloc/test/run-test_ref.c @@ -0,0 +1,302 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test references +*/ +static bool test_ref1(const struct torture_context *ctx) +{ + void *root, *p1, *p2, *ref, *r1; + bool ret = false; + + root = talloc_named_const(ctx, 0, "root"); + if (!root) + goto out; + p1 = talloc_named_const(root, 1, "p1"); + if (!p1) + goto out; + p2 = talloc_named_const(p1, 1, "p2"); + if (!p2) + goto out; + if (!talloc_named_const(p1, 1, "x1")) + goto out; + if (!talloc_named_const(p1, 2, "x2")) + goto out; + if (!talloc_named_const(p1, 3, "x3")) + goto out; + + r1 = talloc_named_const(root, 1, "r1"); + if (!r1) + goto out; + ref = talloc_reference(r1, p2); + if (!ref) + goto out; + + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 2); + + talloc_free(p2); + + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 1); + + talloc_free(p1); + + CHECK_BLOCKS("ref1", r1, 1); + + talloc_free(r1); + + if (talloc_reference(root, NULL)) { + return false; + } + + CHECK_BLOCKS("ref1", root, 1); + + CHECK_SIZE("ref1", root, 0); + ret = true; +out: + talloc_free(root); + return ret; +} + +/* + test references +*/ +static bool test_ref2(const struct torture_context *ctx) +{ + void *root, *p1, *p2, *ref, *r1; + bool ret = false; + + root = talloc_named_const(ctx, 0, "root"); + if (!root) + goto out; + p1 = talloc_named_const(root, 1, "p1"); + if (!p1) + goto out; + if (!talloc_named_const(p1, 1, "x1")) + goto out; + if (!talloc_named_const(p1, 1, "x2")) + goto out; + if (!talloc_named_const(p1, 1, "x3")) + goto out; + p2 = talloc_named_const(p1, 1, "p2"); + if (!p2) + goto out; + + r1 = talloc_named_const(root, 1, "r1"); + if (!r1) + goto out; + ref = talloc_reference(r1, p2); + if (!ref) + goto out; + + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 2); + + talloc_free(ref); + + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 1); + + talloc_free(p2); + + CHECK_BLOCKS("ref2", p1, 4); + CHECK_BLOCKS("ref2", r1, 1); + + talloc_free(p1); + + CHECK_BLOCKS("ref2", r1, 1); + + talloc_free(r1); + + CHECK_SIZE("ref2", root, 0); + ret = true; + +out: + talloc_free(root); + return ret; +} + +/* + test references +*/ +static bool test_ref3(const struct torture_context *ctx) +{ + void *root, *p1, *p2, *ref, *r1; + bool ret = false; + + root = talloc_named_const(ctx, 0, "root"); + if (!root) + goto out; + p1 = talloc_named_const(root, 1, "p1"); + if (!p1) + goto out; + p2 = talloc_named_const(root, 1, "p2"); + if (!p2) + goto out; + r1 = talloc_named_const(p1, 1, "r1"); + if (!r1) + goto out; + ref = talloc_reference(p2, r1); + if (!ref) + goto out; + + CHECK_BLOCKS("ref3", p1, 2); + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); + + talloc_free(p1); + + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); + + talloc_free(p2); + + CHECK_SIZE("ref3", root, 0); + + ret = true; +out: + talloc_free(root); + + return ret; +} + +/* + test references +*/ +static bool test_ref4(const struct torture_context *ctx) +{ + void *root, *p1, *p2, *ref, *r1; + bool ret = false; + + root = talloc_named_const(ctx, 0, "root"); + if (!root) + goto out; + p1 = talloc_named_const(root, 1, "p1"); + if (!p1) + goto out; + if (!talloc_named_const(p1, 1, "x1")) + goto out; + if (!talloc_named_const(p1, 1, "x2")) + goto out; + if (!talloc_named_const(p1, 1, "x3")) + goto out; + p2 = talloc_named_const(p1, 1, "p2"); + if (!p2) + goto out; + + r1 = talloc_named_const(root, 1, "r1"); + if (!r1) + goto out; + ref = talloc_reference(r1, p2); + if (!ref) + goto out; + + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + CHECK_BLOCKS("ref4", r1, 2); + + talloc_free(r1); + + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + + talloc_free(p2); + + CHECK_BLOCKS("ref4", p1, 4); + + talloc_free(p1); + + CHECK_SIZE("ref4", root, 0); + + ret = true; +out: + talloc_free(root); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(34); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_ref1(NULL) + && test_ref2(NULL) + && test_ref3(NULL) + && test_ref4(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_steal.c b/ccan/talloc/test/run-test_steal.c new file mode 100644 index 00000000..346f0917 --- /dev/null +++ b/ccan/talloc/test/run-test_steal.c @@ -0,0 +1,141 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test steal +*/ +static bool test_steal(const struct torture_context *ctx) +{ + void *root, *p1, *p2; + bool ret = false; + + root = talloc_new(ctx); + if (!root) + goto out; + + p1 = talloc_array(root, char, 10); + if (!p1) + goto out; + CHECK_SIZE("steal", p1, 10); + + p2 = talloc_realloc(root, NULL, char, 20); + if (!p2) + goto out; + CHECK_SIZE("steal", p1, 10); + CHECK_SIZE("steal", root, 30); + + torture_assert("steal", talloc_steal(p1, NULL) == NULL, + "failed: stealing NULL should give NULL\n"); + + torture_assert("steal", talloc_steal(p1, p1) == p1, + "failed: stealing to ourselves is a nop\n"); + CHECK_BLOCKS("steal", root, 3); + CHECK_SIZE("steal", root, 30); + + talloc_steal(NULL, p1); + talloc_steal(NULL, p2); + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); + + talloc_free(p1); + talloc_steal(root, p2); + CHECK_BLOCKS("steal", root, 2); + CHECK_SIZE("steal", root, 20); + + talloc_free(p2); + + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); + + talloc_free(root); + root = NULL; + + p1 = talloc_size(NULL, 3); + if (!p1) + goto out; + CHECK_SIZE("steal", NULL, 3); + talloc_free(p1); + ret = true; + +out: + talloc_free(root); + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(16); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_steal(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_talloc_ptrtype.c b/ccan/talloc/test/run-test_talloc_ptrtype.c new file mode 100644 index 00000000..ed637792 --- /dev/null +++ b/ccan/talloc/test/run-test_talloc_ptrtype.c @@ -0,0 +1,137 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +static bool test_talloc_ptrtype(const struct torture_context *ctx) +{ + void *top = talloc_new(ctx); + struct struct1 { + int foo; + int bar; + } *s1, *s2, **s3, ***s4; + const char *location1; + const char *location2; + const char *location3; + const char *location4; + bool ret = false; + + if (!top) + goto out; + + s1 = talloc_ptrtype(top, s1);location1 = __location__; + if (!s1) + goto out; + + ok1(talloc_get_size(s1) == sizeof(struct struct1)); + + ok1(strcmp(location1, talloc_get_name(s1)) == 0); + + s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__; + if (!s2) + goto out; + + ok1(talloc_get_size(s2) == (sizeof(struct struct1) * 10)); + + ok1(strcmp(location2, talloc_get_name(s2)) == 0); + + s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__; + if (!s3) + goto out; + + ok1(talloc_get_size(s3) == (sizeof(struct struct1 *) * 10)); + + torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3), + "talloc_array_ptrtype() sets the wrong name"); + + s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__; + if (!s4) + goto out; + + ok1(talloc_get_size(s4) == (sizeof(struct struct1 **) * 10)); + + torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4), + "talloc_array_ptrtype() sets the wrong name"); + ret = true; + +out: + talloc_free(top); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(10); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_talloc_ptrtype(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_type.c b/ccan/talloc/test/run-test_type.c new file mode 100644 index 00000000..ac45874e --- /dev/null +++ b/ccan/talloc/test/run-test_type.c @@ -0,0 +1,116 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test type checking +*/ +static bool test_type(const struct torture_context *ctx) +{ + void *root; + struct el1 { + int count; + }; + struct el2 { + int count; + }; + struct el1 *el1; + bool ret = false; + + root = talloc_new(ctx); + + el1 = talloc(root, struct el1); + if (!el1) + goto out; + + el1->count = 1; + + torture_assert("type", talloc_get_type(el1, struct el1) == el1, + "type check failed on el1\n"); + torture_assert("type", talloc_get_type(el1, struct el2) == NULL, + "type check failed on el1 with el2\n"); + talloc_set_type(el1, struct el2); + torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1, + "type set failed on el1 with el2\n"); + ret = true; +out: + talloc_free(root); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(5); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_type(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} diff --git a/ccan/talloc/test/run-test_unlink.c b/ccan/talloc/test/run-test_unlink.c new file mode 100644 index 00000000..f38597b0 --- /dev/null +++ b/ccan/talloc/test/run-test_unlink.c @@ -0,0 +1,129 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +/* + test references +*/ +static bool test_unlink1(const struct torture_context *ctx) +{ + void *root, *p1, *p2, *ref, *r1; + bool ret = false; + + root = talloc_named_const(ctx, 0, "root"); + if (!root) + goto out; + + p1 = talloc_named_const(root, 1, "p1"); + if (!p1) + goto out; + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + if (!p2) + goto out; + + r1 = talloc_named_const(p1, 1, "r1"); + if (!r1) + goto out; + ref = talloc_reference(r1, p2); + if (!ref) + goto out; + + CHECK_BLOCKS("unlink", p1, 7); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 2); + + talloc_unlink(r1, p2); + + CHECK_BLOCKS("unlink", p1, 6); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 1); + + talloc_free(p1); + + CHECK_SIZE("unlink", root, 0); + ret = true; +out: + talloc_free(root); + + return ret; +} + +int main(int argc, char *argv[]) +{ + plan_tests(9); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_unlink1(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} + diff --git a/ccan/talloc/test/run-test_unref_reparent.c b/ccan/talloc/test/run-test_unref_reparent.c new file mode 100644 index 00000000..0f0b1a47 --- /dev/null +++ b/ccan/talloc/test/run-test_unref_reparent.c @@ -0,0 +1,153 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + Converted to ccan tests by Rusty Russell 2008 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#define torture_assert(test, expr, str) \ + ok(expr, "%s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str) + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + ok(strcmp(arg1, arg2) == 0, \ + "%s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc) + +#define CHECK_SIZE(test, ptr, tsize) \ + ok(talloc_total_size(ptr) == (tsize), \ + "%s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize) + +#define CHECK_BLOCKS(test, ptr, tblocks) \ + ok(talloc_total_blocks(ptr) == (tblocks), \ + "%s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks) + +#define CHECK_PARENT(test, ptr, parent) \ + ok(talloc_parent(ptr) == (parent), \ + "%s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ + talloc_parent(ptr), \ + (parent)) + +struct torture_context; + +static bool test_unref_reparent(const struct torture_context *ctx) +{ + void *root, *p1, *p2, *c1; + bool ret = false; + + root = talloc_named_const(ctx, 0, "root"); + if (!root) + goto out; + p1 = talloc_named_const(root, 1, "orig parent"); + if (!p1) + goto out; + p2 = talloc_named_const(root, 1, "parent by reference"); + if (!p2) + goto out; + + c1 = talloc_named_const(p1, 1, "child"); + if (!c1) + goto out; + + if (!talloc_reference(p2, c1)) + goto out; + + CHECK_PARENT("unref_reparent", c1, p1); + + talloc_free(p1); + + CHECK_PARENT("unref_reparent", c1, p2); + + talloc_unlink(p2, c1); + + CHECK_SIZE("unref_reparent", root, 1); + + talloc_free(p2); + ret = true; +out: + talloc_free(root); + + return ret; +} + +static bool test_lifeless(const struct torture_context *ctx) +{ + void *top = talloc_new(ctx); + char *parent, *child; + void *child_owner = talloc_new(ctx); + + parent = talloc_strdup(top, "parent"); + if (!parent) + return false; + child = talloc_strdup(parent, "child"); + if (!child) { + talloc_free(parent); + return false; + } + if (!talloc_reference(child, parent)) { + talloc_free(parent); + return false; + } + + if (!talloc_reference(child_owner, child)) { + talloc_unlink(child, parent); + talloc_free(parent); + return false; + } + + talloc_unlink(top, parent); + talloc_free(child); + talloc_free(top); + talloc_free(child_owner); + talloc_free(child); + + return true; +} + +int main(int argc, char *argv[]) +{ + plan_tests(5); + failtest_init(argc, argv); + + talloc_enable_null_tracking(); + if (null_context) { + ok1(test_unref_reparent(NULL) && test_lifeless(NULL)); + /* This closes the leak, but don't free any other leaks! */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + } + failtest_exit(exit_status()); +} diff --git a/ccan/talloc/test/run.c b/ccan/talloc/test/run.c index 06f9249a..564f1e85 100644 --- a/ccan/talloc/test/run.c +++ b/ccan/talloc/test/run.c @@ -948,7 +948,7 @@ int main(void) { struct torture_context *ctx; - plan_tests(288); + plan_tests(289); ctx = talloc_add_external(NULL, normal_realloc, test_lock, test_unlock); torture_local_talloc(NULL); @@ -979,6 +979,10 @@ int main(void) ok(allocations_used() == 0, "%u allocations still used?", allocations_used()); + /* This closes the leak, but make sure we're not freeing unexpected. */ + ok1(!talloc_chunk_from_ptr(null_context)->child); + talloc_disable_null_tracking(); + return exit_status(); } -- 2.39.2