Refactor tests.

Refactor tests to use explicit testing assertions, rather than diff'ing
test output.  This makes the test code a bit shorter, more explicitly
encodes testing intent, and makes test failure diagnosis more
straightforward.
This commit is contained in:
Jason Evans 2013-12-08 20:52:21 -08:00
parent 9f35a71a81
commit 2a83ed0284
31 changed files with 880 additions and 708 deletions

View File

@ -179,12 +179,12 @@ $(C_TESTLIB_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST
$(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c $(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c
$(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c $(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c
$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST $(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST
$(C_TESTLIB_OBJS): CPPFLAGS += -I$(objroot)test/include $(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include
$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST $(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST
$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST $(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST
$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST $(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST
$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c $(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c
$(TESTS_OBJS): CPPFLAGS += -I$(objroot)test/include $(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include
ifneq ($(IMPORTLIB),$(SO)) ifneq ($(IMPORTLIB),$(SO))
$(C_OBJS): CPPFLAGS += -DDLLEXPORT $(C_OBJS): CPPFLAGS += -DDLLEXPORT
endif endif

View File

@ -7,7 +7,7 @@ typedef enum {
dss_prec_secondary = 2, dss_prec_secondary = 2,
dss_prec_limit = 3 dss_prec_limit = 3
} dss_prec_t ; } dss_prec_t;
#define DSS_PREC_DEFAULT dss_prec_secondary #define DSS_PREC_DEFAULT dss_prec_secondary
#define DSS_DEFAULT "secondary" #define DSS_DEFAULT "secondary"

View File

@ -84,7 +84,7 @@
/******************************************************************************/ /******************************************************************************/
#ifdef JEMALLOC_H_EXTERNS #ifdef JEMALLOC_H_EXTERNS
int buferror(char *buf, size_t buflen); int buferror(int err, char *buf, size_t buflen);
uintmax_t malloc_strtoumax(const char *nptr, char **endptr, int base); uintmax_t malloc_strtoumax(const char *nptr, char **endptr, int base);
void malloc_write(const char *s); void malloc_write(const char *s);

View File

@ -43,7 +43,7 @@ pages_map(void *addr, size_t size)
if (munmap(ret, size) == -1) { if (munmap(ret, size) == -1) {
char buf[BUFERROR_BUF]; char buf[BUFERROR_BUF];
buferror(buf, sizeof(buf)); buferror(get_errno(), buf, sizeof(buf));
malloc_printf("<jemalloc: Error in munmap(): %s\n", malloc_printf("<jemalloc: Error in munmap(): %s\n",
buf); buf);
if (opt_abort) if (opt_abort)
@ -69,7 +69,7 @@ pages_unmap(void *addr, size_t size)
{ {
char buf[BUFERROR_BUF]; char buf[BUFERROR_BUF];
buferror(buf, sizeof(buf)); buferror(get_errno(), buf, sizeof(buf));
malloc_printf("<jemalloc>: Error in " malloc_printf("<jemalloc>: Error in "
#ifdef _WIN32 #ifdef _WIN32
"VirtualFree" "VirtualFree"

View File

@ -169,7 +169,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
*/ */
char buf[BUFERROR_BUF]; char buf[BUFERROR_BUF];
buferror(buf, sizeof(buf)); buferror(get_errno(), buf, sizeof(buf));
malloc_printf("<jemalloc>: Error in mremap(): %s\n", malloc_printf("<jemalloc>: Error in mremap(): %s\n",
buf); buf);
if (opt_abort) if (opt_abort)

View File

@ -77,7 +77,7 @@ malloc_write(const char *s)
* provide a wrapper. * provide a wrapper.
*/ */
int int
buferror(char *buf, size_t buflen) buferror(int err, char *buf, size_t buflen)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -85,14 +85,14 @@ buferror(char *buf, size_t buflen)
(LPSTR)buf, buflen, NULL); (LPSTR)buf, buflen, NULL);
return (0); return (0);
#elif defined(_GNU_SOURCE) #elif defined(_GNU_SOURCE)
char *b = strerror_r(errno, buf, buflen); char *b = strerror_r(err, buf, buflen);
if (b != buf) { if (b != buf) {
strncpy(buf, b, buflen); strncpy(buf, b, buflen);
buf[buflen-1] = '\0'; buf[buflen-1] = '\0';
} }
return (0); return (0);
#else #else
return (strerror_r(errno, buf, buflen)); return (strerror_r(err, buf, buflen));
#endif #endif
} }

View File

@ -1,2 +1,177 @@
void test_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2)); #define assert_cmp(t, a, b, cmp, neg_cmp, pri, fmt...) do { \
t a_ = (a); \
t b_ = (b); \
if (!(a_ cmp b_)) { \
p_test_fail( \
"%s:%s:%d: Failed assertion: " \
"(%s) "#cmp" (%s) --> " \
"%"pri" "#neg_cmp" %"pri": ", \
__func__, __FILE__, __LINE__, \
#a, #b, a_, b_, fmt); \
} \
} while (0)
#define assert_ptr_eq(a, b, fmt...) assert_cmp(void *, a, b, ==, \
!=, "p", fmt)
#define assert_ptr_ne(a, b, fmt...) assert_cmp(void *, a, b, !=, \
==, "p", fmt)
#define assert_ptr_null(a, fmt...) assert_cmp(void *, a, NULL, ==, \
!=, "p", fmt)
#define assert_ptr_not_null(a, fmt...) assert_cmp(void *, a, NULL, !=, \
==, "p", fmt)
#define assert_c_eq(a, b, fmt...) assert_cmp(char, a, b, ==, !=, "c", fmt)
#define assert_c_ne(a, b, fmt...) assert_cmp(char, a, b, !=, ==, "c", fmt)
#define assert_c_lt(a, b, fmt...) assert_cmp(char, a, b, <, >=, "c", fmt)
#define assert_c_le(a, b, fmt...) assert_cmp(char, a, b, <=, >, "c", fmt)
#define assert_c_ge(a, b, fmt...) assert_cmp(char, a, b, >=, <, "c", fmt)
#define assert_c_gt(a, b, fmt...) assert_cmp(char, a, b, >, <=, "c", fmt)
#define assert_x_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "#x", fmt)
#define assert_x_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "#x", fmt)
#define assert_x_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "#x", fmt)
#define assert_x_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "#x", fmt)
#define assert_x_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "#x", fmt)
#define assert_x_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "#x", fmt)
#define assert_d_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "d", fmt)
#define assert_d_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "d", fmt)
#define assert_d_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "d", fmt)
#define assert_d_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "d", fmt)
#define assert_d_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "d", fmt)
#define assert_d_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "d", fmt)
#define assert_u_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "u", fmt)
#define assert_u_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "u", fmt)
#define assert_u_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "u", fmt)
#define assert_u_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "u", fmt)
#define assert_u_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "u", fmt)
#define assert_u_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "u", fmt)
#define assert_zd_eq(a, b, fmt...) assert_cmp(ssize_t, a, b, ==, \
!=, "zd", fmt)
#define assert_zd_ne(a, b, fmt...) assert_cmp(ssize_t, a, b, !=, \
==, "zd", fmt)
#define assert_zd_lt(a, b, fmt...) assert_cmp(ssize_t, a, b, <, \
>=, "zd", fmt)
#define assert_zd_le(a, b, fmt...) assert_cmp(ssize_t, a, b, <=, \
>, "zd", fmt)
#define assert_zd_ge(a, b, fmt...) assert_cmp(ssize_t, a, b, >=, \
<, "zd", fmt)
#define assert_zd_gt(a, b, fmt...) assert_cmp(ssize_t, a, b, >, \
<=, "zd", fmt)
#define assert_zu_eq(a, b, fmt...) assert_cmp(size_t, a, b, ==, \
!=, "zu", fmt)
#define assert_zu_ne(a, b, fmt...) assert_cmp(size_t, a, b, !=, \
==, "zu", fmt)
#define assert_zu_lt(a, b, fmt...) assert_cmp(size_t, a, b, <, \
>=, "zu", fmt)
#define assert_zu_le(a, b, fmt...) assert_cmp(size_t, a, b, <=, \
>, "zu", fmt)
#define assert_zu_ge(a, b, fmt...) assert_cmp(size_t, a, b, >=, \
<, "zu", fmt)
#define assert_zu_gt(a, b, fmt...) assert_cmp(size_t, a, b, >, \
<=, "zu", fmt)
#define assert_d64_eq(a, b, fmt...) assert_cmp(int64_t, a, b, ==, \
!=, PRId64, fmt)
#define assert_d64_ne(a, b, fmt...) assert_cmp(int64_t, a, b, !=, \
==, PRId64, fmt)
#define assert_d64_lt(a, b, fmt...) assert_cmp(int64_t, a, b, <, \
>=, PRId64, fmt)
#define assert_d64_le(a, b, fmt...) assert_cmp(int64_t, a, b, <=, \
>, PRId64, fmt)
#define assert_d64_ge(a, b, fmt...) assert_cmp(int64_t, a, b, >=, \
<, PRId64, fmt)
#define assert_d64_gt(a, b, fmt...) assert_cmp(int64_t, a, b, >, \
<=, PRId64, fmt)
#define assert_u64_eq(a, b, fmt...) assert_cmp(uint64_t, a, b, ==, \
!=, PRIu64, fmt)
#define assert_u64_ne(a, b, fmt...) assert_cmp(uint64_t, a, b, !=, \
==, PRIu64, fmt)
#define assert_u64_lt(a, b, fmt...) assert_cmp(uint64_t, a, b, <, \
>=, PRIu64, fmt)
#define assert_u64_le(a, b, fmt...) assert_cmp(uint64_t, a, b, <=, \
>, PRIu64, fmt)
#define assert_u64_ge(a, b, fmt...) assert_cmp(uint64_t, a, b, >=, \
<, PRIu64, fmt)
#define assert_u64_gt(a, b, fmt...) assert_cmp(uint64_t, a, b, >, \
<=, PRIu64, fmt)
#define assert_true(a, fmt...) do { \
bool a_ = (a); \
if (!(a_ == true)) { \
p_test_fail( \
"%s:%s:%d: Failed assertion: " \
"(%s) == true --> %s != true: %s\n", \
__func__, __FILE__, __LINE__, \
#a, a_ ? "true" : "false", fmt); \
} \
} while (0)
#define assert_false(a, fmt...) do { \
bool a_ = (a); \
if (!(a_ == false)) { \
p_test_fail( \
"%s:%s:%d: Failed assertion: " \
"(%s) == false --> %s != false: %s\n", \
__func__, __FILE__, __LINE__, \
#a, a_ ? "true" : "false", fmt); \
} \
} while (0)
#define assert_str_eq(a, b, fmt...) do { \
if (strcmp((a), (b))) { \
p_test_fail( \
"%s:%s:%d: Failed assertion: " \
"(%s) same as (%s) --> " \
"\"%s\" differs from \"%s\": %s\n", \
__func__, __FILE__, __LINE__, #a, #b, a, b, fmt); \
} \
} while (0)
#define assert_str_ne(a, b, fmt...) do { \
if (!strcmp((a), (b))) { \
p_test_fail( \
"%s:%s:%d: Failed assertion: " \
"(%s) differs from (%s) --> " \
"\"%s\" same as \"%s\": %s\n", \
__func__, __FILE__, __LINE__, #a, #b, a, b, fmt); \
} \
} while (0)
/*
* If this enum changes, corresponding changes in test/test.sh.in are also
* necessary.
*/
typedef enum {
test_status_pass = 0,
test_status_skip = 1,
test_status_fail = 2,
test_status_count = 3
} test_status_t;
typedef void (test_t)(void);
#define TEST_BEGIN(f) \
static void \
f(void) \
{ \
p_test_init(#f);
#define TEST_END \
p_test_fini(); \
}
#define test(tests...) \
p_test(tests, NULL)
void test_skip(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2)); void test_skip(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));
void test_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));
/* For private use by macros. */
test_status_t p_test(test_t* t, ...);
void p_test_init(const char *name);
void p_test_fini(void);
void p_test_fail(const char *format, ...);

