diff options
author | Martin Nagy <mnagy@redhat.com> | 2009-10-06 01:34:55 +0200 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2009-11-06 18:06:05 -0500 |
commit | c391633a8cc03f0fc3be0b7c424b28acf94bc878 (patch) | |
tree | e06df7285138bdf7134c4750dfe7b3d3c547312d /server/tests | |
parent | 5f91071ac89de679e9f36e788d7bef757ea0e4bb (diff) | |
download | sssd-c391633a8cc03f0fc3be0b7c424b28acf94bc878.tar.gz sssd-c391633a8cc03f0fc3be0b7c424b28acf94bc878.tar.xz sssd-c391633a8cc03f0fc3be0b7c424b28acf94bc878.zip |
Add simple reference counting wrappers for talloc
Diffstat (limited to 'server/tests')
-rw-r--r-- | server/tests/refcount-tests.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/server/tests/refcount-tests.c b/server/tests/refcount-tests.c new file mode 100644 index 000000000..ff82b4ca8 --- /dev/null +++ b/server/tests/refcount-tests.c @@ -0,0 +1,231 @@ +/* + SSSD + + Reference counting tests. + + Authors: + Martin Nagy <mnagy@redhat.com> + + Copyright (C) Red Hat, Inc 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <check.h> +#include <talloc.h> +#include <tevent.h> +#include <popt.h> + +#include "tests/common.h" +#include "util/util.h" + +/* Interface under test */ +#include "util/refcount.h" + +/* Fail the test if object 'obj' does not have 'num' references. */ +#define REF_ASSERT(obj, num) \ + fail_unless(((obj)->DO_NOT_TOUCH_THIS_MEMBER_refcount == (num)), \ + "Reference count of " #obj " should be %d but is %d", \ + (num), (obj)->DO_NOT_TOUCH_THIS_MEMBER_refcount) + +#define FILLER_SIZE 32 + +struct foo { + REFCOUNT_COMMON; + char a[FILLER_SIZE]; + char b[FILLER_SIZE]; +}; + +struct bar { + char a[FILLER_SIZE]; + REFCOUNT_COMMON; + char b[FILLER_SIZE]; +}; + +struct baz { + char a[FILLER_SIZE]; + char b[FILLER_SIZE]; + REFCOUNT_COMMON; +}; + +#define SET_FILLER(target) do { \ + memset((target)->a, 'a', FILLER_SIZE); \ + memset((target)->b, 'b', FILLER_SIZE); \ +} while (0) + +#define CHECK_FILLER(target) do { \ + int _counter; \ + for (_counter = 0; _counter < FILLER_SIZE; _counter++) { \ + fail_unless((target)->a[_counter] == 'a', "Corrupted memory in " \ + #target "->a[%d] of size %d", _counter, FILLER_SIZE); \ + fail_unless((target)->b[_counter] == 'b', "Corrupted memory in " \ + #target "->b[%d] of size %d", _counter, FILLER_SIZE); \ + } \ +} while (0) + +struct container { + struct foo *foo; + struct bar *bar; + struct baz *baz; +}; + +static struct container *global; + +START_TEST(test_refcount_basic) +{ + struct container *containers; + int i; + + /* First allocate our global storage place. */ + global = talloc(NULL, struct container); + fail_if(global == NULL); + + /* Allocate foo. */ + global->foo = rc_alloc(global, struct foo); + fail_if(global->foo == NULL); + SET_FILLER(global->foo); + REF_ASSERT(global->foo, 1); + + /* Allocate bar. */ + global->bar = rc_alloc(global, struct bar); + fail_if(global->bar == NULL); + SET_FILLER(global->bar); + REF_ASSERT(global->bar, 1); + + /* Allocate baz. */ + global->baz = rc_alloc(global, struct baz); + fail_if(global->baz == NULL); + SET_FILLER(global->baz); + REF_ASSERT(global->baz, 1); + + /* Try multiple attaches. */ + containers = talloc_array(NULL, struct container, 100); + fail_if(containers == NULL); + for (i = 0; i < 100; i++) { + containers[i].foo = rc_reference(containers, struct foo, global->foo); + containers[i].bar = rc_reference(containers, struct bar, global->bar); + containers[i].baz = rc_reference(containers, struct baz, global->baz); + REF_ASSERT(containers[i].foo, i + 2); + REF_ASSERT(global->foo, i + 2); + REF_ASSERT(containers[i].bar, i + 2); + REF_ASSERT(global->bar, i + 2); + REF_ASSERT(containers[i].baz, i + 2); + REF_ASSERT(global->baz, i + 2); + } + talloc_free(containers); + + CHECK_FILLER(global->foo); + CHECK_FILLER(global->bar); + CHECK_FILLER(global->baz); + + REF_ASSERT(global->foo, 1); + REF_ASSERT(global->bar, 1); + REF_ASSERT(global->baz, 1); + + talloc_free(global); +} +END_TEST + +START_TEST(test_refcount_swap) +{ + void *tmp_ctx; + struct container *container1; + struct container *container2; + + tmp_ctx = talloc_new(NULL); + + check_leaks_push(tmp_ctx); + + container1 = talloc(tmp_ctx, struct container); + container2 = talloc(tmp_ctx, struct container); + + /* Allocate. */ + container1->foo = rc_alloc(container1, struct foo); + fail_if(container1->foo == NULL); + SET_FILLER(container1->foo); + + /* Reference. */ + container2->foo = rc_reference(container2, struct foo, container1->foo); + fail_if(container2->foo == NULL); + + /* Make sure everything is as it should be. */ + fail_unless(container1->foo == container2->foo); + REF_ASSERT(container1->foo, 2); + + /* Free in reverse order. */ + talloc_free(container1); + REF_ASSERT(container2->foo, 1); + CHECK_FILLER(container2->foo); + talloc_free(container2); + + check_leaks_pop(tmp_ctx); + talloc_free(tmp_ctx); +} +END_TEST + +Suite *create_suite(void) +{ + Suite *s = suite_create("refcount"); + + TCase *tc = tcase_create("REFCOUNT Tests"); + + /* Do some testing */ + tcase_add_checked_fixture(tc, leak_check_setup, leak_check_teardown); + tcase_add_test(tc, test_refcount_basic); + tcase_add_test(tc, test_refcount_swap); + + /* Add all test cases to the test suite */ + suite_add_tcase(s, tc); + + return s; +} + +int main(int argc, const char *argv[]) +{ + int opt; + poptContext pc; + int failure_count; + Suite *suite; + SRunner *sr; + int debug = 0; + + struct poptOption long_options[] = { + POPT_AUTOHELP + { "debug-level", 'd', POPT_ARG_INT, &debug, 0, "Set debug level", NULL }, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + debug_level = debug; + + suite = create_suite(); + sr = srunner_create(suite); + srunner_set_fork_status(sr, CK_FORK); + srunner_run_all(sr, CK_VERBOSE); + failure_count = srunner_ntests_failed(sr); + srunner_free(sr); + return (failure_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + |