1 #include "test/jemalloc_test.h" 2 3 TEST_BEGIN(test_mallctl_errors) 4 { 5 uint64_t epoch; 6 size_t sz; 7 8 assert_d_eq(mallctl("no_such_name", NULL, NULL, NULL, 0), ENOENT, 9 "mallctl() should return ENOENT for non-existent names"); 10 11 assert_d_eq(mallctl("version", NULL, NULL, "0.0.0", strlen("0.0.0")), 12 EPERM, "mallctl() should return EPERM on attempt to write " 13 "read-only value"); 14 15 assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)-1), 16 EINVAL, "mallctl() should return EINVAL for input size mismatch"); 17 assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)+1), 18 EINVAL, "mallctl() should return EINVAL for input size mismatch"); 19 20 sz = sizeof(epoch)-1; 21 assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL, 22 "mallctl() should return EINVAL for output size mismatch"); 23 sz = sizeof(epoch)+1; 24 assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL, 25 "mallctl() should return EINVAL for output size mismatch"); 26 } 27 TEST_END 28 29 TEST_BEGIN(test_mallctlnametomib_errors) 30 { 31 size_t mib[1]; 32 size_t miblen; 33 34 miblen = sizeof(mib)/sizeof(size_t); 35 assert_d_eq(mallctlnametomib("no_such_name", mib, &miblen), ENOENT, 36 "mallctlnametomib() should return ENOENT for non-existent names"); 37 } 38 TEST_END 39 40 TEST_BEGIN(test_mallctlbymib_errors) 41 { 42 uint64_t epoch; 43 size_t sz; 44 size_t mib[1]; 45 size_t miblen; 46 47 miblen = sizeof(mib)/sizeof(size_t); 48 assert_d_eq(mallctlnametomib("version", mib, &miblen), 0, 49 "Unexpected mallctlnametomib() failure"); 50 51 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, "0.0.0", 52 strlen("0.0.0")), EPERM, "mallctl() should return EPERM on " 53 "attempt to write read-only value"); 54 55 miblen = sizeof(mib)/sizeof(size_t); 56 assert_d_eq(mallctlnametomib("epoch", mib, &miblen), 0, 57 "Unexpected mallctlnametomib() failure"); 58 59 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch, 60 sizeof(epoch)-1), EINVAL, 61 "mallctlbymib() should return EINVAL for input size mismatch"); 62 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch, 63 sizeof(epoch)+1), EINVAL, 64 "mallctlbymib() should return EINVAL for input size mismatch"); 65 66 sz = sizeof(epoch)-1; 67 assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL, 68 "mallctlbymib() should return EINVAL for output size mismatch"); 69 sz = sizeof(epoch)+1; 70 assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL, 71 "mallctlbymib() should return EINVAL for output size mismatch"); 72 } 73 TEST_END 74 75 TEST_BEGIN(test_mallctl_read_write) 76 { 77 uint64_t old_epoch, new_epoch; 78 size_t sz = sizeof(old_epoch); 79 80 /* Blind. */ 81 assert_d_eq(mallctl("epoch", NULL, NULL, NULL, 0), 0, 82 "Unexpected mallctl() failure"); 83 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 84 85 /* Read. */ 86 assert_d_eq(mallctl("epoch", &old_epoch, &sz, NULL, 0), 0, 87 "Unexpected mallctl() failure"); 88 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 89 90 /* Write. */ 91 assert_d_eq(mallctl("epoch", NULL, NULL, &new_epoch, sizeof(new_epoch)), 92 0, "Unexpected mallctl() failure"); 93 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 94 95 /* Read+write. */ 96 assert_d_eq(mallctl("epoch", &old_epoch, &sz, &new_epoch, 97 sizeof(new_epoch)), 0, "Unexpected mallctl() failure"); 98 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 99 } 100 TEST_END 101 102 TEST_BEGIN(test_mallctlnametomib_short_mib) 103 { 104 size_t mib[4]; 105 size_t miblen; 106 107 miblen = 3; 108 mib[3] = 42; 109 assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0, 110 "Unexpected mallctlnametomib() failure"); 111 assert_zu_eq(miblen, 3, "Unexpected mib output length"); 112 assert_zu_eq(mib[3], 42, 113 "mallctlnametomib() wrote past the end of the input mib"); 114 } 115 TEST_END 116 117 TEST_BEGIN(test_mallctl_config) 118 { 119 120 #define TEST_MALLCTL_CONFIG(config) do { \ 121 bool oldval; \ 122 size_t sz = sizeof(oldval); \ 123 assert_d_eq(mallctl("config."#config, &oldval, &sz, NULL, 0), \ 124 0, "Unexpected mallctl() failure"); \ 125 assert_b_eq(oldval, config_##config, "Incorrect config value"); \ 126 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ 127 } while (0) 128 129 TEST_MALLCTL_CONFIG(debug); 130 TEST_MALLCTL_CONFIG(dss); 131 TEST_MALLCTL_CONFIG(fill); 132 TEST_MALLCTL_CONFIG(lazy_lock); 133 TEST_MALLCTL_CONFIG(mremap); 134 TEST_MALLCTL_CONFIG(munmap); 135 TEST_MALLCTL_CONFIG(prof); 136 TEST_MALLCTL_CONFIG(prof_libgcc); 137 TEST_MALLCTL_CONFIG(prof_libunwind); 138 TEST_MALLCTL_CONFIG(stats); 139 TEST_MALLCTL_CONFIG(tcache); 140 TEST_MALLCTL_CONFIG(tls); 141 TEST_MALLCTL_CONFIG(utrace); 142 TEST_MALLCTL_CONFIG(valgrind); 143 TEST_MALLCTL_CONFIG(xmalloc); 144 145 #undef TEST_MALLCTL_CONFIG 146 } 147 TEST_END 148 149 TEST_BEGIN(test_mallctl_opt) 150 { 151 bool config_always = true; 152 153 #define TEST_MALLCTL_OPT(t, opt, config) do { \ 154 t oldval; \ 155 size_t sz = sizeof(oldval); \ 156 int expected = config_##config ? 0 : ENOENT; \ 157 int result = mallctl("opt."#opt, &oldval, &sz, NULL, 0); \ 158 assert_d_eq(result, expected, \ 159 "Unexpected mallctl() result for opt."#opt); \ 160 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ 161 } while (0) 162 163 TEST_MALLCTL_OPT(bool, abort, always); 164 TEST_MALLCTL_OPT(size_t, lg_chunk, always); 165 TEST_MALLCTL_OPT(const char *, dss, always); 166 TEST_MALLCTL_OPT(size_t, narenas, always); 167 TEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always); 168 TEST_MALLCTL_OPT(bool, stats_print, always); 169 TEST_MALLCTL_OPT(bool, junk, fill); 170 TEST_MALLCTL_OPT(size_t, quarantine, fill); 171 TEST_MALLCTL_OPT(bool, redzone, fill); 172 TEST_MALLCTL_OPT(bool, zero, fill); 173 TEST_MALLCTL_OPT(bool, utrace, utrace); 174 TEST_MALLCTL_OPT(bool, valgrind, valgrind); 175 TEST_MALLCTL_OPT(bool, xmalloc, xmalloc); 176 TEST_MALLCTL_OPT(bool, tcache, tcache); 177 TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache); 178 TEST_MALLCTL_OPT(bool, prof, prof); 179 TEST_MALLCTL_OPT(const char *, prof_prefix, prof); 180 TEST_MALLCTL_OPT(bool, prof_active, prof); 181 TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof); 182 TEST_MALLCTL_OPT(bool, prof_accum, prof); 183 TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof); 184 TEST_MALLCTL_OPT(bool, prof_gdump, prof); 185 TEST_MALLCTL_OPT(bool, prof_final, prof); 186 TEST_MALLCTL_OPT(bool, prof_leak, prof); 187 188 #undef TEST_MALLCTL_OPT 189 } 190 TEST_END 191 192 TEST_BEGIN(test_manpage_example) 193 { 194 unsigned nbins, i; 195 size_t mib[4]; 196 size_t len, miblen; 197 198 len = sizeof(nbins); 199 assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0, 200 "Unexpected mallctl() failure"); 201 202 miblen = 4; 203 assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0, 204 "Unexpected mallctlnametomib() failure"); 205 for (i = 0; i < nbins; i++) { 206 size_t bin_size; 207 208 mib[2] = i; 209 len = sizeof(bin_size); 210 assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0), 211 0, "Unexpected mallctlbymib() failure"); 212 /* Do something with bin_size... */ 213 } 214 } 215 TEST_END 216 217 TEST_BEGIN(test_thread_arena) 218 { 219 unsigned arena_old, arena_new, narenas; 220 size_t sz = sizeof(unsigned); 221 222 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 223 "Unexpected mallctl() failure"); 224 assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect"); 225 arena_new = narenas - 1; 226 assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, 227 sizeof(unsigned)), 0, "Unexpected mallctl() failure"); 228 arena_new = 0; 229 assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, 230 sizeof(unsigned)), 0, "Unexpected mallctl() failure"); 231 } 232 TEST_END 233 234 TEST_BEGIN(test_arena_i_purge) 235 { 236 unsigned narenas; 237 size_t sz = sizeof(unsigned); 238 size_t mib[3]; 239 size_t miblen = 3; 240 241 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 242 "Unexpected mallctl() failure"); 243 244 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 245 "Unexpected mallctl() failure"); 246 assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0, 247 "Unexpected mallctlnametomib() failure"); 248 mib[1] = narenas; 249 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, 250 "Unexpected mallctlbymib() failure"); 251 } 252 TEST_END 253 254 TEST_BEGIN(test_arena_i_dss) 255 { 256 const char *dss_prec_old, *dss_prec_new; 257 size_t sz = sizeof(dss_prec_old); 258 259 dss_prec_new = "primary"; 260 assert_d_eq(mallctl("arena.0.dss", &dss_prec_old, &sz, &dss_prec_new, 261 sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); 262 assert_str_ne(dss_prec_old, "primary", 263 "Unexpected default for dss precedence"); 264 265 assert_d_eq(mallctl("arena.0.dss", &dss_prec_new, &sz, &dss_prec_old, 266 sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure"); 267 } 268 TEST_END 269 270 TEST_BEGIN(test_arenas_purge) 271 { 272 unsigned arena = 0; 273 274 assert_d_eq(mallctl("arenas.purge", NULL, NULL, &arena, sizeof(arena)), 275 0, "Unexpected mallctl() failure"); 276 277 assert_d_eq(mallctl("arenas.purge", NULL, NULL, NULL, 0), 0, 278 "Unexpected mallctl() failure"); 279 } 280 TEST_END 281 282 TEST_BEGIN(test_arenas_initialized) 283 { 284 unsigned narenas; 285 size_t sz = sizeof(narenas); 286 287 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 288 "Unexpected mallctl() failure"); 289 { 290 bool initialized[narenas]; 291 292 sz = narenas * sizeof(bool); 293 assert_d_eq(mallctl("arenas.initialized", initialized, &sz, 294 NULL, 0), 0, "Unexpected mallctl() failure"); 295 } 296 } 297 TEST_END 298 299 TEST_BEGIN(test_arenas_constants) 300 { 301 302 #define TEST_ARENAS_CONSTANT(t, name, expected) do { \ 303 t name; \ 304 size_t sz = sizeof(t); \ 305 assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \ 306 "Unexpected mallctl() failure"); \ 307 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 308 } while (0) 309 310 TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM); 311 TEST_ARENAS_CONSTANT(size_t, page, PAGE); 312 TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS); 313 TEST_ARENAS_CONSTANT(size_t, nlruns, nlclasses); 314 315 #undef TEST_ARENAS_CONSTANT 316 } 317 TEST_END 318 319 TEST_BEGIN(test_arenas_bin_constants) 320 { 321 322 #define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \ 323 t name; \ 324 size_t sz = sizeof(t); \ 325 assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \ 326 0, "Unexpected mallctl() failure"); \ 327 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 328 } while (0) 329 330 TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size); 331 TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs); 332 TEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size); 333 334 #undef TEST_ARENAS_BIN_CONSTANT 335 } 336 TEST_END 337 338 TEST_BEGIN(test_arenas_lrun_constants) 339 { 340 341 #define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \ 342 t name; \ 343 size_t sz = sizeof(t); \ 344 assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \ 345 0), 0, "Unexpected mallctl() failure"); \ 346 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 347 } while (0) 348 349 TEST_ARENAS_LRUN_CONSTANT(size_t, size, (1 << LG_PAGE)); 350 351 #undef TEST_ARENAS_LRUN_CONSTANT 352 } 353 TEST_END 354 355 TEST_BEGIN(test_arenas_extend) 356 { 357 unsigned narenas_before, arena, narenas_after; 358 size_t sz = sizeof(unsigned); 359 360 assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0, 361 "Unexpected mallctl() failure"); 362 assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0, 363 "Unexpected mallctl() failure"); 364 assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0, 365 "Unexpected mallctl() failure"); 366 367 assert_u_eq(narenas_before+1, narenas_after, 368 "Unexpected number of arenas before versus after extension"); 369 assert_u_eq(arena, narenas_after-1, "Unexpected arena index"); 370 } 371 TEST_END 372 373 TEST_BEGIN(test_stats_arenas) 374 { 375 376 #define TEST_STATS_ARENAS(t, name) do { \ 377 t name; \ 378 size_t sz = sizeof(t); \ 379 assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \ 380 0), 0, "Unexpected mallctl() failure"); \ 381 } while (0) 382 383 TEST_STATS_ARENAS(const char *, dss); 384 TEST_STATS_ARENAS(unsigned, nthreads); 385 TEST_STATS_ARENAS(size_t, pactive); 386 TEST_STATS_ARENAS(size_t, pdirty); 387 388 #undef TEST_STATS_ARENAS 389 } 390 TEST_END 391 392 int 393 main(void) 394 { 395 396 return (test( 397 test_mallctl_errors, 398 test_mallctlnametomib_errors, 399 test_mallctlbymib_errors, 400 test_mallctl_read_write, 401 test_mallctlnametomib_short_mib, 402 test_mallctl_config, 403 test_mallctl_opt, 404 test_manpage_example, 405 test_thread_arena, 406 test_arena_i_purge, 407 test_arena_i_dss, 408 test_arenas_purge, 409 test_arenas_initialized, 410 test_arenas_constants, 411 test_arenas_bin_constants, 412 test_arenas_lrun_constants, 413 test_arenas_extend, 414 test_stats_arenas)); 415 } 416