View File

@ -7,16 +7,12 @@ je_thread_start(void *arg)
{ {
unsigned thread_ind = (unsigned)(uintptr_t)arg; unsigned thread_ind = (unsigned)(uintptr_t)arg;
unsigned arena_ind; unsigned arena_ind;
int r;
void *p; void *p;
size_t rsz, sz; size_t rsz, sz;
sz = sizeof(arena_ind); sz = sizeof(arena_ind);
if (mallctl("arenas.extend", &arena_ind, &sz, NULL, 0) assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
!= 0) { "Error in arenas.extend");
malloc_printf("Error in arenas.extend\n");
abort();
}
if (thread_ind % 4 != 3) { if (thread_ind % 4 != 3) {
size_t mib[3]; size_t mib[3];
@ -24,36 +20,25 @@ je_thread_start(void *arg)
const char *dss_precs[] = {"disabled", "primary", "secondary"}; const char *dss_precs[] = {"disabled", "primary", "secondary"};
const char *dss = dss_precs[thread_ind % const char *dss = dss_precs[thread_ind %
(sizeof(dss_precs)/sizeof(char*))]; (sizeof(dss_precs)/sizeof(char*))];
if (mallctlnametomib("arena.0.dss", mib, &miblen) != 0) { assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0,
malloc_printf("Error in mallctlnametomib()\n"); "Error in mallctlnametomib()");
abort();
}
mib[1] = arena_ind; mib[1] = arena_ind;
if (mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss, assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss,
sizeof(const char *))) { sizeof(const char *)), 0, "Error in mallctlbymib()");
malloc_printf("Error in mallctlbymib()\n");
abort();
}
} }
r = allocm(&p, &rsz, 1, ALLOCM_ARENA(arena_ind)); assert_d_eq(allocm(&p, &rsz, 1, ALLOCM_ARENA(arena_ind)),
if (r != ALLOCM_SUCCESS) { ALLOCM_SUCCESS, "Unexpected allocm() error");
malloc_printf("Unexpected allocm() error\n");
abort();
}
dallocm(p, 0); dallocm(p, 0);
return (NULL); return (NULL);
} }
int TEST_BEGIN(test_ALLOCM_ARENA)
main(void)
{ {
je_thread_t threads[NTHREADS]; je_thread_t threads[NTHREADS];
unsigned i; unsigned i;
malloc_printf("Test begin\n");
for (i = 0; i < NTHREADS; i++) { for (i = 0; i < NTHREADS; i++) {
je_thread_create(&threads[i], je_thread_start, je_thread_create(&threads[i], je_thread_start,
(void *)(uintptr_t)i); (void *)(uintptr_t)i);
@ -61,7 +46,13 @@ main(void)
for (i = 0; i < NTHREADS; i++) for (i = 0; i < NTHREADS; i++)
je_thread_join(threads[i], NULL); je_thread_join(threads[i], NULL);
}
malloc_printf("Test end\n"); TEST_END
return (0);
int
main(void)
{
return (test(
test_ALLOCM_ARENA));
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -5,34 +5,32 @@
#define MAXALIGN ((size_t)0x2000000LU) #define MAXALIGN ((size_t)0x2000000LU)
#define NITER 4 #define NITER 4
int TEST_BEGIN(test_alignment_errors)
main(void)
{ {
size_t alignment, size, total; size_t alignment;
unsigned i; void *p;
void *p, *ps[NITER];
malloc_printf("Test begin\n");
/* Test error conditions. */
alignment = 0; alignment = 0;
set_errno(0); set_errno(0);
p = aligned_alloc(alignment, 1); p = aligned_alloc(alignment, 1);
if (p != NULL || get_errno() != EINVAL) { assert_false(p != NULL || get_errno() != EINVAL,
malloc_printf( "Expected error for invalid alignment %zu", alignment);
"Expected error for invalid alignment %zu\n", alignment);
}
for (alignment = sizeof(size_t); alignment < MAXALIGN; for (alignment = sizeof(size_t); alignment < MAXALIGN;
alignment <<= 1) { alignment <<= 1) {
set_errno(0); set_errno(0);
p = aligned_alloc(alignment + 1, 1); p = aligned_alloc(alignment + 1, 1);
if (p != NULL || get_errno() != EINVAL) { assert_false(p != NULL || get_errno() != EINVAL,
malloc_printf( "Expected error for invalid alignment %zu",
"Expected error for invalid alignment %zu\n",
alignment + 1); alignment + 1);
} }
} }
TEST_END
TEST_BEGIN(test_oom_errors)
{
size_t alignment, size;
void *p;
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = UINT64_C(0x8000000000000000); alignment = UINT64_C(0x8000000000000000);
@ -43,11 +41,9 @@ main(void)
#endif #endif
set_errno(0); set_errno(0);
p = aligned_alloc(alignment, size); p = aligned_alloc(alignment, size);
if (p != NULL || get_errno() != ENOMEM) { assert_false(p != NULL || get_errno() != ENOMEM,
malloc_printf( "Expected error for aligned_alloc(%zu, %zu)",
"Expected error for aligned_alloc(%zu, %zu)\n",
alignment, size); alignment, size);
}
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = UINT64_C(0x4000000000000000); alignment = UINT64_C(0x4000000000000000);
@ -58,11 +54,9 @@ main(void)
#endif #endif
set_errno(0); set_errno(0);
p = aligned_alloc(alignment, size); p = aligned_alloc(alignment, size);
if (p != NULL || get_errno() != ENOMEM) { assert_false(p != NULL || get_errno() != ENOMEM,
malloc_printf( "Expected error for aligned_alloc(%zu, %zu)",
"Expected error for aligned_alloc(%zu, %zu)\n",
alignment, size); alignment, size);
}
alignment = 0x10LU; alignment = 0x10LU;
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
@ -72,11 +66,17 @@ main(void)
#endif #endif
set_errno(0); set_errno(0);
p = aligned_alloc(alignment, size); p = aligned_alloc(alignment, size);
if (p != NULL || get_errno() != ENOMEM) { assert_false(p != NULL || get_errno() != ENOMEM,
malloc_printf( "Expected error for aligned_alloc(&p, %zu, %zu)",
"Expected error for aligned_alloc(&p, %zu, %zu)\n",
alignment, size); alignment, size);
} }
TEST_END
TEST_BEGIN(test_alignment_and_size)
{
size_t alignment, size, total;
unsigned i;
void *ps[NITER];
for (i = 0; i < NITER; i++) for (i = 0; i < NITER; i++)
ps[i] = NULL; ps[i] = NULL;
@ -85,7 +85,6 @@ main(void)
alignment <= MAXALIGN; alignment <= MAXALIGN;
alignment <<= 1) { alignment <<= 1) {
total = 0; total = 0;
malloc_printf("Alignment: %zu\n", alignment);
for (size = 1; for (size = 1;
size < 3 * alignment && size < (1U << 31); size < 3 * alignment && size < (1U << 31);
size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
@ -94,10 +93,11 @@ main(void)
if (ps[i] == NULL) { if (ps[i] == NULL) {
char buf[BUFERROR_BUF]; char buf[BUFERROR_BUF];
buferror(buf, sizeof(buf)); buferror(get_errno(), buf, sizeof(buf));
test_fail( test_fail(
"Error for size %zu (%#zx): %s\n", "Error for alignment=%zu, "
size, size, buf); "size=%zu (%#zx): %s",
alignment, size, size, buf);
} }
total += malloc_usable_size(ps[i]); total += malloc_usable_size(ps[i]);
if (total >= (MAXALIGN << 1)) if (total >= (MAXALIGN << 1))
@ -111,7 +111,15 @@ main(void)
} }
} }
} }
}
malloc_printf("Test end\n"); TEST_END
return (0);
int
main(void)
{
return (test(
test_alignment_errors,
test_oom_errors,
test_alignment_and_size));
} }

