/** * test_oom_handling: * @func: function to call * @data: data to pass to function * * Tests how well the given function responds to out-of-memory * situations. Calls the function repeatedly, failing a different * call to malloc() each time. If the function ever returns #FALSE, * the test fails. The function should return #TRUE whenever something * valid (such as returning an error, or succeeding) occurs, and #FALSE * if it gets confused in some way. * * Returns #TRUE if the function never returns FALSE */ int test_oom_handling (TestMemoryFunction func, void *data) { int approx_mallocs; /* Run once to see about how many mallocs are involved */ set_fail_alloc_counter (_TEST_INT_MAX); if (!(* func) (data)) return FALSE; approx_mallocs = _TEST_INT_MAX - get_fail_alloc_counter (); set_fail_alloc_failures (1); if (!run_failing_each_malloc (approx_mallocs, func, data)) return FALSE; set_fail_alloc_failures (2); if (!run_failing_each_malloc (approx_mallocs, func, data)) return FALSE; set_fail_alloc_failures (3); if (!run_failing_each_malloc (approx_mallocs, func, data)) return FALSE; set_fail_alloc_counter (_TEST_INT_MAX); return TRUE; }
/** * Tests how well the given function responds to out-of-memory * situations. Calls the function repeatedly, failing a different * call to malloc() each time. If the function ever returns #FALSE, * the test fails. The function should return #TRUE whenever something * valid (such as returning an error, or succeeding) occurs, and #FALSE * if it gets confused in some way. * * @param description description of the test used in verbose output * @param func function to call * @param data data to pass to function * @returns #TRUE if the function never returns FALSE */ dbus_bool_t _dbus_test_oom_handling (const char *description, DBusTestMemoryFunction func, void *data) { int approx_mallocs; const char *setting; int max_failures_to_try; int i; /* Run once to see about how many mallocs are involved */ _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); _dbus_verbose ("Running once to count mallocs\n"); if (!(* func) (data)) return FALSE; approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter (); _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n", description, approx_mallocs); setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES"); if (setting != NULL) { DBusString str; long v; _dbus_string_init_const (&str, setting); v = 4; if (!_dbus_string_parse_int (&str, 0, &v, NULL)) _dbus_warn ("couldn't parse '%s' as integer\n", setting); max_failures_to_try = v; } else { max_failures_to_try = 4; } i = setting ? max_failures_to_try - 1 : 1; while (i < max_failures_to_try) { _dbus_set_fail_alloc_failures (i); if (!run_failing_each_malloc (approx_mallocs, description, func, data)) return FALSE; ++i; } _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n", description); return TRUE; }