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