View File

@ -1,25 +0,0 @@
Test begin
Alignment: 8
Alignment: 16
Alignment: 32
Alignment: 64
Alignment: 128
Alignment: 256
Alignment: 512
Alignment: 1024
Alignment: 2048
Alignment: 4096
Alignment: 8192
Alignment: 16384
Alignment: 32768
Alignment: 65536
Alignment: 131072
Alignment: 262144
Alignment: 524288
Alignment: 1048576
Alignment: 2097152
Alignment: 4194304
Alignment: 8388608
Alignment: 16777216
Alignment: 33554432
Test end

View File

@ -1,5 +1,13 @@
#include "test/jemalloc_test.h" #include "test/jemalloc_test.h"
static const bool config_stats =
#ifdef JEMALLOC_STATS
true
#else
false
#endif
;
void * void *
je_thread_start(void *arg) je_thread_start(void *arg)
{ {
@ -11,65 +19,57 @@ je_thread_start(void *arg)
sz = sizeof(a0); sz = sizeof(a0);
if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) { if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) {
if (err == ENOENT) { if (err == ENOENT)
#ifdef JEMALLOC_STATS goto label_ENOENT;
assert(false); test_fail("%s(): Error in mallctl(): %s", __func__,
#endif
goto label_return;
}
test_fail("%s(): Error in mallctl(): %s\n", __func__,
strerror(err)); strerror(err));
} }
sz = sizeof(ap0); sz = sizeof(ap0);
if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) { if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) {
if (err == ENOENT) { if (err == ENOENT)
#ifdef JEMALLOC_STATS goto label_ENOENT;
assert(false); test_fail("%s(): Error in mallctl(): %s", __func__,
#endif
goto label_return;
}
test_fail("%s(): Error in mallctl(): %s\n", __func__,
strerror(err)); strerror(err));
} }
assert(*ap0 == a0); assert_u64_eq(*ap0, a0,
"\"thread.allocatedp\" should provide a pointer to internal "
"storage");
sz = sizeof(d0); sz = sizeof(d0);
if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) { if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) {
if (err == ENOENT) { if (err == ENOENT)
#ifdef JEMALLOC_STATS goto label_ENOENT;
assert(false); test_fail("%s(): Error in mallctl(): %s", __func__,
#endif
goto label_return;
}
test_fail("%s(): Error in mallctl(): %s\n", __func__,
strerror(err)); strerror(err));
} }
sz = sizeof(dp0); sz = sizeof(dp0);
if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) { if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) {
if (err == ENOENT) { if (err == ENOENT)
#ifdef JEMALLOC_STATS goto label_ENOENT;
assert(false); test_fail("%s(): Error in mallctl(): %s", __func__,
#endif
goto label_return;
}
test_fail("%s(): Error in mallctl(): %s\n", __func__,
strerror(err)); strerror(err));
} }
assert(*dp0 == d0); assert_u64_eq(*dp0, d0,
"\"thread.deallocatedp\" should provide a pointer to internal "
"storage");
p = malloc(1); p = malloc(1);
if (p == NULL) assert_ptr_not_null(p, "Unexpected malloc() error");
test_fail("%s(): Error in malloc()\n", __func__);
sz = sizeof(a1); sz = sizeof(a1);
mallctl("thread.allocated", &a1, &sz, NULL, 0); mallctl("thread.allocated", &a1, &sz, NULL, 0);
sz = sizeof(ap1); sz = sizeof(ap1);
mallctl("thread.allocatedp", &ap1, &sz, NULL, 0); mallctl("thread.allocatedp", &ap1, &sz, NULL, 0);
assert(*ap1 == a1); assert_u64_eq(*ap1, a1,
assert(ap0 == ap1); "Dereferenced \"thread.allocatedp\" value should equal "
"\"thread.allocated\" value");
assert_ptr_eq(ap0, ap1,
"Pointer returned by \"thread.allocatedp\" should not change");
usize = malloc_usable_size(p); usize = malloc_usable_size(p);
assert(a0 + usize <= a1); assert_u64_le(a0 + usize, a1,
"Allocated memory counter should increase by at least the amount "
"explicitly allocated");
free(p); free(p);
@ -77,35 +77,49 @@ je_thread_start(void *arg)
mallctl("thread.deallocated", &d1, &sz, NULL, 0); mallctl("thread.deallocated", &d1, &sz, NULL, 0);
sz = sizeof(dp1); sz = sizeof(dp1);
mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0); mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0);
assert(*dp1 == d1); assert_u64_eq(*dp1, d1,
assert(dp0 == dp1); "Dereferenced \"thread.deallocatedp\" value should equal "
"\"thread.deallocated\" value");
assert_ptr_eq(dp0, dp1,
"Pointer returned by \"thread.deallocatedp\" should not change");
assert(d0 + usize <= d1); assert_u64_le(d0 + usize, d1,
"Deallocated memory counter should increase by at least the amount "
"explicitly deallocated");
label_return: return (NULL);
label_ENOENT:
assert_false(config_stats,
"ENOENT should only be returned if stats are disabled");
test_skip("\"thread.allocated\" mallctl not available");
return (NULL); return (NULL);
} }
TEST_BEGIN(test_main_thread)
{
je_thread_start(NULL);
}
TEST_END
TEST_BEGIN(test_subthread)
{
je_thread_t thread;
je_thread_create(&thread, je_thread_start, NULL);
je_thread_join(thread, NULL);
}
TEST_END
int int
main(void) main(void)
{ {
int ret = 0;
je_thread_t thread;
malloc_printf("Test begin\n"); /* Run tests multiple times to check for bad interactions. */
return (test(
je_thread_start(NULL); test_main_thread,
test_subthread,
je_thread_create(&thread, je_thread_start, NULL); test_main_thread,
je_thread_join(thread, NULL); test_subthread,
test_main_thread));
je_thread_start(NULL);
je_thread_create(&thread, je_thread_start, NULL);
je_thread_join(thread, NULL);
je_thread_start(NULL);
malloc_printf("Test end\n");
return (ret);
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -5,61 +5,44 @@
#define MAXALIGN ((size_t)0x2000000LU) #define MAXALIGN ((size_t)0x2000000LU)
#define NITER 4 #define NITER 4
int TEST_BEGIN(test_basic)
main(void)
{ {
int r; size_t nsz, rsz, sz;
void *p; void *p;
size_t nsz, rsz, sz, alignment, total;
unsigned i;
void *ps[NITER];
malloc_printf("Test begin\n");
sz = 42; sz = 42;
nsz = 0; nsz = 0;
r = nallocm(&nsz, sz, 0); assert_d_eq(nallocm(&nsz, sz, 0), ALLOCM_SUCCESS,
if (r != ALLOCM_SUCCESS) { "Unexpected nallocm() error");
malloc_printf("Unexpected nallocm() error\n");
abort();
}
rsz = 0; rsz = 0;
r = allocm(&p, &rsz, sz, 0); assert_d_eq(allocm(&p, &rsz, sz, 0), ALLOCM_SUCCESS,
if (r != ALLOCM_SUCCESS) { "Unexpected allocm() error");
malloc_printf("Unexpected allocm() error\n"); assert_zu_ge(rsz, sz, "Real size smaller than expected");
abort(); assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch");
} assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
if (rsz < sz) "Unexpected dallocm() error");
malloc_printf("Real size smaller than expected\n");
if (nsz != rsz)
malloc_printf("nallocm()/allocm() rsize mismatch\n");
if (dallocm(p, 0) != ALLOCM_SUCCESS)
malloc_printf("Unexpected dallocm() error\n");
r = allocm(&p, NULL, sz, 0); assert_d_eq(allocm(&p, NULL, sz, 0), ALLOCM_SUCCESS,
if (r != ALLOCM_SUCCESS) { "Unexpected allocm() error");
malloc_printf("Unexpected allocm() error\n"); assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
abort(); "Unexpected dallocm() error");
}
if (dallocm(p, 0) != ALLOCM_SUCCESS)
malloc_printf("Unexpected dallocm() error\n");
nsz = 0; nsz = 0;
r = nallocm(&nsz, sz, ALLOCM_ZERO); assert_d_eq(nallocm(&nsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS,
if (r != ALLOCM_SUCCESS) { "Unexpected nallocm() error");
malloc_printf("Unexpected nallocm() error\n");
abort();
}
rsz = 0; rsz = 0;
r = allocm(&p, &rsz, sz, ALLOCM_ZERO); assert_d_eq(allocm(&p, &rsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS,
if (r != ALLOCM_SUCCESS) { "Unexpected allocm() error");
malloc_printf("Unexpected allocm() error\n"); assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch");
abort(); assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
} "Unexpected dallocm() error");
if (nsz != rsz) }
malloc_printf("nallocm()/allocm() rsize mismatch\n"); TEST_END
if (dallocm(p, 0) != ALLOCM_SUCCESS)
malloc_printf("Unexpected dallocm() error\n"); TEST_BEGIN(test_alignment_errors)
{
void *p;
size_t nsz, rsz, sz, alignment;
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = UINT64_C(0x8000000000000000); alignment = UINT64_C(0x8000000000000000);
@ -69,21 +52,14 @@ main(void)
sz = 0x80000000LU; sz = 0x80000000LU;
#endif #endif
nsz = 0; nsz = 0;
r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)); assert_d_ne(nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)), ALLOCM_SUCCESS,
if (r == ALLOCM_SUCCESS) { "Expected error for nallocm(&nsz, %zu, %#x)",
malloc_printf(
"Expected error for nallocm(&nsz, %zu, %#x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
}
rsz = 0; rsz = 0;
r = allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)); assert_d_ne(allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)),
if (r == ALLOCM_SUCCESS) { ALLOCM_SUCCESS, "Expected error for allocm(&p, %zu, %#x)",
malloc_printf(
"Expected error for allocm(&p, %zu, %#x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
} assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch");
if (nsz != rsz)
malloc_printf("nallocm()/allocm() rsize mismatch\n");
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = UINT64_C(0x4000000000000000); alignment = UINT64_C(0x4000000000000000);
@ -93,16 +69,12 @@ main(void)
sz = 0x84000001LU; sz = 0x84000001LU;
#endif #endif
nsz = 0; nsz = 0;
r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)); assert_d_eq(nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)), ALLOCM_SUCCESS,
if (r != ALLOCM_SUCCESS) "Unexpected nallocm() error");
malloc_printf("Unexpected nallocm() error\n");
rsz = 0; rsz = 0;
r = allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)); assert_d_ne(allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)),
if (r == ALLOCM_SUCCESS) { ALLOCM_SUCCESS, "Expected error for allocm(&p, %zu, %#x)",
malloc_printf(
"Expected error for allocm(&p, %zu, %#x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
}
alignment = 0x10LU; alignment = 0x10LU;
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
@ -111,21 +83,23 @@ main(void)
sz = 0xfffffff0LU; sz = 0xfffffff0LU;
#endif #endif
nsz = 0; nsz = 0;
r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)); assert_d_ne(nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)), ALLOCM_SUCCESS,
if (r == ALLOCM_SUCCESS) { "Expected error for nallocm(&nsz, %zu, %#x)",
malloc_printf(
"Expected error for nallocm(&nsz, %zu, %#x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
}
rsz = 0; rsz = 0;
r = allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)); assert_d_ne(allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)),
if (r == ALLOCM_SUCCESS) { ALLOCM_SUCCESS, "Expected error for allocm(&p, %zu, %#x)",
malloc_printf(
"Expected error for allocm(&p, %zu, %#x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
} assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch");
if (nsz != rsz) }
malloc_printf("nallocm()/allocm() rsize mismatch\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++) for (i = 0; i < NITER; i++)
ps[i] = NULL; ps[i] = NULL;
@ -134,44 +108,35 @@ main(void)
alignment <= MAXALIGN; alignment <= MAXALIGN;
alignment <<= 1) { alignment <<= 1) {
total = 0; total = 0;
malloc_printf("Alignment: %zu\n", alignment);
for (sz = 1; for (sz = 1;
sz < 3 * alignment && sz < (1U << 31); sz < 3 * alignment && sz < (1U << 31);
sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
for (i = 0; i < NITER; i++) { for (i = 0; i < NITER; i++) {
nsz = 0; nsz = 0;
r = nallocm(&nsz, sz, r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment) |
ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); ALLOCM_ZERO);
if (r != ALLOCM_SUCCESS) { assert_d_eq(r, ALLOCM_SUCCESS,
test_fail( "nallocm() error for alignment=%zu, "
"nallocm() error for size %zu" "size=%zu (%#zx): %d",
" (%#zx): %d\n", alignment, sz, sz, r);
sz, sz, r);
}
rsz = 0; rsz = 0;
r = allocm(&ps[i], &rsz, sz, r = allocm(&ps[i], &rsz, sz,
ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); ALLOCM_ALIGN(alignment) | ALLOCM_ZERO);
if (r != ALLOCM_SUCCESS) { assert_d_eq(r, ALLOCM_SUCCESS,
test_fail( "allocm() error for alignment=%zu, "
"allocm() error for size %zu" "size=%zu (%#zx): %d",
" (%#zx): %d\n", alignment, sz, sz, r);
sz, sz, r); assert_zu_ge(rsz, sz,
} "Real size smaller than expected for "
if (rsz < sz) { "alignment=%zu, size=%zu", alignment, sz);
malloc_printf( assert_zu_eq(nsz, rsz,
"Real size smaller than" "nallocm()/allocm() rsize mismatch for "
" expected\n"); "alignment=%zu, size=%zu", alignment, sz);
} assert_ptr_null(
if (nsz != rsz) { (void *)((uintptr_t)ps[i] & (alignment-1)),
malloc_printf(
"nallocm()/allocm() rsize"
" mismatch\n");
}
if ((uintptr_t)p & (alignment-1)) {
malloc_printf(
"%p inadequately aligned for" "%p inadequately aligned for"
" alignment: %zu\n", p, alignment); " alignment=%zu, size=%zu", ps[i],
} alignment, sz);
sallocm(ps[i], &rsz, 0); sallocm(ps[i], &rsz, 0);
total += rsz; total += rsz;
if (total >= (MAXALIGN << 1)) if (total >= (MAXALIGN << 1))
@ -185,7 +150,15 @@ main(void)
} }
} }
} }
}
malloc_printf("Test end\n"); TEST_END
return (0);
int
main(void)
{
return (test(
test_basic,
test_alignment_errors,
test_alignment_and_size));
} }

