xref: /aosp_15_r20/external/jemalloc_new/test/unit/bitmap.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #include "test/jemalloc_test.h"
2*1208bc7eSAndroid Build Coastguard Worker 
3*1208bc7eSAndroid Build Coastguard Worker #define NBITS_TAB \
4*1208bc7eSAndroid Build Coastguard Worker     NB( 1) \
5*1208bc7eSAndroid Build Coastguard Worker     NB( 2) \
6*1208bc7eSAndroid Build Coastguard Worker     NB( 3) \
7*1208bc7eSAndroid Build Coastguard Worker     NB( 4) \
8*1208bc7eSAndroid Build Coastguard Worker     NB( 5) \
9*1208bc7eSAndroid Build Coastguard Worker     NB( 6) \
10*1208bc7eSAndroid Build Coastguard Worker     NB( 7) \
11*1208bc7eSAndroid Build Coastguard Worker     NB( 8) \
12*1208bc7eSAndroid Build Coastguard Worker     NB( 9) \
13*1208bc7eSAndroid Build Coastguard Worker     NB(10) \
14*1208bc7eSAndroid Build Coastguard Worker     NB(11) \
15*1208bc7eSAndroid Build Coastguard Worker     NB(12) \
16*1208bc7eSAndroid Build Coastguard Worker     NB(13) \
17*1208bc7eSAndroid Build Coastguard Worker     NB(14) \
18*1208bc7eSAndroid Build Coastguard Worker     NB(15) \
19*1208bc7eSAndroid Build Coastguard Worker     NB(16) \
20*1208bc7eSAndroid Build Coastguard Worker     NB(17) \
21*1208bc7eSAndroid Build Coastguard Worker     NB(18) \
22*1208bc7eSAndroid Build Coastguard Worker     NB(19) \
23*1208bc7eSAndroid Build Coastguard Worker     NB(20) \
24*1208bc7eSAndroid Build Coastguard Worker     NB(21) \
25*1208bc7eSAndroid Build Coastguard Worker     NB(22) \
26*1208bc7eSAndroid Build Coastguard Worker     NB(23) \
27*1208bc7eSAndroid Build Coastguard Worker     NB(24) \
28*1208bc7eSAndroid Build Coastguard Worker     NB(25) \
29*1208bc7eSAndroid Build Coastguard Worker     NB(26) \
30*1208bc7eSAndroid Build Coastguard Worker     NB(27) \
31*1208bc7eSAndroid Build Coastguard Worker     NB(28) \
32*1208bc7eSAndroid Build Coastguard Worker     NB(29) \
33*1208bc7eSAndroid Build Coastguard Worker     NB(30) \
34*1208bc7eSAndroid Build Coastguard Worker     NB(31) \
35*1208bc7eSAndroid Build Coastguard Worker     NB(32) \
36*1208bc7eSAndroid Build Coastguard Worker     \
37*1208bc7eSAndroid Build Coastguard Worker     NB(33) \
38*1208bc7eSAndroid Build Coastguard Worker     NB(34) \
39*1208bc7eSAndroid Build Coastguard Worker     NB(35) \
40*1208bc7eSAndroid Build Coastguard Worker     NB(36) \
41*1208bc7eSAndroid Build Coastguard Worker     NB(37) \
42*1208bc7eSAndroid Build Coastguard Worker     NB(38) \
43*1208bc7eSAndroid Build Coastguard Worker     NB(39) \
44*1208bc7eSAndroid Build Coastguard Worker     NB(40) \
45*1208bc7eSAndroid Build Coastguard Worker     NB(41) \
46*1208bc7eSAndroid Build Coastguard Worker     NB(42) \
47*1208bc7eSAndroid Build Coastguard Worker     NB(43) \
48*1208bc7eSAndroid Build Coastguard Worker     NB(44) \
49*1208bc7eSAndroid Build Coastguard Worker     NB(45) \
50*1208bc7eSAndroid Build Coastguard Worker     NB(46) \
51*1208bc7eSAndroid Build Coastguard Worker     NB(47) \
52*1208bc7eSAndroid Build Coastguard Worker     NB(48) \
53*1208bc7eSAndroid Build Coastguard Worker     NB(49) \
54*1208bc7eSAndroid Build Coastguard Worker     NB(50) \
55*1208bc7eSAndroid Build Coastguard Worker     NB(51) \
56*1208bc7eSAndroid Build Coastguard Worker     NB(52) \
57*1208bc7eSAndroid Build Coastguard Worker     NB(53) \
58*1208bc7eSAndroid Build Coastguard Worker     NB(54) \
59*1208bc7eSAndroid Build Coastguard Worker     NB(55) \
60*1208bc7eSAndroid Build Coastguard Worker     NB(56) \
61*1208bc7eSAndroid Build Coastguard Worker     NB(57) \
62*1208bc7eSAndroid Build Coastguard Worker     NB(58) \
63*1208bc7eSAndroid Build Coastguard Worker     NB(59) \
64*1208bc7eSAndroid Build Coastguard Worker     NB(60) \
65*1208bc7eSAndroid Build Coastguard Worker     NB(61) \
66*1208bc7eSAndroid Build Coastguard Worker     NB(62) \
67*1208bc7eSAndroid Build Coastguard Worker     NB(63) \
68*1208bc7eSAndroid Build Coastguard Worker     NB(64) \
69*1208bc7eSAndroid Build Coastguard Worker     NB(65) \
70*1208bc7eSAndroid Build Coastguard Worker     \
71*1208bc7eSAndroid Build Coastguard Worker     NB(126) \
72*1208bc7eSAndroid Build Coastguard Worker     NB(127) \
73*1208bc7eSAndroid Build Coastguard Worker     NB(128) \
74*1208bc7eSAndroid Build Coastguard Worker     NB(129) \
75*1208bc7eSAndroid Build Coastguard Worker     NB(130) \
76*1208bc7eSAndroid Build Coastguard Worker     \
77*1208bc7eSAndroid Build Coastguard Worker     NB(254) \
78*1208bc7eSAndroid Build Coastguard Worker     NB(255) \
79*1208bc7eSAndroid Build Coastguard Worker     NB(256) \
80*1208bc7eSAndroid Build Coastguard Worker     NB(257) \
81*1208bc7eSAndroid Build Coastguard Worker     NB(258) \
82*1208bc7eSAndroid Build Coastguard Worker     \
83*1208bc7eSAndroid Build Coastguard Worker     NB(510) \
84*1208bc7eSAndroid Build Coastguard Worker     NB(511) \
85*1208bc7eSAndroid Build Coastguard Worker     NB(512) \
86*1208bc7eSAndroid Build Coastguard Worker     NB(513) \
87*1208bc7eSAndroid Build Coastguard Worker     NB(514) \
88*1208bc7eSAndroid Build Coastguard Worker     \
89*1208bc7eSAndroid Build Coastguard Worker     NB(1024) \
90*1208bc7eSAndroid Build Coastguard Worker     NB(2048) \
91*1208bc7eSAndroid Build Coastguard Worker     NB(4096) \
92*1208bc7eSAndroid Build Coastguard Worker     NB(8192) \
93*1208bc7eSAndroid Build Coastguard Worker     NB(16384) \
94*1208bc7eSAndroid Build Coastguard Worker 
95*1208bc7eSAndroid Build Coastguard Worker static void
test_bitmap_initializer_body(const bitmap_info_t * binfo,size_t nbits)96*1208bc7eSAndroid Build Coastguard Worker test_bitmap_initializer_body(const bitmap_info_t *binfo, size_t nbits) {
97*1208bc7eSAndroid Build Coastguard Worker 	bitmap_info_t binfo_dyn;
98*1208bc7eSAndroid Build Coastguard Worker 	bitmap_info_init(&binfo_dyn, nbits);
99*1208bc7eSAndroid Build Coastguard Worker 
100*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(bitmap_size(binfo), bitmap_size(&binfo_dyn),
101*1208bc7eSAndroid Build Coastguard Worker 	    "Unexpected difference between static and dynamic initialization, "
102*1208bc7eSAndroid Build Coastguard Worker 	    "nbits=%zu", nbits);
103*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(binfo->nbits, binfo_dyn.nbits,
104*1208bc7eSAndroid Build Coastguard Worker 	    "Unexpected difference between static and dynamic initialization, "
105*1208bc7eSAndroid Build Coastguard Worker 	    "nbits=%zu", nbits);
106*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
107*1208bc7eSAndroid Build Coastguard Worker 	assert_u_eq(binfo->nlevels, binfo_dyn.nlevels,
108*1208bc7eSAndroid Build Coastguard Worker 	    "Unexpected difference between static and dynamic initialization, "
109*1208bc7eSAndroid Build Coastguard Worker 	    "nbits=%zu", nbits);
110*1208bc7eSAndroid Build Coastguard Worker 	{
111*1208bc7eSAndroid Build Coastguard Worker 		unsigned i;
112*1208bc7eSAndroid Build Coastguard Worker 
113*1208bc7eSAndroid Build Coastguard Worker 		for (i = 0; i < binfo->nlevels; i++) {
114*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(binfo->levels[i].group_offset,
115*1208bc7eSAndroid Build Coastguard Worker 			    binfo_dyn.levels[i].group_offset,
116*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected difference between static and dynamic "
117*1208bc7eSAndroid Build Coastguard Worker 			    "initialization, nbits=%zu, level=%u", nbits, i);
118*1208bc7eSAndroid Build Coastguard Worker 		}
119*1208bc7eSAndroid Build Coastguard Worker 	}
120*1208bc7eSAndroid Build Coastguard Worker #else
121*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(binfo->ngroups, binfo_dyn.ngroups,
122*1208bc7eSAndroid Build Coastguard Worker 	    "Unexpected difference between static and dynamic initialization");
123*1208bc7eSAndroid Build Coastguard Worker #endif
124*1208bc7eSAndroid Build Coastguard Worker }
125*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_bitmap_initializer)126*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_bitmap_initializer) {
127*1208bc7eSAndroid Build Coastguard Worker #define NB(nbits) {							\
128*1208bc7eSAndroid Build Coastguard Worker 		if (nbits <= BITMAP_MAXBITS) {				\
129*1208bc7eSAndroid Build Coastguard Worker 			bitmap_info_t binfo =				\
130*1208bc7eSAndroid Build Coastguard Worker 			    BITMAP_INFO_INITIALIZER(nbits);		\
131*1208bc7eSAndroid Build Coastguard Worker 			test_bitmap_initializer_body(&binfo, nbits);	\
132*1208bc7eSAndroid Build Coastguard Worker 		}							\
133*1208bc7eSAndroid Build Coastguard Worker 	}
134*1208bc7eSAndroid Build Coastguard Worker 	NBITS_TAB
135*1208bc7eSAndroid Build Coastguard Worker #undef NB
136*1208bc7eSAndroid Build Coastguard Worker }
137*1208bc7eSAndroid Build Coastguard Worker TEST_END
138*1208bc7eSAndroid Build Coastguard Worker 
139*1208bc7eSAndroid Build Coastguard Worker static size_t
test_bitmap_size_body(const bitmap_info_t * binfo,size_t nbits,size_t prev_size)140*1208bc7eSAndroid Build Coastguard Worker test_bitmap_size_body(const bitmap_info_t *binfo, size_t nbits,
141*1208bc7eSAndroid Build Coastguard Worker     size_t prev_size) {
142*1208bc7eSAndroid Build Coastguard Worker 	size_t size = bitmap_size(binfo);
143*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_ge(size, (nbits >> 3),
144*1208bc7eSAndroid Build Coastguard Worker 	    "Bitmap size is smaller than expected");
145*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_ge(size, prev_size, "Bitmap size is smaller than expected");
146*1208bc7eSAndroid Build Coastguard Worker 	return size;
147*1208bc7eSAndroid Build Coastguard Worker }
148*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_bitmap_size)149*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_bitmap_size) {
150*1208bc7eSAndroid Build Coastguard Worker 	size_t nbits, prev_size;
151*1208bc7eSAndroid Build Coastguard Worker 
152*1208bc7eSAndroid Build Coastguard Worker 	prev_size = 0;
153*1208bc7eSAndroid Build Coastguard Worker 	for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
154*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo;
155*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_init(&binfo, nbits);
156*1208bc7eSAndroid Build Coastguard Worker 		prev_size = test_bitmap_size_body(&binfo, nbits, prev_size);
157*1208bc7eSAndroid Build Coastguard Worker 	}
158*1208bc7eSAndroid Build Coastguard Worker #define NB(nbits) {							\
159*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits);	\
160*1208bc7eSAndroid Build Coastguard Worker 		prev_size = test_bitmap_size_body(&binfo, nbits,	\
161*1208bc7eSAndroid Build Coastguard Worker 		    prev_size);						\
162*1208bc7eSAndroid Build Coastguard Worker 	}
163*1208bc7eSAndroid Build Coastguard Worker 	prev_size = 0;
164*1208bc7eSAndroid Build Coastguard Worker 	NBITS_TAB
165*1208bc7eSAndroid Build Coastguard Worker #undef NB
166*1208bc7eSAndroid Build Coastguard Worker }
167*1208bc7eSAndroid Build Coastguard Worker TEST_END
168*1208bc7eSAndroid Build Coastguard Worker 
169*1208bc7eSAndroid Build Coastguard Worker static void
test_bitmap_init_body(const bitmap_info_t * binfo,size_t nbits)170*1208bc7eSAndroid Build Coastguard Worker test_bitmap_init_body(const bitmap_info_t *binfo, size_t nbits) {
171*1208bc7eSAndroid Build Coastguard Worker 	size_t i;
172*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
173*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
174*1208bc7eSAndroid Build Coastguard Worker 
175*1208bc7eSAndroid Build Coastguard Worker 	bitmap_init(bitmap, binfo, false);
176*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nbits; i++) {
177*1208bc7eSAndroid Build Coastguard Worker 		assert_false(bitmap_get(bitmap, binfo, i),
178*1208bc7eSAndroid Build Coastguard Worker 		    "Bit should be unset");
179*1208bc7eSAndroid Build Coastguard Worker 	}
180*1208bc7eSAndroid Build Coastguard Worker 
181*1208bc7eSAndroid Build Coastguard Worker 	bitmap_init(bitmap, binfo, true);
182*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nbits; i++) {
183*1208bc7eSAndroid Build Coastguard Worker 		assert_true(bitmap_get(bitmap, binfo, i), "Bit should be set");
184*1208bc7eSAndroid Build Coastguard Worker 	}
185*1208bc7eSAndroid Build Coastguard Worker 
186*1208bc7eSAndroid Build Coastguard Worker 	free(bitmap);
187*1208bc7eSAndroid Build Coastguard Worker }
188*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_bitmap_init)189*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_bitmap_init) {
190*1208bc7eSAndroid Build Coastguard Worker 	size_t nbits;
191*1208bc7eSAndroid Build Coastguard Worker 
192*1208bc7eSAndroid Build Coastguard Worker 	for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
193*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo;
194*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_init(&binfo, nbits);
195*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_init_body(&binfo, nbits);
196*1208bc7eSAndroid Build Coastguard Worker 	}
197*1208bc7eSAndroid Build Coastguard Worker #define NB(nbits) {							\
198*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits);	\
199*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_init_body(&binfo, nbits);			\
200*1208bc7eSAndroid Build Coastguard Worker 	}
201*1208bc7eSAndroid Build Coastguard Worker 	NBITS_TAB
202*1208bc7eSAndroid Build Coastguard Worker #undef NB
203*1208bc7eSAndroid Build Coastguard Worker }
204*1208bc7eSAndroid Build Coastguard Worker TEST_END
205*1208bc7eSAndroid Build Coastguard Worker 
206*1208bc7eSAndroid Build Coastguard Worker static void
test_bitmap_set_body(const bitmap_info_t * binfo,size_t nbits)207*1208bc7eSAndroid Build Coastguard Worker test_bitmap_set_body(const bitmap_info_t *binfo, size_t nbits) {
208*1208bc7eSAndroid Build Coastguard Worker 	size_t i;
209*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
210*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
211*1208bc7eSAndroid Build Coastguard Worker 	bitmap_init(bitmap, binfo, false);
212*1208bc7eSAndroid Build Coastguard Worker 
213*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nbits; i++) {
214*1208bc7eSAndroid Build Coastguard Worker 		bitmap_set(bitmap, binfo, i);
215*1208bc7eSAndroid Build Coastguard Worker 	}
216*1208bc7eSAndroid Build Coastguard Worker 	assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
217*1208bc7eSAndroid Build Coastguard Worker 	free(bitmap);
218*1208bc7eSAndroid Build Coastguard Worker }
219*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_bitmap_set)220*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_bitmap_set) {
221*1208bc7eSAndroid Build Coastguard Worker 	size_t nbits;
222*1208bc7eSAndroid Build Coastguard Worker 
223*1208bc7eSAndroid Build Coastguard Worker 	for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
224*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo;
225*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_init(&binfo, nbits);
226*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_set_body(&binfo, nbits);
227*1208bc7eSAndroid Build Coastguard Worker 	}
228*1208bc7eSAndroid Build Coastguard Worker #define NB(nbits) {							\
229*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits);	\
230*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_set_body(&binfo, nbits);			\
231*1208bc7eSAndroid Build Coastguard Worker 	}
232*1208bc7eSAndroid Build Coastguard Worker 	NBITS_TAB
233*1208bc7eSAndroid Build Coastguard Worker #undef NB
234*1208bc7eSAndroid Build Coastguard Worker }
235*1208bc7eSAndroid Build Coastguard Worker TEST_END
236*1208bc7eSAndroid Build Coastguard Worker 
237*1208bc7eSAndroid Build Coastguard Worker static void
test_bitmap_unset_body(const bitmap_info_t * binfo,size_t nbits)238*1208bc7eSAndroid Build Coastguard Worker test_bitmap_unset_body(const bitmap_info_t *binfo, size_t nbits) {
239*1208bc7eSAndroid Build Coastguard Worker 	size_t i;
240*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
241*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
242*1208bc7eSAndroid Build Coastguard Worker 	bitmap_init(bitmap, binfo, false);
243*1208bc7eSAndroid Build Coastguard Worker 
244*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nbits; i++) {
245*1208bc7eSAndroid Build Coastguard Worker 		bitmap_set(bitmap, binfo, i);
246*1208bc7eSAndroid Build Coastguard Worker 	}
247*1208bc7eSAndroid Build Coastguard Worker 	assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
248*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nbits; i++) {
249*1208bc7eSAndroid Build Coastguard Worker 		bitmap_unset(bitmap, binfo, i);
250*1208bc7eSAndroid Build Coastguard Worker 	}
251*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nbits; i++) {
252*1208bc7eSAndroid Build Coastguard Worker 		bitmap_set(bitmap, binfo, i);
253*1208bc7eSAndroid Build Coastguard Worker 	}
254*1208bc7eSAndroid Build Coastguard Worker 	assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
255*1208bc7eSAndroid Build Coastguard Worker 	free(bitmap);
256*1208bc7eSAndroid Build Coastguard Worker }
257*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_bitmap_unset)258*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_bitmap_unset) {
259*1208bc7eSAndroid Build Coastguard Worker 	size_t nbits;
260*1208bc7eSAndroid Build Coastguard Worker 
261*1208bc7eSAndroid Build Coastguard Worker 	for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
262*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo;
263*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_init(&binfo, nbits);
264*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_unset_body(&binfo, nbits);
265*1208bc7eSAndroid Build Coastguard Worker 	}
266*1208bc7eSAndroid Build Coastguard Worker #define NB(nbits) {							\
267*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits);	\
268*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_unset_body(&binfo, nbits);			\
269*1208bc7eSAndroid Build Coastguard Worker 	}
270*1208bc7eSAndroid Build Coastguard Worker 	NBITS_TAB
271*1208bc7eSAndroid Build Coastguard Worker #undef NB
272*1208bc7eSAndroid Build Coastguard Worker }
273*1208bc7eSAndroid Build Coastguard Worker TEST_END
274*1208bc7eSAndroid Build Coastguard Worker 
275*1208bc7eSAndroid Build Coastguard Worker static void
test_bitmap_xfu_body(const bitmap_info_t * binfo,size_t nbits)276*1208bc7eSAndroid Build Coastguard Worker test_bitmap_xfu_body(const bitmap_info_t *binfo, size_t nbits) {
277*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
278*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
279*1208bc7eSAndroid Build Coastguard Worker 	bitmap_init(bitmap, binfo, false);
280*1208bc7eSAndroid Build Coastguard Worker 
281*1208bc7eSAndroid Build Coastguard Worker 	/* Iteratively set bits starting at the beginning. */
282*1208bc7eSAndroid Build Coastguard Worker 	for (size_t i = 0; i < nbits; i++) {
283*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
284*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after previous first unset "
285*1208bc7eSAndroid Build Coastguard Worker 		    "bit");
286*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
287*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after previous first unset "
288*1208bc7eSAndroid Build Coastguard Worker 		    "bit");
289*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
290*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after previous first unset "
291*1208bc7eSAndroid Build Coastguard Worker 		    "bit");
292*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
293*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after previous first unset "
294*1208bc7eSAndroid Build Coastguard Worker 		    "bit");
295*1208bc7eSAndroid Build Coastguard Worker 	}
296*1208bc7eSAndroid Build Coastguard Worker 	assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
297*1208bc7eSAndroid Build Coastguard Worker 
298*1208bc7eSAndroid Build Coastguard Worker 	/*
299*1208bc7eSAndroid Build Coastguard Worker 	 * Iteratively unset bits starting at the end, and verify that
300*1208bc7eSAndroid Build Coastguard Worker 	 * bitmap_sfu() reaches the unset bits.
301*1208bc7eSAndroid Build Coastguard Worker 	 */
302*1208bc7eSAndroid Build Coastguard Worker 	for (size_t i = nbits - 1; i < nbits; i--) { /* (nbits..0] */
303*1208bc7eSAndroid Build Coastguard Worker 		bitmap_unset(bitmap, binfo, i);
304*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
305*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should the bit previously unset");
306*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
307*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should the bit previously unset");
308*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
309*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should the bit previously unset");
310*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
311*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should the bit previously unset");
312*1208bc7eSAndroid Build Coastguard Worker 		bitmap_unset(bitmap, binfo, i);
313*1208bc7eSAndroid Build Coastguard Worker 	}
314*1208bc7eSAndroid Build Coastguard Worker 	assert_false(bitmap_get(bitmap, binfo, 0), "Bit should be unset");
315*1208bc7eSAndroid Build Coastguard Worker 
316*1208bc7eSAndroid Build Coastguard Worker 	/*
317*1208bc7eSAndroid Build Coastguard Worker 	 * Iteratively set bits starting at the beginning, and verify that
318*1208bc7eSAndroid Build Coastguard Worker 	 * bitmap_sfu() looks past them.
319*1208bc7eSAndroid Build Coastguard Worker 	 */
320*1208bc7eSAndroid Build Coastguard Worker 	for (size_t i = 1; i < nbits; i++) {
321*1208bc7eSAndroid Build Coastguard Worker 		bitmap_set(bitmap, binfo, i - 1);
322*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
323*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after the bit previously "
324*1208bc7eSAndroid Build Coastguard Worker 		    "set");
325*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
326*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after the bit previously "
327*1208bc7eSAndroid Build Coastguard Worker 		    "set");
328*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
329*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after the bit previously "
330*1208bc7eSAndroid Build Coastguard Worker 		    "set");
331*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
332*1208bc7eSAndroid Build Coastguard Worker 		    "First unset bit should be just after the bit previously "
333*1208bc7eSAndroid Build Coastguard Worker 		    "set");
334*1208bc7eSAndroid Build Coastguard Worker 		bitmap_unset(bitmap, binfo, i);
335*1208bc7eSAndroid Build Coastguard Worker 	}
336*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), nbits - 1,
337*1208bc7eSAndroid Build Coastguard Worker 	    "First unset bit should be the last bit");
338*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(bitmap_ffu(bitmap, binfo, (nbits > 1) ? nbits-2 : nbits-1),
339*1208bc7eSAndroid Build Coastguard Worker 	    nbits - 1, "First unset bit should be the last bit");
340*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(bitmap_ffu(bitmap, binfo, nbits - 1), nbits - 1,
341*1208bc7eSAndroid Build Coastguard Worker 	    "First unset bit should be the last bit");
342*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(bitmap_sfu(bitmap, binfo), nbits - 1,
343*1208bc7eSAndroid Build Coastguard Worker 	    "First unset bit should be the last bit");
344*1208bc7eSAndroid Build Coastguard Worker 	assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
345*1208bc7eSAndroid Build Coastguard Worker 
346*1208bc7eSAndroid Build Coastguard Worker 	/*
347*1208bc7eSAndroid Build Coastguard Worker 	 * Bubble a "usu" pattern through the bitmap and verify that
348*1208bc7eSAndroid Build Coastguard Worker 	 * bitmap_ffu() finds the correct bit for all five min_bit cases.
349*1208bc7eSAndroid Build Coastguard Worker 	 */
350*1208bc7eSAndroid Build Coastguard Worker 	if (nbits >= 3) {
351*1208bc7eSAndroid Build Coastguard Worker 		for (size_t i = 0; i < nbits-2; i++) {
352*1208bc7eSAndroid Build Coastguard Worker 			bitmap_unset(bitmap, binfo, i);
353*1208bc7eSAndroid Build Coastguard Worker 			bitmap_unset(bitmap, binfo, i+2);
354*1208bc7eSAndroid Build Coastguard Worker 			if (i > 0) {
355*1208bc7eSAndroid Build Coastguard Worker 				assert_zu_eq(bitmap_ffu(bitmap, binfo, i-1), i,
356*1208bc7eSAndroid Build Coastguard Worker 				    "Unexpected first unset bit");
357*1208bc7eSAndroid Build Coastguard Worker 			}
358*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
359*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
360*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_ffu(bitmap, binfo, i+1), i+2,
361*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
362*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_ffu(bitmap, binfo, i+2), i+2,
363*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
364*1208bc7eSAndroid Build Coastguard Worker 			if (i + 3 < nbits) {
365*1208bc7eSAndroid Build Coastguard Worker 				assert_zu_eq(bitmap_ffu(bitmap, binfo, i+3),
366*1208bc7eSAndroid Build Coastguard Worker 				    nbits, "Unexpected first unset bit");
367*1208bc7eSAndroid Build Coastguard Worker 			}
368*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
369*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
370*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_sfu(bitmap, binfo), i+2,
371*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
372*1208bc7eSAndroid Build Coastguard Worker 		}
373*1208bc7eSAndroid Build Coastguard Worker 	}
374*1208bc7eSAndroid Build Coastguard Worker 
375*1208bc7eSAndroid Build Coastguard Worker 	/*
376*1208bc7eSAndroid Build Coastguard Worker 	 * Unset the last bit, bubble another unset bit through the bitmap, and
377*1208bc7eSAndroid Build Coastguard Worker 	 * verify that bitmap_ffu() finds the correct bit for all four min_bit
378*1208bc7eSAndroid Build Coastguard Worker 	 * cases.
379*1208bc7eSAndroid Build Coastguard Worker 	 */
380*1208bc7eSAndroid Build Coastguard Worker 	if (nbits >= 3) {
381*1208bc7eSAndroid Build Coastguard Worker 		bitmap_unset(bitmap, binfo, nbits-1);
382*1208bc7eSAndroid Build Coastguard Worker 		for (size_t i = 0; i < nbits-1; i++) {
383*1208bc7eSAndroid Build Coastguard Worker 			bitmap_unset(bitmap, binfo, i);
384*1208bc7eSAndroid Build Coastguard Worker 			if (i > 0) {
385*1208bc7eSAndroid Build Coastguard Worker 				assert_zu_eq(bitmap_ffu(bitmap, binfo, i-1), i,
386*1208bc7eSAndroid Build Coastguard Worker 				    "Unexpected first unset bit");
387*1208bc7eSAndroid Build Coastguard Worker 			}
388*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
389*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
390*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_ffu(bitmap, binfo, i+1), nbits-1,
391*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
392*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_ffu(bitmap, binfo, nbits-1),
393*1208bc7eSAndroid Build Coastguard Worker 			    nbits-1, "Unexpected first unset bit");
394*1208bc7eSAndroid Build Coastguard Worker 
395*1208bc7eSAndroid Build Coastguard Worker 			assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
396*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected first unset bit");
397*1208bc7eSAndroid Build Coastguard Worker 		}
398*1208bc7eSAndroid Build Coastguard Worker 		assert_zu_eq(bitmap_sfu(bitmap, binfo), nbits-1,
399*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected first unset bit");
400*1208bc7eSAndroid Build Coastguard Worker 	}
401*1208bc7eSAndroid Build Coastguard Worker 
402*1208bc7eSAndroid Build Coastguard Worker 	free(bitmap);
403*1208bc7eSAndroid Build Coastguard Worker }
404*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_bitmap_xfu)405*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_bitmap_xfu) {
406*1208bc7eSAndroid Build Coastguard Worker 	size_t nbits;
407*1208bc7eSAndroid Build Coastguard Worker 
408*1208bc7eSAndroid Build Coastguard Worker 	for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
409*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo;
410*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_init(&binfo, nbits);
411*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_xfu_body(&binfo, nbits);
412*1208bc7eSAndroid Build Coastguard Worker 	}
413*1208bc7eSAndroid Build Coastguard Worker #define NB(nbits) {							\
414*1208bc7eSAndroid Build Coastguard Worker 		bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits);	\
415*1208bc7eSAndroid Build Coastguard Worker 		test_bitmap_xfu_body(&binfo, nbits);			\
416*1208bc7eSAndroid Build Coastguard Worker 	}
417*1208bc7eSAndroid Build Coastguard Worker 	NBITS_TAB
418*1208bc7eSAndroid Build Coastguard Worker #undef NB
419*1208bc7eSAndroid Build Coastguard Worker }
420*1208bc7eSAndroid Build Coastguard Worker TEST_END
421*1208bc7eSAndroid Build Coastguard Worker 
422*1208bc7eSAndroid Build Coastguard Worker int
main(void)423*1208bc7eSAndroid Build Coastguard Worker main(void) {
424*1208bc7eSAndroid Build Coastguard Worker 	return test(
425*1208bc7eSAndroid Build Coastguard Worker 	    test_bitmap_initializer,
426*1208bc7eSAndroid Build Coastguard Worker 	    test_bitmap_size,
427*1208bc7eSAndroid Build Coastguard Worker 	    test_bitmap_init,
428*1208bc7eSAndroid Build Coastguard Worker 	    test_bitmap_set,
429*1208bc7eSAndroid Build Coastguard Worker 	    test_bitmap_unset,
430*1208bc7eSAndroid Build Coastguard Worker 	    test_bitmap_xfu);
431*1208bc7eSAndroid Build Coastguard Worker }
432