xref: /aosp_15_r20/external/jemalloc_new/test/src/test.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
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