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