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