blob: 4274603f4d1a0fbbec5339307ea89a41ce381e95 [file] [log] [blame]
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/parse-integer.h>
#include <asm/bug.h>
#define for_each_test(i, test) \
for (i = 0; i < ARRAY_SIZE(test); i++)
#define DEFINE_TEST_OK(type, test_type, test) \
test_type { \
const char *str; \
unsigned int base; \
int expected_rv; \
type expected_val; \
}; \
static const test_type test[] __initconst =
#define TEST_OK(type, fmt, test) \
{ \
unsigned int i; \
\
for_each_test(i, test) { \
const typeof(test[0]) *t = &test[i]; \
type val; \
int rv; \
\
rv = parse_integer(t->str, t->base, &val); \
if (rv != t->expected_rv || val != t->expected_val) { \
WARN(1, "str '%s', base %u, expected %d/"fmt", got %d/"fmt"\n", \
t->str, t->base, t->expected_rv, t->expected_val, rv, val); \
} \
} \
}
struct test_fail {
const char *str;
unsigned int base;
};
#define DEFINE_TEST_FAIL(type, test) \
static const struct test_fail test[] __initconst =
#define TEST_FAIL(type, fmt, test) \
{ \
unsigned int i; \
\
for_each_test(i, test) { \
const typeof(test[0]) *t = &test[i]; \
type val; \
int rv; \
\
val = 113; \
rv = parse_integer(t->str, t->base, &val); \
if (rv >= 0 || val != 113) { \
WARN(1, "str '%s', base %u, expected -E, got %d/"fmt"\n",\
t->str, t->base, rv, val); \
} \
} \
}
DEFINE_TEST_OK(unsigned long long, struct test_ull, test_ull_ok)
{
{"0", 10, 1, 0},
{"1", 10, 1, 1},
{"2", 10, 1, 2},
{"3", 10, 1, 3},
{"4", 10, 1, 4},
{"5", 10, 1, 5},
{"6", 10, 1, 6},
{"7", 10, 1, 7},
{"8", 10, 1, 8},
{"9", 10, 1, 9},
{"0", 8, 1, 0},
{"1", 8, 1, 1},
{"2", 8, 1, 2},
{"3", 8, 1, 3},
{"4", 8, 1, 4},
{"5", 8, 1, 5},
{"6", 8, 1, 6},
{"7", 8, 1, 7},
{"0", 16, 1, 0},
{"1", 16, 1, 1},
{"2", 16, 1, 2},
{"3", 16, 1, 3},
{"4", 16, 1, 4},
{"5", 16, 1, 5},
{"6", 16, 1, 6},
{"7", 16, 1, 7},
{"8", 16, 1, 8},
{"9", 16, 1, 9},
{"a", 16, 1, 10},
{"b", 16, 1, 11},
{"c", 16, 1, 12},
{"d", 16, 1, 13},
{"e", 16, 1, 14},
{"f", 16, 1, 15},
{"A", 16, 1, 10},
{"B", 16, 1, 11},
{"C", 16, 1, 12},
{"D", 16, 1, 13},
{"E", 16, 1, 14},
{"F", 16, 1, 15},
{"127", 10, 3, 127},
{"128", 10, 3, 128},
{"255", 10, 3, 255},
{"256", 10, 3, 256},
{"32767", 10, 5, 32767},
{"32768", 10, 5, 32768},
{"65535", 10, 5, 65535},
{"65536", 10, 5, 65536},
{"2147483647", 10, 10, 2147483647},
{"2147483648", 10, 10, 2147483648ull},
{"4294967295", 10, 10, 4294967295ull},
{"4294967296", 10, 10, 4294967296},
{"9223372036854775807", 10, 19, 9223372036854775807},
{"9223372036854775808", 10, 19, 9223372036854775808ull},
{"18446744073709551615", 10, 20, 18446744073709551615ull},
{"177", 8, 3, 0177},
{"200", 8, 3, 0200},
{"377", 8, 3, 0377},
{"400", 8, 3, 0400},
{"77777", 8, 5, 077777},
{"100000", 8, 6, 0100000},
{"177777", 8, 6, 0177777},
{"200000", 8, 6, 0200000},
{"17777777777", 8, 11, 017777777777},
{"20000000000", 8, 11, 020000000000},
{"37777777777", 8, 11, 037777777777},
{"40000000000", 8, 11, 040000000000},
{"777777777777777777777", 8, 21, 0777777777777777777777},
{"1000000000000000000000", 8, 22, 01000000000000000000000},
{"1777777777777777777777", 8, 22, 01777777777777777777777},
{"7f", 16, 2, 0x7f},
{"80", 16, 2, 0x80},
{"ff", 16, 2, 0xff},
{"100", 16, 3, 0x100},
{"7fff", 16, 4, 0x7fff},
{"8000", 16, 4, 0x8000},
{"ffff", 16, 4, 0xffff},
{"10000", 16, 5, 0x10000},
{"7fffffff", 16, 8, 0x7fffffff},
{"80000000", 16, 8, 0x80000000},
{"ffffffff", 16, 8, 0xffffffff},
{"100000000", 16, 9, 0x100000000},
{"7fffffffffffffff", 16, 16, 0x7fffffffffffffff},
{"8000000000000000", 16, 16, 0x8000000000000000},
{"ffffffffffffffff", 16, 16, 0xffffffffffffffff},
/* test sign */
{"+0", 10, 2, 0},
{"+42", 10, 3, 42},
/* test termination */
{"42/", 10, 2, 42},
{"42:", 10, 2, 42},
{"42/", 8, 2, 042},
{"428", 8, 2, 042},
{"42/", 16, 2, 0x42},
{"42`", 16, 2, 0x42},
{"42g", 16, 2, 0x42},
{"42@", 16, 2, 0x42},
{"42G", 16, 2, 0x42},
/* base autodetection */
{"010", 0, 3, 8},
{"0x10", 0, 4, 16},
{"0X10", 0, 4, 16},
};
static void __init test_parse_integer_ull_ok(void)
{
TEST_OK(unsigned long long, "%llu", test_ull_ok);
}
DEFINE_TEST_FAIL(unsigned long long, test_ull_fail)
{
/* type overflow */
{"10000000000000000000000000000000000000000000000000000000000000000", 2},
{"18446744073709551616", 10},
{"2000000000000000000000", 8},
{"10000000000000000", 16},
{"", 0},
{"", 10},
{"", 8},
{"", 16},
{"+", 0},
{"+", 10},
{"+", 8},
{"+", 16},
{"-", 0},
{"-", 10},
{"-", 8},
{"-", 16},
{" ", 0},
{" ", 10},
{" ", 8},
{" ", 16},
{"\n", 0},
{"\n", 10},
{"\n", 8},
{"\n", 16},
{" 0", 0},
{" 0", 10},
{" 0", 8},
{" 0", 16},
{"\n0", 0},
{"\n0", 10},
{"\n0", 8},
{"\n0", 16},
/* non-digit */
{"/", 10},
{":", 10},
{"/", 8},
{"8", 8},
{"/", 16},
{":", 16},
{"`", 16},
{"g", 16},
{"@", 16},
{"G", 16},
{"/0", 10},
{":0", 10},
{"/0", 8},
{"80", 8},
{"/0", 16},
{":0", 16},
{"`0", 16},
{"g0", 16},
{"@0", 16},
{"G0", 16},
{"-0", 0},
{"-0", 10},
{"-0", 8},
{"-0", 16},
{"-1", 0},
{"-1", 10},
{"-1", 8},
{"-1", 16},
/* accept only one sign */
{"--", 0},
{"--", 10},
{"--", 8},
{"--", 16},
{"-+", 0},
{"-+", 10},
{"-+", 8},
{"-+", 16},
{"+-", 0},
{"+-", 10},
{"+-", 8},
{"+-", 16},
{"++", 0},
{"++", 10},
{"++", 8},
{"++", 16},
{"--0", 0},
{"--0", 10},
{"--0", 8},
{"--0", 16},
{"-+0", 0},
{"-+0", 10},
{"-+0", 8},
{"-+0", 16},
{"+-0", 0},
{"+-0", 10},
{"+-0", 8},
{"+-0", 16},
{"++0", 0},
{"++0", 10},
{"++0", 8},
{"++0", 16},
};
static void __init test_parse_integer_ull_fail(void)
{
TEST_FAIL(unsigned long long, "%llu", test_ull_fail);
}
DEFINE_TEST_OK(long long, struct test_ll, test_ll_ok)
{
{"-9223372036854775808",10, 20, LLONG_MIN},
{"-4294967296", 10, 11, -4294967296},
{"-2147483648", 10, 11, -2147483648ll},
{"-65536", 10, 6, -65536},
{"-32768", 10, 6, -32768},
{"-256", 10, 4, -256},
{"-128", 10, 4, -128},
{"-0", 10, 2, 0},
{"0", 10, 1, 0},
{"127", 10, 3, 127},
{"255", 10, 3, 255},
{"32767", 10, 5, 32767},
{"65535", 10, 5, 65535},
{"2147483647", 10, 10, 2147483647},
{"4294967295", 10, 10, 4294967295ll},
{"9223372036854775807", 10, 19, 9223372036854775807},
};
static void __init test_parse_integer_ll_ok(void)
{
TEST_OK(long long, "%lld", test_ll_ok);
}
DEFINE_TEST_FAIL(long long, test_ll_fail)
{
{"-9223372036854775809", 10},
{"9223372036854775808", 10},
};
static void __init test_parse_integer_ll_fail(void)
{
TEST_FAIL(long long, "%lld", test_ll_fail);
}
DEFINE_TEST_OK(unsigned int, struct test_u, test_u_ok)
{
{"0", 10, 1, 0},
{"127", 10, 3, 127},
{"128", 10, 3, 128},
{"255", 10, 3, 255},
{"256", 10, 3, 256},
{"32767", 10, 5, 32767},
{"32768", 10, 5, 32768},
{"65535", 10, 5, 65535},
{"65536", 10, 5, 65536},
{"2147483647", 10, 10, 2147483647},
{"2147483648", 10, 10, 2147483648u},
{"4294967295", 10, 10, 4294967295u},
};
static void __init test_parse_integer_u_ok(void)
{
TEST_OK(unsigned int, "%u", test_u_ok);
}
DEFINE_TEST_FAIL(unsigned int, test_u_fail)
{
{"4294967296", 10},
{"9223372036854775807", 10},
{"9223372036854775808", 10},
{"18446744073709551615", 10},
};
static void __init test_parse_integer_u_fail(void)
{
TEST_FAIL(unsigned int, "%u", test_u_fail);
}
DEFINE_TEST_OK(int, struct test_i, test_i_ok)
{
{"-2147483648", 10, 11, INT_MIN},
{"-65536", 10, 6, -65536},
{"-32768", 10, 6, -32768},
{"-256", 10, 4, -256},
{"-128", 10, 4, -128},
{"-0", 10, 2, 0},
{"0", 10, 1, 0},
{"127", 10, 3, 127},
{"255", 10, 3, 255},
{"32767", 10, 5, 32767},
{"65535", 10, 5, 65535},
{"2147483647", 10, 10, 2147483647},
};
static void __init test_parse_integer_i_ok(void)
{
TEST_OK(int, "%d", test_i_ok);
}
DEFINE_TEST_FAIL(int, test_i_fail)
{
{"-9223372036854775809", 10},
{"-9223372036854775808", 10},
{"-4294967296", 10},
{"-2147483649", 10},
{"2147483648", 10},
{"4294967295", 10},
{"9223372036854775807", 10},
{"9223372036854775808", 10},
};
static void __init test_parse_integer_i_fail(void)
{
TEST_FAIL(int, "%d", test_i_fail);
}
DEFINE_TEST_OK(unsigned short, struct test_us, test_us_ok)
{
{"0", 10, 1, 0},
{"127", 10, 3, 127},
{"128", 10, 3, 128},
{"255", 10, 3, 255},
{"256", 10, 3, 256},
{"32767", 10, 5, 32767},
{"32768", 10, 5, 32768},
{"65535", 10, 5, 65535},
};
static void __init test_parse_integer_us_ok(void)
{
TEST_OK(unsigned short, "%hu", test_us_ok);
}
DEFINE_TEST_FAIL(unsigned short, test_us_fail)
{
{"65536", 10},
{"2147483647", 10},
{"2147483648", 10},
{"4294967295", 10},
{"4294967296", 10},
{"9223372036854775807", 10},
{"9223372036854775808", 10},
{"18446744073709551615", 10},
};
static void __init test_parse_integer_us_fail(void)
{
TEST_FAIL(unsigned short, "%hu", test_us_fail);
}
DEFINE_TEST_OK(short, struct test_s, test_s_ok)
{
{"-32768", 10, 6, -32768},
{"-256", 10, 4, -256},
{"-128", 10, 4, -128},
{"-0", 10, 2, 0},
{"0", 10, 1, 0},
{"127", 10, 3, 127},
{"255", 10, 3, 255},
{"32767", 10, 5, 32767},
};
static void __init test_parse_integer_s_ok(void)
{
TEST_OK(short, "%hd", test_s_ok);
}
DEFINE_TEST_FAIL(short, test_s_fail)
{
{"-9223372036854775809", 10},
{"-9223372036854775808", 10},
{"-4294967296", 10},
{"-2147483649", 10},
{"-2147483648", 10},
{"-65536", 10},
{"-32769", 10},
{"32768", 10},
{"65535", 10},
{"2147483647", 10},
{"2147483648", 10},
{"4294967295", 10},
{"9223372036854775807", 10},
{"9223372036854775808", 10},
};
static void __init test_parse_integer_s_fail(void)
{
TEST_FAIL(short, "%hd", test_s_fail);
}
DEFINE_TEST_OK(unsigned char, struct test_uc, test_uc_ok)
{
{"0", 10, 1, 0},
{"127", 10, 3, 127},
{"128", 10, 3, 128},
{"255", 10, 3, 255},
};
static void __init test_parse_integer_uc_ok(void)
{
TEST_OK(unsigned char, "%hhu", test_uc_ok);
}
DEFINE_TEST_FAIL(unsigned char, test_uc_fail)
{
{"256", 10},
{"32767", 10},
{"32768", 10},
{"65535", 10},
{"65536", 10},
{"2147483647", 10},
{"2147483648", 10},
{"4294967295", 10},
{"4294967296", 10},
{"9223372036854775807", 10},
{"9223372036854775808", 10},
{"18446744073709551615", 10},
};
static void __init test_parse_integer_uc_fail(void)
{
TEST_FAIL(unsigned char, "%hhu", test_uc_fail);
}
DEFINE_TEST_OK(signed char, struct test_sc, test_sc_ok)
{
{"-128", 10, 4, -128},
{"-0", 10, 2, 0},
{"0", 10, 1, 0},
{"127", 10, 3, 127},
};
static void __init test_parse_integer_sc_ok(void)
{
TEST_OK(signed char, "%hhd", test_sc_ok);
}
DEFINE_TEST_FAIL(signed char, test_sc_fail)
{
{"-9223372036854775809", 10},
{"-9223372036854775808", 10},
{"-4294967296", 10},
{"-2147483649", 10},
{"-2147483648", 10},
{"-65536", 10},
{"-32769", 10},
{"-32768", 10},
{"-256", 10},
{"-129", 10},
{"128", 10},
{"255", 10},
{"32767", 10},
{"32768", 10},
{"65535", 10},
{"2147483647", 10},
{"2147483648", 10},
{"4294967295", 10},
{"9223372036854775807", 10},
{"9223372036854775808", 10},
};
static void __init test_parse_integer_sc_fail(void)
{
TEST_FAIL(signed char, "%hhd", test_sc_fail);
}
static int __init test_parse_integer_init(void)
{
test_parse_integer_ull_ok();
test_parse_integer_ull_fail();
test_parse_integer_ll_ok();
test_parse_integer_ll_fail();
test_parse_integer_u_ok();
test_parse_integer_u_fail();
test_parse_integer_i_ok();
test_parse_integer_i_fail();
test_parse_integer_us_ok();
test_parse_integer_us_fail();
test_parse_integer_s_ok();
test_parse_integer_s_fail();
test_parse_integer_uc_ok();
test_parse_integer_uc_fail();
test_parse_integer_sc_ok();
test_parse_integer_sc_fail();
return -EINVAL;
}
module_init(test_parse_integer_init);
MODULE_LICENSE("Dual BSD/GPL");