diff options
author | Alex Lapenkou <lapenkov@fb.com> | 2021-09-01 13:00:01 -0700 |
---|---|---|
committer | Alexander Lapenkov <lapenkov.a@yandex.ru> | 2021-09-22 15:04:01 -0700 |
commit | a9031a0970df9c999873617423f789bd46bfe619 (patch) | |
tree | 3ad66313811401baad2e4048b985c9d3c5740b0d /test | |
parent | f7d46b81197b9879e1f572f9a4d3bfe3b8f850b9 (diff) | |
download | jemalloc-a9031a0970df9c999873617423f789bd46bfe619.tar.gz |
Allow setting a dump hook
If users want to be notified when a heap dump occurs, they can set this hook.
Diffstat (limited to 'test')
-rw-r--r-- | test/unit/prof_hook.c | 114 |
1 files changed, 111 insertions, 3 deletions
diff --git a/test/unit/prof_hook.c b/test/unit/prof_hook.c index 32d0e9ea..6480d930 100644 --- a/test/unit/prof_hook.c +++ b/test/unit/prof_hook.c @@ -1,6 +1,11 @@ #include "test/jemalloc_test.h" +const char *dump_filename = "/dev/null"; + +prof_backtrace_hook_t default_hook; + bool mock_bt_hook_called = false; +bool mock_dump_hook_called = false; void mock_bt_hook(void **vec, unsigned *len, unsigned max_len) { @@ -11,7 +16,38 @@ mock_bt_hook(void **vec, unsigned *len, unsigned max_len) { mock_bt_hook_called = true; } -TEST_BEGIN(test_prof_backtrace_hook) { +void +mock_bt_augmenting_hook(void **vec, unsigned *len, unsigned max_len) { + default_hook(vec, len, max_len); + expect_u_gt(*len, 0, "Default backtrace hook returned empty backtrace"); + expect_u_lt(*len, max_len, + "Default backtrace hook returned too large backtrace"); + + /* Add a separator between default frames and augmented */ + vec[*len] = (void *)0x030303030; + (*len)++; + + /* Add more stack frames */ + for (unsigned i = 0; i < 3; ++i) { + if (*len == max_len) { + break; + } + vec[*len] = (void *)((uintptr_t)i); + (*len)++; + } + + + mock_bt_hook_called = true; +} + +void +mock_dump_hook(const char *filename) { + mock_dump_hook_called = true; + expect_str_eq(filename, dump_filename, + "Incorrect file name passed to the dump hook"); +} + +TEST_BEGIN(test_prof_backtrace_hook_replace) { test_skip_if(!config_prof); @@ -27,7 +63,6 @@ TEST_BEGIN(test_prof_backtrace_hook) { NULL, 0, (void *)&null_hook, sizeof(null_hook)), EINVAL, "Incorrectly allowed NULL backtrace hook"); - prof_backtrace_hook_t default_hook; size_t default_hook_sz = sizeof(prof_backtrace_hook_t); prof_backtrace_hook_t hook = &mock_bt_hook; expect_d_eq(mallctl("experimental.hooks.prof_backtrace", @@ -54,8 +89,81 @@ TEST_BEGIN(test_prof_backtrace_hook) { } TEST_END +TEST_BEGIN(test_prof_backtrace_hook_augment) { + + test_skip_if(!config_prof); + + mock_bt_hook_called = false; + + void *p0 = mallocx(1, 0); + assert_ptr_not_null(p0, "Failed to allocate"); + + expect_false(mock_bt_hook_called, "Called mock hook before it's set"); + + size_t default_hook_sz = sizeof(prof_backtrace_hook_t); + prof_backtrace_hook_t hook = &mock_bt_augmenting_hook; + expect_d_eq(mallctl("experimental.hooks.prof_backtrace", + (void *)&default_hook, &default_hook_sz, (void *)&hook, + sizeof(hook)), 0, "Unexpected mallctl failure setting hook"); + + void *p1 = mallocx(1, 0); + assert_ptr_not_null(p1, "Failed to allocate"); + + expect_true(mock_bt_hook_called, "Didn't call mock hook"); + + prof_backtrace_hook_t current_hook; + size_t current_hook_sz = sizeof(prof_backtrace_hook_t); + expect_d_eq(mallctl("experimental.hooks.prof_backtrace", + (void *)¤t_hook, ¤t_hook_sz, (void *)&default_hook, + sizeof(default_hook)), 0, + "Unexpected mallctl failure resetting hook to default"); + + expect_ptr_eq(current_hook, hook, + "Hook returned by mallctl is not equal to mock hook"); + + dallocx(p1, 0); + dallocx(p0, 0); +} +TEST_END + +TEST_BEGIN(test_prof_dump_hook) { + + test_skip_if(!config_prof); + + mock_dump_hook_called = false; + + expect_d_eq(mallctl("prof.dump", NULL, NULL, (void *)&dump_filename, + sizeof(dump_filename)), 0, "Failed to dump heap profile"); + + expect_false(mock_dump_hook_called, "Called dump hook before it's set"); + + size_t default_hook_sz = sizeof(prof_dump_hook_t); + prof_dump_hook_t hook = &mock_dump_hook; + expect_d_eq(mallctl("experimental.hooks.prof_dump", + (void *)&default_hook, &default_hook_sz, (void *)&hook, + sizeof(hook)), 0, "Unexpected mallctl failure setting hook"); + + expect_d_eq(mallctl("prof.dump", NULL, NULL, (void *)&dump_filename, + sizeof(dump_filename)), 0, "Failed to dump heap profile"); + + expect_true(mock_dump_hook_called, "Didn't call mock hook"); + + prof_dump_hook_t current_hook; + size_t current_hook_sz = sizeof(prof_dump_hook_t); + expect_d_eq(mallctl("experimental.hooks.prof_dump", + (void *)¤t_hook, ¤t_hook_sz, (void *)&default_hook, + sizeof(default_hook)), 0, + "Unexpected mallctl failure resetting hook to default"); + + expect_ptr_eq(current_hook, hook, + "Hook returned by mallctl is not equal to mock hook"); +} +TEST_END + int main(void) { return test( - test_prof_backtrace_hook); + test_prof_backtrace_hook_replace, + test_prof_backtrace_hook_augment, + test_prof_dump_hook); } |