View File

@ -1,25 +0,0 @@
Test begin
Alignment: 8
Alignment: 16
Alignment: 32
Alignment: 64
Alignment: 128
Alignment: 256
Alignment: 512
Alignment: 1024
Alignment: 2048
Alignment: 4096
Alignment: 8192
Alignment: 16384
Alignment: 32768
Alignment: 65536
Alignment: 131072
Alignment: 262144
Alignment: 524288
Alignment: 1048576
Alignment: 2097152
Alignment: 4194304
Alignment: 8388608
Alignment: 16777216
Alignment: 33554432
Test end

View File

@ -1,59 +1,45 @@
#include "test/jemalloc_test.h" #include "test/jemalloc_test.h"
int TEST_BEGIN(test_mremap)
main(void)
{ {
int ret, err; int err;
size_t sz, lg_chunk, chunksize, i; size_t sz, lg_chunk, chunksize, i;
char *p, *q; char *p, *q;
malloc_printf("Test begin\n");
sz = sizeof(lg_chunk); sz = sizeof(lg_chunk);
if ((err = mallctl("opt.lg_chunk", &lg_chunk, &sz, NULL, 0))) { err = mallctl("opt.lg_chunk", &lg_chunk, &sz, NULL, 0);
assert(err != ENOENT); assert_d_eq(err, 0, "Error in mallctl(): %s", strerror(err));
malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
strerror(err));
ret = 1;
goto label_return;
}
chunksize = ((size_t)1U) << lg_chunk; chunksize = ((size_t)1U) << lg_chunk;
p = (char *)malloc(chunksize); p = (char *)malloc(chunksize);
if (p == NULL) { assert_ptr_not_null(p, "malloc(%zu) --> %p", chunksize, p);
malloc_printf("malloc(%zu) --> %p\n", chunksize, p);
ret = 1;
goto label_return;
}
memset(p, 'a', chunksize); memset(p, 'a', chunksize);
q = (char *)realloc(p, chunksize * 2); q = (char *)realloc(p, chunksize * 2);
if (q == NULL) { assert_ptr_not_null(q, "realloc(%p, %zu) --> %p", p, chunksize * 2,
malloc_printf("realloc(%p, %zu) --> %p\n", p, chunksize * 2,
q); q);
ret = 1;
goto label_return;
}
for (i = 0; i < chunksize; i++) { for (i = 0; i < chunksize; i++) {
assert(q[i] == 'a'); assert_c_eq(q[i], 'a',
"realloc() should preserve existing bytes across copies");
} }
p = q; p = q;
q = (char *)realloc(p, chunksize); q = (char *)realloc(p, chunksize);
if (q == NULL) { assert_ptr_not_null(q, "realloc(%p, %zu) --> %p", p, chunksize, q);
malloc_printf("realloc(%p, %zu) --> %p\n", p, chunksize, q);
ret = 1;
goto label_return;
}
for (i = 0; i < chunksize; i++) { for (i = 0; i < chunksize; i++) {
assert(q[i] == 'a'); assert_c_eq(q[i], 'a',
"realloc() should preserve existing bytes across copies");
} }
free(q); free(q);
}
ret = 0; TEST_END
label_return:
malloc_printf("Test end\n"); int
return (ret); main(void)
{
return (test(
test_mremap));
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -5,35 +5,30 @@
#define MAXALIGN ((size_t)0x2000000LU) #define MAXALIGN ((size_t)0x2000000LU)
#define NITER 4 #define NITER 4
int TEST_BEGIN(test_alignment_errors)
main(void)
{ {
size_t alignment, size, total; size_t alignment;
unsigned i; void *p;
int err;
void *p, *ps[NITER];
malloc_printf("Test begin\n");
/* Test error conditions. */
for (alignment = 0; alignment < sizeof(void *); alignment++) { for (alignment = 0; alignment < sizeof(void *); alignment++) {
err = posix_memalign(&p, alignment, 1); assert_d_eq(posix_memalign(&p, alignment, 1), EINVAL,
if (err != EINVAL) { "Expected error for invalid alignment %zu",
malloc_printf(
"Expected error for invalid alignment %zu\n",
alignment); alignment);
} }
}
for (alignment = sizeof(size_t); alignment < MAXALIGN; for (alignment = sizeof(size_t); alignment < MAXALIGN;
alignment <<= 1) { alignment <<= 1) {
err = posix_memalign(&p, alignment + 1, 1); assert_d_ne(posix_memalign(&p, alignment + 1, 1), 0,
if (err == 0) { "Expected error for invalid alignment %zu",
malloc_printf(
"Expected error for invalid alignment %zu\n",
alignment + 1); alignment + 1);
} }
} }
TEST_END
TEST_BEGIN(test_oom_errors)
{
size_t alignment, size;
void *p;
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = UINT64_C(0x8000000000000000); alignment = UINT64_C(0x8000000000000000);
@ -42,12 +37,9 @@ main(void)
alignment = 0x80000000LU; alignment = 0x80000000LU;
size = 0x80000000LU; size = 0x80000000LU;
#endif #endif
err = posix_memalign(&p, alignment, size); assert_d_ne(posix_memalign(&p, alignment, size), 0,
if (err == 0) { "Expected error for posix_memalign(&p, %zu, %zu)",
malloc_printf(
"Expected error for posix_memalign(&p, %zu, %zu)\n",
alignment, size); alignment, size);
}
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = UINT64_C(0x4000000000000000); alignment = UINT64_C(0x4000000000000000);
@ -56,12 +48,9 @@ main(void)
alignment = 0x40000000LU; alignment = 0x40000000LU;
size = 0x84000001LU; size = 0x84000001LU;
#endif #endif
err = posix_memalign(&p, alignment, size); assert_d_ne(posix_memalign(&p, alignment, size), 0,
if (err == 0) { "Expected error for posix_memalign(&p, %zu, %zu)",
malloc_printf(
"Expected error for posix_memalign(&p, %zu, %zu)\n",
alignment, size); alignment, size);
}
alignment = 0x10LU; alignment = 0x10LU;
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
@ -69,12 +58,18 @@ main(void)
#else #else
size = 0xfffffff0LU; size = 0xfffffff0LU;
#endif #endif
err = posix_memalign(&p, alignment, size); assert_d_ne(posix_memalign(&p, alignment, size), 0,
if (err == 0) { "Expected error for posix_memalign(&p, %zu, %zu)",
malloc_printf(
"Expected error for posix_memalign(&p, %zu, %zu)\n",
alignment, size); alignment, size);
} }
TEST_END
TEST_BEGIN(test_alignment_and_size)
{
size_t alignment, size, total;
unsigned i;
int err;
void *ps[NITER];
for (i = 0; i < NITER; i++) for (i = 0; i < NITER; i++)
ps[i] = NULL; ps[i] = NULL;
@ -83,7 +78,6 @@ main(void)
alignment <= MAXALIGN; alignment <= MAXALIGN;
alignment <<= 1) { alignment <<= 1) {
total = 0; total = 0;
malloc_printf("Alignment: %zu\n", alignment);
for (size = 1; for (size = 1;
size < 3 * alignment && size < (1U << 31); size < 3 * alignment && size < (1U << 31);
size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
@ -91,9 +85,13 @@ main(void)
err = posix_memalign(&ps[i], err = posix_memalign(&ps[i],
alignment, size); alignment, size);
if (err) { if (err) {
char buf[BUFERROR_BUF];
buferror(get_errno(), buf, sizeof(buf));
test_fail( test_fail(
"Error for size %zu (%#zx): %s\n", "Error for alignment=%zu, "
size, size, strerror(err)); "size=%zu (%#zx): %s",
alignment, size, size, buf);
} }
total += malloc_usable_size(ps[i]); total += malloc_usable_size(ps[i]);
if (total >= (MAXALIGN << 1)) if (total >= (MAXALIGN << 1))
@ -107,7 +105,15 @@ main(void)
} }
} }
} }
}
malloc_printf("Test end\n"); TEST_END
return (0);
int
main(void)
{
return (test(
test_alignment_errors,
test_oom_errors,
test_alignment_and_size));
} }

