From 23c31df07ce1652d83f53a21151556747876ed0b Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Sat, 3 Nov 2007 17:21:53 -0400 Subject: [PATCH] implement OOM testing The glib dep removal. It has begun. --- polkit/Makefile.am | 1 + polkit/polkit-action.c | 72 ++++++++++++----- polkit/polkit-error.c | 54 +++++++++---- polkit/polkit-memory.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++ polkit/polkit-memory.h | 59 ++++++++++++++ polkit/polkit-test.c | 70 +++++++++++++++-- polkit/polkit-test.h | 10 +++ 7 files changed, 430 insertions(+), 46 deletions(-) create mode 100644 polkit/polkit-memory.c create mode 100644 polkit/polkit-memory.h diff --git a/polkit/Makefile.am b/polkit/Makefile.am index fe25807..835d840 100644 --- a/polkit/Makefile.am +++ b/polkit/Makefile.am @@ -41,6 +41,7 @@ libpolkit_la_SOURCES = \ polkit.h \ polkit-private.h \ polkit-types.h \ + polkit-memory.h polkit-memory.c \ polkit-sysdeps.h polkit-sysdeps.c \ polkit-error.h polkit-error.c \ polkit-result.h polkit-result.c \ diff --git a/polkit/polkit-action.c b/polkit/polkit-action.c index fd62b20..ac7fea6 100644 --- a/polkit/polkit-action.c +++ b/polkit/polkit-action.c @@ -40,7 +40,9 @@ #include "polkit-debug.h" #include "polkit-action.h" #include "polkit-utils.h" -#include +#include "polkit-utils.h" +#include "polkit-memory.h" +#include "polkit-test.h" /** * SECTION:polkit-action @@ -72,8 +74,11 @@ PolKitAction * polkit_action_new (void) { PolKitAction *action; - action = g_new0 (PolKitAction, 1); + action = p_new0 (PolKitAction, 1); + if (action == NULL) + goto out; action->refcount = 1; +out: return action; } @@ -108,8 +113,8 @@ polkit_action_unref (PolKitAction *action) action->refcount--; if (action->refcount > 0) return; - g_free (action->id); - g_free (action); + p_free (action->id); + p_free (action); } /** @@ -127,8 +132,11 @@ polkit_action_set_action_id (PolKitAction *action, const char *action_id) g_return_val_if_fail (action != NULL, FALSE); g_return_val_if_fail (polkit_action_validate_id (action_id), FALSE); if (action->id != NULL) - g_free (action->id); - action->id = g_strdup (action_id); + p_free (action->id); + action->id = p_strdup (action_id); + if (action->id == NULL) + return FALSE; + return TRUE; } @@ -226,8 +234,8 @@ polkit_action_validate (PolKitAction *action) #ifdef POLKIT_BUILD_TESTS -polkit_bool_t -_test_polkit_action (void) +static polkit_bool_t +_run_test (void) { int n; char *valid_action_ids[] = {"org.example.action", @@ -254,21 +262,43 @@ _test_polkit_action (void) PolKitAction *a; char *s; a = polkit_action_new (); - g_assert (! polkit_action_get_action_id (a, &s)); - g_assert (polkit_action_set_action_id (a, "org.example.action")); - g_assert (polkit_action_validate (a)); - polkit_action_ref (a); - g_assert (polkit_action_validate (a)); - polkit_action_unref (a); - g_assert (polkit_action_set_action_id (a, "org.example.action2")); - g_assert (polkit_action_validate (a)); - g_assert (polkit_action_get_action_id (a, &s)); - g_assert (strcmp (s, "org.example.action2") == 0); - polkit_action_debug (a); - polkit_action_unref (a); - a = NULL; + if (a == NULL) { + /* OOM */ + } else { + + g_assert (! polkit_action_get_action_id (a, &s)); + + if (!polkit_action_set_action_id (a, "org.example.action")) { + /* OOM */ + } else { + g_assert (polkit_action_validate (a)); + polkit_action_ref (a); + g_assert (polkit_action_validate (a)); + polkit_action_unref (a); + g_assert (polkit_action_validate (a)); + + if (!polkit_action_set_action_id (a, "org.example.action2")) { + /* OOM */ + } else { + g_assert (polkit_action_validate (a)); + g_assert (polkit_action_get_action_id (a, &s)); + g_assert (strcmp (s, "org.example.action2") == 0); + polkit_action_debug (a); + } + } + + polkit_action_unref (a); + } + return TRUE; } +PolKitTest _test_action = { + "polkit_action", + NULL, + NULL, + _run_test +}; + #endif /* POLKIT_BUILD_TESTS */ diff --git a/polkit/polkit-error.c b/polkit/polkit-error.c index c70c698..19c7f76 100644 --- a/polkit/polkit-error.c +++ b/polkit/polkit-error.c @@ -50,6 +50,7 @@ #include "polkit-error.h" #include "polkit-debug.h" #include "polkit-test.h" +#include "polkit-memory.h" /** * PolKitError: @@ -151,13 +152,13 @@ polkit_error_free (PolKitError *error) { g_return_if_fail (error != NULL); if (!error->is_static) { - g_free (error->error_message); - g_free (error); + p_free (error->error_message); + p_free (error); } } -//static PolKitError _oom_error = {true, POLKIT_ERROR_OUT_OF_MEMORY, "Out of memory"}; +static PolKitError _oom_error = {TRUE, POLKIT_ERROR_OUT_OF_MEMORY, "Pre-allocated OOM error object"}; /** * polkit_error_set_error: @@ -177,24 +178,33 @@ polkit_error_set_error (PolKitError **error, PolKitErrorCode error_code, const c PolKitError *e; g_return_val_if_fail (error != NULL, FALSE); + g_return_val_if_fail (format != NULL, FALSE); g_return_val_if_fail (error_code >= 0 && error_code < POLKIT_ERROR_NUM_ERROR_CODES, FALSE); - e = g_new0 (PolKitError, 1); - e->is_static = FALSE; - e->error_code = error_code; - va_start (args, format); - e->error_message = g_strdup_vprintf (format, args); - va_end (args); - - *error = e; + e = p_new0 (PolKitError, 1); + if (e == NULL) { + *error = &_oom_error; + } else { + e->is_static = FALSE; + e->error_code = error_code; + va_start (args, format); + e->error_message = p_strdup_vprintf (format, args); + va_end (args); + if (e->error_message == NULL) { + p_free (e); + *error = &_oom_error; + } else { + *error = e; + } + } return TRUE; } #ifdef POLKIT_BUILD_TESTS -polkit_bool_t -_test_polkit_error (void) +static polkit_bool_t +_run_test (void) { unsigned int n; PolKitError *e; @@ -208,11 +218,13 @@ _test_polkit_error (void) for (n = 0; n < POLKIT_ERROR_NUM_ERROR_CODES; n++) { polkit_error_set_error (&e, n, "Testing error code %d", n); g_assert (polkit_error_is_set (e)); - g_assert (polkit_error_get_error_code (e) == n); - g_assert (strcmp (polkit_error_get_error_name (e), error_names[n]) == 0); + g_assert (polkit_error_get_error_code (e) == n || polkit_error_get_error_code (e) == POLKIT_ERROR_OUT_OF_MEMORY); + g_assert (strcmp (polkit_error_get_error_name (e), error_names[polkit_error_get_error_code (e)]) == 0); - snprintf (s, sizeof (s), "Testing error code %d", n); - g_assert (strcmp (polkit_error_get_error_message (e), s) == 0); + if (polkit_error_get_error_code (e) != POLKIT_ERROR_OUT_OF_MEMORY) { + snprintf (s, sizeof (s), "Testing error code %d", n); + g_assert (strcmp (polkit_error_get_error_message (e), s) == 0); + } polkit_error_free (e); } @@ -220,4 +232,12 @@ _test_polkit_error (void) return TRUE; } + +PolKitTest _test_error = { + "polkit_error", + NULL, + NULL, + _run_test +}; + #endif /* POLKIT_BUILD_TESTS */ diff --git a/polkit/polkit-memory.c b/polkit/polkit-memory.c new file mode 100644 index 0000000..4e88f4d --- /dev/null +++ b/polkit/polkit-memory.c @@ -0,0 +1,210 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-memory.c : Memory management + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#ifdef POLKIT_BUILD_TESTS + +static int _cur_allocs = 0; +static int _total_allocs = 0; +static int _fail_nth = -1; + +void +_polkit_memory_reset (void) +{ + _cur_allocs = 0; + _total_allocs = 0; + _fail_nth = -1; +} + +int +_polkit_memory_get_current_allocations (void) +{ + return _cur_allocs; +} + +int +_polkit_memory_get_total_allocations (void) +{ + return _total_allocs; +} + +void +_polkit_memory_fail_nth_alloc (int number) +{ + _fail_nth = number; +} + +void * +p_malloc (size_t bytes) +{ + void *p; + + if (_fail_nth != -1 && _total_allocs == _fail_nth) { + return NULL; + } + + p = malloc (bytes); + + if (p != NULL) { + _cur_allocs++; + _total_allocs++; + } + + return p; +} + +void * +p_malloc0 (size_t bytes) +{ + void *p; + + if (_fail_nth != -1 && _total_allocs == _fail_nth) { + return NULL; + } + + p = calloc (1, bytes); + + if (p != NULL) { + _cur_allocs++; + _total_allocs++; + } + + return p; +} + +void +p_free (void *memory) +{ + free (memory); + if (memory != NULL) { + _cur_allocs--; + } +} + +char * +p_strdup (const char *s) +{ + void *p; + size_t len; + + len = strlen (s) + 1; + + p = p_malloc (len + 1); + if (p == NULL) + goto out; + + memcpy (p, s, len + 1); + +out: + return p; +} + +/*--------------------------------------------------------------------------------------------------------------*/ +#else +/*--------------------------------------------------------------------------------------------------------------*/ + +void * +p_malloc (size_t bytes) +{ + return malloc (bytes); +} + +void * +p_malloc0 (size_t bytes) +{ + return calloc (1, bytes); +} + +void +p_free (void *memory) +{ + free (memory); +} + +void +_polkit_memory_reset (void) +{ +} + +int +_polkit_memory_get_current_allocations (void) +{ + return -1; +} + +int +_polkit_memory_get_total_allocations (void) +{ + return -1; +} + +void +_polkit_memory_fail_nth_alloc (int number) +{ +} + +char * +p_strdup (const char *s) +{ + return strdup (s); +} + +#endif /* POLKIT_BUILD_TESTS */ + +char* +p_strdup_printf (const char *format, ...) +{ + char *s; + va_list args; + + va_start (args, format); + s = p_strdup_vprintf (format, args); + va_end (args); + + return s; +} + +char* +p_strdup_vprintf (const char *format, va_list args) +{ + char *s; + char *gs; + /* TODO: reimplement */ + gs = g_strdup_vprintf (format, args); + s = p_strdup (gs); + g_free (gs); + + return s; +} diff --git a/polkit/polkit-memory.h b/polkit/polkit-memory.h new file mode 100644 index 0000000..7b969d8 --- /dev/null +++ b/polkit/polkit-memory.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-memory.h : Memory management + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#if !defined (POLKIT_COMPILATION) +#error "polkit-memory.h is a private file" +#endif + +#ifndef POLKIT_MEMORY_H +#define POLKIT_MEMORY_H + +#include +#include + +POLKIT_BEGIN_DECLS + +void *p_malloc (size_t bytes); +void *p_malloc0 (size_t bytes); +void p_free (void *memory); +char *p_strdup (const char *s); + +#define p_new(type, count) ((type*)p_malloc (sizeof (type) * (count))); +#define p_new0(type, count) ((type*)p_malloc0 (sizeof (type) * (count))); + +void _polkit_memory_reset (void); +int _polkit_memory_get_current_allocations (void); +int _polkit_memory_get_total_allocations (void); +void _polkit_memory_fail_nth_alloc (int number); + +char* p_strdup_printf (const char *format, ...); +char* p_strdup_vprintf (const char *format, va_list args); + + +POLKIT_END_DECLS + +#endif /* POLKIT_MEMORY_H */ + + diff --git a/polkit/polkit-test.c b/polkit/polkit-test.c index fbd7a3e..50b3142 100644 --- a/polkit/polkit-test.c +++ b/polkit/polkit-test.c @@ -26,23 +26,77 @@ #include #include #include +#include + +#define MAX_TESTS 64 + +static PolKitTest *tests[] = { + &_test_action, + &_test_error, +}; int main (int argc, char *argv[]) { int ret; + int n; + int num_tests; - ret = 1; - printf ("Running unit tests for libpolkit\n"); + ret = 0; - if (!_test_polkit_action ()) - goto out; + num_tests = sizeof (tests) / sizeof (PolKitTest*); - if (!_test_polkit_error ()) - goto out; + printf ("Running %d unit tests\n", num_tests); + for (n = 0; n < num_tests; n++) { + int m; + int total_allocs; + int delta; + PolKitTest *test = tests[n]; - ret = 0; -out: + _polkit_memory_reset (); + + if (test->setup != NULL) + test->setup (); + + printf ("Running: %s\n", test->name); + if (!test->run ()) { + printf ("Failed\n"); + ret = 1; + goto test_done; + } + + total_allocs = _polkit_memory_get_total_allocations (); + printf (" Unit test made %d allocations in total\n", total_allocs); + + delta = _polkit_memory_get_current_allocations (); + if (delta != 0) { + printf (" Unit test leaked %d allocations\n", delta); + ret = 1; + } + + for (m = 0; m < total_allocs; m++) { + printf (" Failing allocation %d of %d\n", m + 1, total_allocs); + + _polkit_memory_reset (); + _polkit_memory_fail_nth_alloc (m); + + if (!test->run ()) { + printf (" Failed\n"); + ret = 1; + continue; + } + + delta = _polkit_memory_get_current_allocations (); + if (delta != 0) { + printf (" Unit test leaked %d allocations\n", delta); + ret = 1; + } + } + + test_done: + if (test->teardown != NULL) + test->teardown (); + } return ret; } diff --git a/polkit/polkit-test.h b/polkit/polkit-test.h index 5ca3e54..aace39d 100644 --- a/polkit/polkit-test.h +++ b/polkit/polkit-test.h @@ -37,6 +37,16 @@ POLKIT_BEGIN_DECLS polkit_bool_t _test_polkit_action (void); polkit_bool_t _test_polkit_error (void); +typedef struct { + const char *name; + void (*setup) (void); + void (*teardown) (void); + polkit_bool_t (*run) (void); +} PolKitTest; + +extern PolKitTest _test_action; +extern PolKitTest _test_error; + POLKIT_END_DECLS #endif /* POLKIT_TEST_H */ -- 2.7.4