xref: /linux/lib/tests/ffs_kunit.c (revision b3a7bb71bfcd56c8266af8cf2a5dee3802e7a449)
1*b3a7bb71SKees Cook // SPDX-License-Identifier: GPL-2.0-only
2*b3a7bb71SKees Cook /*
3*b3a7bb71SKees Cook  * KUnit tests for ffs()-family functions
4*b3a7bb71SKees Cook  */
5*b3a7bb71SKees Cook #include <kunit/test.h>
6*b3a7bb71SKees Cook #include <linux/bitops.h>
7*b3a7bb71SKees Cook 
8*b3a7bb71SKees Cook /*
9*b3a7bb71SKees Cook  * Test data structures
10*b3a7bb71SKees Cook  */
11*b3a7bb71SKees Cook struct ffs_test_case {
12*b3a7bb71SKees Cook 	unsigned long input;
13*b3a7bb71SKees Cook 	int expected_ffs;	/* ffs() result (1-based) */
14*b3a7bb71SKees Cook 	int expected_fls;	/* fls() result (1-based) */
15*b3a7bb71SKees Cook 	const char *description;
16*b3a7bb71SKees Cook };
17*b3a7bb71SKees Cook 
18*b3a7bb71SKees Cook struct ffs64_test_case {
19*b3a7bb71SKees Cook 	u64 input;
20*b3a7bb71SKees Cook 	int expected_fls64;		    /* fls64() result (1-based) */
21*b3a7bb71SKees Cook 	unsigned int expected_ffs64_0based; /* __ffs64() result (0-based) */
22*b3a7bb71SKees Cook 	const char *description;
23*b3a7bb71SKees Cook };
24*b3a7bb71SKees Cook 
25*b3a7bb71SKees Cook /*
26*b3a7bb71SKees Cook  * Basic edge cases - core functionality validation
27*b3a7bb71SKees Cook  */
28*b3a7bb71SKees Cook static const struct ffs_test_case basic_test_cases[] = {
29*b3a7bb71SKees Cook 	/* Zero case - special handling */
30*b3a7bb71SKees Cook 	{0x00000000, 0, 0, "zero value"},
31*b3a7bb71SKees Cook 
32*b3a7bb71SKees Cook 	/* Single bit patterns - powers of 2 */
33*b3a7bb71SKees Cook 	{0x00000001, 1, 1, "bit 0 set"},
34*b3a7bb71SKees Cook 	{0x00000002, 2, 2, "bit 1 set"},
35*b3a7bb71SKees Cook 	{0x00000004, 3, 3, "bit 2 set"},
36*b3a7bb71SKees Cook 	{0x00000008, 4, 4, "bit 3 set"},
37*b3a7bb71SKees Cook 	{0x00000010, 5, 5, "bit 4 set"},
38*b3a7bb71SKees Cook 	{0x00000020, 6, 6, "bit 5 set"},
39*b3a7bb71SKees Cook 	{0x00000040, 7, 7, "bit 6 set"},
40*b3a7bb71SKees Cook 	{0x00000080, 8, 8, "bit 7 set"},
41*b3a7bb71SKees Cook 	{0x00000100, 9, 9, "bit 8 set"},
42*b3a7bb71SKees Cook 	{0x00008000, 16, 16, "bit 15 set"},
43*b3a7bb71SKees Cook 	{0x00010000, 17, 17, "bit 16 set"},
44*b3a7bb71SKees Cook 	{0x40000000, 31, 31, "bit 30 set"},
45*b3a7bb71SKees Cook 	{0x80000000, 32, 32, "bit 31 set (sign bit)"},
46*b3a7bb71SKees Cook 
47*b3a7bb71SKees Cook 	/* Maximum values */
48*b3a7bb71SKees Cook 	{0xFFFFFFFF, 1, 32, "all bits set"},
49*b3a7bb71SKees Cook 
50*b3a7bb71SKees Cook 	/* Multiple bit patterns */
51*b3a7bb71SKees Cook 	{0x00000003, 1, 2, "bits 0-1 set"},
52*b3a7bb71SKees Cook 	{0x00000007, 1, 3, "bits 0-2 set"},
53*b3a7bb71SKees Cook 	{0x0000000F, 1, 4, "bits 0-3 set"},
54*b3a7bb71SKees Cook 	{0x000000FF, 1, 8, "bits 0-7 set"},
55*b3a7bb71SKees Cook 	{0x0000FFFF, 1, 16, "bits 0-15 set"},
56*b3a7bb71SKees Cook 	{0x7FFFFFFF, 1, 31, "bits 0-30 set"},
57*b3a7bb71SKees Cook 
58*b3a7bb71SKees Cook 	/* Sparse patterns */
59*b3a7bb71SKees Cook 	{0x00000101, 1, 9, "bits 0,8 set"},
60*b3a7bb71SKees Cook 	{0x00001001, 1, 13, "bits 0,12 set"},
61*b3a7bb71SKees Cook 	{0x80000001, 1, 32, "bits 0,31 set"},
62*b3a7bb71SKees Cook 	{0x40000002, 2, 31, "bits 1,30 set"},
63*b3a7bb71SKees Cook };
64*b3a7bb71SKees Cook 
65*b3a7bb71SKees Cook /*
66*b3a7bb71SKees Cook  * 64-bit test cases
67*b3a7bb71SKees Cook  */
68*b3a7bb71SKees Cook static const struct ffs64_test_case ffs64_test_cases[] = {
69*b3a7bb71SKees Cook 	/* Zero case */
70*b3a7bb71SKees Cook 	{0x0000000000000000ULL, 0, 0, "zero value"},
71*b3a7bb71SKees Cook 
72*b3a7bb71SKees Cook 	/* Single bit patterns */
73*b3a7bb71SKees Cook 	{0x0000000000000001ULL, 1, 0, "bit 0 set"},
74*b3a7bb71SKees Cook 	{0x0000000000000002ULL, 2, 1, "bit 1 set"},
75*b3a7bb71SKees Cook 	{0x0000000000000004ULL, 3, 2, "bit 2 set"},
76*b3a7bb71SKees Cook 	{0x0000000000000008ULL, 4, 3, "bit 3 set"},
77*b3a7bb71SKees Cook 	{0x0000000000008000ULL, 16, 15, "bit 15 set"},
78*b3a7bb71SKees Cook 	{0x0000000000010000ULL, 17, 16, "bit 16 set"},
79*b3a7bb71SKees Cook 	{0x0000000080000000ULL, 32, 31, "bit 31 set"},
80*b3a7bb71SKees Cook 	{0x0000000100000000ULL, 33, 32, "bit 32 set"},
81*b3a7bb71SKees Cook 	{0x0000000200000000ULL, 34, 33, "bit 33 set"},
82*b3a7bb71SKees Cook 	{0x4000000000000000ULL, 63, 62, "bit 62 set"},
83*b3a7bb71SKees Cook 	{0x8000000000000000ULL, 64, 63, "bit 63 set (sign bit)"},
84*b3a7bb71SKees Cook 
85*b3a7bb71SKees Cook 	/* Maximum values */
86*b3a7bb71SKees Cook 	{0xFFFFFFFFFFFFFFFFULL, 64, 0, "all bits set"},
87*b3a7bb71SKees Cook 
88*b3a7bb71SKees Cook 	/* Cross 32-bit boundary patterns */
89*b3a7bb71SKees Cook 	{0x00000000FFFFFFFFULL, 32, 0, "lower 32 bits set"},
90*b3a7bb71SKees Cook 	{0xFFFFFFFF00000000ULL, 64, 32, "upper 32 bits set"},
91*b3a7bb71SKees Cook 	{0x8000000000000001ULL, 64, 0, "bits 0,63 set"},
92*b3a7bb71SKees Cook 	{0x4000000000000002ULL, 63, 1, "bits 1,62 set"},
93*b3a7bb71SKees Cook 
94*b3a7bb71SKees Cook 	/* Mixed patterns */
95*b3a7bb71SKees Cook 	{0x00000001FFFFFFFFULL, 33, 0, "bit 32 + lower 32 bits"},
96*b3a7bb71SKees Cook 	{0xFFFFFFFF80000000ULL, 64, 31, "upper 32 bits + bit 31"},
97*b3a7bb71SKees Cook };
98*b3a7bb71SKees Cook 
99*b3a7bb71SKees Cook /*
100*b3a7bb71SKees Cook  * Helper function to validate ffs results with detailed error messages
101*b3a7bb71SKees Cook  */
102*b3a7bb71SKees Cook static void validate_ffs_result(struct kunit *test, unsigned long input,
103*b3a7bb71SKees Cook 				int actual, int expected, const char *func_name,
104*b3a7bb71SKees Cook 				const char *description)
105*b3a7bb71SKees Cook {
106*b3a7bb71SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, actual, expected,
107*b3a7bb71SKees Cook 			    "%s(0x%08lx) [%s]: expected %d, got %d",
108*b3a7bb71SKees Cook 			    func_name, input, description, expected, actual);
109*b3a7bb71SKees Cook }
110*b3a7bb71SKees Cook 
111*b3a7bb71SKees Cook /*
112*b3a7bb71SKees Cook  * Helper function to validate 64-bit ffs results
113*b3a7bb71SKees Cook  */
114*b3a7bb71SKees Cook static void validate_ffs64_result(struct kunit *test, u64 input,
115*b3a7bb71SKees Cook 				  int actual, int expected, const char *func_name,
116*b3a7bb71SKees Cook 				  const char *description)
117*b3a7bb71SKees Cook {
118*b3a7bb71SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, actual, expected,
119*b3a7bb71SKees Cook 			    "%s(0x%016llx) [%s]: expected %d, got %d",
120*b3a7bb71SKees Cook 			    func_name, input, description, expected, actual);
121*b3a7bb71SKees Cook }
122*b3a7bb71SKees Cook 
123*b3a7bb71SKees Cook /*
124*b3a7bb71SKees Cook  * Helper function to validate mathematical relationships between functions
125*b3a7bb71SKees Cook  */
126*b3a7bb71SKees Cook static void validate_ffs_relationships(struct kunit *test, unsigned long input)
127*b3a7bb71SKees Cook {
128*b3a7bb71SKees Cook 	int ffs_result;
129*b3a7bb71SKees Cook 	int fls_result;
130*b3a7bb71SKees Cook 	unsigned int ffs_0based;
131*b3a7bb71SKees Cook 	unsigned int fls_0based;
132*b3a7bb71SKees Cook 
133*b3a7bb71SKees Cook 	if (input == 0) {
134*b3a7bb71SKees Cook 		/* Special case: zero input */
135*b3a7bb71SKees Cook 		KUNIT_EXPECT_EQ(test, ffs(input), 0);
136*b3a7bb71SKees Cook 		KUNIT_EXPECT_EQ(test, fls(input), 0);
137*b3a7bb71SKees Cook 		/* __ffs and __fls are undefined for 0, but often return specific values */
138*b3a7bb71SKees Cook 		return;
139*b3a7bb71SKees Cook 	}
140*b3a7bb71SKees Cook 
141*b3a7bb71SKees Cook 	ffs_result = ffs(input);
142*b3a7bb71SKees Cook 	fls_result = fls(input);
143*b3a7bb71SKees Cook 	ffs_0based = __ffs(input);
144*b3a7bb71SKees Cook 	fls_0based = __fls(input);
145*b3a7bb71SKees Cook 
146*b3a7bb71SKees Cook 	/* Relationship: ffs(x) == __ffs(x) + 1 for x != 0 */
147*b3a7bb71SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, ffs_result, ffs_0based + 1,
148*b3a7bb71SKees Cook 			    "ffs(0x%08lx) != __ffs(0x%08lx) + 1: %d != %u + 1",
149*b3a7bb71SKees Cook 			    input, input, ffs_result, ffs_0based);
150*b3a7bb71SKees Cook 
151*b3a7bb71SKees Cook 	/* Relationship: fls(x) == __fls(x) + 1 for x != 0 */
152*b3a7bb71SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, fls_result, fls_0based + 1,
153*b3a7bb71SKees Cook 			    "fls(0x%08lx) != __fls(0x%08lx) + 1: %d != %u + 1",
154*b3a7bb71SKees Cook 			    input, input, fls_result, fls_0based);
155*b3a7bb71SKees Cook 
156*b3a7bb71SKees Cook 	/* Range validation */
157*b3a7bb71SKees Cook 	KUNIT_EXPECT_GE(test, ffs_result, 1);
158*b3a7bb71SKees Cook 	KUNIT_EXPECT_LE(test, ffs_result, BITS_PER_LONG);
159*b3a7bb71SKees Cook 	KUNIT_EXPECT_GE(test, fls_result, 1);
160*b3a7bb71SKees Cook 	KUNIT_EXPECT_LE(test, fls_result, BITS_PER_LONG);
161*b3a7bb71SKees Cook }
162*b3a7bb71SKees Cook 
163*b3a7bb71SKees Cook /*
164*b3a7bb71SKees Cook  * Helper function to validate 64-bit relationships
165*b3a7bb71SKees Cook  */
166*b3a7bb71SKees Cook static void validate_ffs64_relationships(struct kunit *test, u64 input)
167*b3a7bb71SKees Cook {
168*b3a7bb71SKees Cook 	int fls64_result;
169*b3a7bb71SKees Cook 	unsigned int ffs64_0based;
170*b3a7bb71SKees Cook 
171*b3a7bb71SKees Cook 	if (input == 0) {
172*b3a7bb71SKees Cook 		KUNIT_EXPECT_EQ(test, fls64(input), 0);
173*b3a7bb71SKees Cook 		return;
174*b3a7bb71SKees Cook 	}
175*b3a7bb71SKees Cook 
176*b3a7bb71SKees Cook 	fls64_result = fls64(input);
177*b3a7bb71SKees Cook 	ffs64_0based = __ffs64(input);
178*b3a7bb71SKees Cook 
179*b3a7bb71SKees Cook 	/* Range validation */
180*b3a7bb71SKees Cook 	KUNIT_EXPECT_GE(test, fls64_result, 1);
181*b3a7bb71SKees Cook 	KUNIT_EXPECT_LE(test, fls64_result, 64);
182*b3a7bb71SKees Cook 	KUNIT_EXPECT_LT(test, ffs64_0based, 64);
183*b3a7bb71SKees Cook 
184*b3a7bb71SKees Cook 	/*
185*b3a7bb71SKees Cook 	 * Relationships with 32-bit functions should hold for small values
186*b3a7bb71SKees Cook 	 * on all architectures.
187*b3a7bb71SKees Cook 	 */
188*b3a7bb71SKees Cook 	if (input <= 0xFFFFFFFFULL) {
189*b3a7bb71SKees Cook 		unsigned long input_32 = (unsigned long)input;
190*b3a7bb71SKees Cook 		KUNIT_EXPECT_EQ_MSG(test, fls64(input), fls(input_32),
191*b3a7bb71SKees Cook 				    "fls64(0x%llx) != fls(0x%lx): %d != %d",
192*b3a7bb71SKees Cook 				    input, input_32, fls64(input), fls(input_32));
193*b3a7bb71SKees Cook 
194*b3a7bb71SKees Cook 		if (input != 0) {
195*b3a7bb71SKees Cook 			KUNIT_EXPECT_EQ_MSG(test, __ffs64(input), __ffs(input_32),
196*b3a7bb71SKees Cook 					    "__ffs64(0x%llx) != __ffs(0x%lx): %lu != %lu",
197*b3a7bb71SKees Cook 					    input, input_32,
198*b3a7bb71SKees Cook 					    (unsigned long)__ffs64(input),
199*b3a7bb71SKees Cook 					    (unsigned long)__ffs(input_32));
200*b3a7bb71SKees Cook 		}
201*b3a7bb71SKees Cook 	}
202*b3a7bb71SKees Cook }
203*b3a7bb71SKees Cook 
204*b3a7bb71SKees Cook /*
205*b3a7bb71SKees Cook  * Test basic correctness of all ffs-family functions
206*b3a7bb71SKees Cook  */
207*b3a7bb71SKees Cook static void ffs_basic_correctness_test(struct kunit *test)
208*b3a7bb71SKees Cook {
209*b3a7bb71SKees Cook 	int i;
210*b3a7bb71SKees Cook 
211*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(basic_test_cases); i++) {
212*b3a7bb71SKees Cook 		const struct ffs_test_case *tc = &basic_test_cases[i];
213*b3a7bb71SKees Cook 
214*b3a7bb71SKees Cook 		/* Test ffs() */
215*b3a7bb71SKees Cook 		validate_ffs_result(test, tc->input, ffs(tc->input),
216*b3a7bb71SKees Cook 				    tc->expected_ffs, "ffs", tc->description);
217*b3a7bb71SKees Cook 
218*b3a7bb71SKees Cook 		/* Test fls() */
219*b3a7bb71SKees Cook 		validate_ffs_result(test, tc->input, fls(tc->input),
220*b3a7bb71SKees Cook 				    tc->expected_fls, "fls", tc->description);
221*b3a7bb71SKees Cook 
222*b3a7bb71SKees Cook 		/* Test __ffs() - skip zero case as it's undefined */
223*b3a7bb71SKees Cook 		if (tc->input != 0) {
224*b3a7bb71SKees Cook 			/* Calculate expected __ffs() result: __ffs(x) == ffs(x) - 1 */
225*b3a7bb71SKees Cook 			unsigned int expected_ffs_0based = tc->expected_ffs - 1;
226*b3a7bb71SKees Cook 			validate_ffs_result(test, tc->input, __ffs(tc->input),
227*b3a7bb71SKees Cook 					    expected_ffs_0based, "__ffs", tc->description);
228*b3a7bb71SKees Cook 		}
229*b3a7bb71SKees Cook 
230*b3a7bb71SKees Cook 		/* Test __fls() - skip zero case as it's undefined */
231*b3a7bb71SKees Cook 		if (tc->input != 0) {
232*b3a7bb71SKees Cook 			/* Calculate expected __fls() result: __fls(x) == fls(x) - 1 */
233*b3a7bb71SKees Cook 			unsigned int expected_fls_0based = tc->expected_fls - 1;
234*b3a7bb71SKees Cook 			validate_ffs_result(test, tc->input, __fls(tc->input),
235*b3a7bb71SKees Cook 					    expected_fls_0based, "__fls", tc->description);
236*b3a7bb71SKees Cook 		}
237*b3a7bb71SKees Cook 	}
238*b3a7bb71SKees Cook }
239*b3a7bb71SKees Cook 
240*b3a7bb71SKees Cook /*
241*b3a7bb71SKees Cook  * Test 64-bit function correctness
242*b3a7bb71SKees Cook  */
243*b3a7bb71SKees Cook static void ffs64_correctness_test(struct kunit *test)
244*b3a7bb71SKees Cook {
245*b3a7bb71SKees Cook 	int i;
246*b3a7bb71SKees Cook 
247*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(ffs64_test_cases); i++) {
248*b3a7bb71SKees Cook 		const struct ffs64_test_case *tc = &ffs64_test_cases[i];
249*b3a7bb71SKees Cook 
250*b3a7bb71SKees Cook 		/* Test fls64() */
251*b3a7bb71SKees Cook 		validate_ffs64_result(test, tc->input, fls64(tc->input),
252*b3a7bb71SKees Cook 				      tc->expected_fls64, "fls64", tc->description);
253*b3a7bb71SKees Cook 
254*b3a7bb71SKees Cook 		/* Test __ffs64() - skip zero case as it's undefined */
255*b3a7bb71SKees Cook 		if (tc->input != 0) {
256*b3a7bb71SKees Cook 			validate_ffs64_result(test, tc->input, __ffs64(tc->input),
257*b3a7bb71SKees Cook 					      tc->expected_ffs64_0based, "__ffs64",
258*b3a7bb71SKees Cook 					      tc->description);
259*b3a7bb71SKees Cook 		}
260*b3a7bb71SKees Cook 	}
261*b3a7bb71SKees Cook }
262*b3a7bb71SKees Cook 
263*b3a7bb71SKees Cook /*
264*b3a7bb71SKees Cook  * Test mathematical relationships between functions
265*b3a7bb71SKees Cook  */
266*b3a7bb71SKees Cook static void ffs_mathematical_relationships_test(struct kunit *test)
267*b3a7bb71SKees Cook {
268*b3a7bb71SKees Cook 	int i;
269*b3a7bb71SKees Cook 
270*b3a7bb71SKees Cook 	/* Test basic cases */
271*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(basic_test_cases); i++) {
272*b3a7bb71SKees Cook 		validate_ffs_relationships(test, basic_test_cases[i].input);
273*b3a7bb71SKees Cook 	}
274*b3a7bb71SKees Cook 
275*b3a7bb71SKees Cook 	/* Test 64-bit cases */
276*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(ffs64_test_cases); i++) {
277*b3a7bb71SKees Cook 		validate_ffs64_relationships(test, ffs64_test_cases[i].input);
278*b3a7bb71SKees Cook 	}
279*b3a7bb71SKees Cook }
280*b3a7bb71SKees Cook 
281*b3a7bb71SKees Cook /*
282*b3a7bb71SKees Cook  * Test edge cases and boundary conditions
283*b3a7bb71SKees Cook  */
284*b3a7bb71SKees Cook static void ffs_edge_cases_test(struct kunit *test)
285*b3a7bb71SKees Cook {
286*b3a7bb71SKees Cook 	unsigned long test_patterns[] = {
287*b3a7bb71SKees Cook 		/* Powers of 2 */
288*b3a7bb71SKees Cook 		1UL, 2UL, 4UL, 8UL, 16UL, 32UL, 64UL, 128UL,
289*b3a7bb71SKees Cook 		256UL, 512UL, 1024UL, 2048UL, 4096UL, 8192UL,
290*b3a7bb71SKees Cook 
291*b3a7bb71SKees Cook 		/* Powers of 2 minus 1 */
292*b3a7bb71SKees Cook 		1UL, 3UL, 7UL, 15UL, 31UL, 63UL, 127UL, 255UL,
293*b3a7bb71SKees Cook 		511UL, 1023UL, 2047UL, 4095UL, 8191UL,
294*b3a7bb71SKees Cook 
295*b3a7bb71SKees Cook 		/* Boundary values */
296*b3a7bb71SKees Cook 		0x7FFFFFFFUL,	/* Maximum positive 32-bit */
297*b3a7bb71SKees Cook 		0x80000000UL,	/* Minimum negative 32-bit */
298*b3a7bb71SKees Cook 		0xFFFFFFFFUL,	/* Maximum 32-bit unsigned */
299*b3a7bb71SKees Cook 	};
300*b3a7bb71SKees Cook 	int i;
301*b3a7bb71SKees Cook 
302*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(test_patterns); i++) {
303*b3a7bb71SKees Cook 		validate_ffs_relationships(test, test_patterns[i]);
304*b3a7bb71SKees Cook 	}
305*b3a7bb71SKees Cook }
306*b3a7bb71SKees Cook 
307*b3a7bb71SKees Cook /*
308*b3a7bb71SKees Cook  * Test 64-bit edge cases
309*b3a7bb71SKees Cook  */
310*b3a7bb71SKees Cook static void ffs64_edge_cases_test(struct kunit *test)
311*b3a7bb71SKees Cook {
312*b3a7bb71SKees Cook 	u64 test_patterns_64[] = {
313*b3a7bb71SKees Cook 		/* 64-bit powers of 2 */
314*b3a7bb71SKees Cook 		0x0000000100000000ULL,	/* 2^32 */
315*b3a7bb71SKees Cook 		0x0000000200000000ULL,	/* 2^33 */
316*b3a7bb71SKees Cook 		0x0000000400000000ULL,	/* 2^34 */
317*b3a7bb71SKees Cook 		0x0000001000000000ULL,	/* 2^36 */
318*b3a7bb71SKees Cook 		0x0000010000000000ULL,	/* 2^40 */
319*b3a7bb71SKees Cook 		0x0001000000000000ULL,	/* 2^48 */
320*b3a7bb71SKees Cook 		0x0100000000000000ULL,	/* 2^56 */
321*b3a7bb71SKees Cook 		0x4000000000000000ULL,	/* 2^62 */
322*b3a7bb71SKees Cook 		0x8000000000000000ULL,	/* 2^63 */
323*b3a7bb71SKees Cook 
324*b3a7bb71SKees Cook 		/* Cross-boundary patterns */
325*b3a7bb71SKees Cook 		0x00000000FFFFFFFFULL,	/* Lower 32 bits */
326*b3a7bb71SKees Cook 		0xFFFFFFFF00000000ULL,	/* Upper 32 bits */
327*b3a7bb71SKees Cook 		0x7FFFFFFFFFFFFFFFULL,	/* Maximum positive 64-bit */
328*b3a7bb71SKees Cook 		0xFFFFFFFFFFFFFFFFULL,	/* Maximum 64-bit unsigned */
329*b3a7bb71SKees Cook 	};
330*b3a7bb71SKees Cook 	int i;
331*b3a7bb71SKees Cook 
332*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(test_patterns_64); i++) {
333*b3a7bb71SKees Cook 		validate_ffs64_relationships(test, test_patterns_64[i]);
334*b3a7bb71SKees Cook 	}
335*b3a7bb71SKees Cook }
336*b3a7bb71SKees Cook 
337*b3a7bb71SKees Cook /*
338*b3a7bb71SKees Cook  * ffz() test data - Find First Zero bit test cases
339*b3a7bb71SKees Cook  */
340*b3a7bb71SKees Cook struct ffz_test_case {
341*b3a7bb71SKees Cook 	unsigned long input;
342*b3a7bb71SKees Cook 	unsigned long expected_ffz;
343*b3a7bb71SKees Cook 	const char *description;
344*b3a7bb71SKees Cook };
345*b3a7bb71SKees Cook 
346*b3a7bb71SKees Cook static const struct ffz_test_case ffz_test_cases[] = {
347*b3a7bb71SKees Cook 	/* Zero bits in specific positions */
348*b3a7bb71SKees Cook 	{0xFFFFFFFE, 0, "bit 0 is zero"},      /* ...11111110 */
349*b3a7bb71SKees Cook 	{0xFFFFFFFD, 1, "bit 1 is zero"},      /* ...11111101 */
350*b3a7bb71SKees Cook 	{0xFFFFFFFB, 2, "bit 2 is zero"},      /* ...11111011 */
351*b3a7bb71SKees Cook 	{0xFFFFFFF7, 3, "bit 3 is zero"},      /* ...11110111 */
352*b3a7bb71SKees Cook 	{0xFFFFFFEF, 4, "bit 4 is zero"},      /* ...11101111 */
353*b3a7bb71SKees Cook 	{0xFFFFFFDF, 5, "bit 5 is zero"},      /* ...11011111 */
354*b3a7bb71SKees Cook 	{0xFFFFFFBF, 6, "bit 6 is zero"},      /* ...10111111 */
355*b3a7bb71SKees Cook 	{0xFFFFFF7F, 7, "bit 7 is zero"},      /* ...01111111 */
356*b3a7bb71SKees Cook 	{0xFFFFFEFF, 8, "bit 8 is zero"},      /* Gap in bit 8 */
357*b3a7bb71SKees Cook 	{0xFFFF7FFF, 15, "bit 15 is zero"},    /* Gap in bit 15 */
358*b3a7bb71SKees Cook 	{0xFFFEFFFF, 16, "bit 16 is zero"},    /* Gap in bit 16 */
359*b3a7bb71SKees Cook 	{0xBFFFFFFF, 30, "bit 30 is zero"},    /* Gap in bit 30 */
360*b3a7bb71SKees Cook 	{0x7FFFFFFF, 31, "bit 31 is zero"},    /* 01111111... */
361*b3a7bb71SKees Cook 
362*b3a7bb71SKees Cook 	/* Multiple zero patterns */
363*b3a7bb71SKees Cook 	{0xFFFFFFFC, 0, "bits 0-1 are zero"},  /* ...11111100 */
364*b3a7bb71SKees Cook 	{0xFFFFFFF8, 0, "bits 0-2 are zero"},  /* ...11111000 */
365*b3a7bb71SKees Cook 	{0xFFFFFFF0, 0, "bits 0-3 are zero"},  /* ...11110000 */
366*b3a7bb71SKees Cook 	{0xFFFFFF00, 0, "bits 0-7 are zero"},  /* ...00000000 */
367*b3a7bb71SKees Cook 	{0xFFFF0000, 0, "bits 0-15 are zero"}, /* Lower 16 bits zero */
368*b3a7bb71SKees Cook 
369*b3a7bb71SKees Cook 	/* All zeros (special case) */
370*b3a7bb71SKees Cook 	{0x00000000, 0, "all bits zero"},
371*b3a7bb71SKees Cook 
372*b3a7bb71SKees Cook 	/* Complex patterns */
373*b3a7bb71SKees Cook 	{0xFFFDFFFF, 17, "bit 17 is zero"},    /* Gap in bit 17 */
374*b3a7bb71SKees Cook 	{0xFFF7FFFF, 19, "bit 19 is zero"},    /* Gap in bit 19 */
375*b3a7bb71SKees Cook 	{0xF7FFFFFF, 27, "bit 27 is zero"},    /* Gap in bit 27 */
376*b3a7bb71SKees Cook 	{0xDFFFFFFF, 29, "bit 29 is zero"},    /* Gap in bit 29 */
377*b3a7bb71SKees Cook };
378*b3a7bb71SKees Cook 
379*b3a7bb71SKees Cook /*
380*b3a7bb71SKees Cook  * Test basic correctness of ffz() function
381*b3a7bb71SKees Cook  */
382*b3a7bb71SKees Cook static void ffz_basic_correctness_test(struct kunit *test)
383*b3a7bb71SKees Cook {
384*b3a7bb71SKees Cook 	int i;
385*b3a7bb71SKees Cook 
386*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(ffz_test_cases); i++) {
387*b3a7bb71SKees Cook 		const struct ffz_test_case *tc = &ffz_test_cases[i];
388*b3a7bb71SKees Cook 		unsigned long result = ffz(tc->input);
389*b3a7bb71SKees Cook 
390*b3a7bb71SKees Cook 		KUNIT_EXPECT_EQ_MSG(test, result, tc->expected_ffz,
391*b3a7bb71SKees Cook 				    "ffz(0x%08lx) [%s]: expected %lu, got %lu",
392*b3a7bb71SKees Cook 				    tc->input, tc->description, tc->expected_ffz, result);
393*b3a7bb71SKees Cook 	}
394*b3a7bb71SKees Cook }
395*b3a7bb71SKees Cook 
396*b3a7bb71SKees Cook /*
397*b3a7bb71SKees Cook  * Test mathematical relationships between ffz() and other functions
398*b3a7bb71SKees Cook  */
399*b3a7bb71SKees Cook static void validate_ffz_relationships(struct kunit *test, unsigned long input)
400*b3a7bb71SKees Cook {
401*b3a7bb71SKees Cook 	unsigned long ffz_result;
402*b3a7bb71SKees Cook 
403*b3a7bb71SKees Cook 	if (input == 0) {
404*b3a7bb71SKees Cook 		/* ffz(0) should return 0 (first zero bit is at position 0) */
405*b3a7bb71SKees Cook 		KUNIT_EXPECT_EQ(test, ffz(input), 0);
406*b3a7bb71SKees Cook 		return;
407*b3a7bb71SKees Cook 	}
408*b3a7bb71SKees Cook 
409*b3a7bb71SKees Cook 	if (input == ~0UL) {
410*b3a7bb71SKees Cook 		/* ffz(~0) is undefined (no zero bits) - just verify it doesn't crash */
411*b3a7bb71SKees Cook 		ffz_result = ffz(input);
412*b3a7bb71SKees Cook 		/* Implementation-defined behavior, just ensure it completes */
413*b3a7bb71SKees Cook 		return;
414*b3a7bb71SKees Cook 	}
415*b3a7bb71SKees Cook 
416*b3a7bb71SKees Cook 	ffz_result = ffz(input);
417*b3a7bb71SKees Cook 
418*b3a7bb71SKees Cook 	/* Range validation - result should be within valid bit range */
419*b3a7bb71SKees Cook 	KUNIT_EXPECT_LT(test, ffz_result, BITS_PER_LONG);
420*b3a7bb71SKees Cook 
421*b3a7bb71SKees Cook 	/* Verify the bit at ffz_result position is actually zero */
422*b3a7bb71SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, (input >> ffz_result) & 1, 0,
423*b3a7bb71SKees Cook 			    "ffz(0x%08lx) = %lu, but bit %lu is not zero",
424*b3a7bb71SKees Cook 			    input, ffz_result, ffz_result);
425*b3a7bb71SKees Cook 
426*b3a7bb71SKees Cook 	/* Core relationship: if we set the ffz bit, ffz should find a different bit */
427*b3a7bb71SKees Cook 	if (ffz_result < BITS_PER_LONG - 1) {
428*b3a7bb71SKees Cook 		unsigned long modified = input | (1UL << ffz_result);
429*b3a7bb71SKees Cook 		if (modified != ~0UL) { /* Skip if all bits would be set */
430*b3a7bb71SKees Cook 			unsigned long new_ffz = ffz(modified);
431*b3a7bb71SKees Cook 			KUNIT_EXPECT_NE_MSG(test, new_ffz, ffz_result,
432*b3a7bb71SKees Cook 					    "ffz(0x%08lx) = %lu, but setting that bit doesn't change ffz result",
433*b3a7bb71SKees Cook 					    input, ffz_result);
434*b3a7bb71SKees Cook 		}
435*b3a7bb71SKees Cook 	}
436*b3a7bb71SKees Cook }
437*b3a7bb71SKees Cook 
438*b3a7bb71SKees Cook static void ffz_mathematical_relationships_test(struct kunit *test)
439*b3a7bb71SKees Cook {
440*b3a7bb71SKees Cook 	unsigned long test_patterns[] = {
441*b3a7bb71SKees Cook 		/* Powers of 2 with one bit clear */
442*b3a7bb71SKees Cook 		0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7,
443*b3a7bb71SKees Cook 		0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F,
444*b3a7bb71SKees Cook 
445*b3a7bb71SKees Cook 		/* Multiple patterns */
446*b3a7bb71SKees Cook 		0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF00000,
447*b3a7bb71SKees Cook 		0x7FFFFFFF, 0x3FFFFFFF, 0x1FFFFFFF, 0x0FFFFFFF,
448*b3a7bb71SKees Cook 
449*b3a7bb71SKees Cook 		/* Complex bit patterns */
450*b3a7bb71SKees Cook 		0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333,
451*b3a7bb71SKees Cook 		0xF0F0F0F0, 0x0F0F0F0F, 0xFF00FF00, 0x00FF00FF,
452*b3a7bb71SKees Cook 	};
453*b3a7bb71SKees Cook 	int i;
454*b3a7bb71SKees Cook 
455*b3a7bb71SKees Cook 	/* Test basic test cases */
456*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(ffz_test_cases); i++) {
457*b3a7bb71SKees Cook 		validate_ffz_relationships(test, ffz_test_cases[i].input);
458*b3a7bb71SKees Cook 	}
459*b3a7bb71SKees Cook 
460*b3a7bb71SKees Cook 	/* Test additional patterns */
461*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(test_patterns); i++) {
462*b3a7bb71SKees Cook 		validate_ffz_relationships(test, test_patterns[i]);
463*b3a7bb71SKees Cook 	}
464*b3a7bb71SKees Cook }
465*b3a7bb71SKees Cook 
466*b3a7bb71SKees Cook /*
467*b3a7bb71SKees Cook  * Test edge cases and boundary conditions for ffz()
468*b3a7bb71SKees Cook  */
469*b3a7bb71SKees Cook static void ffz_edge_cases_test(struct kunit *test)
470*b3a7bb71SKees Cook {
471*b3a7bb71SKees Cook 	unsigned long edge_patterns[] = {
472*b3a7bb71SKees Cook 		/* Boundary values */
473*b3a7bb71SKees Cook 		0x00000000,  /* All zeros */
474*b3a7bb71SKees Cook 		0x80000000,  /* Only MSB set */
475*b3a7bb71SKees Cook 		0x00000001,  /* Only LSB set */
476*b3a7bb71SKees Cook 		0x7FFFFFFF,  /* MSB clear */
477*b3a7bb71SKees Cook 		0xFFFFFFFE,  /* LSB clear */
478*b3a7bb71SKees Cook 
479*b3a7bb71SKees Cook 		/* Powers of 2 complement patterns (one zero bit each) */
480*b3a7bb71SKees Cook 		~(1UL << 0),  ~(1UL << 1),  ~(1UL << 2),  ~(1UL << 3),
481*b3a7bb71SKees Cook 		~(1UL << 4),  ~(1UL << 8),  ~(1UL << 16), ~(1UL << 31),
482*b3a7bb71SKees Cook 
483*b3a7bb71SKees Cook 		/* Walking zero patterns */
484*b3a7bb71SKees Cook 		0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7,
485*b3a7bb71SKees Cook 		0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F,
486*b3a7bb71SKees Cook 		0xFFFFFEFF, 0xFFFFFDFF, 0xFFFFFBFF, 0xFFFFF7FF,
487*b3a7bb71SKees Cook 
488*b3a7bb71SKees Cook 		/* Multiple zeros */
489*b3a7bb71SKees Cook 		0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF00000,
490*b3a7bb71SKees Cook 		0xFF000000, 0xF0000000, 0x00000000,
491*b3a7bb71SKees Cook 	};
492*b3a7bb71SKees Cook 	int i;
493*b3a7bb71SKees Cook 
494*b3a7bb71SKees Cook 	for (i = 0; i < ARRAY_SIZE(edge_patterns); i++) {
495*b3a7bb71SKees Cook 		validate_ffz_relationships(test, edge_patterns[i]);
496*b3a7bb71SKees Cook 	}
497*b3a7bb71SKees Cook }
498*b3a7bb71SKees Cook 
499*b3a7bb71SKees Cook /*
500*b3a7bb71SKees Cook  * KUnit test case definitions
501*b3a7bb71SKees Cook  */
502*b3a7bb71SKees Cook static struct kunit_case ffs_test_cases[] = {
503*b3a7bb71SKees Cook 	KUNIT_CASE(ffs_basic_correctness_test),
504*b3a7bb71SKees Cook 	KUNIT_CASE(ffs64_correctness_test),
505*b3a7bb71SKees Cook 	KUNIT_CASE(ffs_mathematical_relationships_test),
506*b3a7bb71SKees Cook 	KUNIT_CASE(ffs_edge_cases_test),
507*b3a7bb71SKees Cook 	KUNIT_CASE(ffs64_edge_cases_test),
508*b3a7bb71SKees Cook 	KUNIT_CASE(ffz_basic_correctness_test),
509*b3a7bb71SKees Cook 	KUNIT_CASE(ffz_mathematical_relationships_test),
510*b3a7bb71SKees Cook 	KUNIT_CASE(ffz_edge_cases_test),
511*b3a7bb71SKees Cook 	KUNIT_CASE(ffs_attribute_const_test),
512*b3a7bb71SKees Cook 	{}
513*b3a7bb71SKees Cook };
514*b3a7bb71SKees Cook 
515*b3a7bb71SKees Cook /*
516*b3a7bb71SKees Cook  * KUnit test suite definition
517*b3a7bb71SKees Cook  */
518*b3a7bb71SKees Cook static struct kunit_suite ffs_test_suite = {
519*b3a7bb71SKees Cook 	.name = "ffs",
520*b3a7bb71SKees Cook 	.test_cases = ffs_test_cases,
521*b3a7bb71SKees Cook };
522*b3a7bb71SKees Cook 
523*b3a7bb71SKees Cook kunit_test_suites(&ffs_test_suite);
524*b3a7bb71SKees Cook 
525*b3a7bb71SKees Cook MODULE_DESCRIPTION("KUnit tests for ffs()-family functions");
526*b3a7bb71SKees Cook MODULE_LICENSE("GPL");
527