View File

@ -1,25 +0,0 @@
Test begin
Alignment: 8
Alignment: 16
Alignment: 32
Alignment: 64
Alignment: 128
Alignment: 256
Alignment: 512
Alignment: 1024
Alignment: 2048
Alignment: 4096
Alignment: 8192
Alignment: 16384
Alignment: 32768
Alignment: 65536
Alignment: 131072
Alignment: 262144
Alignment: 524288
Alignment: 1048576
Alignment: 2097152
Alignment: 4194304
Alignment: 8388608
Alignment: 16777216
Alignment: 33554432
Test end

View File

@ -2,127 +2,112 @@
#include "test/jemalloc_test.h" #include "test/jemalloc_test.h"
TEST_BEGIN(test_same_size)
{
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, 0, ALLOCM_NO_MOVE), ALLOCM_SUCCESS,
"Unexpected rallocm() error");
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_extra_no_move)
{
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, sz-42, ALLOCM_NO_MOVE),
ALLOCM_SUCCESS, "Unexpected rallocm() error");
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_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
int int
main(void) main(void)
{ {
size_t pagesize;
void *p, *q;
size_t sz, tsz;
int r;
malloc_printf("Test begin\n"); return (test(
test_same_size,
/* Get page size. */ test_extra_no_move,
{ test_no_move_fail,
#ifdef _WIN32 test_grow_and_shrink));
SYSTEM_INFO si;
GetSystemInfo(&si);
pagesize = (size_t)si.dwPageSize;
#else
long result = sysconf(_SC_PAGESIZE);
assert(result != -1);
pagesize = (size_t)result;
#endif
}
r = allocm(&p, &sz, 42, 0);
if (r != ALLOCM_SUCCESS) {
malloc_printf("Unexpected allocm() error\n");
abort();
}
q = p;
r = rallocm(&q, &tsz, sz, 0, ALLOCM_NO_MOVE);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (q != p)
malloc_printf("Unexpected object move\n");
if (tsz != sz) {
malloc_printf("Unexpected size change: %zu --> %zu\n",
sz, tsz);
}
q = p;
r = rallocm(&q, &tsz, sz, 5, ALLOCM_NO_MOVE);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (q != p)
malloc_printf("Unexpected object move\n");
if (tsz != sz) {
malloc_printf("Unexpected size change: %zu --> %zu\n",
sz, tsz);
}
q = p;
r = rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE);
if (r != ALLOCM_ERR_NOT_MOVED)
malloc_printf("Unexpected rallocm() result\n");
if (q != p)
malloc_printf("Unexpected object move\n");
if (tsz != sz) {
malloc_printf("Unexpected size change: %zu --> %zu\n",
sz, tsz);
}
q = p;
r = rallocm(&q, &tsz, sz + 5, 0, 0);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (q == p)
malloc_printf("Expected object move\n");
if (tsz == sz) {
malloc_printf("Expected size change: %zu --> %zu\n",
sz, tsz);
}
p = q;
sz = tsz;
r = rallocm(&q, &tsz, pagesize*2, 0, 0);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (q == p)
malloc_printf("Expected object move\n");
if (tsz == sz) {
malloc_printf("Expected size change: %zu --> %zu\n",
sz, tsz);
}
p = q;
sz = tsz;
r = rallocm(&q, &tsz, pagesize*4, 0, 0);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (tsz == sz) {
malloc_printf("Expected size change: %zu --> %zu\n",
sz, tsz);
}
p = q;
sz = tsz;
r = rallocm(&q, &tsz, pagesize*2, 0, ALLOCM_NO_MOVE);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (q != p)
malloc_printf("Unexpected object move\n");
if (tsz == sz) {
malloc_printf("Expected size change: %zu --> %zu\n",
sz, tsz);
}
sz = tsz;
r = rallocm(&q, &tsz, pagesize*4, 0, ALLOCM_NO_MOVE);
if (r != ALLOCM_SUCCESS)
malloc_printf("Unexpected rallocm() error\n");
if (q != p)
malloc_printf("Unexpected object move\n");
if (tsz == sz) {
malloc_printf("Expected size change: %zu --> %zu\n",
sz, tsz);
}
sz = tsz;
dallocm(p, 0);
malloc_printf("Test end\n");
return (0);
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -12,36 +12,33 @@ je_thread_start(void *arg)
int err; int err;
p = malloc(1); p = malloc(1);
if (p == NULL) { assert_ptr_not_null(p, "Error in malloc()");
malloc_printf("%s(): Error in malloc()\n", __func__);
return (void *)1;
}
free(p); free(p);
size = sizeof(arena_ind); size = sizeof(arena_ind);
if ((err = mallctl("thread.arena", &arena_ind, &size, &main_arena_ind, if ((err = mallctl("thread.arena", &arena_ind, &size, &main_arena_ind,
sizeof(main_arena_ind)))) { sizeof(main_arena_ind)))) {
malloc_printf("%s(): Error in mallctl(): %s\n", __func__, char buf[BUFERROR_BUF];
strerror(err));
return (void *)1; buferror(err, buf, sizeof(buf));
test_fail("Error in mallctl(): %s", buf);
} }
size = sizeof(arena_ind); size = sizeof(arena_ind);
if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) {
0))) { char buf[BUFERROR_BUF];
malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
strerror(err)); buferror(err, buf, sizeof(buf));
return (void *)1; test_fail("Error in mallctl(): %s", buf);
} }
assert(arena_ind == main_arena_ind); assert_u_eq(arena_ind, main_arena_ind,
"Arena index should be same as for main thread");
return (NULL); return (NULL);
} }
int TEST_BEGIN(test_thread_arena)
main(void)
{ {
int ret = 0;
void *p; void *p;
unsigned arena_ind; unsigned arena_ind;
size_t size; size_t size;
@ -49,21 +46,15 @@ main(void)
je_thread_t threads[NTHREADS]; je_thread_t threads[NTHREADS];
unsigned i; unsigned i;
malloc_printf("Test begin\n");
p = malloc(1); p = malloc(1);
if (p == NULL) { assert_ptr_not_null(p, "Error in malloc()");
malloc_printf("%s(): Error in malloc()\n", __func__);
ret = 1;
goto label_return;
}
size = sizeof(arena_ind); size = sizeof(arena_ind);
if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) { if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) {
malloc_printf("%s(): Error in mallctl(): %s\n", __func__, char buf[BUFERROR_BUF];
strerror(err));
ret = 1; buferror(err, buf, sizeof(buf));
goto label_return; test_fail("Error in mallctl(): %s", buf);
} }
for (i = 0; i < NTHREADS; i++) { for (i = 0; i < NTHREADS; i++) {
@ -74,11 +65,15 @@ main(void)
for (i = 0; i < NTHREADS; i++) { for (i = 0; i < NTHREADS; i++) {
intptr_t join_ret; intptr_t join_ret;
je_thread_join(threads[i], (void *)&join_ret); je_thread_join(threads[i], (void *)&join_ret);
if (join_ret != 0) assert_zd_eq(join_ret, 0, "Unexpected thread join error");
ret = 1;
} }
}
label_return: TEST_END
malloc_printf("Test end\n");
return (ret); int
main(void)
{
return (test(
test_thread_arena));
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -1,5 +1,13 @@
#include "test/jemalloc_test.h" #include "test/jemalloc_test.h"
static const bool config_tcache =
#ifdef JEMALLOC_TCACHE
true
#else
false
#endif
;
void * void *
je_thread_start(void *arg) je_thread_start(void *arg)
{ {
@ -10,81 +18,96 @@ je_thread_start(void *arg)
sz = sizeof(bool); sz = sizeof(bool);
if ((err = mallctl("thread.tcache.enabled", &e0, &sz, NULL, 0))) { if ((err = mallctl("thread.tcache.enabled", &e0, &sz, NULL, 0))) {
if (err == ENOENT) { if (err == ENOENT) {
#ifdef JEMALLOC_TCACHE assert_false(config_tcache,
assert(false); "ENOENT should only be returned if tcache is "
#endif "disabled");
} }
goto label_return; goto label_ENOENT;
} }
if (e0) { if (e0) {
e1 = false; e1 = false;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz),
== 0); 0, "Unexpected mallctl() error");
assert(e0); assert_true(e0, "tcache should be enabled");
} }
e1 = true; e1 = true;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0 == false); "Unexpected mallctl() error");
assert_false(e0, "tcache should be disabled");
e1 = true; e1 = true;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0); "Unexpected mallctl() error");
assert_true(e0, "tcache should be enabled");
e1 = false; e1 = false;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0); "Unexpected mallctl() error");
assert_true(e0, "tcache should be enabled");
e1 = false; e1 = false;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0 == false); "Unexpected mallctl() error");
assert_false(e0, "tcache should be disabled");
free(malloc(1)); free(malloc(1));
e1 = true; e1 = true;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0 == false); "Unexpected mallctl() error");
assert_false(e0, "tcache should be disabled");
free(malloc(1)); free(malloc(1));
e1 = true; e1 = true;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0); "Unexpected mallctl() error");
assert_true(e0, "tcache should be enabled");
free(malloc(1)); free(malloc(1));
e1 = false; e1 = false;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0); "Unexpected mallctl() error");
assert_true(e0, "tcache should be enabled");
free(malloc(1)); free(malloc(1));
e1 = false; e1 = false;
assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0); assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
assert(e0 == false); "Unexpected mallctl() error");
assert_false(e0, "tcache should be disabled");
free(malloc(1)); free(malloc(1));
label_return: return (NULL);
label_ENOENT:
test_skip("\"thread.tcache.enabled\" mallctl not available");
return (NULL); return (NULL);
} }
TEST_BEGIN(test_main_thread)
{
je_thread_start(NULL);
}
TEST_END
TEST_BEGIN(test_subthread)
{
je_thread_t thread;
je_thread_create(&thread, je_thread_start, NULL);
je_thread_join(thread, NULL);
}
TEST_END
int int
main(void) main(void)
{ {
int ret = 0;
je_thread_t thread;
malloc_printf("Test begin\n"); /* Run tests multiple times to check for bad interactions. */
return (test(
je_thread_start(NULL); test_main_thread,
test_subthread,
je_thread_create(&thread, je_thread_start, NULL); test_main_thread,
je_thread_join(thread, NULL); test_subthread,
test_main_thread));
je_thread_start(NULL);
je_thread_create(&thread, je_thread_start, NULL);
je_thread_join(thread, NULL);
je_thread_start(NULL);
malloc_printf("Test end\n");
return (ret);
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -1,19 +1,9 @@
#include "test/jemalloc_test.h" #include "test/jemalloc_test.h"
#define JEMALLOC_TEST_EXIT_FAIL 1 static unsigned test_count = 0;
#define JEMALLOC_TEST_EXIT_SKIP 2 static test_status_t test_counts[test_status_count] = {0, 0, 0};
static test_status_t test_status = test_status_pass;
JEMALLOC_ATTR(format(printf, 1, 2)) static const char * test_name = "";
void
test_fail(const char *format, ...)
{
va_list ap;
va_start(ap, format);
malloc_vcprintf(NULL, NULL, format, ap);
va_end(ap);
exit(JEMALLOC_TEST_EXIT_FAIL);
}
JEMALLOC_ATTR(format(printf, 1, 2)) JEMALLOC_ATTR(format(printf, 1, 2))
void void
@ -24,5 +14,83 @@ test_skip(const char *format, ...)
va_start(ap, format); va_start(ap, format);
malloc_vcprintf(NULL, NULL, format, ap); malloc_vcprintf(NULL, NULL, format, ap);
va_end(ap); va_end(ap);
exit(JEMALLOC_TEST_EXIT_SKIP); test_status = test_status_skip;
}
JEMALLOC_ATTR(format(printf, 1, 2))
void
test_fail(const char *format, ...)
{
va_list ap;
va_start(ap, format);
malloc_vcprintf(NULL, NULL, format, ap);
va_end(ap);
test_status = test_status_fail;
}
static const char *
test_status_string(test_status_t test_status)
{
switch (test_status) {
case test_status_pass: return "pass";
case test_status_skip: return "skip";
case test_status_fail: return "fail";
default: not_reached();
}
}
void
p_test_init(const char *name)
{
test_count++;
test_status = test_status_pass;
test_name = name;
}
void
p_test_fini(void)
{
test_counts[test_status]++;
malloc_printf("%s: %s\n", test_name, test_status_string(test_status));
}
test_status_t
p_test(test_t* t, ...)
{
test_status_t ret = test_status_pass;
va_list ap;
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("tests: %u, pass: %u, skip: %u, fail: %u\n",
test_count,
test_counts[test_status_pass],
test_counts[test_status_skip],
test_counts[test_status_fail]);
return (ret);
}
void
p_test_fail(const char *format, ...)
{
va_list ap;
va_start(ap, format);
malloc_vcprintf(NULL, NULL, format, ap);
format = va_arg(ap, const char *);
malloc_vcprintf(NULL, NULL, format, ap);
va_end(ap);
malloc_printf("\n");
test_status = test_status_fail;
} }

