aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2016-06-14 14:24:23 -0700
committerChristopher Ferris <cferris@google.com>2016-06-14 14:24:23 -0700
commit5ab62bd1b55ef0804dbea305f8697bf9d247f3a4 (patch)
tree9cc8f6f8968bfb297d351dfc227ccd14d3378c6e /test
parent95800fe1cea79136934ecd02c6b6f8a064d0007e (diff)
parent3de035335255d553bdb344c32ffdb603816195d8 (diff)
downloadjemalloc-5ab62bd1b55ef0804dbea305f8697bf9d247f3a4.tar.gz
Merge remote-tracking branch 'aosp/upstream-release' into fix
Bug: 28860984 Change-Id: I9eaf67f53f9872177d068d660d1e051cecdc82a0
Diffstat (limited to 'test')
-rw-r--r--test/include/test/jemalloc_test.h.in78
-rw-r--r--test/include/test/test.h4
-rw-r--r--test/integration/chunk.c73
-rw-r--r--test/integration/mallocx.c52
-rw-r--r--test/integration/xallocx.c4
-rw-r--r--test/src/test.c56
-rw-r--r--test/src/timer.c5
-rw-r--r--test/stress/microbench.c3
-rw-r--r--test/unit/a0.c19
-rw-r--r--test/unit/arena_reset.c159
-rw-r--r--test/unit/bitmap.c4
-rw-r--r--test/unit/ckh.c46
-rw-r--r--test/unit/fork.c64
-rw-r--r--test/unit/junk.c21
-rw-r--r--test/unit/junk_alloc.c2
-rw-r--r--test/unit/junk_free.c2
-rw-r--r--test/unit/ph.c290
-rw-r--r--test/unit/prof_reset.c3
-rw-r--r--test/unit/stats.c10
-rw-r--r--test/unit/tsd.c5
-rw-r--r--test/unit/util.c24
-rw-r--r--test/unit/witness.c278
-rw-r--r--test/unit/zero.c16
23 files changed, 1054 insertions, 164 deletions
diff --git a/test/include/test/jemalloc_test.h.in b/test/include/test/jemalloc_test.h.in
index 0a3dbea..1f36e46 100644
--- a/test/include/test/jemalloc_test.h.in
+++ b/test/include/test/jemalloc_test.h.in
@@ -19,39 +19,6 @@
# include <pthread.h>
#endif
-/******************************************************************************/
-/*
- * Define always-enabled assertion macros, so that test assertions execute even
- * if assertions are disabled in the library code. These definitions must
- * exist prior to including "jemalloc/internal/util.h".
- */
-#define assert(e) do { \
- if (!(e)) { \
- malloc_printf( \
- "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \
- __FILE__, __LINE__, #e); \
- abort(); \
- } \
-} while (0)
-
-#define not_reached() do { \
- malloc_printf( \
- "<jemalloc>: %s:%d: Unreachable code reached\n", \
- __FILE__, __LINE__); \
- abort(); \
-} while (0)
-
-#define not_implemented() do { \
- malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \
- __FILE__, __LINE__); \
- abort(); \
-} while (0)
-
-#define assert_not_implemented(e) do { \
- if (!(e)) \
- not_implemented(); \
-} while (0)
-
#include "test/jemalloc_test_defs.h"
#ifdef JEMALLOC_OSSPIN
@@ -86,6 +53,14 @@
# include "jemalloc/internal/jemalloc_internal_defs.h"
# include "jemalloc/internal/jemalloc_internal_macros.h"
+static const bool config_debug =
+#ifdef JEMALLOC_DEBUG
+ true
+#else
+ false
+#endif
+ ;
+
# define JEMALLOC_N(n) @private_namespace@##n
# include "jemalloc/internal/private_namespace.h"
@@ -149,3 +124,40 @@
#include "test/thd.h"
#define MEXP 19937
#include "test/SFMT.h"
+
+/******************************************************************************/
+/*
+ * Define always-enabled assertion macros, so that test assertions execute even
+ * if assertions are disabled in the library code.
+ */
+#undef assert
+#undef not_reached
+#undef not_implemented
+#undef assert_not_implemented
+
+#define assert(e) do { \
+ if (!(e)) { \
+ malloc_printf( \
+ "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \
+ __FILE__, __LINE__, #e); \
+ abort(); \
+ } \
+} while (0)
+
+#define not_reached() do { \
+ malloc_printf( \
+ "<jemalloc>: %s:%d: Unreachable code reached\n", \
+ __FILE__, __LINE__); \
+ abort(); \
+} while (0)
+
+#define not_implemented() do { \
+ malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \
+ __FILE__, __LINE__); \
+ abort(); \
+} while (0)
+
+#define assert_not_implemented(e) do { \
+ if (!(e)) \
+ not_implemented(); \
+} while (0)
diff --git a/test/include/test/test.h b/test/include/test/test.h
index 3cf901f..c8112eb 100644
--- a/test/include/test/test.h
+++ b/test/include/test/test.h
@@ -311,6 +311,9 @@ label_test_end: \
#define test(...) \
p_test(__VA_ARGS__, NULL)
+#define test_no_malloc_init(...) \
+ p_test_no_malloc_init(__VA_ARGS__, NULL)
+
#define test_skip_if(e) do { \
if (e) { \
test_skip("%s:%s:%d: Test skipped: (%s)", \
@@ -324,6 +327,7 @@ void test_fail(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);
/* For private use by macros. */
test_status_t p_test(test_t *t, ...);
+test_status_t p_test_no_malloc_init(test_t *t, ...);
void p_test_init(const char *name);
void p_test_fini(void);
void p_test_fail(const char *prefix, const char *message);
diff --git a/test/integration/chunk.c b/test/integration/chunk.c
index af1c9a5..ff9bf96 100644
--- a/test/integration/chunk.c
+++ b/test/integration/chunk.c
@@ -121,6 +121,10 @@ TEST_BEGIN(test_chunk)
{
void *p;
size_t old_size, new_size, large0, large1, huge0, huge1, huge2, sz;
+ unsigned arena_ind;
+ int flags;
+ size_t hooks_mib[3], purge_mib[3];
+ size_t hooks_miblen, purge_miblen;
chunk_hooks_t new_hooks = {
chunk_alloc,
chunk_dalloc,
@@ -132,10 +136,19 @@ TEST_BEGIN(test_chunk)
};
bool xallocx_success_a, xallocx_success_b, xallocx_success_c;
+ sz = sizeof(unsigned);
+ assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
+ "Unexpected mallctl() failure");
+ flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
+
/* Install custom chunk hooks. */
+ hooks_miblen = sizeof(hooks_mib)/sizeof(size_t);
+ assert_d_eq(mallctlnametomib("arena.0.chunk_hooks", hooks_mib,
+ &hooks_miblen), 0, "Unexpected mallctlnametomib() failure");
+ hooks_mib[1] = (size_t)arena_ind;
old_size = sizeof(chunk_hooks_t);
new_size = sizeof(chunk_hooks_t);
- assert_d_eq(mallctl("arena.0.chunk_hooks", &old_hooks, &old_size,
+ assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, &old_hooks, &old_size,
&new_hooks, new_size), 0, "Unexpected chunk_hooks error");
orig_hooks = old_hooks;
assert_ptr_ne(old_hooks.alloc, chunk_alloc, "Unexpected alloc error");
@@ -165,45 +178,49 @@ TEST_BEGIN(test_chunk)
"Unexpected arenas.hchunk.2.size failure");
/* Test dalloc/decommit/purge cascade. */
+ purge_miblen = sizeof(purge_mib)/sizeof(size_t);
+ assert_d_eq(mallctlnametomib("arena.0.purge", purge_mib, &purge_miblen),
+ 0, "Unexpected mallctlnametomib() failure");
+ purge_mib[1] = (size_t)arena_ind;
do_dalloc = false;
do_decommit = false;
- p = mallocx(huge0 * 2, 0);
+ p = mallocx(huge0 * 2, flags);
assert_ptr_not_null(p, "Unexpected mallocx() error");
did_dalloc = false;
did_decommit = false;
did_purge = false;
did_split = false;
- xallocx_success_a = (xallocx(p, huge0, 0, 0) == huge0);
- assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
- "Unexpected arena.0.purge error");
+ xallocx_success_a = (xallocx(p, huge0, 0, flags) == huge0);
+ assert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),
+ 0, "Unexpected arena.%u.purge error", arena_ind);
if (xallocx_success_a) {
assert_true(did_dalloc, "Expected dalloc");
assert_false(did_decommit, "Unexpected decommit");
assert_true(did_purge, "Expected purge");
}
assert_true(did_split, "Expected split");
- dallocx(p, 0);
+ dallocx(p, flags);
do_dalloc = true;
/* Test decommit/commit and observe split/merge. */
do_dalloc = false;
do_decommit = true;
- p = mallocx(huge0 * 2, 0);
+ p = mallocx(huge0 * 2, flags);
assert_ptr_not_null(p, "Unexpected mallocx() error");
did_decommit = false;
did_commit = false;
did_split = false;
did_merge = false;
- xallocx_success_b = (xallocx(p, huge0, 0, 0) == huge0);
- assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
- "Unexpected arena.0.purge error");
+ xallocx_success_b = (xallocx(p, huge0, 0, flags) == huge0);
+ assert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),
+ 0, "Unexpected arena.%u.purge error", arena_ind);
if (xallocx_success_b)
assert_true(did_split, "Expected split");
- xallocx_success_c = (xallocx(p, huge0 * 2, 0, 0) == huge0 * 2);
+ xallocx_success_c = (xallocx(p, huge0 * 2, 0, flags) == huge0 * 2);
assert_b_eq(did_decommit, did_commit, "Expected decommit/commit match");
if (xallocx_success_b && xallocx_success_c)
assert_true(did_merge, "Expected merge");
- dallocx(p, 0);
+ dallocx(p, flags);
do_dalloc = true;
do_decommit = false;
@@ -214,42 +231,42 @@ TEST_BEGIN(test_chunk)
* successful xallocx() from size=huge2 to size=huge1 is
* guaranteed to leave trailing purgeable memory.
*/
- p = mallocx(huge2, 0);
+ p = mallocx(huge2, flags);
assert_ptr_not_null(p, "Unexpected mallocx() error");
did_purge = false;
- assert_zu_eq(xallocx(p, huge1, 0, 0), huge1,
+ assert_zu_eq(xallocx(p, huge1, 0, flags), huge1,
"Unexpected xallocx() failure");
assert_true(did_purge, "Expected purge");
- dallocx(p, 0);
+ dallocx(p, flags);
}
/* Test decommit for large allocations. */
do_decommit = true;
- p = mallocx(large1, 0);
+ p = mallocx(large1, flags);
assert_ptr_not_null(p, "Unexpected mallocx() error");
- assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
- "Unexpected arena.0.purge error");
+ assert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),
+ 0, "Unexpected arena.%u.purge error", arena_ind);
did_decommit = false;
- assert_zu_eq(xallocx(p, large0, 0, 0), large0,
+ assert_zu_eq(xallocx(p, large0, 0, flags), large0,
"Unexpected xallocx() failure");
- assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
- "Unexpected arena.0.purge error");
+ assert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),
+ 0, "Unexpected arena.%u.purge error", arena_ind);
did_commit = false;
- assert_zu_eq(xallocx(p, large1, 0, 0), large1,
+ assert_zu_eq(xallocx(p, large1, 0, flags), large1,
"Unexpected xallocx() failure");
assert_b_eq(did_decommit, did_commit, "Expected decommit/commit match");
- dallocx(p, 0);
+ dallocx(p, flags);
do_decommit = false;
/* Make sure non-huge allocation succeeds. */
- p = mallocx(42, 0);
+ p = mallocx(42, flags);
assert_ptr_not_null(p, "Unexpected mallocx() error");
- dallocx(p, 0);
+ dallocx(p, flags);
/* Restore chunk hooks. */
- assert_d_eq(mallctl("arena.0.chunk_hooks", NULL, NULL, &old_hooks,
- new_size), 0, "Unexpected chunk_hooks error");
- assert_d_eq(mallctl("arena.0.chunk_hooks", &old_hooks, &old_size,
+ assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, NULL, NULL,
+ &old_hooks, new_size), 0, "Unexpected chunk_hooks error");
+ assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, &old_hooks, &old_size,
NULL, 0), 0, "Unexpected chunk_hooks error");
assert_ptr_eq(old_hooks.alloc, orig_hooks.alloc,
"Unexpected alloc error");
diff --git a/test/integration/mallocx.c b/test/integration/mallocx.c
index 42eee10..55e1a09 100644
--- a/test/integration/mallocx.c
+++ b/test/integration/mallocx.c
@@ -1,5 +1,9 @@
#include "test/jemalloc_test.h"
+#ifdef JEMALLOC_FILL
+const char *malloc_conf = "junk:false";
+#endif
+
static unsigned
get_nsizes_impl(const char *cmd)
{
@@ -69,35 +73,41 @@ TEST_END
TEST_BEGIN(test_oom)
{
- size_t hugemax, size, alignment;
-
- hugemax = get_huge_size(get_nhuge()-1);
+ size_t hugemax;
+ bool oom;
+ void *ptrs[3];
+ unsigned i;
/*
- * It should be impossible to allocate two objects that each consume
- * more than half the virtual address space.
+ * It should be impossible to allocate three objects that each consume
+ * nearly half the virtual address space.
*/
- {
- void *p;
-
- p = mallocx(hugemax, 0);
- if (p != NULL) {
- assert_ptr_null(mallocx(hugemax, 0),
- "Expected OOM for mallocx(size=%#zx, 0)", hugemax);
- dallocx(p, 0);
- }
+ hugemax = get_huge_size(get_nhuge()-1);
+ oom = false;
+ for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
+ ptrs[i] = mallocx(hugemax, 0);
+ if (ptrs[i] == NULL)
+ oom = true;
+ }
+ assert_true(oom,
+ "Expected OOM during series of calls to mallocx(size=%zu, 0)",
+ hugemax);
+ for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
+ if (ptrs[i] != NULL)
+ dallocx(ptrs[i], 0);
}
#if LG_SIZEOF_PTR == 3
- size = ZU(0x8000000000000000);
- alignment = ZU(0x8000000000000000);
+ assert_ptr_null(mallocx(0x8000000000000000ULL,
+ MALLOCX_ALIGN(0x8000000000000000ULL)),
+ "Expected OOM for mallocx()");
+ assert_ptr_null(mallocx(0x8000000000000000ULL,
+ MALLOCX_ALIGN(0x80000000)),
+ "Expected OOM for mallocx()");
#else
- size = ZU(0x80000000);
- alignment = ZU(0x80000000);
+ assert_ptr_null(mallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)),
+ "Expected OOM for mallocx()");
#endif
- assert_ptr_null(mallocx(size, MALLOCX_ALIGN(alignment)),
- "Expected OOM for mallocx(size=%#zx, MALLOCX_ALIGN(%#zx)", size,
- alignment);
}
TEST_END
diff --git a/test/integration/xallocx.c b/test/integration/xallocx.c
index 5c4998b..ad292bb 100644
--- a/test/integration/xallocx.c
+++ b/test/integration/xallocx.c
@@ -1,5 +1,9 @@
#include "test/jemalloc_test.h"
+#ifdef JEMALLOC_FILL
+const char *malloc_conf = "junk:false";
+#endif
+
/*
* Use a separate arena for xallocx() extension/contraction tests so that
* internal allocation e.g. by heap profiling can't interpose allocations where
diff --git a/test/src/test.c b/test/src/test.c
index 8173614..d70cc75 100644
--- a/test/src/test.c
+++ b/test/src/test.c
@@ -60,32 +60,30 @@ p_test_fini(void)
malloc_printf("%s: %s\n", test_name, test_status_string(test_status));
}
-test_status_t
-p_test(test_t *t, ...)
+static test_status_t
+p_test_impl(bool do_malloc_init, test_t *t, va_list ap)
{
test_status_t ret;
- va_list ap;
- /*
- * Make sure initialization occurs prior to running tests. Tests are
- * special because they may use internal facilities prior to triggering
- * initialization as a side effect of calling into the public API. This
- * is a final safety that works even if jemalloc_constructor() doesn't
- * run, as for MSVC builds.
- */
- if (nallocx(1, 0) == 0) {
- malloc_printf("Initialization error");
- return (test_status_fail);
+ if (do_malloc_init) {
+ /*
+ * Make sure initialization occurs prior to running tests.
+ * Tests are special because they may use internal facilities
+ * prior to triggering initialization as a side effect of
+ * calling into the public API.
+ */
+ if (nallocx(1, 0) == 0) {
+ malloc_printf("Initialization error");
+ return (test_status_fail);
+ }
}
ret = test_status_pass;
- va_start(ap, t);
for (; t != NULL; t = va_arg(ap, test_t *)) {
t();
if (test_status > ret)
ret = test_status;
}
- va_end(ap);
malloc_printf("--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\n",
test_status_string(test_status_pass),
@@ -98,6 +96,34 @@ p_test(test_t *t, ...)
return (ret);
}
+test_status_t
+p_test(test_t *t, ...)
+{
+ test_status_t ret;
+ va_list ap;
+
+ ret = test_status_pass;
+ va_start(ap, t);
+ ret = p_test_impl(true, t, ap);
+ va_end(ap);
+
+ return (ret);
+}
+
+test_status_t
+p_test_no_malloc_init(test_t *t, ...)
+{
+ test_status_t ret;
+ va_list ap;
+
+ ret = test_status_pass;
+ va_start(ap, t);
+ ret = p_test_impl(false, t, ap);
+ va_end(ap);
+
+ return (ret);
+}
+
void
p_test_fail(const char *prefix, const char *message)
{
diff --git a/test/src/timer.c b/test/src/timer.c
index e91b3cf..3c7e63a 100644
--- a/test/src/timer.c
+++ b/test/src/timer.c
@@ -32,9 +32,8 @@ timer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen)
uint64_t t0 = timer_usec(a);
uint64_t t1 = timer_usec(b);
uint64_t mult;
- unsigned i = 0;
- unsigned j;
- int n;
+ size_t i = 0;
+ size_t j, n;
/* Whole. */
n = malloc_snprintf(&buf[i], buflen-i, "%"FMTu64, t0 / t1);
diff --git a/test/stress/microbench.c b/test/stress/microbench.c
index ee39fea..7dc45f8 100644
--- a/test/stress/microbench.c
+++ b/test/stress/microbench.c
@@ -1,7 +1,8 @@
#include "test/jemalloc_test.h"
JEMALLOC_INLINE_C void
-time_func(timedelta_t *timer, uint64_t nwarmup, uint64_t niter, void (*func)(void))
+time_func(timedelta_t *timer, uint64_t nwarmup, uint64_t niter,
+ void (*func)(void))
{
uint64_t i;
diff --git a/test/unit/a0.c b/test/unit/a0.c
new file mode 100644
index 0000000..b9ba45a
--- /dev/null
+++ b/test/unit/a0.c
@@ -0,0 +1,19 @@
+#include "test/jemalloc_test.h"
+
+TEST_BEGIN(test_a0)
+{
+ void *p;
+
+ p = a0malloc(1);
+ assert_ptr_not_null(p, "Unexpected a0malloc() error");
+ a0dalloc(p);
+}
+TEST_END
+
+int
+main(void)
+{
+
+ return (test_no_malloc_init(
+ test_a0));
+}
diff --git a/test/unit/arena_reset.c b/test/unit/arena_reset.c
new file mode 100644
index 0000000..8ba36c2
--- /dev/null
+++ b/test/unit/arena_reset.c
@@ -0,0 +1,159 @@
+#include "test/jemalloc_test.h"
+
+#ifdef JEMALLOC_PROF
+const char *malloc_conf = "prof:true,lg_prof_sample:0";
+#endif
+
+static unsigned
+get_nsizes_impl(const char *cmd)
+{
+ unsigned ret;
+ size_t z;
+
+ z = sizeof(unsigned);
+ assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
+ "Unexpected mallctl(\"%s\", ...) failure", cmd);
+
+ return (ret);
+}
+
+static unsigned
+get_nsmall(void)
+{
+
+ return (get_nsizes_impl("arenas.nbins"));
+}
+
+static unsigned
+get_nlarge(void)
+{
+
+ return (get_nsizes_impl("arenas.nlruns"));
+}
+
+static unsigned
+get_nhuge(void)
+{
+
+ return (get_nsizes_impl("arenas.nhchunks"));
+}
+
+static size_t
+get_size_impl(const char *cmd, size_t ind)
+{
+ size_t ret;
+ size_t z;
+ size_t mib[4];
+ size_t miblen = 4;
+
+ z = sizeof(size_t);
+ assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
+ 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
+ mib[2] = ind;
+ z = sizeof(size_t);
+ assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
+ 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
+
+ return (ret);
+}
+
+static size_t
+get_small_size(size_t ind)
+{
+
+ return (get_size_impl("arenas.bin.0.size", ind));
+}
+
+static size_t
+get_large_size(size_t ind)
+{
+
+ return (get_size_impl("arenas.lrun.0.size", ind));
+}
+
+static size_t
+get_huge_size(size_t ind)
+{
+
+ return (get_size_impl("arenas.hchunk.0.size", ind));
+}
+
+TEST_BEGIN(test_arena_reset)
+{
+#define NHUGE 4
+ unsigned arena_ind, nsmall, nlarge, nhuge, nptrs, i;
+ size_t sz, miblen;
+ void **ptrs;
+ int flags;
+ size_t mib[3];
+ tsdn_t *tsdn;
+
+ test_skip_if((config_valgrind && unlikely(in_valgrind)) || (config_fill
+ && unlikely(opt_quarantine)));
+
+ sz = sizeof(unsigned);
+ assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
+ "Unexpected mallctl() failure");
+
+ flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
+
+ nsmall = get_nsmall();
+ nlarge = get_nlarge();
+ nhuge = get_nhuge() > NHUGE ? NHUGE : get_nhuge();
+ nptrs = nsmall + nlarge + nhuge;
+ ptrs = (void **)malloc(nptrs * sizeof(void *));
+ assert_ptr_not_null(ptrs, "Unexpected malloc() failure");
+
+ /* Allocate objects with a wide range of sizes. */
+ for (i = 0; i < nsmall; i++) {
+ sz = get_small_size(i);
+ ptrs[i] = mallocx(sz, flags);
+ assert_ptr_not_null(ptrs[i],
+ "Unexpected mallocx(%zu, %#x) failure", sz, flags);
+ }
+ for (i = 0; i < nlarge; i++) {
+ sz = get_large_size(i);
+ ptrs[nsmall + i] = mallocx(sz, flags);
+ assert_ptr_not_null(ptrs[i],
+ "Unexpected mallocx(%zu, %#x) failure", sz, flags);
+ }
+ for (i = 0; i < nhuge; i++) {
+ sz = get_huge_size(i);
+ ptrs[nsmall + nlarge + i] = mallocx(sz, flags);
+ assert_ptr_not_null(ptrs[i],
+ "Unexpected mallocx(%zu, %#x) failure", sz, flags);
+ }
+
+ tsdn = tsdn_fetch();
+
+ /* Verify allocations. */
+ for (i = 0; i < nptrs; i++) {
+ assert_zu_gt(ivsalloc(tsdn, ptrs[i], false), 0,
+ "Allocation should have queryable size");
+ }
+
+ /* Reset. */
+ miblen = sizeof(mib)/sizeof(size_t);
+ assert_d_eq(mallctlnametomib("arena.0.reset", mib, &miblen), 0,
+ "Unexpected mallctlnametomib() failure");
+ mib[1] = (size_t)arena_ind;
+ assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
+ "Unexpected mallctlbymib() failure");
+
+ /* Verify allocations no longer exist. */
+ for (i = 0; i < nptrs; i++) {
+ assert_zu_eq(ivsalloc(tsdn, ptrs[i], false), 0,
+ "Allocation should no longer exist");
+ }
+
+ free(ptrs);
+}
+TEST_END
+
+int
+main(void)
+{
+
+ return (test(
+ test_arena_reset));
+}
diff --git a/test/unit/bitmap.c b/test/unit/bitmap.c
index 1ab0bb8..a2dd546 100644
--- a/test/unit/bitmap.c
+++ b/test/unit/bitmap.c
@@ -101,7 +101,7 @@ TEST_BEGIN(test_bitmap_sfu)
bitmap_info_t binfo;
bitmap_info_init(&binfo, i);
{
- ssize_t j;
+ size_t j;
bitmap_t *bitmap = (bitmap_t *)malloc(
bitmap_size(&binfo));
bitmap_init(bitmap, &binfo);
@@ -119,7 +119,7 @@ TEST_BEGIN(test_bitmap_sfu)
* Iteratively unset bits starting at the end, and
* verify that bitmap_sfu() reaches the unset bits.
*/
- for (j = i - 1; j >= 0; j--) {
+ for (j = i - 1; j < i; j--) { /* (i..0] */
bitmap_unset(bitmap, &binfo, j);
assert_zd_eq(bitmap_sfu(bitmap, &binfo), j,
"First unset bit should the bit previously "
diff --git a/test/unit/ckh.c b/test/unit/ckh.c
index b117595..961e2ac 100644
--- a/test/unit/ckh.c
+++ b/test/unit/ckh.c
@@ -2,24 +2,24 @@
TEST_BEGIN(test_new_delete)
{
- tsd_t *tsd;
+ tsdn_t *tsdn;
ckh_t ckh;
- tsd = tsd_fetch();
+ tsdn = tsdn_fetch();
- assert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash, ckh_string_keycomp),
- "Unexpected ckh_new() error");
- ckh_delete(tsd, &ckh);
+ assert_false(ckh_new(tsdn, &ckh, 2, ckh_string_hash,
+ ckh_string_keycomp), "Unexpected ckh_new() error");
+ ckh_delete(tsdn, &ckh);
- assert_false(ckh_new(tsd, &ckh, 3, ckh_pointer_hash,
+ assert_false(ckh_new(tsdn, &ckh, 3, ckh_pointer_hash,
ckh_pointer_keycomp), "Unexpected ckh_new() error");
- ckh_delete(tsd, &ckh);
+ ckh_delete(tsdn, &ckh);
}
TEST_END
TEST_BEGIN(test_count_insert_search_remove)
{
- tsd_t *tsd;
+ tsdn_t *tsdn;
ckh_t ckh;
const char *strs[] = {
"a string",
@@ -30,17 +30,17 @@ TEST_BEGIN(test_count_insert_search_remove)
const char *missing = "A string not in the hash table.";
size_t i;
- tsd = tsd_fetch();
+ tsdn = tsdn_fetch();
- assert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash, ckh_string_keycomp),
- "Unexpected ckh_new() error");
+ assert_false(ckh_new(tsdn, &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]);
+ ckh_insert(tsdn, &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));
@@ -85,7 +85,7 @@ TEST_BEGIN(test_count_insert_search_remove)
vp = (i & 2) ? &v.p : NULL;
k.p = NULL;
v.p = NULL;
- assert_false(ckh_remove(tsd, &ckh, strs[i], kp, vp),
+ assert_false(ckh_remove(tsdn, &ckh, strs[i], kp, vp),
"Unexpected ckh_remove() error");
ks = (i & 1) ? strs[i] : (const char *)NULL;
@@ -101,22 +101,22 @@ TEST_BEGIN(test_count_insert_search_remove)
ckh_count(&ckh));
}
- ckh_delete(tsd, &ckh);
+ ckh_delete(tsdn, &ckh);
}
TEST_END
TEST_BEGIN(test_insert_iter_remove)
{
#define NITEMS ZU(1000)
- tsd_t *tsd;
+ tsdn_t *tsdn;
ckh_t ckh;
void **p[NITEMS];
void *q, *r;
size_t i;
- tsd = tsd_fetch();
+ tsdn = tsdn_fetch();
- assert_false(ckh_new(tsd, &ckh, 2, ckh_pointer_hash,
+ assert_false(ckh_new(tsdn, &ckh, 2, ckh_pointer_hash,
ckh_pointer_keycomp), "Unexpected ckh_new() error");
for (i = 0; i < NITEMS; i++) {
@@ -128,7 +128,7 @@ TEST_BEGIN(test_insert_iter_remove)
size_t j;
for (j = i; j < NITEMS; j++) {
- assert_false(ckh_insert(tsd, &ckh, p[j], p[j]),
+ assert_false(ckh_insert(tsdn, &ckh, p[j], p[j]),
"Unexpected ckh_insert() failure");
assert_false(ckh_search(&ckh, p[j], &q, &r),
"Unexpected ckh_search() failure");
@@ -143,13 +143,13 @@ TEST_BEGIN(test_insert_iter_remove)
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),
+ assert_false(ckh_remove(tsdn, &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),
+ assert_true(ckh_remove(tsdn, &ckh, p[j], &q, &r),
"Unexpected ckh_remove() success");
}
@@ -184,13 +184,13 @@ TEST_BEGIN(test_insert_iter_remove)
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),
+ assert_false(ckh_remove(tsdn, &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),
+ assert_true(ckh_remove(tsdn, &ckh, p[i], &q, &r),
"Unexpected ckh_remove() success");
dallocx(p[i], 0);
}
@@ -198,7 +198,7 @@ TEST_BEGIN(test_insert_iter_remove)
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);
+ ckh_delete(tsdn, &ckh);
#undef NITEMS
}
TEST_END
diff --git a/test/unit/fork.c b/test/unit/fork.c
new file mode 100644
index 0000000..46c815e
--- /dev/null
+++ b/test/unit/fork.c
@@ -0,0 +1,64 @@
+#include "test/jemalloc_test.h"
+
+#ifndef _WIN32
+#include <sys/wait.h>
+#endif
+
+TEST_BEGIN(test_fork)
+{
+#ifndef _WIN32
+ void *p;
+ pid_t pid;
+
+ p = malloc(1);
+ assert_ptr_not_null(p, "Unexpected malloc() failure");
+
+ pid = fork();
+
+ free(p);
+
+ p = malloc(64);
+ assert_ptr_not_null(p, "Unexpected malloc() failure");
+ free(p);
+
+ if (pid == -1) {
+ /* Error. */
+ test_fail("Unexpected fork() failure");
+ } else if (pid == 0) {
+ /* Child. */
+ exit(0);
+ } else {
+ int status;
+
+ /* Parent. */
+ while (true) {
+ if (waitpid(pid, &status, 0) == -1)
+ test_fail("Unexpected waitpid() failure");
+ if (WIFSIGNALED(status)) {
+ test_fail("Unexpected child termination due to "
+ "signal %d", WTERMSIG(status));
+ break;
+ }
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ test_fail(
+ "Unexpected child exit value %d",
+ WEXITSTATUS(status));
+ }
+ break;
+ }
+ }
+ }
+#else
+ test_skip("fork(2) is irrelevant to Windows");
+#endif
+}
+TEST_END
+
+int
+main(void)
+{
+
+ return (test(
+ test_fork));
+}
diff --git a/test/unit/junk.c b/test/unit/junk.c
index b23dd1e..acddc60 100644
--- a/test/unit/junk.c
+++ b/test/unit/junk.c
@@ -29,7 +29,7 @@ arena_dalloc_junk_small_intercept(void *ptr, arena_bin_info_t *bin_info)
arena_dalloc_junk_small_orig(ptr, bin_info);
for (i = 0; i < bin_info->reg_size; i++) {
- assert_c_eq(((char *)ptr)[i], 0x5a,
+ assert_u_eq(((uint8_t *)ptr)[i], JEMALLOC_FREE_JUNK,
"Missing junk fill for byte %zu/%zu of deallocated region",
i, bin_info->reg_size);
}
@@ -44,7 +44,7 @@ arena_dalloc_junk_large_intercept(void *ptr, size_t usize)
arena_dalloc_junk_large_orig(ptr, usize);
for (i = 0; i < usize; i++) {
- assert_c_eq(((char *)ptr)[i], 0x5a,
+ assert_u_eq(((uint8_t *)ptr)[i], JEMALLOC_FREE_JUNK,
"Missing junk fill for byte %zu/%zu of deallocated region",
i, usize);
}
@@ -53,10 +53,10 @@ arena_dalloc_junk_large_intercept(void *ptr, size_t usize)
}
static void
-huge_dalloc_junk_intercept(void *ptr, size_t usize)
+huge_dalloc_junk_intercept(tsdn_t *tsdn, void *ptr, size_t usize)
{
- huge_dalloc_junk_orig(ptr, usize);
+ huge_dalloc_junk_orig(tsdn, ptr, usize);
/*
* The conditions under which junk filling actually occurs are nuanced
* enough that it doesn't make sense to duplicate the decision logic in
@@ -69,7 +69,7 @@ huge_dalloc_junk_intercept(void *ptr, size_t usize)
static void
test_junk(size_t sz_min, size_t sz_max)
{
- char *s;
+ uint8_t *s;
size_t sz_prev, sz, i;
if (opt_junk_free) {
@@ -82,23 +82,23 @@ test_junk(size_t sz_min, size_t sz_max)
}
sz_prev = 0;
- s = (char *)mallocx(sz_min, 0);
+ s = (uint8_t *)mallocx(sz_min, 0);
assert_ptr_not_null((void *)s, "Unexpected mallocx() failure");
for (sz = sallocx(s, 0); sz <= sz_max;
sz_prev = sz, sz = sallocx(s, 0)) {
if (sz_prev > 0) {
- assert_c_eq(s[0], 'a',
+ assert_u_eq(s[0], 'a',
"Previously allocated byte %zu/%zu is corrupted",
ZU(0), sz_prev);
- assert_c_eq(s[sz_prev-1], 'a',
+ assert_u_eq(s[sz_prev-1], 'a',
"Previously allocated byte %zu/%zu is corrupted",
sz_prev-1, sz_prev);
}
for (i = sz_prev; i < sz; i++) {
if (opt_junk_alloc) {
- assert_c_eq(s[i], 0xa5,
+ assert_u_eq(s[i], JEMALLOC_ALLOC_JUNK,
"Newly allocated byte %zu/%zu isn't "
"junk-filled", i, sz);
}
@@ -107,7 +107,7 @@ test_junk(size_t sz_min, size_t sz_max)
if (xallocx(s, sz+1, 0, 0) == sz) {
watch_junking(s);
- s = (char *)rallocx(s, sz+1, 0);
+ s = (uint8_t *)rallocx(s, sz+1, 0);
assert_ptr_not_null((void *)s,
"Unexpected rallocx() failure");
assert_true(!opt_junk_free || saw_junking,
@@ -244,7 +244,6 @@ int
main(void)
{
- assert(!config_fill || opt_junk_alloc || opt_junk_free);
return (test(
test_junk_small,
test_junk_large,
diff --git a/test/unit/junk_alloc.c b/test/unit/junk_alloc.c
index 8db3331..a5895b5 100644
--- a/test/unit/junk_alloc.c
+++ b/test/unit/junk_alloc.c
@@ -1,3 +1,3 @@
-#define JEMALLOC_TEST_JUNK_OPT "junk:alloc"
+#define JEMALLOC_TEST_JUNK_OPT "junk:alloc"
#include "junk.c"
#undef JEMALLOC_TEST_JUNK_OPT
diff --git a/test/unit/junk_free.c b/test/unit/junk_free.c
index 482a61d..bb5183c 100644
--- a/test/unit/junk_free.c
+++ b/test/unit/junk_free.c
@@ -1,3 +1,3 @@
-#define JEMALLOC_TEST_JUNK_OPT "junk:free"
+#define JEMALLOC_TEST_JUNK_OPT "junk:free"
#include "junk.c"
#undef JEMALLOC_TEST_JUNK_OPT
diff --git a/test/unit/ph.c b/test/unit/ph.c
new file mode 100644
index 0000000..da442f0
--- /dev/null
+++ b/test/unit/ph.c
@@ -0,0 +1,290 @@
+#include "test/jemalloc_test.h"
+
+typedef struct node_s node_t;
+
+struct node_s {
+#define NODE_MAGIC 0x9823af7e
+ uint32_t magic;
+ phn(node_t) link;
+ uint64_t key;
+};
+
+static int
+node_cmp(const node_t *a, const node_t *b)
+{
+ int ret;
+
+ ret = (a->key > b->key) - (a->key < b->key);
+ if (ret == 0) {
+ /*
+ * Duplicates are not allowed in the heap, so force an
+ * arbitrary ordering for non-identical items with equal keys.
+ */
+ ret = (((uintptr_t)a) > ((uintptr_t)b))
+ - (((uintptr_t)a) < ((uintptr_t)b));
+ }
+ return (ret);
+}
+
+static int
+node_cmp_magic(const node_t *a, const node_t *b) {
+
+ assert_u32_eq(a->magic, NODE_MAGIC, "Bad magic");
+ assert_u32_eq(b->magic, NODE_MAGIC, "Bad magic");
+
+ return (node_cmp(a, b));
+}
+
+typedef ph(node_t) heap_t;
+ph_gen(static, heap_, heap_t, node_t, link, node_cmp_magic);
+
+static void
+node_print(const node_t *node, unsigned depth)
+{
+ unsigned i;
+ node_t *leftmost_child, *sibling;
+
+ for (i = 0; i < depth; i++)
+ malloc_printf("\t");
+ malloc_printf("%2"FMTu64"\n", node->key);
+
+ leftmost_child = phn_lchild_get(node_t, link, node);
+ if (leftmost_child == NULL)
+ return;
+ node_print(leftmost_child, depth + 1);
+
+ for (sibling = phn_next_get(node_t, link, leftmost_child); sibling !=
+ NULL; sibling = phn_next_get(node_t, link, sibling)) {
+ node_print(sibling, depth + 1);
+ }
+}
+
+static void
+heap_print(const heap_t *heap)
+{
+ node_t *auxelm;
+
+ malloc_printf("vvv heap %p vvv\n", heap);
+ if (heap->ph_root == NULL)
+ goto label_return;
+
+ node_print(heap->ph_root, 0);
+
+ for (auxelm = phn_next_get(node_t, link, heap->ph_root); auxelm != NULL;
+ auxelm = phn_next_get(node_t, link, auxelm)) {
+ assert_ptr_eq(phn_next_get(node_t, link, phn_prev_get(node_t,
+ link, auxelm)), auxelm,
+ "auxelm's prev doesn't link to auxelm");
+ node_print(auxelm, 0);
+ }
+
+label_return:
+ malloc_printf("^^^ heap %p ^^^\n", heap);
+}
+
+static unsigned
+node_validate(const node_t *node, const node_t *parent)
+{
+ unsigned nnodes = 1;
+ node_t *leftmost_child, *sibling;
+
+ if (parent != NULL) {
+ assert_d_ge(node_cmp_magic(node, parent), 0,
+ "Child is less than parent");
+ }
+
+ leftmost_child = phn_lchild_get(node_t, link, node);
+ if (leftmost_child == NULL)
+ return (nnodes);
+ assert_ptr_eq((void *)phn_prev_get(node_t, link, leftmost_child),
+ (void *)node, "Leftmost child does not link to node");
+ nnodes += node_validate(leftmost_child, node);
+
+ for (sibling = phn_next_get(node_t, link, leftmost_child); sibling !=
+ NULL; sibling = phn_next_get(node_t, link, sibling)) {
+ assert_ptr_eq(phn_next_get(node_t, link, phn_prev_get(node_t,
+ link, sibling)), sibling,
+ "sibling's prev doesn't link to sibling");
+ nnodes += node_validate(sibling, node);
+ }
+ return (nnodes);
+}
+
+static unsigned
+heap_validate(const heap_t *heap)
+{
+ unsigned nnodes = 0;
+ node_t *auxelm;
+
+ if (heap->ph_root == NULL)
+ goto label_return;
+
+ nnodes += node_validate(heap->ph_root, NULL);
+
+ for (auxelm = phn_next_get(node_t, link, heap->ph_root); auxelm != NULL;
+ auxelm = phn_next_get(node_t, link, auxelm)) {
+ assert_ptr_eq(phn_next_get(node_t, link, phn_prev_get(node_t,
+ link, auxelm)), auxelm,
+ "auxelm's prev doesn't link to auxelm");
+ nnodes += node_validate(auxelm, NULL);
+ }
+
+label_return:
+ if (false)
+ heap_print(heap);
+ return (nnodes);
+}
+
+TEST_BEGIN(test_ph_empty)
+{
+ heap_t heap;
+
+ heap_new(&heap);
+ assert_true(heap_empty(&heap), "Heap should be empty");
+ assert_ptr_null(heap_first(&heap), "Unexpected node");
+}
+TEST_END
+
+static void
+node_remove(heap_t *heap, node_t *node)
+{
+
+ heap_remove(heap, node);
+
+ node->magic = 0;
+}
+
+static node_t *
+node_remove_first(heap_t *heap)
+{
+ node_t *node = heap_remove_first(heap);
+ node->magic = 0;
+ return (node);
+}
+
+TEST_BEGIN(test_ph_random)
+{
+#define NNODES 25
+#define NBAGS 250
+#define SEED 42
+ sfmt_t *sfmt;
+ uint64_t bag[NNODES];
+ heap_t heap;
+ node_t nodes[NNODES];
+ unsigned i, j, k;
+
+ sfmt = init_gen_rand(SEED);
+ for (i = 0; i < NBAGS; i++) {
+ switch (i) {
+ case 0:
+ /* Insert in order. */
+ for (j = 0; j < NNODES; j++)
+ bag[j] = j;
+ break;
+ case 1:
+ /* Insert in reverse order. */
+ for (j = 0; j < NNODES; j++)
+ bag[j] = NNODES - j - 1;
+ break;
+ default:
+ for (j = 0; j < NNODES; j++)
+ bag[j] = gen_rand64_range(sfmt, NNODES);
+ }
+
+ for (j = 1; j <= NNODES; j++) {
+ /* Initialize heap and nodes. */
+ heap_new(&heap);
+ assert_u_eq(heap_validate(&heap), 0,
+ "Incorrect node count");
+ for (k = 0; k < j; k++) {
+ nodes[k].magic = NODE_MAGIC;
+ nodes[k].key = bag[k];
+ }
+
+ /* Insert nodes. */
+ for (k = 0; k < j; k++) {
+ heap_insert(&heap, &nodes[k]);
+ if (i % 13 == 12) {
+ /* Trigger merging. */
+ assert_ptr_not_null(heap_first(&heap),
+ "Heap should not be empty");
+ }
+ assert_u_eq(heap_validate(&heap), k + 1,
+ "Incorrect node count");
+ }
+
+ assert_false(heap_empty(&heap),
+ "Heap should not be empty");
+
+ /* Remove nodes. */
+ switch (i % 4) {
+ case 0:
+ for (k = 0; k < j; k++) {
+ assert_u_eq(heap_validate(&heap), j - k,
+ "Incorrect node count");
+ node_remove(&heap, &nodes[k]);
+ assert_u_eq(heap_validate(&heap), j - k
+ - 1, "Incorrect node count");
+ }
+ break;
+ case 1:
+ for (k = j; k > 0; k--) {
+ node_remove(&heap, &nodes[k-1]);
+ assert_u_eq(heap_validate(&heap), k - 1,
+ "Incorrect node count");
+ }
+ break;
+ case 2: {
+ node_t *prev = NULL;
+ for (k = 0; k < j; k++) {
+ node_t *node = node_remove_first(&heap);
+ assert_u_eq(heap_validate(&heap), j - k
+ - 1, "Incorrect node count");
+ if (prev != NULL) {
+ assert_d_ge(node_cmp(node,
+ prev), 0,
+ "Bad removal order");
+ }
+ prev = node;
+ }
+ break;
+ } case 3: {
+ node_t *prev = NULL;
+ for (k = 0; k < j; k++) {
+ node_t *node = heap_first(&heap);
+ assert_u_eq(heap_validate(&heap), j - k,
+ "Incorrect node count");
+ if (prev != NULL) {
+ assert_d_ge(node_cmp(node,
+ prev), 0,
+ "Bad removal order");
+ }
+ node_remove(&heap, node);
+ assert_u_eq(heap_validate(&heap), j - k
+ - 1, "Incorrect node count");
+ prev = node;
+ }
+ break;
+ } default:
+ not_reached();
+ }
+
+ assert_ptr_null(heap_first(&heap),
+ "Heap should be empty");
+ assert_true(heap_empty(&heap), "Heap should be empty");
+ }
+ }
+ fini_gen_rand(sfmt);
+#undef NNODES
+#undef SEED
+}
+TEST_END
+
+int
+main(void)
+{
+
+ return (test(
+ test_ph_empty,
+ test_ph_random));
+}
diff --git a/test/unit/prof_reset.c b/test/unit/prof_reset.c
index 69983e5..5ae45fd 100644
--- a/test/unit/prof_reset.c
+++ b/test/unit/prof_reset.c
@@ -94,7 +94,8 @@ TEST_END
bool prof_dump_header_intercepted = false;
prof_cnt_t cnt_all_copy = {0, 0, 0, 0};
static bool
-prof_dump_header_intercept(bool propagate_err, const prof_cnt_t *cnt_all)
+prof_dump_header_intercept(tsdn_t *tsdn, bool propagate_err,
+ const prof_cnt_t *cnt_all)
{
prof_dump_header_intercepted = true;
diff --git a/test/unit/stats.c b/test/unit/stats.c
index 6e80316..a9a3981 100644
--- a/test/unit/stats.c
+++ b/test/unit/stats.c
@@ -220,11 +220,11 @@ TEST_BEGIN(test_stats_arenas_large)
if (config_stats) {
assert_zu_gt(allocated, 0,
"allocated should be greater than zero");
- assert_zu_gt(nmalloc, 0,
+ assert_u64_gt(nmalloc, 0,
"nmalloc should be greater than zero");
- assert_zu_ge(nmalloc, ndalloc,
+ assert_u64_ge(nmalloc, ndalloc,
"nmalloc should be at least as large as ndalloc");
- assert_zu_gt(nrequests, 0,
+ assert_u64_gt(nrequests, 0,
"nrequests should be greater than zero");
}
@@ -262,9 +262,9 @@ TEST_BEGIN(test_stats_arenas_huge)
if (config_stats) {
assert_zu_gt(allocated, 0,
"allocated should be greater than zero");
- assert_zu_gt(nmalloc, 0,
+ assert_u64_gt(nmalloc, 0,
"nmalloc should be greater than zero");
- assert_zu_ge(nmalloc, ndalloc,
+ assert_u64_ge(nmalloc, ndalloc,
"nmalloc should be at least as large as ndalloc");
}
diff --git a/test/unit/tsd.c b/test/unit/tsd.c
index 8be787f..7dde4b7 100644
--- a/test/unit/tsd.c
+++ b/test/unit/tsd.c
@@ -99,6 +99,11 @@ int
main(void)
{
+ /* Core tsd bootstrapping must happen prior to data_tsd_boot(). */
+ if (nallocx(1, 0) == 0) {
+ malloc_printf("Initialization error");
+ return (test_status_fail);
+ }
data_tsd_boot();
return (test(
diff --git a/test/unit/util.c b/test/unit/util.c
index 2f65aad..c958dc0 100644
--- a/test/unit/util.c
+++ b/test/unit/util.c
@@ -4,27 +4,27 @@
unsigned i, pow2; \
t x; \
\
- assert_zu_eq(pow2_ceil_##suf(0), 0, "Unexpected result"); \
+ assert_##suf##_eq(pow2_ceil_##suf(0), 0, "Unexpected result"); \
\
for (i = 0; i < sizeof(t) * 8; i++) { \
- assert_zu_eq(pow2_ceil_##suf(((t)1) << i), ((t)1) << i, \
- "Unexpected result"); \
+ assert_##suf##_eq(pow2_ceil_##suf(((t)1) << i), ((t)1) \
+ << i, "Unexpected result"); \
} \
\
for (i = 2; i < sizeof(t) * 8; i++) { \
- assert_zu_eq(pow2_ceil_##suf((((t)1) << i) - 1), \
+ assert_##suf##_eq(pow2_ceil_##suf((((t)1) << i) - 1), \
((t)1) << i, "Unexpected result"); \
} \
\
for (i = 0; i < sizeof(t) * 8 - 1; i++) { \
- assert_zu_eq(pow2_ceil_##suf((((t)1) << i) + 1), \
+ assert_##suf##_eq(pow2_ceil_##suf((((t)1) << i) + 1), \
((t)1) << (i+1), "Unexpected result"); \
} \
\
for (pow2 = 1; pow2 < 25; pow2++) { \
for (x = (((t)1) << (pow2-1)) + 1; x <= ((t)1) << pow2; \
x++) { \
- assert_zu_eq(pow2_ceil_##suf(x), \
+ assert_##suf##_eq(pow2_ceil_##suf(x), \
((t)1) << pow2, \
"Unexpected result, x=%"pri, x); \
} \
@@ -160,14 +160,14 @@ TEST_BEGIN(test_malloc_snprintf_truncated)
{
#define BUFLEN 15
char buf[BUFLEN];
- int result;
+ size_t result;
size_t len;
-#define TEST(expected_str_untruncated, ...) do { \
+#define TEST(expected_str_untruncated, ...) do { \
result = malloc_snprintf(buf, len, __VA_ARGS__); \
assert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0, \
"Unexpected string inequality (\"%s\" vs \"%s\")", \
- buf, expected_str_untruncated); \
- assert_d_eq(result, strlen(expected_str_untruncated), \
+ buf, expected_str_untruncated); \
+ assert_zu_eq(result, strlen(expected_str_untruncated), \
"Unexpected result"); \
} while (0)
@@ -193,11 +193,11 @@ TEST_BEGIN(test_malloc_snprintf)
{
#define BUFLEN 128
char buf[BUFLEN];
- int result;
+ size_t result;
#define TEST(expected_str, ...) do { \
result = malloc_snprintf(buf, sizeof(buf), __VA_ARGS__); \
assert_str_eq(buf, expected_str, "Unexpected output"); \
- assert_d_eq(result, strlen(expected_str), "Unexpected result"); \
+ assert_zu_eq(result, strlen(expected_str), "Unexpected result");\
} while (0)
TEST("hello", "hello");
diff --git a/test/unit/witness.c b/test/unit/witness.c
new file mode 100644
index 0000000..ed17275
--- /dev/null
+++ b/test/unit/witness.c
@@ -0,0 +1,278 @@
+#include "test/jemalloc_test.h"
+
+static witness_lock_error_t *witness_lock_error_orig;
+static witness_owner_error_t *witness_owner_error_orig;
+static witness_not_owner_error_t *witness_not_owner_error_orig;
+static witness_lockless_error_t *witness_lockless_error_orig;
+
+static bool saw_lock_error;
+static bool saw_owner_error;
+static bool saw_not_owner_error;
+static bool saw_lockless_error;
+
+static void
+witness_lock_error_intercept(const witness_list_t *witnesses,
+ const witness_t *witness)
+{
+
+ saw_lock_error = true;
+}
+
+static void
+witness_owner_error_intercept(const witness_t *witness)
+{
+
+ saw_owner_error = true;
+}
+
+static void
+witness_not_owner_error_intercept(const witness_t *witness)
+{
+
+ saw_not_owner_error = true;
+}
+
+static void
+witness_lockless_error_intercept(const witness_list_t *witnesses)
+{
+
+ saw_lockless_error = true;
+}
+
+static int
+witness_comp(const witness_t *a, const witness_t *b)
+{
+
+ assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank");
+
+ return (strcmp(a->name, b->name));
+}
+
+static int
+witness_comp_reverse(const witness_t *a, const witness_t *b)
+{
+
+ assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank");
+
+ return (-strcmp(a->name, b->name));
+}
+
+TEST_BEGIN(test_witness)
+{
+ witness_t a, b;
+ tsdn_t *tsdn;
+
+ test_skip_if(!config_debug);
+
+ tsdn = tsdn_fetch();
+
+ witness_assert_lockless(tsdn);
+
+ witness_init(&a, "a", 1, NULL);
+ witness_assert_not_owner(tsdn, &a);
+ witness_lock(tsdn, &a);
+ witness_assert_owner(tsdn, &a);
+
+ witness_init(&b, "b", 2, NULL);
+ witness_assert_not_owner(tsdn, &b);
+ witness_lock(tsdn, &b);
+ witness_assert_owner(tsdn, &b);
+
+ witness_unlock(tsdn, &a);
+ witness_unlock(tsdn, &b);
+
+ witness_assert_lockless(tsdn);
+}
+TEST_END
+
+TEST_BEGIN(test_witness_comp)
+{
+ witness_t a, b, c, d;
+ tsdn_t *tsdn;
+
+ test_skip_if(!config_debug);
+
+ tsdn = tsdn_fetch();
+
+ witness_assert_lockless(tsdn);
+
+ witness_init(&a, "a", 1, witness_comp);
+ witness_assert_not_owner(tsdn, &a);
+ witness_lock(tsdn, &a);
+ witness_assert_owner(tsdn, &a);
+
+ witness_init(&b, "b", 1, witness_comp);
+ witness_assert_not_owner(tsdn, &b);
+ witness_lock(tsdn, &b);
+ witness_assert_owner(tsdn, &b);
+ witness_unlock(tsdn, &b);
+
+ witness_lock_error_orig = witness_lock_error;
+ witness_lock_error = witness_lock_error_intercept;
+ saw_lock_error = false;
+
+ witness_init(&c, "c", 1, witness_comp_reverse);
+ witness_assert_not_owner(tsdn, &c);
+ assert_false(saw_lock_error, "Unexpected witness lock error");
+ witness_lock(tsdn, &c);
+ assert_true(saw_lock_error, "Expected witness lock error");
+ witness_unlock(tsdn, &c);
+
+ saw_lock_error = false;
+
+ witness_init(&d, "d", 1, NULL);
+ witness_assert_not_owner(tsdn, &d);
+ assert_false(saw_lock_error, "Unexpected witness lock error");
+ witness_lock(tsdn, &d);
+ assert_true(saw_lock_error, "Expected witness lock error");
+ witness_unlock(tsdn, &d);
+
+ witness_unlock(tsdn, &a);
+
+ witness_assert_lockless(tsdn);
+
+ witness_lock_error = witness_lock_error_orig;
+}
+TEST_END
+
+TEST_BEGIN(test_witness_reversal)
+{
+ witness_t a, b;
+ tsdn_t *tsdn;
+
+ test_skip_if(!config_debug);
+
+ witness_lock_error_orig = witness_lock_error;
+ witness_lock_error = witness_lock_error_intercept;
+ saw_lock_error = false;
+
+ tsdn = tsdn_fetch();
+
+ witness_assert_lockless(tsdn);
+
+ witness_init(&a, "a", 1, NULL);
+ witness_init(&b, "b", 2, NULL);
+
+ witness_lock(tsdn, &b);
+ assert_false(saw_lock_error, "Unexpected witness lock error");
+ witness_lock(tsdn, &a);
+ assert_true(saw_lock_error, "Expected witness lock error");
+
+ witness_unlock(tsdn, &a);
+ witness_unlock(tsdn, &b);
+
+ witness_assert_lockless(tsdn);
+
+ witness_lock_error = witness_lock_error_orig;
+}
+TEST_END
+
+TEST_BEGIN(test_witness_recursive)
+{
+ witness_t a;
+ tsdn_t *tsdn;
+
+ test_skip_if(!config_debug);
+
+ witness_not_owner_error_orig = witness_not_owner_error;
+ witness_not_owner_error = witness_not_owner_error_intercept;
+ saw_not_owner_error = false;
+
+ witness_lock_error_orig = witness_lock_error;
+ witness_lock_error = witness_lock_error_intercept;
+ saw_lock_error = false;
+
+ tsdn = tsdn_fetch();
+
+ witness_assert_lockless(tsdn);
+
+ witness_init(&a, "a", 1, NULL);
+
+ witness_lock(tsdn, &a);
+ assert_false(saw_lock_error, "Unexpected witness lock error");
+ assert_false(saw_not_owner_error, "Unexpected witness not owner error");
+ witness_lock(tsdn, &a);
+ assert_true(saw_lock_error, "Expected witness lock error");
+ assert_true(saw_not_owner_error, "Expected witness not owner error");
+
+ witness_unlock(tsdn, &a);
+
+ witness_assert_lockless(tsdn);
+
+ witness_owner_error = witness_owner_error_orig;
+ witness_lock_error = witness_lock_error_orig;
+
+}
+TEST_END
+
+TEST_BEGIN(test_witness_unlock_not_owned)
+{
+ witness_t a;
+ tsdn_t *tsdn;
+
+ test_skip_if(!config_debug);
+
+ witness_owner_error_orig = witness_owner_error;
+ witness_owner_error = witness_owner_error_intercept;
+ saw_owner_error = false;
+
+ tsdn = tsdn_fetch();
+
+ witness_assert_lockless(tsdn);
+
+ witness_init(&a, "a", 1, NULL);
+
+ assert_false(saw_owner_error, "Unexpected owner error");
+ witness_unlock(tsdn, &a);
+ assert_true(saw_owner_error, "Expected owner error");
+
+ witness_assert_lockless(tsdn);
+
+ witness_owner_error = witness_owner_error_orig;
+}
+TEST_END
+
+TEST_BEGIN(test_witness_lockful)
+{
+ witness_t a;
+ tsdn_t *tsdn;
+
+ test_skip_if(!config_debug);
+
+ witness_lockless_error_orig = witness_lockless_error;
+ witness_lockless_error = witness_lockless_error_intercept;
+ saw_lockless_error = false;
+
+ tsdn = tsdn_fetch();
+
+ witness_assert_lockless(tsdn);
+
+ witness_init(&a, "a", 1, NULL);
+
+ assert_false(saw_lockless_error, "Unexpected lockless error");
+ witness_assert_lockless(tsdn);
+
+ witness_lock(tsdn, &a);
+ witness_assert_lockless(tsdn);
+ assert_true(saw_lockless_error, "Expected lockless error");
+
+ witness_unlock(tsdn, &a);
+
+ witness_assert_lockless(tsdn);
+
+ witness_lockless_error = witness_lockless_error_orig;
+}
+TEST_END
+
+int
+main(void)
+{
+
+ return (test(
+ test_witness,
+ test_witness_comp,
+ test_witness_reversal,
+ test_witness_recursive,
+ test_witness_unlock_not_owned,
+ test_witness_lockful));
+}
diff --git a/test/unit/zero.c b/test/unit/zero.c
index 93afc2b..30ebe37 100644
--- a/test/unit/zero.c
+++ b/test/unit/zero.c
@@ -8,39 +8,41 @@ const char *malloc_conf =
static void
test_zero(size_t sz_min, size_t sz_max)
{
- char *s;
+ uint8_t *s;
size_t sz_prev, sz, i;
+#define MAGIC ((uint8_t)0x61)
sz_prev = 0;
- s = (char *)mallocx(sz_min, 0);
+ s = (uint8_t *)mallocx(sz_min, 0);
assert_ptr_not_null((void *)s, "Unexpected mallocx() failure");
for (sz = sallocx(s, 0); sz <= sz_max;
sz_prev = sz, sz = sallocx(s, 0)) {
if (sz_prev > 0) {
- assert_c_eq(s[0], 'a',
+ assert_u_eq(s[0], MAGIC,
"Previously allocated byte %zu/%zu is corrupted",
ZU(0), sz_prev);
- assert_c_eq(s[sz_prev-1], 'a',
+ assert_u_eq(s[sz_prev-1], MAGIC,
"Previously allocated byte %zu/%zu is corrupted",
sz_prev-1, sz_prev);
}
for (i = sz_prev; i < sz; i++) {
- assert_c_eq(s[i], 0x0,
+ assert_u_eq(s[i], 0x0,
"Newly allocated byte %zu/%zu isn't zero-filled",
i, sz);
- s[i] = 'a';
+ s[i] = MAGIC;
}
if (xallocx(s, sz+1, 0, 0) == sz) {
- s = (char *)rallocx(s, sz+1, 0);
+ s = (uint8_t *)rallocx(s, sz+1, 0);
assert_ptr_not_null((void *)s,
"Unexpected rallocx() failure");
}
}
dallocx(s, 0);
+#undef MAGIC
}
TEST_BEGIN(test_zero_small)