1*1208bc7eSAndroid Build Coastguard Worker #include "test/jemalloc_test.h"
2*1208bc7eSAndroid Build Coastguard Worker
3*1208bc7eSAndroid Build Coastguard Worker /* Test status state. */
4*1208bc7eSAndroid Build Coastguard Worker
5*1208bc7eSAndroid Build Coastguard Worker static unsigned test_count = 0;
6*1208bc7eSAndroid Build Coastguard Worker static test_status_t test_counts[test_status_count] = {0, 0, 0};
7*1208bc7eSAndroid Build Coastguard Worker static test_status_t test_status = test_status_pass;
8*1208bc7eSAndroid Build Coastguard Worker static const char * test_name = "";
9*1208bc7eSAndroid Build Coastguard Worker
10*1208bc7eSAndroid Build Coastguard Worker /* Reentrancy testing helpers. */
11*1208bc7eSAndroid Build Coastguard Worker
12*1208bc7eSAndroid Build Coastguard Worker #define NUM_REENTRANT_ALLOCS 20
13*1208bc7eSAndroid Build Coastguard Worker typedef enum {
14*1208bc7eSAndroid Build Coastguard Worker non_reentrant = 0,
15*1208bc7eSAndroid Build Coastguard Worker libc_reentrant = 1,
16*1208bc7eSAndroid Build Coastguard Worker arena_new_reentrant = 2
17*1208bc7eSAndroid Build Coastguard Worker } reentrancy_t;
18*1208bc7eSAndroid Build Coastguard Worker static reentrancy_t reentrancy;
19*1208bc7eSAndroid Build Coastguard Worker
20*1208bc7eSAndroid Build Coastguard Worker static bool libc_hook_ran = false;
21*1208bc7eSAndroid Build Coastguard Worker static bool arena_new_hook_ran = false;
22*1208bc7eSAndroid Build Coastguard Worker
23*1208bc7eSAndroid Build Coastguard Worker static const char *
reentrancy_t_str(reentrancy_t r)24*1208bc7eSAndroid Build Coastguard Worker reentrancy_t_str(reentrancy_t r) {
25*1208bc7eSAndroid Build Coastguard Worker switch (r) {
26*1208bc7eSAndroid Build Coastguard Worker case non_reentrant:
27*1208bc7eSAndroid Build Coastguard Worker return "non-reentrant";
28*1208bc7eSAndroid Build Coastguard Worker case libc_reentrant:
29*1208bc7eSAndroid Build Coastguard Worker return "libc-reentrant";
30*1208bc7eSAndroid Build Coastguard Worker case arena_new_reentrant:
31*1208bc7eSAndroid Build Coastguard Worker return "arena_new-reentrant";
32*1208bc7eSAndroid Build Coastguard Worker default:
33*1208bc7eSAndroid Build Coastguard Worker unreachable();
34*1208bc7eSAndroid Build Coastguard Worker }
35*1208bc7eSAndroid Build Coastguard Worker }
36*1208bc7eSAndroid Build Coastguard Worker
37*1208bc7eSAndroid Build Coastguard Worker static void
do_hook(bool * hook_ran,void (** hook)())38*1208bc7eSAndroid Build Coastguard Worker do_hook(bool *hook_ran, void (**hook)()) {
39*1208bc7eSAndroid Build Coastguard Worker *hook_ran = true;
40*1208bc7eSAndroid Build Coastguard Worker *hook = NULL;
41*1208bc7eSAndroid Build Coastguard Worker
42*1208bc7eSAndroid Build Coastguard Worker size_t alloc_size = 1;
43*1208bc7eSAndroid Build Coastguard Worker for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) {
44*1208bc7eSAndroid Build Coastguard Worker free(malloc(alloc_size));
45*1208bc7eSAndroid Build Coastguard Worker alloc_size *= 2;
46*1208bc7eSAndroid Build Coastguard Worker }
47*1208bc7eSAndroid Build Coastguard Worker }
48*1208bc7eSAndroid Build Coastguard Worker
49*1208bc7eSAndroid Build Coastguard Worker static void
libc_reentrancy_hook()50*1208bc7eSAndroid Build Coastguard Worker libc_reentrancy_hook() {
51*1208bc7eSAndroid Build Coastguard Worker do_hook(&libc_hook_ran, &hooks_libc_hook);
52*1208bc7eSAndroid Build Coastguard Worker }
53*1208bc7eSAndroid Build Coastguard Worker
54*1208bc7eSAndroid Build Coastguard Worker static void
arena_new_reentrancy_hook()55*1208bc7eSAndroid Build Coastguard Worker arena_new_reentrancy_hook() {
56*1208bc7eSAndroid Build Coastguard Worker do_hook(&arena_new_hook_ran, &hooks_arena_new_hook);
57*1208bc7eSAndroid Build Coastguard Worker }
58*1208bc7eSAndroid Build Coastguard Worker
59*1208bc7eSAndroid Build Coastguard Worker /* Actual test infrastructure. */
60*1208bc7eSAndroid Build Coastguard Worker bool
test_is_reentrant()61*1208bc7eSAndroid Build Coastguard Worker test_is_reentrant() {
62*1208bc7eSAndroid Build Coastguard Worker return reentrancy != non_reentrant;
63*1208bc7eSAndroid Build Coastguard Worker }
64*1208bc7eSAndroid Build Coastguard Worker
65*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_FORMAT_PRINTF(1, 2)
66*1208bc7eSAndroid Build Coastguard Worker void
test_skip(const char * format,...)67*1208bc7eSAndroid Build Coastguard Worker test_skip(const char *format, ...) {
68*1208bc7eSAndroid Build Coastguard Worker va_list ap;
69*1208bc7eSAndroid Build Coastguard Worker
70*1208bc7eSAndroid Build Coastguard Worker va_start(ap, format);
71*1208bc7eSAndroid Build Coastguard Worker malloc_vcprintf(NULL, NULL, format, ap);
72*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
73*1208bc7eSAndroid Build Coastguard Worker malloc_printf("\n");
74*1208bc7eSAndroid Build Coastguard Worker test_status = test_status_skip;
75*1208bc7eSAndroid Build Coastguard Worker }
76*1208bc7eSAndroid Build Coastguard Worker
77*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_FORMAT_PRINTF(1, 2)
78*1208bc7eSAndroid Build Coastguard Worker void
test_fail(const char * format,...)79*1208bc7eSAndroid Build Coastguard Worker test_fail(const char *format, ...) {
80*1208bc7eSAndroid Build Coastguard Worker va_list ap;
81*1208bc7eSAndroid Build Coastguard Worker
82*1208bc7eSAndroid Build Coastguard Worker va_start(ap, format);
83*1208bc7eSAndroid Build Coastguard Worker malloc_vcprintf(NULL, NULL, format, ap);
84*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
85*1208bc7eSAndroid Build Coastguard Worker malloc_printf("\n");
86*1208bc7eSAndroid Build Coastguard Worker test_status = test_status_fail;
87*1208bc7eSAndroid Build Coastguard Worker }
88*1208bc7eSAndroid Build Coastguard Worker
89*1208bc7eSAndroid Build Coastguard Worker static const char *
test_status_string(test_status_t test_status)90*1208bc7eSAndroid Build Coastguard Worker test_status_string(test_status_t test_status) {
91*1208bc7eSAndroid Build Coastguard Worker switch (test_status) {
92*1208bc7eSAndroid Build Coastguard Worker case test_status_pass: return "pass";
93*1208bc7eSAndroid Build Coastguard Worker case test_status_skip: return "skip";
94*1208bc7eSAndroid Build Coastguard Worker case test_status_fail: return "fail";
95*1208bc7eSAndroid Build Coastguard Worker default: not_reached();
96*1208bc7eSAndroid Build Coastguard Worker }
97*1208bc7eSAndroid Build Coastguard Worker }
98*1208bc7eSAndroid Build Coastguard Worker
99*1208bc7eSAndroid Build Coastguard Worker void
p_test_init(const char * name)100*1208bc7eSAndroid Build Coastguard Worker p_test_init(const char *name) {
101*1208bc7eSAndroid Build Coastguard Worker test_count++;
102*1208bc7eSAndroid Build Coastguard Worker test_status = test_status_pass;
103*1208bc7eSAndroid Build Coastguard Worker test_name = name;
104*1208bc7eSAndroid Build Coastguard Worker }
105*1208bc7eSAndroid Build Coastguard Worker
106*1208bc7eSAndroid Build Coastguard Worker void
p_test_fini(void)107*1208bc7eSAndroid Build Coastguard Worker p_test_fini(void) {
108*1208bc7eSAndroid Build Coastguard Worker test_counts[test_status]++;
109*1208bc7eSAndroid Build Coastguard Worker malloc_printf("%s (%s): %s\n", test_name, reentrancy_t_str(reentrancy),
110*1208bc7eSAndroid Build Coastguard Worker test_status_string(test_status));
111*1208bc7eSAndroid Build Coastguard Worker }
112*1208bc7eSAndroid Build Coastguard Worker
113*1208bc7eSAndroid Build Coastguard Worker static test_status_t
p_test_impl(bool do_malloc_init,bool do_reentrant,test_t * t,va_list ap)114*1208bc7eSAndroid Build Coastguard Worker p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) {
115*1208bc7eSAndroid Build Coastguard Worker test_status_t ret;
116*1208bc7eSAndroid Build Coastguard Worker
117*1208bc7eSAndroid Build Coastguard Worker if (do_malloc_init) {
118*1208bc7eSAndroid Build Coastguard Worker /*
119*1208bc7eSAndroid Build Coastguard Worker * Make sure initialization occurs prior to running tests.
120*1208bc7eSAndroid Build Coastguard Worker * Tests are special because they may use internal facilities
121*1208bc7eSAndroid Build Coastguard Worker * prior to triggering initialization as a side effect of
122*1208bc7eSAndroid Build Coastguard Worker * calling into the public API.
123*1208bc7eSAndroid Build Coastguard Worker */
124*1208bc7eSAndroid Build Coastguard Worker if (nallocx(1, 0) == 0) {
125*1208bc7eSAndroid Build Coastguard Worker malloc_printf("Initialization error");
126*1208bc7eSAndroid Build Coastguard Worker return test_status_fail;
127*1208bc7eSAndroid Build Coastguard Worker }
128*1208bc7eSAndroid Build Coastguard Worker }
129*1208bc7eSAndroid Build Coastguard Worker
130*1208bc7eSAndroid Build Coastguard Worker ret = test_status_pass;
131*1208bc7eSAndroid Build Coastguard Worker for (; t != NULL; t = va_arg(ap, test_t *)) {
132*1208bc7eSAndroid Build Coastguard Worker /* Non-reentrant run. */
133*1208bc7eSAndroid Build Coastguard Worker reentrancy = non_reentrant;
134*1208bc7eSAndroid Build Coastguard Worker hooks_arena_new_hook = hooks_libc_hook = NULL;
135*1208bc7eSAndroid Build Coastguard Worker t();
136*1208bc7eSAndroid Build Coastguard Worker if (test_status > ret) {
137*1208bc7eSAndroid Build Coastguard Worker ret = test_status;
138*1208bc7eSAndroid Build Coastguard Worker }
139*1208bc7eSAndroid Build Coastguard Worker /* Reentrant run. */
140*1208bc7eSAndroid Build Coastguard Worker if (do_reentrant) {
141*1208bc7eSAndroid Build Coastguard Worker reentrancy = libc_reentrant;
142*1208bc7eSAndroid Build Coastguard Worker hooks_arena_new_hook = NULL;
143*1208bc7eSAndroid Build Coastguard Worker hooks_libc_hook = &libc_reentrancy_hook;
144*1208bc7eSAndroid Build Coastguard Worker t();
145*1208bc7eSAndroid Build Coastguard Worker if (test_status > ret) {
146*1208bc7eSAndroid Build Coastguard Worker ret = test_status;
147*1208bc7eSAndroid Build Coastguard Worker }
148*1208bc7eSAndroid Build Coastguard Worker
149*1208bc7eSAndroid Build Coastguard Worker reentrancy = arena_new_reentrant;
150*1208bc7eSAndroid Build Coastguard Worker hooks_libc_hook = NULL;
151*1208bc7eSAndroid Build Coastguard Worker hooks_arena_new_hook = &arena_new_reentrancy_hook;
152*1208bc7eSAndroid Build Coastguard Worker t();
153*1208bc7eSAndroid Build Coastguard Worker if (test_status > ret) {
154*1208bc7eSAndroid Build Coastguard Worker ret = test_status;
155*1208bc7eSAndroid Build Coastguard Worker }
156*1208bc7eSAndroid Build Coastguard Worker }
157*1208bc7eSAndroid Build Coastguard Worker }
158*1208bc7eSAndroid Build Coastguard Worker
159*1208bc7eSAndroid Build Coastguard Worker malloc_printf("--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\n",
160*1208bc7eSAndroid Build Coastguard Worker test_status_string(test_status_pass),
161*1208bc7eSAndroid Build Coastguard Worker test_counts[test_status_pass], test_count,
162*1208bc7eSAndroid Build Coastguard Worker test_status_string(test_status_skip),
163*1208bc7eSAndroid Build Coastguard Worker test_counts[test_status_skip], test_count,
164*1208bc7eSAndroid Build Coastguard Worker test_status_string(test_status_fail),
165*1208bc7eSAndroid Build Coastguard Worker test_counts[test_status_fail], test_count);
166*1208bc7eSAndroid Build Coastguard Worker
167*1208bc7eSAndroid Build Coastguard Worker return ret;
168*1208bc7eSAndroid Build Coastguard Worker }
169*1208bc7eSAndroid Build Coastguard Worker
170*1208bc7eSAndroid Build Coastguard Worker test_status_t
p_test(test_t * t,...)171*1208bc7eSAndroid Build Coastguard Worker p_test(test_t *t, ...) {
172*1208bc7eSAndroid Build Coastguard Worker test_status_t ret;
173*1208bc7eSAndroid Build Coastguard Worker va_list ap;
174*1208bc7eSAndroid Build Coastguard Worker
175*1208bc7eSAndroid Build Coastguard Worker ret = test_status_pass;
176*1208bc7eSAndroid Build Coastguard Worker va_start(ap, t);
177*1208bc7eSAndroid Build Coastguard Worker ret = p_test_impl(true, true, t, ap);
178*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
179*1208bc7eSAndroid Build Coastguard Worker
180*1208bc7eSAndroid Build Coastguard Worker return ret;
181*1208bc7eSAndroid Build Coastguard Worker }
182*1208bc7eSAndroid Build Coastguard Worker
183*1208bc7eSAndroid Build Coastguard Worker test_status_t
p_test_no_reentrancy(test_t * t,...)184*1208bc7eSAndroid Build Coastguard Worker p_test_no_reentrancy(test_t *t, ...) {
185*1208bc7eSAndroid Build Coastguard Worker test_status_t ret;
186*1208bc7eSAndroid Build Coastguard Worker va_list ap;
187*1208bc7eSAndroid Build Coastguard Worker
188*1208bc7eSAndroid Build Coastguard Worker ret = test_status_pass;
189*1208bc7eSAndroid Build Coastguard Worker va_start(ap, t);
190*1208bc7eSAndroid Build Coastguard Worker ret = p_test_impl(true, false, t, ap);
191*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
192*1208bc7eSAndroid Build Coastguard Worker
193*1208bc7eSAndroid Build Coastguard Worker return ret;
194*1208bc7eSAndroid Build Coastguard Worker }
195*1208bc7eSAndroid Build Coastguard Worker
196*1208bc7eSAndroid Build Coastguard Worker test_status_t
p_test_no_malloc_init(test_t * t,...)197*1208bc7eSAndroid Build Coastguard Worker p_test_no_malloc_init(test_t *t, ...) {
198*1208bc7eSAndroid Build Coastguard Worker test_status_t ret;
199*1208bc7eSAndroid Build Coastguard Worker va_list ap;
200*1208bc7eSAndroid Build Coastguard Worker
201*1208bc7eSAndroid Build Coastguard Worker ret = test_status_pass;
202*1208bc7eSAndroid Build Coastguard Worker va_start(ap, t);
203*1208bc7eSAndroid Build Coastguard Worker /*
204*1208bc7eSAndroid Build Coastguard Worker * We also omit reentrancy from bootstrapping tests, since we don't
205*1208bc7eSAndroid Build Coastguard Worker * (yet) care about general reentrancy during bootstrapping.
206*1208bc7eSAndroid Build Coastguard Worker */
207*1208bc7eSAndroid Build Coastguard Worker ret = p_test_impl(false, false, t, ap);
208*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
209*1208bc7eSAndroid Build Coastguard Worker
210*1208bc7eSAndroid Build Coastguard Worker return ret;
211*1208bc7eSAndroid Build Coastguard Worker }
212*1208bc7eSAndroid Build Coastguard Worker
213*1208bc7eSAndroid Build Coastguard Worker void
p_test_fail(const char * prefix,const char * message)214*1208bc7eSAndroid Build Coastguard Worker p_test_fail(const char *prefix, const char *message) {
215*1208bc7eSAndroid Build Coastguard Worker malloc_cprintf(NULL, NULL, "%s%s\n", prefix, message);
216*1208bc7eSAndroid Build Coastguard Worker test_status = test_status_fail;
217*1208bc7eSAndroid Build Coastguard Worker }
218