View File

@ -11,27 +11,42 @@ case @abi@ in
;; ;;
esac esac
total=0 # Corresponds to test_status_t.
failures=0 pass_code=0
echo "=========================================" skip_code=1
fail_code=2
echo "================================================================================"
pass_count=0
skip_count=0
fail_count=0
for t in $@; do for t in $@; do
total=`expr $total + 1` echo "${t}:"
/bin/echo -n "${t} ... "
${t}@exe@ @abs_srcroot@ @abs_objroot@ > @objroot@${t}.out 2>&1 ${t}@exe@ @abs_srcroot@ @abs_objroot@ > @objroot@${t}.out 2>&1
result=$? result_code=$?
if [ -e "@srcroot@${t}.exp" ] ; then /bin/echo -n " "
diff -w -u @srcroot@${t}.exp @objroot@${t}.out >/dev/null 2>&1 tail -n 1 @objroot@${t}.out
fail=$? case ${result_code} in
if [ "${fail}" -eq "1" ] ; then ${pass_code})
failures=`expr ${failures} + 1` pass_count=$((pass_count+1))
echo "*** FAIL ***" ;;
else ${skip_code})
echo "pass" skip_count=$((skip_count+1))
fi ;;
else ${fail_code})
echo "*** FAIL *** (.exp file is missing)" fail_count=$((fail_count+1))
failures=`expr ${failures} + 1` echo " *** ${t} failure; see @objroot@${t}.out for full output ***" 1>&2
fi ;;
*)
echo "Test harness error" 1>&2
exit 1
esac
done done
echo "=========================================" echo "================================================================================"
echo "Failures: ${failures}/${total}" echo "Test suite summary: pass: ${pass_count}, skip: ${skip_count}, fail: ${fail_count}"
if [ ${fail_count} -eq 0 ] ; then
exit 0
else
exit 1
fi

