TEST_END TEST_BEGIN(test_extra_small) { size_t small0, small1, hugemax; void *p; /* Get size classes. */ small0 = get_small_size(0); small1 = get_small_size(1); hugemax = get_huge_size(get_nhuge()-1); p = mallocx(small0, 0); assert_ptr_not_null(p, "Unexpected mallocx() error"); assert_zu_eq(xallocx(p, small1, 0, 0), small0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, small1, 0, 0), small0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, small0, small1 - small0, 0), small0, "Unexpected xallocx() behavior"); /* Test size+extra overflow. */ assert_zu_eq(xallocx(p, small0, hugemax - small0 + 1, 0), small0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, small0, SIZE_T_MAX - small0, 0), small0, "Unexpected xallocx() behavior"); dallocx(p, 0); }
static void test_bitmap_initializer_body(const bitmap_info_t *binfo, size_t nbits) { bitmap_info_t binfo_dyn; bitmap_info_init(&binfo_dyn, nbits); assert_zu_eq(bitmap_size(binfo), bitmap_size(&binfo_dyn), "Unexpected difference between static and dynamic initialization, " "nbits=%zu", nbits); assert_zu_eq(binfo->nbits, binfo_dyn.nbits, "Unexpected difference between static and dynamic initialization, " "nbits=%zu", nbits); #ifdef BITMAP_USE_TREE assert_u_eq(binfo->nlevels, binfo_dyn.nlevels, "Unexpected difference between static and dynamic initialization, " "nbits=%zu", nbits); { unsigned i; for (i = 0; i < binfo->nlevels; i++) { assert_zu_eq(binfo->levels[i].group_offset, binfo_dyn.levels[i].group_offset, "Unexpected difference between static and dynamic " "initialization, nbits=%zu, level=%u", nbits, i); } } #else assert_zu_eq(binfo->ngroups, binfo_dyn.ngroups, "Unexpected difference between static and dynamic initialization"); #endif }
TEST_END TEST_BEGIN(test_mallctl_read_write) { uint64_t old_epoch, new_epoch; size_t sz = sizeof(old_epoch); /* Blind. */ assert_d_eq(mallctl("epoch", NULL, NULL, NULL, 0), 0, "Unexpected mallctl() failure"); assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); /* Read. */ assert_d_eq(mallctl("epoch", (void *)&old_epoch, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); /* Write. */ assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&new_epoch, sizeof(new_epoch)), 0, "Unexpected mallctl() failure"); assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); /* Read+write. */ assert_d_eq(mallctl("epoch", (void *)&old_epoch, &sz, (void *)&new_epoch, sizeof(new_epoch)), 0, "Unexpected mallctl() failure"); assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); }
TEST_END TEST_BEGIN(test_basic) { #define MAXSZ (((size_t)1) << 26) size_t sz; for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) { size_t nsz, rsz; void *p; nsz = nallocx(sz, 0); assert_zu_ne(nsz, 0, "Unexpected nallocx() error"); p = mallocx(sz, 0); assert_ptr_not_null(p, "Unexpected mallocx() error"); rsz = sallocx(p, 0); assert_zu_ge(rsz, sz, "Real size smaller than expected"); assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch"); dallocx(p, 0); p = mallocx(sz, 0); assert_ptr_not_null(p, "Unexpected mallocx() error"); dallocx(p, 0); nsz = nallocx(sz, MALLOCX_ZERO); assert_zu_ne(nsz, 0, "Unexpected nallocx() error"); p = mallocx(sz, MALLOCX_ZERO); assert_ptr_not_null(p, "Unexpected mallocx() error"); rsz = sallocx(p, 0); assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch"); dallocx(p, 0); } #undef MAXSZ }
TEST_END TEST_BEGIN(test_large_run_size) { bool cache_oblivious; unsigned nlruns, i; size_t sz, run_size_prev, ceil_prev; size_t mib[4]; size_t miblen = sizeof(mib) / sizeof(size_t); /* * Iterate over all large size classes, get their run sizes, and verify * that the quantized size is the same as the run size. */ sz = sizeof(bool); assert_d_eq(mallctl("config.cache_oblivious", &cache_oblivious, &sz, NULL, 0), 0, "Unexpected mallctl failure"); sz = sizeof(unsigned); assert_d_eq(mallctl("arenas.nlruns", &nlruns, &sz, NULL, 0), 0, "Unexpected mallctl failure"); assert_d_eq(mallctlnametomib("arenas.lrun.0.size", mib, &miblen), 0, "Unexpected mallctlnametomib failure"); for (i = 0; i < nlruns; i++) { size_t lrun_size, run_size, floor, ceil; mib[2] = i; sz = sizeof(size_t); assert_d_eq(mallctlbymib(mib, miblen, &lrun_size, &sz, NULL, 0), 0, "Unexpected mallctlbymib failure"); run_size = cache_oblivious ? lrun_size + PAGE : lrun_size; floor = run_quantize_floor(run_size); ceil = run_quantize_ceil(run_size); assert_zu_eq(run_size, floor, "Large run quantization should be a no-op for precise " "size (lrun_size=%zu, run_size=%zu)", lrun_size, run_size); assert_zu_eq(run_size, ceil, "Large run quantization should be a no-op for precise " "size (lrun_size=%zu, run_size=%zu)", lrun_size, run_size); if (i > 0) { assert_zu_eq(run_size_prev, run_quantize_floor(run_size - PAGE), "Floor should be a precise size"); if (run_size_prev < ceil_prev) { assert_zu_eq(ceil_prev, run_size, "Ceiling should be a precise size " "(run_size_prev=%zu, ceil_prev=%zu, " "run_size=%zu)", run_size_prev, ceil_prev, run_size); } } run_size_prev = floor; ceil_prev = run_quantize_ceil(run_size + PAGE); } }
static void arena_ralloc_junk_large_intercept(void *ptr, size_t old_usize, size_t usize) { arena_ralloc_junk_large_orig(ptr, old_usize, usize); assert_zu_eq(old_usize, arena_maxclass, "Unexpected old_usize"); assert_zu_eq(usize, arena_maxclass-PAGE, "Unexpected usize"); most_recently_trimmed = ptr; }
TEST_END TEST_BEGIN(test_psize_classes) { size_t size_class, max_size_class; pszind_t pind, max_pind; max_size_class = get_max_size_class(); max_pind = psz2ind(max_size_class); for (pind = 0, size_class = pind2sz(pind); pind < max_pind || size_class < max_size_class; pind++, size_class = pind2sz(pind)) { assert_true(pind < max_pind, "Loop conditionals should be equivalent; pind=%u, " "size_class=%zu (%#zx)", pind, size_class, size_class); assert_true(size_class < max_size_class, "Loop conditionals should be equivalent; pind=%u, " "size_class=%zu (%#zx)", pind, size_class, size_class); assert_u_eq(pind, psz2ind(size_class), "psz2ind() does not reverse pind2sz(): pind=%u -->" " size_class=%zu --> pind=%u --> size_class=%zu", pind, size_class, psz2ind(size_class), pind2sz(psz2ind(size_class))); assert_zu_eq(size_class, pind2sz(psz2ind(size_class)), "pind2sz() does not reverse psz2ind(): pind=%u -->" " size_class=%zu --> pind=%u --> size_class=%zu", pind, size_class, psz2ind(size_class), pind2sz(psz2ind(size_class))); assert_u_eq(pind+1, psz2ind(size_class+1), "Next size_class does not round up properly"); assert_zu_eq(size_class, (pind > 0) ? psz2u(pind2sz(pind-1)+1) : psz2u(1), "psz2u() does not round up to size class"); assert_zu_eq(size_class, psz2u(size_class-1), "psz2u() does not round up to size class"); assert_zu_eq(size_class, psz2u(size_class), "psz2u() does not compute same size class"); assert_zu_eq(psz2u(size_class+1), pind2sz(pind+1), "psz2u() does not round up to next size class"); } assert_u_eq(pind, psz2ind(pind2sz(pind)), "psz2ind() does not reverse pind2sz()"); assert_zu_eq(max_size_class, pind2sz(psz2ind(max_size_class)), "pind2sz() does not reverse psz2ind()"); assert_zu_eq(size_class, psz2u(pind2sz(pind-1)+1), "psz2u() does not round up to size class"); assert_zu_eq(size_class, psz2u(size_class-1), "psz2u() does not round up to size class"); assert_zu_eq(size_class, psz2u(size_class), "psz2u() does not compute same size class"); }
static void prof_sampling_probe_impl(bool expect_sample, const char *func, int line) { void *p; size_t expected_backtraces = expect_sample ? 1 : 0; assert_zu_eq(prof_bt_count(), 0, "%s():%d: Expected 0 backtraces", func, line); p = mallocx(1, 0); assert_ptr_not_null(p, "Unexpected mallocx() failure"); assert_zu_eq(prof_bt_count(), expected_backtraces, "%s():%d: Unexpected backtrace count", func, line); dallocx(p, 0); }
TEST_END TEST_BEGIN(test_mallctlnametomib_short_mib) { size_t mib[4]; size_t miblen; miblen = 3; mib[3] = 42; assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0, "Unexpected mallctlnametomib() failure"); assert_zu_eq(miblen, 3, "Unexpected mib output length"); assert_zu_eq(mib[3], 42, "mallctlnametomib() wrote past the end of the input mib"); }
TEST_END TEST_BEGIN(test_max_background_threads) { test_skip_if(!have_background_thread); size_t max_n_thds; size_t opt_max_n_thds; size_t sz_m = sizeof(max_n_thds); assert_d_eq(mallctl("opt.max_background_threads", &opt_max_n_thds, &sz_m, NULL, 0), 0, "Failed to get opt.max_background_threads"); assert_d_eq(mallctl("max_background_threads", &max_n_thds, &sz_m, NULL, 0), 0, "Failed to get max background threads"); assert_zu_eq(opt_max_n_thds, max_n_thds, "max_background_threads and " "opt.max_background_threads should match"); assert_d_eq(mallctl("max_background_threads", NULL, NULL, &max_n_thds, sz_m), 0, "Failed to set max background threads"); unsigned id; size_t sz_u = sizeof(unsigned); for (unsigned i = 0; i < 10 * ncpus; i++) { assert_d_eq(mallctl("arenas.create", &id, &sz_u, NULL, 0), 0, "Failed to create arena"); } bool enable = true; size_t sz_b = sizeof(bool); assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0, "Failed to enable background threads"); assert_zu_eq(n_background_threads, max_n_thds, "Number of background threads should not change.\n"); size_t new_max_thds = max_n_thds - 1; if (new_max_thds > 0) { assert_d_eq(mallctl("max_background_threads", NULL, NULL, &new_max_thds, sz_m), 0, "Failed to set max background threads"); assert_zu_eq(n_background_threads, new_max_thds, "Number of background threads should decrease by 1.\n"); } new_max_thds = 1; assert_d_eq(mallctl("max_background_threads", NULL, NULL, &new_max_thds, sz_m), 0, "Failed to set max background threads"); assert_zu_eq(n_background_threads, new_max_thds, "Number of background threads should be 1.\n"); }
TEST_END TEST_BEGIN(test_alignment_and_size) { int r; size_t nsz, rsz, sz, alignment, total; unsigned i; void *ps[NITER]; for (i = 0; i < NITER; i++) ps[i] = NULL; for (alignment = 8; alignment <= MAXALIGN; alignment <<= 1) { total = 0; for (sz = 1; sz < 3 * alignment && sz < (1U << 31); sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { for (i = 0; i < NITER; i++) { nsz = 0; r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); assert_d_eq(r, ALLOCM_SUCCESS, "nallocm() error for alignment=%zu, " "size=%zu (%#zx): %d", alignment, sz, sz, r); rsz = 0; r = allocm(&ps[i], &rsz, sz, ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); assert_d_eq(r, ALLOCM_SUCCESS, "allocm() error for alignment=%zu, " "size=%zu (%#zx): %d", alignment, sz, sz, r); assert_zu_ge(rsz, sz, "Real size smaller than expected for " "alignment=%zu, size=%zu", alignment, sz); assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch for " "alignment=%zu, size=%zu", alignment, sz); assert_ptr_null( (void *)((uintptr_t)ps[i] & (alignment-1)), "%p inadequately aligned for" " alignment=%zu, size=%zu", ps[i], alignment, sz); sallocm(ps[i], &rsz, 0); total += rsz; if (total >= (MAXALIGN << 1)) break; } for (i = 0; i < NITER; i++) { if (ps[i] != NULL) { dallocm(ps[i], 0); ps[i] = NULL; } } } } }
TEST_END TEST_BEGIN(test_alignment_and_size) { #define MAXALIGN (((size_t)1) << 25) #define NITER 4 size_t nsz, rsz, sz, alignment, total; unsigned i; void *ps[NITER]; for (i = 0; i < NITER; i++) ps[i] = NULL; for (alignment = 8; alignment <= MAXALIGN; alignment <<= 1) { total = 0; for (sz = 1; sz < 3 * alignment && sz < (1U << 31); sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { for (i = 0; i < NITER; i++) { nsz = nallocx(sz, MALLOCX_ALIGN(alignment) | MALLOCX_ZERO); assert_zu_ne(nsz, 0, "nallocx() error for alignment=%zu, " "size=%zu (%#zx)", alignment, sz, sz); ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) | MALLOCX_ZERO); assert_ptr_not_null(ps[i], "mallocx() error for alignment=%zu, " "size=%zu (%#zx)", alignment, sz, sz); rsz = sallocx(ps[i], 0); assert_zu_ge(rsz, sz, "Real size smaller than expected for " "alignment=%zu, size=%zu", alignment, sz); assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch for " "alignment=%zu, size=%zu", alignment, sz); assert_ptr_null( (void *)((uintptr_t)ps[i] & (alignment-1)), "%p inadequately aligned for" " alignment=%zu, size=%zu", ps[i], alignment, sz); total += rsz; if (total >= (MAXALIGN << 1)) break; } for (i = 0; i < NITER; i++) { if (ps[i] != NULL) { dallocx(ps[i], 0); ps[i] = NULL; } } } } #undef MAXALIGN #undef NITER }
static void test_zero(size_t szmin, size_t szmax) { int flags = MALLOCX_ARENA(arena_ind()) | MALLOCX_ZERO; size_t sz, nsz; void *p; #define FILL_BYTE 0x7aU sz = szmax; p = mallocx(sz, flags); assert_ptr_not_null(p, "Unexpected mallocx() error"); assert_false(validate_fill(p, 0x00, 0, sz), "Memory not filled: sz=%zu", sz); /* * Fill with non-zero so that non-debug builds are more likely to detect * errors. */ memset(p, FILL_BYTE, sz); assert_false(validate_fill(p, FILL_BYTE, 0, sz), "Memory not filled: sz=%zu", sz); /* Shrink in place so that we can expect growing in place to succeed. */ sz = szmin; assert_zu_eq(xallocx(p, sz, 0, flags), sz, "Unexpected xallocx() error"); assert_false(validate_fill(p, FILL_BYTE, 0, sz), "Memory not filled: sz=%zu", sz); for (sz = szmin; sz < szmax; sz = nsz) { nsz = nallocx(sz+1, flags); assert_zu_eq(xallocx(p, sz+1, 0, flags), nsz, "Unexpected xallocx() failure"); assert_false(validate_fill(p, FILL_BYTE, 0, sz), "Memory not filled: sz=%zu", sz); assert_false(validate_fill(p, 0x00, sz, nsz-sz), "Memory not filled: sz=%zu, nsz-sz=%zu", sz, nsz-sz); memset((void *)((uintptr_t)p + sz), FILL_BYTE, nsz-sz); assert_false(validate_fill(p, FILL_BYTE, 0, nsz), "Memory not filled: nsz=%zu", nsz); } dallocx(p, flags); }
TEST_END TEST_BEGIN(test_no_move_fail) { void *p; size_t sz, tsz; p = mallocx(42, 0); assert_ptr_not_null(p, "Unexpected mallocx() error"); sz = sallocx(p, 0); tsz = xallocx(p, sz + 5, 0, 0); assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); dallocx(p, 0); }
TEST_END TEST_BEGIN(test_no_move_fail) { void *p, *q; size_t sz, tsz; assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS, "Unexpected allocm() error"); q = p; assert_d_eq(rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE), ALLOCM_ERR_NOT_MOVED, "Unexpected rallocm() result"); assert_ptr_eq(q, p, "Unexpected object move"); assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, "Unexpected dallocm() error"); }
TEST_END TEST_BEGIN(test_grow_and_shrink) { void *p, *q; size_t tsz; #define NCYCLES 3 unsigned i, j; #define NSZS 2500 size_t szs[NSZS]; #define MAXSZ ZU(12 * 1024 * 1024) assert_d_eq(allocm(&p, &szs[0], 1, 0), ALLOCM_SUCCESS, "Unexpected allocm() error"); for (i = 0; i < NCYCLES; i++) { for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) { q = p; assert_d_eq(rallocm(&q, &szs[j], szs[j-1]+1, 0, 0), ALLOCM_SUCCESS, "Unexpected rallocm() error for size=%zu-->%zu", szs[j-1], szs[j-1]+1); assert_zu_ne(szs[j], szs[j-1]+1, "Expected size to at least: %zu", szs[j-1]+1); p = q; } for (j--; j > 0; j--) { q = p; assert_d_eq(rallocm(&q, &tsz, szs[j-1], 0, 0), ALLOCM_SUCCESS, "Unexpected rallocm() error for size=%zu-->%zu", szs[j], szs[j-1]); assert_zu_eq(tsz, szs[j-1], "Expected size=%zu, got size=%zu", szs[j-1], tsz); p = q; } } assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, "Unexpected dallocm() error"); }
TEST_END TEST_BEGIN(test_overflow) { size_t max_size_class; max_size_class = get_max_size_class(); assert_u_eq(size2index(max_size_class+1), NSIZES, "size2index() should return NSIZES on overflow"); assert_u_eq(size2index(ZU(PTRDIFF_MAX)+1), NSIZES, "size2index() should return NSIZES on overflow"); assert_u_eq(size2index(SIZE_T_MAX), NSIZES, "size2index() should return NSIZES on overflow"); assert_zu_eq(s2u(max_size_class+1), 0, "s2u() should return 0 for unsupported size"); assert_zu_eq(s2u(ZU(PTRDIFF_MAX)+1), 0, "s2u() should return 0 for unsupported size"); assert_zu_eq(s2u(SIZE_T_MAX), 0, "s2u() should return 0 on overflow"); assert_u_eq(psz2ind(max_size_class+1), NPSIZES, "psz2ind() should return NPSIZES on overflow"); assert_u_eq(psz2ind(ZU(PTRDIFF_MAX)+1), NPSIZES, "psz2ind() should return NPSIZES on overflow"); assert_u_eq(psz2ind(SIZE_T_MAX), NPSIZES, "psz2ind() should return NPSIZES on overflow"); assert_zu_eq(psz2u(max_size_class+1), 0, "psz2u() should return 0 for unsupported size"); assert_zu_eq(psz2u(ZU(PTRDIFF_MAX)+1), 0, "psz2u() should return 0 for unsupported size"); assert_zu_eq(psz2u(SIZE_T_MAX), 0, "psz2u() should return 0 on overflow"); }
TEST_END TEST_BEGIN(test_insert_iter_remove) { #define NITEMS ZU(1000) tsd_t *tsd; ckh_t ckh; void **p[NITEMS]; void *q, *r; size_t i; tsd = tsd_fetch(); assert_false(ckh_new(tsd, &ckh, 2, ckh_pointer_hash, ckh_pointer_keycomp), "Unexpected ckh_new() error"); for (i = 0; i < NITEMS; i++) { p[i] = mallocx(i+1, 0); assert_ptr_not_null(p[i], "Unexpected mallocx() failure"); } for (i = 0; i < NITEMS; i++) { size_t j; for (j = i; j < NITEMS; j++) { assert_false(ckh_insert(tsd, &ckh, p[j], p[j]), "Unexpected ckh_insert() failure"); assert_false(ckh_search(&ckh, p[j], &q, &r), "Unexpected ckh_search() failure"); assert_ptr_eq(p[j], q, "Key pointer mismatch"); assert_ptr_eq(p[j], r, "Value pointer mismatch"); } assert_zu_eq(ckh_count(&ckh), NITEMS, "ckh_count() should return %zu, but it returned %zu", NITEMS, ckh_count(&ckh)); for (j = i + 1; j < NITEMS; j++) { assert_false(ckh_search(&ckh, p[j], NULL, NULL), "Unexpected ckh_search() failure"); assert_false(ckh_remove(tsd, &ckh, p[j], &q, &r), "Unexpected ckh_remove() failure"); assert_ptr_eq(p[j], q, "Key pointer mismatch"); assert_ptr_eq(p[j], r, "Value pointer mismatch"); assert_true(ckh_search(&ckh, p[j], NULL, NULL), "Unexpected ckh_search() success"); assert_true(ckh_remove(tsd, &ckh, p[j], &q, &r), "Unexpected ckh_remove() success"); } { bool seen[NITEMS]; size_t tabind; memset(seen, 0, sizeof(seen)); for (tabind = 0; !ckh_iter(&ckh, &tabind, &q, &r);) { size_t k; assert_ptr_eq(q, r, "Key and val not equal"); for (k = 0; k < NITEMS; k++) { if (p[k] == q) { assert_false(seen[k], "Item %zu already seen", k); seen[k] = true; break; } } } for (j = 0; j < i + 1; j++) assert_true(seen[j], "Item %zu not seen", j); for (; j < NITEMS; j++) assert_false(seen[j], "Item %zu seen", j); } } for (i = 0; i < NITEMS; i++) { assert_false(ckh_search(&ckh, p[i], NULL, NULL), "Unexpected ckh_search() failure"); assert_false(ckh_remove(tsd, &ckh, p[i], &q, &r), "Unexpected ckh_remove() failure"); assert_ptr_eq(p[i], q, "Key pointer mismatch"); assert_ptr_eq(p[i], r, "Value pointer mismatch"); assert_true(ckh_search(&ckh, p[i], NULL, NULL), "Unexpected ckh_search() success"); assert_true(ckh_remove(tsd, &ckh, p[i], &q, &r), "Unexpected ckh_remove() success"); dallocx(p[i], 0); } assert_zu_eq(ckh_count(&ckh), 0, "ckh_count() should return %zu, but it returned %zu", ZU(0), ckh_count(&ckh)); ckh_delete(tsd, &ckh); #undef NITEMS }
TEST_END TEST_BEGIN(test_count_insert_search_remove) { tsd_t *tsd; ckh_t ckh; const char *strs[] = { "a string", "A string", "a string.", "A string." }; const char *missing = "A string not in the hash table."; size_t i; tsd = tsd_fetch(); assert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash, ckh_string_keycomp), "Unexpected ckh_new() error"); assert_zu_eq(ckh_count(&ckh), 0, "ckh_count() should return %zu, but it returned %zu", ZU(0), ckh_count(&ckh)); /* Insert. */ for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) { ckh_insert(tsd, &ckh, strs[i], strs[i]); assert_zu_eq(ckh_count(&ckh), i+1, "ckh_count() should return %zu, but it returned %zu", i+1, ckh_count(&ckh)); } /* Search. */ for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) { union { void *p; const char *s; } k, v; void **kp, **vp; const char *ks, *vs; kp = (i & 1) ? &k.p : NULL; vp = (i & 2) ? &v.p : NULL; k.p = NULL; v.p = NULL; assert_false(ckh_search(&ckh, strs[i], kp, vp), "Unexpected ckh_search() error"); ks = (i & 1) ? strs[i] : (const char *)NULL; vs = (i & 2) ? strs[i] : (const char *)NULL; assert_ptr_eq((void *)ks, (void *)k.s, "Key mismatch, i=%zu", i); assert_ptr_eq((void *)vs, (void *)v.s, "Value mismatch, i=%zu", i); } assert_true(ckh_search(&ckh, missing, NULL, NULL), "Unexpected ckh_search() success"); /* Remove. */ for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) { union { void *p; const char *s; } k, v; void **kp, **vp; const char *ks, *vs; kp = (i & 1) ? &k.p : NULL; vp = (i & 2) ? &v.p : NULL; k.p = NULL; v.p = NULL; assert_false(ckh_remove(tsd, &ckh, strs[i], kp, vp), "Unexpected ckh_remove() error"); ks = (i & 1) ? strs[i] : (const char *)NULL; vs = (i & 2) ? strs[i] : (const char *)NULL; assert_ptr_eq((void *)ks, (void *)k.s, "Key mismatch, i=%zu", i); assert_ptr_eq((void *)vs, (void *)v.s, "Value mismatch, i=%zu", i); assert_zu_eq(ckh_count(&ckh), sizeof(strs)/sizeof(const char *) - i - 1, "ckh_count() should return %zu, but it returned %zu", sizeof(strs)/sizeof(const char *) - i - 1, ckh_count(&ckh)); } ckh_delete(tsd, &ckh); }
TEST_END TEST_BEGIN(test_extra_huge) { int flags = MALLOCX_ARENA(arena_ind()); size_t largemax, huge1, huge2, huge3, hugemax; void *p; /* Get size classes. */ largemax = get_large_size(get_nlarge()-1); huge1 = get_huge_size(1); huge2 = get_huge_size(2); huge3 = get_huge_size(3); hugemax = get_huge_size(get_nhuge()-1); p = mallocx(huge3, flags); assert_ptr_not_null(p, "Unexpected mallocx() error"); assert_zu_eq(xallocx(p, huge3, 0, flags), huge3, "Unexpected xallocx() behavior"); /* Test size decrease with zero extra. */ assert_zu_ge(xallocx(p, huge1, 0, flags), huge1, "Unexpected xallocx() behavior"); assert_zu_ge(xallocx(p, largemax, 0, flags), huge1, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, huge3, 0, flags), huge3, "Unexpected xallocx() behavior"); /* Test size decrease with non-zero extra. */ assert_zu_eq(xallocx(p, huge1, huge3 - huge1, flags), huge3, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, huge2, huge3 - huge2, flags), huge3, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, huge1, huge2 - huge1, flags), huge2, "Unexpected xallocx() behavior"); assert_zu_ge(xallocx(p, largemax, huge1 - largemax, flags), huge1, "Unexpected xallocx() behavior"); assert_zu_ge(xallocx(p, huge1, 0, flags), huge1, "Unexpected xallocx() behavior"); /* Test size increase with zero extra. */ assert_zu_le(xallocx(p, huge3, 0, flags), huge3, "Unexpected xallocx() behavior"); assert_zu_le(xallocx(p, hugemax+1, 0, flags), huge3, "Unexpected xallocx() behavior"); assert_zu_ge(xallocx(p, huge1, 0, flags), huge1, "Unexpected xallocx() behavior"); /* Test size increase with non-zero extra. */ assert_zu_le(xallocx(p, huge1, SIZE_T_MAX - huge1, flags), hugemax, "Unexpected xallocx() behavior"); assert_zu_ge(xallocx(p, huge1, 0, flags), huge1, "Unexpected xallocx() behavior"); /* Test size increase with non-zero extra. */ assert_zu_le(xallocx(p, huge1, huge3 - huge1, flags), huge3, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, huge3, 0, flags), huge3, "Unexpected xallocx() behavior"); /* Test size+extra overflow. */ assert_zu_le(xallocx(p, huge3, hugemax - huge3 + 1, flags), hugemax, "Unexpected xallocx() behavior"); dallocx(p, flags); }
TEST_END TEST_BEGIN(test_extra_large) { int flags = MALLOCX_ARENA(arena_ind()); size_t smallmax, large0, large1, large2, huge0, hugemax; void *p; /* Get size classes. */ smallmax = get_small_size(get_nsmall()-1); large0 = get_large_size(0); large1 = get_large_size(1); large2 = get_large_size(2); huge0 = get_huge_size(0); hugemax = get_huge_size(get_nhuge()-1); p = mallocx(large2, flags); assert_ptr_not_null(p, "Unexpected mallocx() error"); assert_zu_eq(xallocx(p, large2, 0, flags), large2, "Unexpected xallocx() behavior"); /* Test size decrease with zero extra. */ assert_zu_eq(xallocx(p, large0, 0, flags), large0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, smallmax, 0, flags), large0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large2, 0, flags), large2, "Unexpected xallocx() behavior"); /* Test size decrease with non-zero extra. */ assert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large1, large2 - large1, flags), large2, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large0, large1 - large0, flags), large1, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, smallmax, large0 - smallmax, flags), large0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large0, 0, flags), large0, "Unexpected xallocx() behavior"); /* Test size increase with zero extra. */ assert_zu_eq(xallocx(p, large2, 0, flags), large2, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, huge0, 0, flags), large2, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large0, 0, flags), large0, "Unexpected xallocx() behavior"); /* Test size increase with non-zero extra. */ assert_zu_lt(xallocx(p, large0, huge0 - large0, flags), huge0, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large0, 0, flags), large0, "Unexpected xallocx() behavior"); /* Test size increase with non-zero extra. */ assert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2, "Unexpected xallocx() behavior"); assert_zu_eq(xallocx(p, large2, 0, flags), large2, "Unexpected xallocx() behavior"); /* Test size+extra overflow. */ assert_zu_lt(xallocx(p, large2, hugemax - large2 + 1, flags), huge0, "Unexpected xallocx() behavior"); dallocx(p, flags); }