xref: /linux/lib/tests/scanf_kunit.c (revision 97c1f302f2bc318ed88aa4a49641a3b60b33f7a5)
1*97c1f302STamir Duberstein // SPDX-License-Identifier: GPL-2.0-only
2*97c1f302STamir Duberstein /*
3*97c1f302STamir Duberstein  * Test cases for sscanf facility.
4*97c1f302STamir Duberstein  */
5*97c1f302STamir Duberstein 
6*97c1f302STamir Duberstein #include <kunit/test.h>
7*97c1f302STamir Duberstein #include <linux/bitops.h>
8*97c1f302STamir Duberstein #include <linux/kernel.h>
9*97c1f302STamir Duberstein #include <linux/module.h>
10*97c1f302STamir Duberstein #include <linux/overflow.h>
11*97c1f302STamir Duberstein #include <linux/prandom.h>
12*97c1f302STamir Duberstein #include <linux/slab.h>
13*97c1f302STamir Duberstein #include <linux/string.h>
14*97c1f302STamir Duberstein 
15*97c1f302STamir Duberstein #define BUF_SIZE 1024
16*97c1f302STamir Duberstein 
17*97c1f302STamir Duberstein static char *test_buffer;
18*97c1f302STamir Duberstein static char *fmt_buffer;
19*97c1f302STamir Duberstein static struct rnd_state rnd_state;
20*97c1f302STamir Duberstein 
21*97c1f302STamir Duberstein typedef void (*check_fn)(struct kunit *test, const char *file, const int line,
22*97c1f302STamir Duberstein 			 const void *check_data, const char *string, const char *fmt, int n_args,
23*97c1f302STamir Duberstein 			 va_list ap);
24*97c1f302STamir Duberstein 
25*97c1f302STamir Duberstein static void __scanf(7, 9)
26*97c1f302STamir Duberstein _test(struct kunit *test, const char *file, const int line, check_fn fn, const void *check_data,
27*97c1f302STamir Duberstein 	const char *string, const char *fmt, int n_args, ...)
28*97c1f302STamir Duberstein {
29*97c1f302STamir Duberstein 	va_list ap, ap_copy;
30*97c1f302STamir Duberstein 	int ret;
31*97c1f302STamir Duberstein 
32*97c1f302STamir Duberstein 	va_start(ap, n_args);
33*97c1f302STamir Duberstein 	va_copy(ap_copy, ap);
34*97c1f302STamir Duberstein 	ret = vsscanf(string, fmt, ap_copy);
35*97c1f302STamir Duberstein 	va_end(ap_copy);
36*97c1f302STamir Duberstein 
37*97c1f302STamir Duberstein 	if (ret != n_args) {
38*97c1f302STamir Duberstein 		KUNIT_FAIL(test, "%s:%d: vsscanf(\"%s\", \"%s\", ...) returned %d expected %d",
39*97c1f302STamir Duberstein 			   file, line, string, fmt, ret, n_args);
40*97c1f302STamir Duberstein 	} else {
41*97c1f302STamir Duberstein 		(*fn)(test, file, line, check_data, string, fmt, n_args, ap);
42*97c1f302STamir Duberstein 	}
43*97c1f302STamir Duberstein 
44*97c1f302STamir Duberstein 	va_end(ap);
45*97c1f302STamir Duberstein }
46*97c1f302STamir Duberstein 
47*97c1f302STamir Duberstein #define _check_numbers_template(arg_fmt, expect, str, fmt, n_args, ap)		\
48*97c1f302STamir Duberstein do {										\
49*97c1f302STamir Duberstein 	for (; n_args > 0; n_args--, expect++) {				\
50*97c1f302STamir Duberstein 		typeof(*expect) got = *va_arg(ap, typeof(expect));		\
51*97c1f302STamir Duberstein 		if (got != *expect) {						\
52*97c1f302STamir Duberstein 			KUNIT_FAIL(test,					\
53*97c1f302STamir Duberstein 				   "%s:%d: vsscanf(\"%s\", \"%s\", ...) expected " arg_fmt " got " arg_fmt, \
54*97c1f302STamir Duberstein 				   file, line, str, fmt, *expect, got);		\
55*97c1f302STamir Duberstein 			return;							\
56*97c1f302STamir Duberstein 		}								\
57*97c1f302STamir Duberstein 	}									\
58*97c1f302STamir Duberstein } while (0)
59*97c1f302STamir Duberstein 
60*97c1f302STamir Duberstein static void check_ull(struct kunit *test, const char *file, const int line, const void *check_data,
61*97c1f302STamir Duberstein 		      const char *string, const char *fmt, int n_args, va_list ap)
62*97c1f302STamir Duberstein {
63*97c1f302STamir Duberstein 	const unsigned long long *pval = check_data;
64*97c1f302STamir Duberstein 
65*97c1f302STamir Duberstein 	_check_numbers_template("%llu", pval, string, fmt, n_args, ap);
66*97c1f302STamir Duberstein }
67*97c1f302STamir Duberstein 
68*97c1f302STamir Duberstein static void check_ll(struct kunit *test, const char *file, const int line, const void *check_data,
69*97c1f302STamir Duberstein 		     const char *string, const char *fmt, int n_args, va_list ap)
70*97c1f302STamir Duberstein {
71*97c1f302STamir Duberstein 	const long long *pval = check_data;
72*97c1f302STamir Duberstein 
73*97c1f302STamir Duberstein 	_check_numbers_template("%lld", pval, string, fmt, n_args, ap);
74*97c1f302STamir Duberstein }
75*97c1f302STamir Duberstein 
76*97c1f302STamir Duberstein static void check_ulong(struct kunit *test, const char *file, const int line,
77*97c1f302STamir Duberstein 			const void *check_data, const char *string, const char *fmt, int n_args,
78*97c1f302STamir Duberstein 			va_list ap)
79*97c1f302STamir Duberstein {
80*97c1f302STamir Duberstein 	const unsigned long *pval = check_data;
81*97c1f302STamir Duberstein 
82*97c1f302STamir Duberstein 	_check_numbers_template("%lu", pval, string, fmt, n_args, ap);
83*97c1f302STamir Duberstein }
84*97c1f302STamir Duberstein 
85*97c1f302STamir Duberstein static void check_long(struct kunit *test, const char *file, const int line, const void *check_data,
86*97c1f302STamir Duberstein 		       const char *string, const char *fmt, int n_args, va_list ap)
87*97c1f302STamir Duberstein {
88*97c1f302STamir Duberstein 	const long *pval = check_data;
89*97c1f302STamir Duberstein 
90*97c1f302STamir Duberstein 	_check_numbers_template("%ld", pval, string, fmt, n_args, ap);
91*97c1f302STamir Duberstein }
92*97c1f302STamir Duberstein 
93*97c1f302STamir Duberstein static void check_uint(struct kunit *test, const char *file, const int line, const void *check_data,
94*97c1f302STamir Duberstein 		       const char *string, const char *fmt, int n_args, va_list ap)
95*97c1f302STamir Duberstein {
96*97c1f302STamir Duberstein 	const unsigned int *pval = check_data;
97*97c1f302STamir Duberstein 
98*97c1f302STamir Duberstein 	_check_numbers_template("%u", pval, string, fmt, n_args, ap);
99*97c1f302STamir Duberstein }
100*97c1f302STamir Duberstein 
101*97c1f302STamir Duberstein static void check_int(struct kunit *test, const char *file, const int line, const void *check_data,
102*97c1f302STamir Duberstein 		      const char *string, const char *fmt, int n_args, va_list ap)
103*97c1f302STamir Duberstein {
104*97c1f302STamir Duberstein 	const int *pval = check_data;
105*97c1f302STamir Duberstein 
106*97c1f302STamir Duberstein 	_check_numbers_template("%d", pval, string, fmt, n_args, ap);
107*97c1f302STamir Duberstein }
108*97c1f302STamir Duberstein 
109*97c1f302STamir Duberstein static void check_ushort(struct kunit *test, const char *file, const int line,
110*97c1f302STamir Duberstein 			 const void *check_data, const char *string, const char *fmt, int n_args,
111*97c1f302STamir Duberstein 			 va_list ap)
112*97c1f302STamir Duberstein {
113*97c1f302STamir Duberstein 	const unsigned short *pval = check_data;
114*97c1f302STamir Duberstein 
115*97c1f302STamir Duberstein 	_check_numbers_template("%hu", pval, string, fmt, n_args, ap);
116*97c1f302STamir Duberstein }
117*97c1f302STamir Duberstein 
118*97c1f302STamir Duberstein static void check_short(struct kunit *test, const char *file, const int line,
119*97c1f302STamir Duberstein 			const void *check_data, const char *string, const char *fmt, int n_args,
120*97c1f302STamir Duberstein 			va_list ap)
121*97c1f302STamir Duberstein {
122*97c1f302STamir Duberstein 	const short *pval = check_data;
123*97c1f302STamir Duberstein 
124*97c1f302STamir Duberstein 	_check_numbers_template("%hd", pval, string, fmt, n_args, ap);
125*97c1f302STamir Duberstein }
126*97c1f302STamir Duberstein 
127*97c1f302STamir Duberstein static void check_uchar(struct kunit *test, const char *file, const int line,
128*97c1f302STamir Duberstein 			const void *check_data, const char *string, const char *fmt, int n_args,
129*97c1f302STamir Duberstein 			va_list ap)
130*97c1f302STamir Duberstein {
131*97c1f302STamir Duberstein 	const unsigned char *pval = check_data;
132*97c1f302STamir Duberstein 
133*97c1f302STamir Duberstein 	_check_numbers_template("%hhu", pval, string, fmt, n_args, ap);
134*97c1f302STamir Duberstein }
135*97c1f302STamir Duberstein 
136*97c1f302STamir Duberstein static void check_char(struct kunit *test, const char *file, const int line, const void *check_data,
137*97c1f302STamir Duberstein 		       const char *string, const char *fmt, int n_args, va_list ap)
138*97c1f302STamir Duberstein {
139*97c1f302STamir Duberstein 	const signed char *pval = check_data;
140*97c1f302STamir Duberstein 
141*97c1f302STamir Duberstein 	_check_numbers_template("%hhd", pval, string, fmt, n_args, ap);
142*97c1f302STamir Duberstein }
143*97c1f302STamir Duberstein 
144*97c1f302STamir Duberstein /* Selection of interesting numbers to test, copied from test-kstrtox.c */
145*97c1f302STamir Duberstein static const unsigned long long numbers[] = {
146*97c1f302STamir Duberstein 	0x0ULL,
147*97c1f302STamir Duberstein 	0x1ULL,
148*97c1f302STamir Duberstein 	0x7fULL,
149*97c1f302STamir Duberstein 	0x80ULL,
150*97c1f302STamir Duberstein 	0x81ULL,
151*97c1f302STamir Duberstein 	0xffULL,
152*97c1f302STamir Duberstein 	0x100ULL,
153*97c1f302STamir Duberstein 	0x101ULL,
154*97c1f302STamir Duberstein 	0x7fffULL,
155*97c1f302STamir Duberstein 	0x8000ULL,
156*97c1f302STamir Duberstein 	0x8001ULL,
157*97c1f302STamir Duberstein 	0xffffULL,
158*97c1f302STamir Duberstein 	0x10000ULL,
159*97c1f302STamir Duberstein 	0x10001ULL,
160*97c1f302STamir Duberstein 	0x7fffffffULL,
161*97c1f302STamir Duberstein 	0x80000000ULL,
162*97c1f302STamir Duberstein 	0x80000001ULL,
163*97c1f302STamir Duberstein 	0xffffffffULL,
164*97c1f302STamir Duberstein 	0x100000000ULL,
165*97c1f302STamir Duberstein 	0x100000001ULL,
166*97c1f302STamir Duberstein 	0x7fffffffffffffffULL,
167*97c1f302STamir Duberstein 	0x8000000000000000ULL,
168*97c1f302STamir Duberstein 	0x8000000000000001ULL,
169*97c1f302STamir Duberstein 	0xfffffffffffffffeULL,
170*97c1f302STamir Duberstein 	0xffffffffffffffffULL,
171*97c1f302STamir Duberstein };
172*97c1f302STamir Duberstein 
173*97c1f302STamir Duberstein #define value_representable_in_type(T, val)					 \
174*97c1f302STamir Duberstein (is_signed_type(T)								 \
175*97c1f302STamir Duberstein 	? ((long long)(val) >= type_min(T)) && ((long long)(val) <= type_max(T)) \
176*97c1f302STamir Duberstein 	: ((unsigned long long)(val) <= type_max(T)))
177*97c1f302STamir Duberstein 
178*97c1f302STamir Duberstein 
179*97c1f302STamir Duberstein #define test_one_number(T, gen_fmt, scan_fmt, val, fn)			\
180*97c1f302STamir Duberstein do {									\
181*97c1f302STamir Duberstein 	const T expect_val = (T)(val);					\
182*97c1f302STamir Duberstein 	T result = ~expect_val; /* should be overwritten */		\
183*97c1f302STamir Duberstein 									\
184*97c1f302STamir Duberstein 	snprintf(test_buffer, BUF_SIZE, gen_fmt, expect_val);		\
185*97c1f302STamir Duberstein 	_test(test, __FILE__, __LINE__, fn, &expect_val, test_buffer, "%" scan_fmt, 1, &result);\
186*97c1f302STamir Duberstein } while (0)
187*97c1f302STamir Duberstein 
188*97c1f302STamir Duberstein #define simple_numbers_loop(T, gen_fmt, scan_fmt, fn)			\
189*97c1f302STamir Duberstein do {									\
190*97c1f302STamir Duberstein 	int i;								\
191*97c1f302STamir Duberstein 									\
192*97c1f302STamir Duberstein 	for (i = 0; i < ARRAY_SIZE(numbers); i++) {			\
193*97c1f302STamir Duberstein 		if (value_representable_in_type(T, numbers[i]))		\
194*97c1f302STamir Duberstein 			test_one_number(T, gen_fmt, scan_fmt,		\
195*97c1f302STamir Duberstein 					numbers[i], fn);		\
196*97c1f302STamir Duberstein 									\
197*97c1f302STamir Duberstein 		if (value_representable_in_type(T, -numbers[i]))	\
198*97c1f302STamir Duberstein 			test_one_number(T, gen_fmt, scan_fmt,		\
199*97c1f302STamir Duberstein 					-numbers[i], fn);		\
200*97c1f302STamir Duberstein 	}								\
201*97c1f302STamir Duberstein } while (0)
202*97c1f302STamir Duberstein 
203*97c1f302STamir Duberstein static void numbers_simple(struct kunit *test)
204*97c1f302STamir Duberstein {
205*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned long long,	"%llu",	  "llu", check_ull);
206*97c1f302STamir Duberstein 	simple_numbers_loop(long long,		"%lld",	  "lld", check_ll);
207*97c1f302STamir Duberstein 	simple_numbers_loop(long long,		"%lld",	  "lli", check_ll);
208*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned long long,	"%llx",	  "llx", check_ull);
209*97c1f302STamir Duberstein 	simple_numbers_loop(long long,		"%llx",	  "llx", check_ll);
210*97c1f302STamir Duberstein 	simple_numbers_loop(long long,		"0x%llx", "lli", check_ll);
211*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned long long, "0x%llx", "llx", check_ull);
212*97c1f302STamir Duberstein 	simple_numbers_loop(long long,		"0x%llx", "llx", check_ll);
213*97c1f302STamir Duberstein 
214*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned long,	"%lu",	  "lu", check_ulong);
215*97c1f302STamir Duberstein 	simple_numbers_loop(long,		"%ld",	  "ld", check_long);
216*97c1f302STamir Duberstein 	simple_numbers_loop(long,		"%ld",	  "li", check_long);
217*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned long,	"%lx",	  "lx", check_ulong);
218*97c1f302STamir Duberstein 	simple_numbers_loop(long,		"%lx",	  "lx", check_long);
219*97c1f302STamir Duberstein 	simple_numbers_loop(long,		"0x%lx",  "li", check_long);
220*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned long,	"0x%lx",  "lx", check_ulong);
221*97c1f302STamir Duberstein 	simple_numbers_loop(long,		"0x%lx",  "lx", check_long);
222*97c1f302STamir Duberstein 
223*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned int,	"%u",	  "u", check_uint);
224*97c1f302STamir Duberstein 	simple_numbers_loop(int,		"%d",	  "d", check_int);
225*97c1f302STamir Duberstein 	simple_numbers_loop(int,		"%d",	  "i", check_int);
226*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned int,	"%x",	  "x", check_uint);
227*97c1f302STamir Duberstein 	simple_numbers_loop(int,		"%x",	  "x", check_int);
228*97c1f302STamir Duberstein 	simple_numbers_loop(int,		"0x%x",   "i", check_int);
229*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned int,	"0x%x",   "x", check_uint);
230*97c1f302STamir Duberstein 	simple_numbers_loop(int,		"0x%x",   "x", check_int);
231*97c1f302STamir Duberstein 
232*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned short,	"%hu",	  "hu", check_ushort);
233*97c1f302STamir Duberstein 	simple_numbers_loop(short,		"%hd",	  "hd", check_short);
234*97c1f302STamir Duberstein 	simple_numbers_loop(short,		"%hd",	  "hi", check_short);
235*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned short,	"%hx",	  "hx", check_ushort);
236*97c1f302STamir Duberstein 	simple_numbers_loop(short,		"%hx",	  "hx", check_short);
237*97c1f302STamir Duberstein 	simple_numbers_loop(short,		"0x%hx",  "hi", check_short);
238*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned short,	"0x%hx",  "hx", check_ushort);
239*97c1f302STamir Duberstein 	simple_numbers_loop(short,		"0x%hx",  "hx", check_short);
240*97c1f302STamir Duberstein 
241*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned char,	"%hhu",	  "hhu", check_uchar);
242*97c1f302STamir Duberstein 	simple_numbers_loop(signed char,	"%hhd",	  "hhd", check_char);
243*97c1f302STamir Duberstein 	simple_numbers_loop(signed char,	"%hhd",	  "hhi", check_char);
244*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned char,	"%hhx",	  "hhx", check_uchar);
245*97c1f302STamir Duberstein 	simple_numbers_loop(signed char,	"%hhx",	  "hhx", check_char);
246*97c1f302STamir Duberstein 	simple_numbers_loop(signed char,	"0x%hhx", "hhi", check_char);
247*97c1f302STamir Duberstein 	simple_numbers_loop(unsigned char,	"0x%hhx", "hhx", check_uchar);
248*97c1f302STamir Duberstein 	simple_numbers_loop(signed char,	"0x%hhx", "hhx", check_char);
249*97c1f302STamir Duberstein }
250*97c1f302STamir Duberstein 
251*97c1f302STamir Duberstein /*
252*97c1f302STamir Duberstein  * This gives a better variety of number "lengths" in a small sample than
253*97c1f302STamir Duberstein  * the raw prandom*() functions (Not mathematically rigorous!!).
254*97c1f302STamir Duberstein  * Variabilty of length and value is more important than perfect randomness.
255*97c1f302STamir Duberstein  */
256*97c1f302STamir Duberstein static u32 next_test_random(u32 max_bits)
257*97c1f302STamir Duberstein {
258*97c1f302STamir Duberstein 	u32 n_bits = hweight32(prandom_u32_state(&rnd_state)) % (max_bits + 1);
259*97c1f302STamir Duberstein 
260*97c1f302STamir Duberstein 	return prandom_u32_state(&rnd_state) & GENMASK(n_bits, 0);
261*97c1f302STamir Duberstein }
262*97c1f302STamir Duberstein 
263*97c1f302STamir Duberstein static unsigned long long next_test_random_ull(void)
264*97c1f302STamir Duberstein {
265*97c1f302STamir Duberstein 	u32 rand1 = prandom_u32_state(&rnd_state);
266*97c1f302STamir Duberstein 	u32 n_bits = (hweight32(rand1) * 3) % 64;
267*97c1f302STamir Duberstein 	u64 val = (u64)prandom_u32_state(&rnd_state) * rand1;
268*97c1f302STamir Duberstein 
269*97c1f302STamir Duberstein 	return val & GENMASK_ULL(n_bits, 0);
270*97c1f302STamir Duberstein }
271*97c1f302STamir Duberstein 
272*97c1f302STamir Duberstein #define random_for_type(T)				\
273*97c1f302STamir Duberstein 	((T)(sizeof(T) <= sizeof(u32)			\
274*97c1f302STamir Duberstein 		? next_test_random(BITS_PER_TYPE(T))	\
275*97c1f302STamir Duberstein 		: next_test_random_ull()))
276*97c1f302STamir Duberstein 
277*97c1f302STamir Duberstein /*
278*97c1f302STamir Duberstein  * Define a pattern of negative and positive numbers to ensure we get
279*97c1f302STamir Duberstein  * some of both within the small number of samples in a test string.
280*97c1f302STamir Duberstein  */
281*97c1f302STamir Duberstein #define NEGATIVES_PATTERN 0x3246	/* 00110010 01000110 */
282*97c1f302STamir Duberstein 
283*97c1f302STamir Duberstein #define fill_random_array(arr)							\
284*97c1f302STamir Duberstein do {										\
285*97c1f302STamir Duberstein 	unsigned int neg_pattern = NEGATIVES_PATTERN;				\
286*97c1f302STamir Duberstein 	int i;									\
287*97c1f302STamir Duberstein 										\
288*97c1f302STamir Duberstein 	for (i = 0; i < ARRAY_SIZE(arr); i++, neg_pattern >>= 1) {		\
289*97c1f302STamir Duberstein 		(arr)[i] = random_for_type(typeof((arr)[0]));			\
290*97c1f302STamir Duberstein 		if (is_signed_type(typeof((arr)[0])) && (neg_pattern & 1))	\
291*97c1f302STamir Duberstein 			(arr)[i] = -(arr)[i];					\
292*97c1f302STamir Duberstein 	}									\
293*97c1f302STamir Duberstein } while (0)
294*97c1f302STamir Duberstein 
295*97c1f302STamir Duberstein /*
296*97c1f302STamir Duberstein  * Convenience wrapper around snprintf() to append at buf_pos in buf,
297*97c1f302STamir Duberstein  * updating buf_pos and returning the number of characters appended.
298*97c1f302STamir Duberstein  * On error buf_pos is not changed and return value is 0.
299*97c1f302STamir Duberstein  */
300*97c1f302STamir Duberstein static int __printf(4, 5)
301*97c1f302STamir Duberstein append_fmt(char *buf, int *buf_pos, int buf_len, const char *val_fmt, ...)
302*97c1f302STamir Duberstein {
303*97c1f302STamir Duberstein 	va_list ap;
304*97c1f302STamir Duberstein 	int field_len;
305*97c1f302STamir Duberstein 
306*97c1f302STamir Duberstein 	va_start(ap, val_fmt);
307*97c1f302STamir Duberstein 	field_len = vsnprintf(buf + *buf_pos, buf_len - *buf_pos, val_fmt, ap);
308*97c1f302STamir Duberstein 	va_end(ap);
309*97c1f302STamir Duberstein 
310*97c1f302STamir Duberstein 	if (field_len < 0)
311*97c1f302STamir Duberstein 		field_len = 0;
312*97c1f302STamir Duberstein 
313*97c1f302STamir Duberstein 	*buf_pos += field_len;
314*97c1f302STamir Duberstein 
315*97c1f302STamir Duberstein 	return field_len;
316*97c1f302STamir Duberstein }
317*97c1f302STamir Duberstein 
318*97c1f302STamir Duberstein /*
319*97c1f302STamir Duberstein  * Convenience function to append the field delimiter string
320*97c1f302STamir Duberstein  * to both the value string and format string buffers.
321*97c1f302STamir Duberstein  */
322*97c1f302STamir Duberstein static void append_delim(char *str_buf, int *str_buf_pos, int str_buf_len,
323*97c1f302STamir Duberstein 				char *fmt_buf, int *fmt_buf_pos, int fmt_buf_len,
324*97c1f302STamir Duberstein 				const char *delim_str)
325*97c1f302STamir Duberstein {
326*97c1f302STamir Duberstein 	append_fmt(str_buf, str_buf_pos, str_buf_len, delim_str);
327*97c1f302STamir Duberstein 	append_fmt(fmt_buf, fmt_buf_pos, fmt_buf_len, delim_str);
328*97c1f302STamir Duberstein }
329*97c1f302STamir Duberstein 
330*97c1f302STamir Duberstein #define test_array_8(fn, check_data, string, fmt, arr)				\
331*97c1f302STamir Duberstein do {										\
332*97c1f302STamir Duberstein 	BUILD_BUG_ON(ARRAY_SIZE(arr) != 8);					\
333*97c1f302STamir Duberstein 	_test(test, __FILE__, __LINE__, fn, check_data, string, fmt, 8,		\
334*97c1f302STamir Duberstein 		&(arr)[0], &(arr)[1], &(arr)[2], &(arr)[3],			\
335*97c1f302STamir Duberstein 		&(arr)[4], &(arr)[5], &(arr)[6], &(arr)[7]);			\
336*97c1f302STamir Duberstein } while (0)
337*97c1f302STamir Duberstein 
338*97c1f302STamir Duberstein #define numbers_list_8(T, gen_fmt, field_sep, scan_fmt, fn)			\
339*97c1f302STamir Duberstein do {										\
340*97c1f302STamir Duberstein 	int i, pos = 0, fmt_pos = 0;						\
341*97c1f302STamir Duberstein 	T expect[8], result[8];							\
342*97c1f302STamir Duberstein 										\
343*97c1f302STamir Duberstein 	fill_random_array(expect);						\
344*97c1f302STamir Duberstein 										\
345*97c1f302STamir Duberstein 	for (i = 0; i < ARRAY_SIZE(expect); i++) {				\
346*97c1f302STamir Duberstein 		if (i != 0)							\
347*97c1f302STamir Duberstein 			append_delim(test_buffer, &pos, BUF_SIZE,		\
348*97c1f302STamir Duberstein 				     fmt_buffer, &fmt_pos, BUF_SIZE,		\
349*97c1f302STamir Duberstein 				     field_sep);				\
350*97c1f302STamir Duberstein 										\
351*97c1f302STamir Duberstein 		append_fmt(test_buffer, &pos, BUF_SIZE, gen_fmt, expect[i]);	\
352*97c1f302STamir Duberstein 		append_fmt(fmt_buffer, &fmt_pos, BUF_SIZE, "%%%s", scan_fmt);	\
353*97c1f302STamir Duberstein 	}									\
354*97c1f302STamir Duberstein 										\
355*97c1f302STamir Duberstein 	test_array_8(fn, expect, test_buffer, fmt_buffer, result);		\
356*97c1f302STamir Duberstein } while (0)
357*97c1f302STamir Duberstein 
358*97c1f302STamir Duberstein #define numbers_list_fix_width(T, gen_fmt, field_sep, width, scan_fmt, fn)	\
359*97c1f302STamir Duberstein do {										\
360*97c1f302STamir Duberstein 	char full_fmt[16];							\
361*97c1f302STamir Duberstein 										\
362*97c1f302STamir Duberstein 	snprintf(full_fmt, sizeof(full_fmt), "%u%s", width, scan_fmt);		\
363*97c1f302STamir Duberstein 	numbers_list_8(T, gen_fmt, field_sep, full_fmt, fn);			\
364*97c1f302STamir Duberstein } while (0)
365*97c1f302STamir Duberstein 
366*97c1f302STamir Duberstein #define numbers_list_val_width(T, gen_fmt, field_sep, scan_fmt, fn)		\
367*97c1f302STamir Duberstein do {										\
368*97c1f302STamir Duberstein 	int i, val_len, pos = 0, fmt_pos = 0;					\
369*97c1f302STamir Duberstein 	T expect[8], result[8];							\
370*97c1f302STamir Duberstein 										\
371*97c1f302STamir Duberstein 	fill_random_array(expect);						\
372*97c1f302STamir Duberstein 										\
373*97c1f302STamir Duberstein 	for (i = 0; i < ARRAY_SIZE(expect); i++) {				\
374*97c1f302STamir Duberstein 		if (i != 0)							\
375*97c1f302STamir Duberstein 			append_delim(test_buffer, &pos, BUF_SIZE,		\
376*97c1f302STamir Duberstein 				     fmt_buffer, &fmt_pos, BUF_SIZE, field_sep);\
377*97c1f302STamir Duberstein 										\
378*97c1f302STamir Duberstein 		val_len = append_fmt(test_buffer, &pos, BUF_SIZE, gen_fmt,	\
379*97c1f302STamir Duberstein 				     expect[i]);				\
380*97c1f302STamir Duberstein 		append_fmt(fmt_buffer, &fmt_pos, BUF_SIZE,			\
381*97c1f302STamir Duberstein 			   "%%%u%s", val_len, scan_fmt);			\
382*97c1f302STamir Duberstein 	}									\
383*97c1f302STamir Duberstein 										\
384*97c1f302STamir Duberstein 	test_array_8(fn, expect, test_buffer, fmt_buffer, result);		\
385*97c1f302STamir Duberstein } while (0)
386*97c1f302STamir Duberstein 
387*97c1f302STamir Duberstein static void numbers_list_ll(struct kunit *test, const char *delim)
388*97c1f302STamir Duberstein {
389*97c1f302STamir Duberstein 	numbers_list_8(unsigned long long, "%llu",   delim, "llu", check_ull);
390*97c1f302STamir Duberstein 	numbers_list_8(long long,	   "%lld",   delim, "lld", check_ll);
391*97c1f302STamir Duberstein 	numbers_list_8(long long,	   "%lld",   delim, "lli", check_ll);
392*97c1f302STamir Duberstein 	numbers_list_8(unsigned long long, "%llx",   delim, "llx", check_ull);
393*97c1f302STamir Duberstein 	numbers_list_8(unsigned long long, "0x%llx", delim, "llx", check_ull);
394*97c1f302STamir Duberstein 	numbers_list_8(long long,	   "0x%llx", delim, "lli", check_ll);
395*97c1f302STamir Duberstein }
396*97c1f302STamir Duberstein 
397*97c1f302STamir Duberstein static void numbers_list_l(struct kunit *test, const char *delim)
398*97c1f302STamir Duberstein {
399*97c1f302STamir Duberstein 	numbers_list_8(unsigned long,	   "%lu",    delim, "lu", check_ulong);
400*97c1f302STamir Duberstein 	numbers_list_8(long,		   "%ld",    delim, "ld", check_long);
401*97c1f302STamir Duberstein 	numbers_list_8(long,		   "%ld",    delim, "li", check_long);
402*97c1f302STamir Duberstein 	numbers_list_8(unsigned long,	   "%lx",    delim, "lx", check_ulong);
403*97c1f302STamir Duberstein 	numbers_list_8(unsigned long,	   "0x%lx",  delim, "lx", check_ulong);
404*97c1f302STamir Duberstein 	numbers_list_8(long,		   "0x%lx",  delim, "li", check_long);
405*97c1f302STamir Duberstein }
406*97c1f302STamir Duberstein 
407*97c1f302STamir Duberstein static void numbers_list_d(struct kunit *test, const char *delim)
408*97c1f302STamir Duberstein {
409*97c1f302STamir Duberstein 	numbers_list_8(unsigned int,	   "%u",     delim, "u", check_uint);
410*97c1f302STamir Duberstein 	numbers_list_8(int,		   "%d",     delim, "d", check_int);
411*97c1f302STamir Duberstein 	numbers_list_8(int,		   "%d",     delim, "i", check_int);
412*97c1f302STamir Duberstein 	numbers_list_8(unsigned int,	   "%x",     delim, "x", check_uint);
413*97c1f302STamir Duberstein 	numbers_list_8(unsigned int,	   "0x%x",   delim, "x", check_uint);
414*97c1f302STamir Duberstein 	numbers_list_8(int,		   "0x%x",   delim, "i", check_int);
415*97c1f302STamir Duberstein }
416*97c1f302STamir Duberstein 
417*97c1f302STamir Duberstein static void numbers_list_h(struct kunit *test, const char *delim)
418*97c1f302STamir Duberstein {
419*97c1f302STamir Duberstein 	numbers_list_8(unsigned short,	   "%hu",    delim, "hu", check_ushort);
420*97c1f302STamir Duberstein 	numbers_list_8(short,		   "%hd",    delim, "hd", check_short);
421*97c1f302STamir Duberstein 	numbers_list_8(short,		   "%hd",    delim, "hi", check_short);
422*97c1f302STamir Duberstein 	numbers_list_8(unsigned short,	   "%hx",    delim, "hx", check_ushort);
423*97c1f302STamir Duberstein 	numbers_list_8(unsigned short,	   "0x%hx",  delim, "hx", check_ushort);
424*97c1f302STamir Duberstein 	numbers_list_8(short,		   "0x%hx",  delim, "hi", check_short);
425*97c1f302STamir Duberstein }
426*97c1f302STamir Duberstein 
427*97c1f302STamir Duberstein static void numbers_list_hh(struct kunit *test, const char *delim)
428*97c1f302STamir Duberstein {
429*97c1f302STamir Duberstein 	numbers_list_8(unsigned char,	   "%hhu",   delim, "hhu", check_uchar);
430*97c1f302STamir Duberstein 	numbers_list_8(signed char,	   "%hhd",   delim, "hhd", check_char);
431*97c1f302STamir Duberstein 	numbers_list_8(signed char,	   "%hhd",   delim, "hhi", check_char);
432*97c1f302STamir Duberstein 	numbers_list_8(unsigned char,	   "%hhx",   delim, "hhx", check_uchar);
433*97c1f302STamir Duberstein 	numbers_list_8(unsigned char,	   "0x%hhx", delim, "hhx", check_uchar);
434*97c1f302STamir Duberstein 	numbers_list_8(signed char,	   "0x%hhx", delim, "hhi", check_char);
435*97c1f302STamir Duberstein }
436*97c1f302STamir Duberstein 
437*97c1f302STamir Duberstein static void numbers_list(struct kunit *test, const char *delim)
438*97c1f302STamir Duberstein {
439*97c1f302STamir Duberstein 	numbers_list_ll(test, delim);
440*97c1f302STamir Duberstein 	numbers_list_l(test, delim);
441*97c1f302STamir Duberstein 	numbers_list_d(test, delim);
442*97c1f302STamir Duberstein 	numbers_list_h(test, delim);
443*97c1f302STamir Duberstein 	numbers_list_hh(test, delim);
444*97c1f302STamir Duberstein }
445*97c1f302STamir Duberstein 
446*97c1f302STamir Duberstein static void numbers_list_field_width_ll(struct kunit *test, const char *delim)
447*97c1f302STamir Duberstein {
448*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long long, "%llu",   delim, 20, "llu", check_ull);
449*97c1f302STamir Duberstein 	numbers_list_fix_width(long long,	   "%lld",   delim, 20, "lld", check_ll);
450*97c1f302STamir Duberstein 	numbers_list_fix_width(long long,	   "%lld",   delim, 20, "lli", check_ll);
451*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long long, "%llx",   delim, 16, "llx", check_ull);
452*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long long, "0x%llx", delim, 18, "llx", check_ull);
453*97c1f302STamir Duberstein 	numbers_list_fix_width(long long,	   "0x%llx", delim, 18, "lli", check_ll);
454*97c1f302STamir Duberstein }
455*97c1f302STamir Duberstein 
456*97c1f302STamir Duberstein static void numbers_list_field_width_l(struct kunit *test, const char *delim)
457*97c1f302STamir Duberstein {
458*97c1f302STamir Duberstein #if BITS_PER_LONG == 64
459*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long,	"%lu",	     delim, 20, "lu", check_ulong);
460*97c1f302STamir Duberstein 	numbers_list_fix_width(long,		"%ld",	     delim, 20, "ld", check_long);
461*97c1f302STamir Duberstein 	numbers_list_fix_width(long,		"%ld",	     delim, 20, "li", check_long);
462*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long,	"%lx",	     delim, 16, "lx", check_ulong);
463*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long,	"0x%lx",     delim, 18, "lx", check_ulong);
464*97c1f302STamir Duberstein 	numbers_list_fix_width(long,		"0x%lx",     delim, 18, "li", check_long);
465*97c1f302STamir Duberstein #else
466*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long,	"%lu",	     delim, 10, "lu", check_ulong);
467*97c1f302STamir Duberstein 	numbers_list_fix_width(long,		"%ld",	     delim, 11, "ld", check_long);
468*97c1f302STamir Duberstein 	numbers_list_fix_width(long,		"%ld",	     delim, 11, "li", check_long);
469*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long,	"%lx",	     delim, 8,  "lx", check_ulong);
470*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned long,	"0x%lx",     delim, 10, "lx", check_ulong);
471*97c1f302STamir Duberstein 	numbers_list_fix_width(long,		"0x%lx",     delim, 10, "li", check_long);
472*97c1f302STamir Duberstein #endif
473*97c1f302STamir Duberstein }
474*97c1f302STamir Duberstein 
475*97c1f302STamir Duberstein static void numbers_list_field_width_d(struct kunit *test, const char *delim)
476*97c1f302STamir Duberstein {
477*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned int,	"%u",	     delim, 10, "u", check_uint);
478*97c1f302STamir Duberstein 	numbers_list_fix_width(int,		"%d",	     delim, 11, "d", check_int);
479*97c1f302STamir Duberstein 	numbers_list_fix_width(int,		"%d",	     delim, 11, "i", check_int);
480*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned int,	"%x",	     delim, 8,  "x", check_uint);
481*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned int,	"0x%x",	     delim, 10, "x", check_uint);
482*97c1f302STamir Duberstein 	numbers_list_fix_width(int,		"0x%x",	     delim, 10, "i", check_int);
483*97c1f302STamir Duberstein }
484*97c1f302STamir Duberstein 
485*97c1f302STamir Duberstein static void numbers_list_field_width_h(struct kunit *test, const char *delim)
486*97c1f302STamir Duberstein {
487*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned short,	"%hu",	     delim, 5, "hu", check_ushort);
488*97c1f302STamir Duberstein 	numbers_list_fix_width(short,		"%hd",	     delim, 6, "hd", check_short);
489*97c1f302STamir Duberstein 	numbers_list_fix_width(short,		"%hd",	     delim, 6, "hi", check_short);
490*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned short,	"%hx",	     delim, 4, "hx", check_ushort);
491*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned short,	"0x%hx",     delim, 6, "hx", check_ushort);
492*97c1f302STamir Duberstein 	numbers_list_fix_width(short,		"0x%hx",     delim, 6, "hi", check_short);
493*97c1f302STamir Duberstein }
494*97c1f302STamir Duberstein 
495*97c1f302STamir Duberstein static void numbers_list_field_width_hh(struct kunit *test, const char *delim)
496*97c1f302STamir Duberstein {
497*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned char,	"%hhu",	     delim, 3, "hhu", check_uchar);
498*97c1f302STamir Duberstein 	numbers_list_fix_width(signed char,	"%hhd",	     delim, 4, "hhd", check_char);
499*97c1f302STamir Duberstein 	numbers_list_fix_width(signed char,	"%hhd",	     delim, 4, "hhi", check_char);
500*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned char,	"%hhx",	     delim, 2, "hhx", check_uchar);
501*97c1f302STamir Duberstein 	numbers_list_fix_width(unsigned char,	"0x%hhx",    delim, 4, "hhx", check_uchar);
502*97c1f302STamir Duberstein 	numbers_list_fix_width(signed char,	"0x%hhx",    delim, 4, "hhi", check_char);
503*97c1f302STamir Duberstein }
504*97c1f302STamir Duberstein 
505*97c1f302STamir Duberstein /*
506*97c1f302STamir Duberstein  * List of numbers separated by delim. Each field width specifier is the
507*97c1f302STamir Duberstein  * maximum possible digits for the given type and base.
508*97c1f302STamir Duberstein  */
509*97c1f302STamir Duberstein static void numbers_list_field_width_typemax(struct kunit *test, const char *delim)
510*97c1f302STamir Duberstein {
511*97c1f302STamir Duberstein 	numbers_list_field_width_ll(test, delim);
512*97c1f302STamir Duberstein 	numbers_list_field_width_l(test, delim);
513*97c1f302STamir Duberstein 	numbers_list_field_width_d(test, delim);
514*97c1f302STamir Duberstein 	numbers_list_field_width_h(test, delim);
515*97c1f302STamir Duberstein 	numbers_list_field_width_hh(test, delim);
516*97c1f302STamir Duberstein }
517*97c1f302STamir Duberstein 
518*97c1f302STamir Duberstein static void numbers_list_field_width_val_ll(struct kunit *test, const char *delim)
519*97c1f302STamir Duberstein {
520*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned long long, "%llu",   delim, "llu", check_ull);
521*97c1f302STamir Duberstein 	numbers_list_val_width(long long,	   "%lld",   delim, "lld", check_ll);
522*97c1f302STamir Duberstein 	numbers_list_val_width(long long,	   "%lld",   delim, "lli", check_ll);
523*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned long long, "%llx",   delim, "llx", check_ull);
524*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned long long, "0x%llx", delim, "llx", check_ull);
525*97c1f302STamir Duberstein 	numbers_list_val_width(long long,	   "0x%llx", delim, "lli", check_ll);
526*97c1f302STamir Duberstein }
527*97c1f302STamir Duberstein 
528*97c1f302STamir Duberstein static void numbers_list_field_width_val_l(struct kunit *test, const char *delim)
529*97c1f302STamir Duberstein {
530*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned long,	"%lu",	     delim, "lu", check_ulong);
531*97c1f302STamir Duberstein 	numbers_list_val_width(long,		"%ld",	     delim, "ld", check_long);
532*97c1f302STamir Duberstein 	numbers_list_val_width(long,		"%ld",	     delim, "li", check_long);
533*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned long,	"%lx",	     delim, "lx", check_ulong);
534*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned long,	"0x%lx",     delim, "lx", check_ulong);
535*97c1f302STamir Duberstein 	numbers_list_val_width(long,		"0x%lx",     delim, "li", check_long);
536*97c1f302STamir Duberstein }
537*97c1f302STamir Duberstein 
538*97c1f302STamir Duberstein static void numbers_list_field_width_val_d(struct kunit *test, const char *delim)
539*97c1f302STamir Duberstein {
540*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned int,	"%u",	     delim, "u", check_uint);
541*97c1f302STamir Duberstein 	numbers_list_val_width(int,		"%d",	     delim, "d", check_int);
542*97c1f302STamir Duberstein 	numbers_list_val_width(int,		"%d",	     delim, "i", check_int);
543*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned int,	"%x",	     delim, "x", check_uint);
544*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned int,	"0x%x",	     delim, "x", check_uint);
545*97c1f302STamir Duberstein 	numbers_list_val_width(int,		"0x%x",	     delim, "i", check_int);
546*97c1f302STamir Duberstein }
547*97c1f302STamir Duberstein 
548*97c1f302STamir Duberstein static void numbers_list_field_width_val_h(struct kunit *test, const char *delim)
549*97c1f302STamir Duberstein {
550*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned short,	"%hu",	     delim, "hu", check_ushort);
551*97c1f302STamir Duberstein 	numbers_list_val_width(short,		"%hd",	     delim, "hd", check_short);
552*97c1f302STamir Duberstein 	numbers_list_val_width(short,		"%hd",	     delim, "hi", check_short);
553*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned short,	"%hx",	     delim, "hx", check_ushort);
554*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned short,	"0x%hx",     delim, "hx", check_ushort);
555*97c1f302STamir Duberstein 	numbers_list_val_width(short,		"0x%hx",     delim, "hi", check_short);
556*97c1f302STamir Duberstein }
557*97c1f302STamir Duberstein 
558*97c1f302STamir Duberstein static void numbers_list_field_width_val_hh(struct kunit *test, const char *delim)
559*97c1f302STamir Duberstein {
560*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned char,	"%hhu",	     delim, "hhu", check_uchar);
561*97c1f302STamir Duberstein 	numbers_list_val_width(signed char,	"%hhd",	     delim, "hhd", check_char);
562*97c1f302STamir Duberstein 	numbers_list_val_width(signed char,	"%hhd",	     delim, "hhi", check_char);
563*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned char,	"%hhx",	     delim, "hhx", check_uchar);
564*97c1f302STamir Duberstein 	numbers_list_val_width(unsigned char,	"0x%hhx",    delim, "hhx", check_uchar);
565*97c1f302STamir Duberstein 	numbers_list_val_width(signed char,	"0x%hhx",    delim, "hhi", check_char);
566*97c1f302STamir Duberstein }
567*97c1f302STamir Duberstein 
568*97c1f302STamir Duberstein /*
569*97c1f302STamir Duberstein  * List of numbers separated by delim. Each field width specifier is the
570*97c1f302STamir Duberstein  * exact length of the corresponding value digits in the string being scanned.
571*97c1f302STamir Duberstein  */
572*97c1f302STamir Duberstein static void numbers_list_field_width_val_width(struct kunit *test, const char *delim)
573*97c1f302STamir Duberstein {
574*97c1f302STamir Duberstein 	numbers_list_field_width_val_ll(test, delim);
575*97c1f302STamir Duberstein 	numbers_list_field_width_val_l(test, delim);
576*97c1f302STamir Duberstein 	numbers_list_field_width_val_d(test, delim);
577*97c1f302STamir Duberstein 	numbers_list_field_width_val_h(test, delim);
578*97c1f302STamir Duberstein 	numbers_list_field_width_val_hh(test, delim);
579*97c1f302STamir Duberstein }
580*97c1f302STamir Duberstein 
581*97c1f302STamir Duberstein /*
582*97c1f302STamir Duberstein  * Slice a continuous string of digits without field delimiters, containing
583*97c1f302STamir Duberstein  * numbers of varying length, using the field width to extract each group
584*97c1f302STamir Duberstein  * of digits. For example the hex values c0,3,bf01,303 would have a
585*97c1f302STamir Duberstein  * string representation of "c03bf01303" and extracted with "%2x%1x%4x%3x".
586*97c1f302STamir Duberstein  */
587*97c1f302STamir Duberstein static void numbers_slice(struct kunit *test)
588*97c1f302STamir Duberstein {
589*97c1f302STamir Duberstein 	numbers_list_field_width_val_width(test, "");
590*97c1f302STamir Duberstein }
591*97c1f302STamir Duberstein 
592*97c1f302STamir Duberstein #define test_number_prefix(T, str, scan_fmt, expect0, expect1, n_args, fn)	\
593*97c1f302STamir Duberstein do {										\
594*97c1f302STamir Duberstein 	const T expect[2] = { expect0, expect1 };				\
595*97c1f302STamir Duberstein 	T result[2] = { (T)~expect[0], (T)~expect[1] };				\
596*97c1f302STamir Duberstein 										\
597*97c1f302STamir Duberstein 	_test(test, __FILE__, __LINE__, fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]);\
598*97c1f302STamir Duberstein } while (0)
599*97c1f302STamir Duberstein 
600*97c1f302STamir Duberstein /*
601*97c1f302STamir Duberstein  * Number prefix is >= field width.
602*97c1f302STamir Duberstein  * Expected behaviour is derived from testing userland sscanf.
603*97c1f302STamir Duberstein  */
604*97c1f302STamir Duberstein static void numbers_prefix_overflow(struct kunit *test)
605*97c1f302STamir Duberstein {
606*97c1f302STamir Duberstein 	/*
607*97c1f302STamir Duberstein 	 * Negative decimal with a field of width 1, should quit scanning
608*97c1f302STamir Duberstein 	 * and return 0.
609*97c1f302STamir Duberstein 	 */
610*97c1f302STamir Duberstein 	test_number_prefix(long long,	"-1 1", "%1lld %lld",	0, 0, 0, check_ll);
611*97c1f302STamir Duberstein 	test_number_prefix(long,	"-1 1", "%1ld %ld",	0, 0, 0, check_long);
612*97c1f302STamir Duberstein 	test_number_prefix(int,		"-1 1", "%1d %d",	0, 0, 0, check_int);
613*97c1f302STamir Duberstein 	test_number_prefix(short,	"-1 1", "%1hd %hd",	0, 0, 0, check_short);
614*97c1f302STamir Duberstein 	test_number_prefix(signed char,	"-1 1", "%1hhd %hhd",	0, 0, 0, check_char);
615*97c1f302STamir Duberstein 
616*97c1f302STamir Duberstein 	test_number_prefix(long long,	"-1 1", "%1lli %lli",	0, 0, 0, check_ll);
617*97c1f302STamir Duberstein 	test_number_prefix(long,	"-1 1", "%1li %li",	0, 0, 0, check_long);
618*97c1f302STamir Duberstein 	test_number_prefix(int,		"-1 1", "%1i %i",	0, 0, 0, check_int);
619*97c1f302STamir Duberstein 	test_number_prefix(short,	"-1 1", "%1hi %hi",	0, 0, 0, check_short);
620*97c1f302STamir Duberstein 	test_number_prefix(signed char,	"-1 1", "%1hhi %hhi",	0, 0, 0, check_char);
621*97c1f302STamir Duberstein 
622*97c1f302STamir Duberstein 	/*
623*97c1f302STamir Duberstein 	 * 0x prefix in a field of width 1: 0 is a valid digit so should
624*97c1f302STamir Duberstein 	 * convert. Next field scan starts at the 'x' which isn't a digit so
625*97c1f302STamir Duberstein 	 * scan quits with one field converted.
626*97c1f302STamir Duberstein 	 */
627*97c1f302STamir Duberstein 	test_number_prefix(unsigned long long,	"0xA7", "%1llx%llx", 0, 0, 1, check_ull);
628*97c1f302STamir Duberstein 	test_number_prefix(unsigned long,	"0xA7", "%1lx%lx",   0, 0, 1, check_ulong);
629*97c1f302STamir Duberstein 	test_number_prefix(unsigned int,	"0xA7", "%1x%x",     0, 0, 1, check_uint);
630*97c1f302STamir Duberstein 	test_number_prefix(unsigned short,	"0xA7", "%1hx%hx",   0, 0, 1, check_ushort);
631*97c1f302STamir Duberstein 	test_number_prefix(unsigned char,	"0xA7", "%1hhx%hhx", 0, 0, 1, check_uchar);
632*97c1f302STamir Duberstein 	test_number_prefix(long long,		"0xA7", "%1lli%llx", 0, 0, 1, check_ll);
633*97c1f302STamir Duberstein 	test_number_prefix(long,		"0xA7", "%1li%lx",   0, 0, 1, check_long);
634*97c1f302STamir Duberstein 	test_number_prefix(int,			"0xA7", "%1i%x",     0, 0, 1, check_int);
635*97c1f302STamir Duberstein 	test_number_prefix(short,		"0xA7", "%1hi%hx",   0, 0, 1, check_short);
636*97c1f302STamir Duberstein 	test_number_prefix(char,		"0xA7", "%1hhi%hhx", 0, 0, 1, check_char);
637*97c1f302STamir Duberstein 
638*97c1f302STamir Duberstein 	/*
639*97c1f302STamir Duberstein 	 * 0x prefix in a field of width 2 using %x conversion: first field
640*97c1f302STamir Duberstein 	 * converts to 0. Next field scan starts at the character after "0x".
641*97c1f302STamir Duberstein 	 * Both fields will convert.
642*97c1f302STamir Duberstein 	 */
643*97c1f302STamir Duberstein 	test_number_prefix(unsigned long long,	"0xA7", "%2llx%llx", 0, 0xa7, 2, check_ull);
644*97c1f302STamir Duberstein 	test_number_prefix(unsigned long,	"0xA7", "%2lx%lx",   0, 0xa7, 2, check_ulong);
645*97c1f302STamir Duberstein 	test_number_prefix(unsigned int,	"0xA7", "%2x%x",     0, 0xa7, 2, check_uint);
646*97c1f302STamir Duberstein 	test_number_prefix(unsigned short,	"0xA7", "%2hx%hx",   0, 0xa7, 2, check_ushort);
647*97c1f302STamir Duberstein 	test_number_prefix(unsigned char,	"0xA7", "%2hhx%hhx", 0, 0xa7, 2, check_uchar);
648*97c1f302STamir Duberstein 
649*97c1f302STamir Duberstein 	/*
650*97c1f302STamir Duberstein 	 * 0x prefix in a field of width 2 using %i conversion: first field
651*97c1f302STamir Duberstein 	 * converts to 0. Next field scan starts at the character after "0x",
652*97c1f302STamir Duberstein 	 * which will convert if can be interpreted as decimal but will fail
653*97c1f302STamir Duberstein 	 * if it contains any hex digits (since no 0x prefix).
654*97c1f302STamir Duberstein 	 */
655*97c1f302STamir Duberstein 	test_number_prefix(long long,	"0x67", "%2lli%lli", 0, 67, 2, check_ll);
656*97c1f302STamir Duberstein 	test_number_prefix(long,	"0x67", "%2li%li",   0, 67, 2, check_long);
657*97c1f302STamir Duberstein 	test_number_prefix(int,		"0x67", "%2i%i",     0, 67, 2, check_int);
658*97c1f302STamir Duberstein 	test_number_prefix(short,	"0x67", "%2hi%hi",   0, 67, 2, check_short);
659*97c1f302STamir Duberstein 	test_number_prefix(char,	"0x67", "%2hhi%hhi", 0, 67, 2, check_char);
660*97c1f302STamir Duberstein 
661*97c1f302STamir Duberstein 	test_number_prefix(long long,	"0xA7", "%2lli%lli", 0, 0,  1, check_ll);
662*97c1f302STamir Duberstein 	test_number_prefix(long,	"0xA7", "%2li%li",   0, 0,  1, check_long);
663*97c1f302STamir Duberstein 	test_number_prefix(int,		"0xA7", "%2i%i",     0, 0,  1, check_int);
664*97c1f302STamir Duberstein 	test_number_prefix(short,	"0xA7", "%2hi%hi",   0, 0,  1, check_short);
665*97c1f302STamir Duberstein 	test_number_prefix(char,	"0xA7", "%2hhi%hhi", 0, 0,  1, check_char);
666*97c1f302STamir Duberstein }
667*97c1f302STamir Duberstein 
668*97c1f302STamir Duberstein #define _test_simple_strtoxx(T, fn, gen_fmt, expect, base)			\
669*97c1f302STamir Duberstein do {										\
670*97c1f302STamir Duberstein 	T got;									\
671*97c1f302STamir Duberstein 	char *endp;								\
672*97c1f302STamir Duberstein 	int len;								\
673*97c1f302STamir Duberstein 										\
674*97c1f302STamir Duberstein 	len = snprintf(test_buffer, BUF_SIZE, gen_fmt, expect);			\
675*97c1f302STamir Duberstein 	got = (fn)(test_buffer, &endp, base);					\
676*97c1f302STamir Duberstein 	if (got != (expect)) {							\
677*97c1f302STamir Duberstein 		KUNIT_FAIL(test, #fn "(\"%s\", %d): got " gen_fmt " expected " gen_fmt, \
678*97c1f302STamir Duberstein 			   test_buffer, base, got, expect);			\
679*97c1f302STamir Duberstein 	} else if (endp != test_buffer + len) {					\
680*97c1f302STamir Duberstein 		KUNIT_FAIL(test, #fn "(\"%s\", %d) startp=0x%px got endp=0x%px expected 0x%px", \
681*97c1f302STamir Duberstein 			   test_buffer, base, test_buffer,			\
682*97c1f302STamir Duberstein 			   test_buffer + len, endp);				\
683*97c1f302STamir Duberstein 	}									\
684*97c1f302STamir Duberstein } while (0)
685*97c1f302STamir Duberstein 
686*97c1f302STamir Duberstein #define test_simple_strtoxx(T, fn, gen_fmt, base)				\
687*97c1f302STamir Duberstein do {										\
688*97c1f302STamir Duberstein 	int i;									\
689*97c1f302STamir Duberstein 										\
690*97c1f302STamir Duberstein 	for (i = 0; i < ARRAY_SIZE(numbers); i++) {				\
691*97c1f302STamir Duberstein 		_test_simple_strtoxx(T, fn, gen_fmt, (T)numbers[i], base);	\
692*97c1f302STamir Duberstein 										\
693*97c1f302STamir Duberstein 		if (is_signed_type(T))						\
694*97c1f302STamir Duberstein 			_test_simple_strtoxx(T, fn, gen_fmt,			\
695*97c1f302STamir Duberstein 					      -(T)numbers[i], base);		\
696*97c1f302STamir Duberstein 	}									\
697*97c1f302STamir Duberstein } while (0)
698*97c1f302STamir Duberstein 
699*97c1f302STamir Duberstein static void test_simple_strtoull(struct kunit *test)
700*97c1f302STamir Duberstein {
701*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   10);
702*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   0);
703*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llx",   16);
704*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 16);
705*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 0);
706*97c1f302STamir Duberstein }
707*97c1f302STamir Duberstein 
708*97c1f302STamir Duberstein static void test_simple_strtoll(struct kunit *test)
709*97c1f302STamir Duberstein {
710*97c1f302STamir Duberstein 	test_simple_strtoxx(long long, simple_strtoll, "%lld",	 10);
711*97c1f302STamir Duberstein 	test_simple_strtoxx(long long, simple_strtoll, "%lld",	 0);
712*97c1f302STamir Duberstein 	test_simple_strtoxx(long long, simple_strtoll, "%llx",	 16);
713*97c1f302STamir Duberstein 	test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 16);
714*97c1f302STamir Duberstein 	test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 0);
715*97c1f302STamir Duberstein }
716*97c1f302STamir Duberstein 
717*97c1f302STamir Duberstein static void test_simple_strtoul(struct kunit *test)
718*97c1f302STamir Duberstein {
719*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   10);
720*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   0);
721*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long, simple_strtoul, "%lx",   16);
722*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 16);
723*97c1f302STamir Duberstein 	test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 0);
724*97c1f302STamir Duberstein }
725*97c1f302STamir Duberstein 
726*97c1f302STamir Duberstein static void test_simple_strtol(struct kunit *test)
727*97c1f302STamir Duberstein {
728*97c1f302STamir Duberstein 	test_simple_strtoxx(long, simple_strtol, "%ld",   10);
729*97c1f302STamir Duberstein 	test_simple_strtoxx(long, simple_strtol, "%ld",   0);
730*97c1f302STamir Duberstein 	test_simple_strtoxx(long, simple_strtol, "%lx",   16);
731*97c1f302STamir Duberstein 	test_simple_strtoxx(long, simple_strtol, "0x%lx", 16);
732*97c1f302STamir Duberstein 	test_simple_strtoxx(long, simple_strtol, "0x%lx", 0);
733*97c1f302STamir Duberstein }
734*97c1f302STamir Duberstein 
735*97c1f302STamir Duberstein /* Selection of common delimiters/separators between numbers in a string. */
736*97c1f302STamir Duberstein static const char * const number_delimiters[] = {
737*97c1f302STamir Duberstein 	" ", ":", ",", "-", "/",
738*97c1f302STamir Duberstein };
739*97c1f302STamir Duberstein 
740*97c1f302STamir Duberstein static void test_numbers(struct kunit *test)
741*97c1f302STamir Duberstein {
742*97c1f302STamir Duberstein 	int i;
743*97c1f302STamir Duberstein 
744*97c1f302STamir Duberstein 	/* String containing only one number. */
745*97c1f302STamir Duberstein 	numbers_simple(test);
746*97c1f302STamir Duberstein 
747*97c1f302STamir Duberstein 	/* String with multiple numbers separated by delimiter. */
748*97c1f302STamir Duberstein 	for (i = 0; i < ARRAY_SIZE(number_delimiters); i++) {
749*97c1f302STamir Duberstein 		numbers_list(test, number_delimiters[i]);
750*97c1f302STamir Duberstein 
751*97c1f302STamir Duberstein 		/* Field width may be longer than actual field digits. */
752*97c1f302STamir Duberstein 		numbers_list_field_width_typemax(test, number_delimiters[i]);
753*97c1f302STamir Duberstein 
754*97c1f302STamir Duberstein 		/* Each field width exactly length of actual field digits. */
755*97c1f302STamir Duberstein 		numbers_list_field_width_val_width(test, number_delimiters[i]);
756*97c1f302STamir Duberstein 	}
757*97c1f302STamir Duberstein 
758*97c1f302STamir Duberstein 	/* Slice continuous sequence of digits using field widths. */
759*97c1f302STamir Duberstein 	numbers_slice(test);
760*97c1f302STamir Duberstein 
761*97c1f302STamir Duberstein 	numbers_prefix_overflow(test);
762*97c1f302STamir Duberstein }
763*97c1f302STamir Duberstein 
764*97c1f302STamir Duberstein static void scanf_test(struct kunit *test)
765*97c1f302STamir Duberstein {
766*97c1f302STamir Duberstein 	test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
767*97c1f302STamir Duberstein 	if (!test_buffer)
768*97c1f302STamir Duberstein 		return;
769*97c1f302STamir Duberstein 
770*97c1f302STamir Duberstein 	fmt_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
771*97c1f302STamir Duberstein 	if (!fmt_buffer) {
772*97c1f302STamir Duberstein 		kfree(test_buffer);
773*97c1f302STamir Duberstein 		return;
774*97c1f302STamir Duberstein 	}
775*97c1f302STamir Duberstein 
776*97c1f302STamir Duberstein 	prandom_seed_state(&rnd_state, 3141592653589793238ULL);
777*97c1f302STamir Duberstein 
778*97c1f302STamir Duberstein 	test_numbers(test);
779*97c1f302STamir Duberstein 
780*97c1f302STamir Duberstein 	test_simple_strtoull(test);
781*97c1f302STamir Duberstein 	test_simple_strtoll(test);
782*97c1f302STamir Duberstein 	test_simple_strtoul(test);
783*97c1f302STamir Duberstein 	test_simple_strtol(test);
784*97c1f302STamir Duberstein 
785*97c1f302STamir Duberstein 	kfree(fmt_buffer);
786*97c1f302STamir Duberstein 	kfree(test_buffer);
787*97c1f302STamir Duberstein }
788*97c1f302STamir Duberstein 
789*97c1f302STamir Duberstein static struct kunit_case scanf_test_cases[] = {
790*97c1f302STamir Duberstein 	KUNIT_CASE(scanf_test),
791*97c1f302STamir Duberstein 	{}
792*97c1f302STamir Duberstein };
793*97c1f302STamir Duberstein 
794*97c1f302STamir Duberstein static struct kunit_suite scanf_test_suite = {
795*97c1f302STamir Duberstein 	.name = "scanf",
796*97c1f302STamir Duberstein 	.test_cases = scanf_test_cases,
797*97c1f302STamir Duberstein };
798*97c1f302STamir Duberstein 
799*97c1f302STamir Duberstein kunit_test_suite(scanf_test_suite);
800*97c1f302STamir Duberstein 
801*97c1f302STamir Duberstein MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
802*97c1f302STamir Duberstein MODULE_DESCRIPTION("Test cases for sscanf facility");
803*97c1f302STamir Duberstein MODULE_LICENSE("GPL v2");
804