View File

@ -6,21 +6,21 @@
# define MAXBITS (1U << LG_BITMAP_MAXBITS) # define MAXBITS (1U << LG_BITMAP_MAXBITS)
#endif #endif
static void TEST_BEGIN(test_bitmap_size)
test_bitmap_size(void)
{ {
size_t i, prev_size; size_t i, prev_size;
prev_size = 0; prev_size = 0;
for (i = 1; i <= MAXBITS; i++) { for (i = 1; i <= MAXBITS; i++) {
size_t size = bitmap_size(i); size_t size = bitmap_size(i);
assert(size >= prev_size); assert_true(size >= prev_size,
"Bitmap size is smaller than expected");
prev_size = size; prev_size = size;
} }
} }
TEST_END
static void TEST_BEGIN(test_bitmap_init)
test_bitmap_init(void)
{ {
size_t i; size_t i;
@ -33,15 +33,17 @@ test_bitmap_init(void)
bitmap_info_ngroups(&binfo)); bitmap_info_ngroups(&binfo));
bitmap_init(bitmap, &binfo); bitmap_init(bitmap, &binfo);
for (j = 0; j < i; j++) for (j = 0; j < i; j++) {
assert(bitmap_get(bitmap, &binfo, j) == false); assert_false(bitmap_get(bitmap, &binfo, j),
"Bit should be unset");
}
free(bitmap); free(bitmap);
} }
} }
} }
TEST_END
static void TEST_BEGIN(test_bitmap_set)
test_bitmap_set(void)
{ {
size_t i; size_t i;
@ -56,14 +58,15 @@ test_bitmap_set(void)
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
bitmap_set(bitmap, &binfo, j); bitmap_set(bitmap, &binfo, j);
assert(bitmap_full(bitmap, &binfo)); assert_true(bitmap_full(bitmap, &binfo),
"All bits should be set");
free(bitmap); free(bitmap);
} }
} }
} }
TEST_END
static void TEST_BEGIN(test_bitmap_unset)
test_bitmap_unset(void)
{ {
size_t i; size_t i;
@ -78,19 +81,21 @@ test_bitmap_unset(void)
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
bitmap_set(bitmap, &binfo, j); bitmap_set(bitmap, &binfo, j);
assert(bitmap_full(bitmap, &binfo)); assert_true(bitmap_full(bitmap, &binfo),
"All bits should be set");
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
bitmap_unset(bitmap, &binfo, j); bitmap_unset(bitmap, &binfo, j);
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
bitmap_set(bitmap, &binfo, j); bitmap_set(bitmap, &binfo, j);
assert(bitmap_full(bitmap, &binfo)); assert_true(bitmap_full(bitmap, &binfo),
"All bits should be set");
free(bitmap); free(bitmap);
} }
} }
} }
TEST_END
static void TEST_BEGIN(test_bitmap_sfu)
test_bitmap_sfu(void)
{ {
size_t i; size_t i;
@ -104,9 +109,13 @@ test_bitmap_sfu(void)
bitmap_init(bitmap, &binfo); bitmap_init(bitmap, &binfo);
/* Iteratively set bits starting at the beginning. */ /* Iteratively set bits starting at the beginning. */
for (j = 0; j < i; j++) for (j = 0; j < i; j++) {
assert(bitmap_sfu(bitmap, &binfo) == j); assert_zd_eq(bitmap_sfu(bitmap, &binfo), j,
assert(bitmap_full(bitmap, &binfo)); "First unset bit should be just after "
"previous first unset bit");
}
assert_true(bitmap_full(bitmap, &binfo),
"All bits should be set");
/* /*
* Iteratively unset bits starting at the end, and * Iteratively unset bits starting at the end, and
@ -114,10 +123,13 @@ test_bitmap_sfu(void)
*/ */
for (j = i - 1; j >= 0; j--) { for (j = i - 1; j >= 0; j--) {
bitmap_unset(bitmap, &binfo, j); bitmap_unset(bitmap, &binfo, j);
assert(bitmap_sfu(bitmap, &binfo) == j); assert_zd_eq(bitmap_sfu(bitmap, &binfo), j,
"First unset bit should the bit previously "
"unset");
bitmap_unset(bitmap, &binfo, j); bitmap_unset(bitmap, &binfo, j);
} }
assert(bitmap_get(bitmap, &binfo, 0) == false); assert_false(bitmap_get(bitmap, &binfo, 0),
"Bit should be unset");
/* /*
* Iteratively set bits starting at the beginning, and * Iteratively set bits starting at the beginning, and
@ -125,27 +137,29 @@ test_bitmap_sfu(void)
*/ */
for (j = 1; j < i; j++) { for (j = 1; j < i; j++) {
bitmap_set(bitmap, &binfo, j - 1); bitmap_set(bitmap, &binfo, j - 1);
assert(bitmap_sfu(bitmap, &binfo) == j); assert_zd_eq(bitmap_sfu(bitmap, &binfo), j,
"First unset bit should be just after the "
"bit previously set");
bitmap_unset(bitmap, &binfo, j); bitmap_unset(bitmap, &binfo, j);
} }
assert(bitmap_sfu(bitmap, &binfo) == i - 1); assert_zd_eq(bitmap_sfu(bitmap, &binfo), i - 1,
assert(bitmap_full(bitmap, &binfo)); "First unset bit should be the last bit");
assert_true(bitmap_full(bitmap, &binfo),
"All bits should be set");
free(bitmap); free(bitmap);
} }
} }
} }
TEST_END
int int
main(void) main(void)
{ {
malloc_printf("Test begin\n");
test_bitmap_size(); return (test(
test_bitmap_init(); test_bitmap_size,
test_bitmap_set(); test_bitmap_init,
test_bitmap_unset(); test_bitmap_set,
test_bitmap_sfu(); test_bitmap_unset,
test_bitmap_sfu));
malloc_printf("Test end\n");
return (0);
} }

