1*7bdf38e5Schristos #include "test/jemalloc_test.h" 2*7bdf38e5Schristos 3*7bdf38e5Schristos const char *dump_filename = "/dev/null"; 4*7bdf38e5Schristos 5*7bdf38e5Schristos prof_backtrace_hook_t default_hook; 6*7bdf38e5Schristos 7*7bdf38e5Schristos bool mock_bt_hook_called = false; 8*7bdf38e5Schristos bool mock_dump_hook_called = false; 9*7bdf38e5Schristos 10*7bdf38e5Schristos void 11*7bdf38e5Schristos mock_bt_hook(void **vec, unsigned *len, unsigned max_len) { 12*7bdf38e5Schristos *len = max_len; 13*7bdf38e5Schristos for (unsigned i = 0; i < max_len; ++i) { 14*7bdf38e5Schristos vec[i] = (void *)((uintptr_t)i); 15*7bdf38e5Schristos } 16*7bdf38e5Schristos mock_bt_hook_called = true; 17*7bdf38e5Schristos } 18*7bdf38e5Schristos 19*7bdf38e5Schristos void 20*7bdf38e5Schristos mock_bt_augmenting_hook(void **vec, unsigned *len, unsigned max_len) { 21*7bdf38e5Schristos default_hook(vec, len, max_len); 22*7bdf38e5Schristos expect_u_gt(*len, 0, "Default backtrace hook returned empty backtrace"); 23*7bdf38e5Schristos expect_u_lt(*len, max_len, 24*7bdf38e5Schristos "Default backtrace hook returned too large backtrace"); 25*7bdf38e5Schristos 26*7bdf38e5Schristos /* Add a separator between default frames and augmented */ 27*7bdf38e5Schristos vec[*len] = (void *)0x030303030; 28*7bdf38e5Schristos (*len)++; 29*7bdf38e5Schristos 30*7bdf38e5Schristos /* Add more stack frames */ 31*7bdf38e5Schristos for (unsigned i = 0; i < 3; ++i) { 32*7bdf38e5Schristos if (*len == max_len) { 33*7bdf38e5Schristos break; 34*7bdf38e5Schristos } 35*7bdf38e5Schristos vec[*len] = (void *)((uintptr_t)i); 36*7bdf38e5Schristos (*len)++; 37*7bdf38e5Schristos } 38*7bdf38e5Schristos 39*7bdf38e5Schristos 40*7bdf38e5Schristos mock_bt_hook_called = true; 41*7bdf38e5Schristos } 42*7bdf38e5Schristos 43*7bdf38e5Schristos void 44*7bdf38e5Schristos mock_dump_hook(const char *filename) { 45*7bdf38e5Schristos mock_dump_hook_called = true; 46*7bdf38e5Schristos expect_str_eq(filename, dump_filename, 47*7bdf38e5Schristos "Incorrect file name passed to the dump hook"); 48*7bdf38e5Schristos } 49*7bdf38e5Schristos 50*7bdf38e5Schristos TEST_BEGIN(test_prof_backtrace_hook_replace) { 51*7bdf38e5Schristos 52*7bdf38e5Schristos test_skip_if(!config_prof); 53*7bdf38e5Schristos 54*7bdf38e5Schristos mock_bt_hook_called = false; 55*7bdf38e5Schristos 56*7bdf38e5Schristos void *p0 = mallocx(1, 0); 57*7bdf38e5Schristos assert_ptr_not_null(p0, "Failed to allocate"); 58*7bdf38e5Schristos 59*7bdf38e5Schristos expect_false(mock_bt_hook_called, "Called mock hook before it's set"); 60*7bdf38e5Schristos 61*7bdf38e5Schristos prof_backtrace_hook_t null_hook = NULL; 62*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_backtrace", 63*7bdf38e5Schristos NULL, 0, (void *)&null_hook, sizeof(null_hook)), 64*7bdf38e5Schristos EINVAL, "Incorrectly allowed NULL backtrace hook"); 65*7bdf38e5Schristos 66*7bdf38e5Schristos size_t default_hook_sz = sizeof(prof_backtrace_hook_t); 67*7bdf38e5Schristos prof_backtrace_hook_t hook = &mock_bt_hook; 68*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_backtrace", 69*7bdf38e5Schristos (void *)&default_hook, &default_hook_sz, (void *)&hook, 70*7bdf38e5Schristos sizeof(hook)), 0, "Unexpected mallctl failure setting hook"); 71*7bdf38e5Schristos 72*7bdf38e5Schristos void *p1 = mallocx(1, 0); 73*7bdf38e5Schristos assert_ptr_not_null(p1, "Failed to allocate"); 74*7bdf38e5Schristos 75*7bdf38e5Schristos expect_true(mock_bt_hook_called, "Didn't call mock hook"); 76*7bdf38e5Schristos 77*7bdf38e5Schristos prof_backtrace_hook_t current_hook; 78*7bdf38e5Schristos size_t current_hook_sz = sizeof(prof_backtrace_hook_t); 79*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_backtrace", 80*7bdf38e5Schristos (void *)¤t_hook, ¤t_hook_sz, (void *)&default_hook, 81*7bdf38e5Schristos sizeof(default_hook)), 0, 82*7bdf38e5Schristos "Unexpected mallctl failure resetting hook to default"); 83*7bdf38e5Schristos 84*7bdf38e5Schristos expect_ptr_eq(current_hook, hook, 85*7bdf38e5Schristos "Hook returned by mallctl is not equal to mock hook"); 86*7bdf38e5Schristos 87*7bdf38e5Schristos dallocx(p1, 0); 88*7bdf38e5Schristos dallocx(p0, 0); 89*7bdf38e5Schristos } 90*7bdf38e5Schristos TEST_END 91*7bdf38e5Schristos 92*7bdf38e5Schristos TEST_BEGIN(test_prof_backtrace_hook_augment) { 93*7bdf38e5Schristos 94*7bdf38e5Schristos test_skip_if(!config_prof); 95*7bdf38e5Schristos 96*7bdf38e5Schristos mock_bt_hook_called = false; 97*7bdf38e5Schristos 98*7bdf38e5Schristos void *p0 = mallocx(1, 0); 99*7bdf38e5Schristos assert_ptr_not_null(p0, "Failed to allocate"); 100*7bdf38e5Schristos 101*7bdf38e5Schristos expect_false(mock_bt_hook_called, "Called mock hook before it's set"); 102*7bdf38e5Schristos 103*7bdf38e5Schristos size_t default_hook_sz = sizeof(prof_backtrace_hook_t); 104*7bdf38e5Schristos prof_backtrace_hook_t hook = &mock_bt_augmenting_hook; 105*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_backtrace", 106*7bdf38e5Schristos (void *)&default_hook, &default_hook_sz, (void *)&hook, 107*7bdf38e5Schristos sizeof(hook)), 0, "Unexpected mallctl failure setting hook"); 108*7bdf38e5Schristos 109*7bdf38e5Schristos void *p1 = mallocx(1, 0); 110*7bdf38e5Schristos assert_ptr_not_null(p1, "Failed to allocate"); 111*7bdf38e5Schristos 112*7bdf38e5Schristos expect_true(mock_bt_hook_called, "Didn't call mock hook"); 113*7bdf38e5Schristos 114*7bdf38e5Schristos prof_backtrace_hook_t current_hook; 115*7bdf38e5Schristos size_t current_hook_sz = sizeof(prof_backtrace_hook_t); 116*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_backtrace", 117*7bdf38e5Schristos (void *)¤t_hook, ¤t_hook_sz, (void *)&default_hook, 118*7bdf38e5Schristos sizeof(default_hook)), 0, 119*7bdf38e5Schristos "Unexpected mallctl failure resetting hook to default"); 120*7bdf38e5Schristos 121*7bdf38e5Schristos expect_ptr_eq(current_hook, hook, 122*7bdf38e5Schristos "Hook returned by mallctl is not equal to mock hook"); 123*7bdf38e5Schristos 124*7bdf38e5Schristos dallocx(p1, 0); 125*7bdf38e5Schristos dallocx(p0, 0); 126*7bdf38e5Schristos } 127*7bdf38e5Schristos TEST_END 128*7bdf38e5Schristos 129*7bdf38e5Schristos TEST_BEGIN(test_prof_dump_hook) { 130*7bdf38e5Schristos 131*7bdf38e5Schristos test_skip_if(!config_prof); 132*7bdf38e5Schristos 133*7bdf38e5Schristos mock_dump_hook_called = false; 134*7bdf38e5Schristos 135*7bdf38e5Schristos expect_d_eq(mallctl("prof.dump", NULL, NULL, (void *)&dump_filename, 136*7bdf38e5Schristos sizeof(dump_filename)), 0, "Failed to dump heap profile"); 137*7bdf38e5Schristos 138*7bdf38e5Schristos expect_false(mock_dump_hook_called, "Called dump hook before it's set"); 139*7bdf38e5Schristos 140*7bdf38e5Schristos size_t default_hook_sz = sizeof(prof_dump_hook_t); 141*7bdf38e5Schristos prof_dump_hook_t hook = &mock_dump_hook; 142*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_dump", 143*7bdf38e5Schristos (void *)&default_hook, &default_hook_sz, (void *)&hook, 144*7bdf38e5Schristos sizeof(hook)), 0, "Unexpected mallctl failure setting hook"); 145*7bdf38e5Schristos 146*7bdf38e5Schristos expect_d_eq(mallctl("prof.dump", NULL, NULL, (void *)&dump_filename, 147*7bdf38e5Schristos sizeof(dump_filename)), 0, "Failed to dump heap profile"); 148*7bdf38e5Schristos 149*7bdf38e5Schristos expect_true(mock_dump_hook_called, "Didn't call mock hook"); 150*7bdf38e5Schristos 151*7bdf38e5Schristos prof_dump_hook_t current_hook; 152*7bdf38e5Schristos size_t current_hook_sz = sizeof(prof_dump_hook_t); 153*7bdf38e5Schristos expect_d_eq(mallctl("experimental.hooks.prof_dump", 154*7bdf38e5Schristos (void *)¤t_hook, ¤t_hook_sz, (void *)&default_hook, 155*7bdf38e5Schristos sizeof(default_hook)), 0, 156*7bdf38e5Schristos "Unexpected mallctl failure resetting hook to default"); 157*7bdf38e5Schristos 158*7bdf38e5Schristos expect_ptr_eq(current_hook, hook, 159*7bdf38e5Schristos "Hook returned by mallctl is not equal to mock hook"); 160*7bdf38e5Schristos } 161*7bdf38e5Schristos TEST_END 162*7bdf38e5Schristos 163*7bdf38e5Schristos int 164*7bdf38e5Schristos main(void) { 165*7bdf38e5Schristos return test( 166*7bdf38e5Schristos test_prof_backtrace_hook_replace, 167*7bdf38e5Schristos test_prof_backtrace_hook_augment, 168*7bdf38e5Schristos test_prof_dump_hook); 169*7bdf38e5Schristos } 170