From f0d7e2a1cacdffcbc84e5ad2bdd04f405dcaeb65 Mon Sep 17 00:00:00 2001 From: Martin Nagy Date: Wed, 21 Oct 2009 17:24:13 +0200 Subject: Add a new set of helpful common functions for tests The leak_check_setup() and leak_check_teardown() functions can be added to a test case with tcase_add_checked_fixture(). They will make sure that all tests are checked for memory leaks. However, since talloc is hierarchical and automatically frees the children, this will not catch all cases, but might still be helpful. The check_leaks(ctx, bytes) function takes a talloc context as an argument and the number of bytes it should be using up (children included). The total byte size used up by the context is determined by the talloc_total_size() function. If the size doesn't agree, check_leaks() will print out a talloc report on the context and makes the current test fail. The check_leaks_push() and check_leaks_pop() both take a talloc context as an argument. Every time push is called, the context is "pushed" onto an internal stack and it's current size is noted. When the context is later "poped", the pop function will make sure that the size is the same as when it was pushed. It will also check that it's not called out-of-order or if the stack isn't empty. --- server/Makefile.am | 3 +- server/tests/common.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ server/tests/common.h | 19 +++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 server/tests/common.c create mode 100644 server/tests/common.h diff --git a/server/Makefile.am b/server/Makefile.am index 81f438d36..a2c36874a 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -270,7 +270,8 @@ dist_noinst_HEADERS = \ tools/sss_sync_ops.h \ resolv/async_resolv.h \ resolv/ares/ares_parse_srv_reply.h \ - resolv/ares/ares_parse_txt_reply.h + resolv/ares/ares_parse_txt_reply.h \ + tests/common.h #################### diff --git a/server/tests/common.c b/server/tests/common.c new file mode 100644 index 000000000..5b341abce --- /dev/null +++ b/server/tests/common.c @@ -0,0 +1,104 @@ +/* + SSSD + + Common utilities for check-based tests using talloc. + + Authors: + Martin Nagy + + 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 . +*/ + +#include +#include + +#include "tests/common.h" +#include "util/dlinklist.h" +#include "util/util.h" + +struct size_snapshot { + struct size_snapshot *prev; + struct size_snapshot *next; + + TALLOC_CTX *ctx; + size_t bytes_allocated; +}; + +static struct size_snapshot *snapshot_stack; + +void +_check_leaks(TALLOC_CTX *ctx, size_t bytes, const char *location) +{ + size_t bytes_allocated; + + bytes_allocated = talloc_total_size(ctx); + if (bytes_allocated != bytes) { + fprintf(stderr, "Leak report for %s:\n", location); + talloc_report_full(NULL, stderr); + fail("%s: memory leaks detected, %d bytes still allocated", + location, bytes_allocated - bytes); + } +} + +void +check_leaks_push(TALLOC_CTX *ctx) +{ + struct size_snapshot *snapshot; + + snapshot = talloc(NULL, struct size_snapshot); + snapshot->ctx = ctx; + snapshot->bytes_allocated = talloc_total_size(ctx); + DLIST_ADD(snapshot_stack, snapshot); +} + +void +_check_leaks_pop(TALLOC_CTX *ctx, const char *location) +{ + struct size_snapshot *snapshot; + TALLOC_CTX *old_ctx; + size_t bytes_allocated; + + if (snapshot_stack == NULL) { + fail("%s: trying to pop an empty stack"); + } + + snapshot = snapshot_stack; + DLIST_REMOVE(snapshot_stack, snapshot); + + old_ctx = snapshot->ctx; + bytes_allocated = snapshot->bytes_allocated; + + fail_if(old_ctx != ctx, "Bad push/pop order"); + + talloc_zfree(snapshot); + _check_leaks(old_ctx, bytes_allocated, location); +} + +void +leak_check_setup(void) +{ + talloc_enable_null_tracking(); +} + +void +leak_check_teardown(void) +{ + if (snapshot_stack != NULL) { + fail("Exiting with a non-empty stack"); + } + talloc_free(talloc_autofree_context()); + check_leaks(NULL, 0); +} diff --git a/server/tests/common.h b/server/tests/common.h new file mode 100644 index 000000000..39a2b8e07 --- /dev/null +++ b/server/tests/common.h @@ -0,0 +1,19 @@ +#ifndef __TESTS_COMMON_H__ +#define __TESTS_COMMON_H__ + +#include + +#define check_leaks(ctx, bytes) _check_leaks((ctx), (bytes), __location__) +void _check_leaks(TALLOC_CTX *ctx, + size_t bytes, + const char *location); + +void check_leaks_push(TALLOC_CTX *ctx); + +#define check_leaks_pop(ctx) _check_leaks_pop((ctx), __location__) +void _check_leaks_pop(TALLOC_CTX *ctx, const char *location); + +void leak_check_setup(void); +void leak_check_teardown(void); + +#endif /* !__TESTS_COMMON_H__ */ -- cgit