View File

@ -1,2 +0,0 @@
Test begin
Test end

View File

@ -4,12 +4,16 @@
typedef unsigned int data_t; typedef unsigned int data_t;
static bool data_cleanup_executed;
void void
data_cleanup(void *arg) data_cleanup(void *arg)
{ {
data_t *data = (data_t *)arg; data_t *data = (data_t *)arg;
malloc_printf("Cleanup for data %x.\n", *data); assert_x_eq(*data, THREAD_DATA,
"Argument passed into cleanup function should match tsd value");
data_cleanup_executed = true;
} }
malloc_tsd_protos(, data, data_t) malloc_tsd_protos(, data, data_t)
@ -21,34 +25,47 @@ malloc_tsd_funcs(, data, data_t, DATA_INIT, data_cleanup)
void * void *
je_thread_start(void *arg) je_thread_start(void *arg)
{ {
data_t d = (data_t)(uintptr_t) arg; data_t d = (data_t)(uintptr_t)arg;
malloc_printf("Initial tsd_get returns %x. Expected %x.\n", assert_x_eq(*data_tsd_get(), DATA_INIT,
*data_tsd_get(), DATA_INIT); "Initial tsd get should return initialization value");
data_tsd_set(&d); data_tsd_set(&d);
malloc_printf("After tsd_set: %x. Expected %x.\n", assert_x_eq(*data_tsd_get(), d,
*data_tsd_get(), d); "After tsd set, tsd get should return value that was set");
d = 0; d = 0;
malloc_printf("After resetting local data: %x. Expected %x.\n", assert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg,
*data_tsd_get(), (data_t)(uintptr_t) arg); "Resetting local data should have no effect on tsd");
return NULL; return NULL;
} }
int TEST_BEGIN(test_tsd_main_thread)
main(void) {
je_thread_start((void *) 0xa5f3e329);
}
TEST_END
TEST_BEGIN(test_tsd_sub_thread)
{ {
je_thread_t thread; je_thread_t thread;
malloc_printf("Test begin\n"); data_cleanup_executed = false;
data_tsd_boot();
je_thread_start((void *) 0xa5f3e329);
je_thread_create(&thread, je_thread_start, (void *) THREAD_DATA); je_thread_create(&thread, je_thread_start, (void *) THREAD_DATA);
je_thread_join(thread, NULL); je_thread_join(thread, NULL);
assert_true(data_cleanup_executed,
malloc_printf("Test end\n"); "Cleanup function should have executed");
return (0); }
TEST_END
int
main(void)
{
data_tsd_boot();
return (test(
test_tsd_main_thread,
test_tsd_sub_thread));
} }

View File

@ -1,9 +0,0 @@
Test begin
Initial tsd_get returns 12345678. Expected 12345678.
After tsd_set: a5f3e329. Expected a5f3e329.
After resetting local data: a5f3e329. Expected a5f3e329.
Initial tsd_get returns 12345678. Expected 12345678.
After tsd_set: 72b65c10. Expected 72b65c10.
After resetting local data: 72b65c10. Expected 72b65c10.
Cleanup for data 72b65c10.
Test end