Use with CONFIG_PARSE_INTEGER=y.

Signed-off-by: Alexey Dobriyan <[email protected]>
---
 lib/Kconfig.debug        |   3 +
 lib/Makefile             |   1 +
 lib/test-parse-integer.c | 563 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 567 insertions(+)
 create mode 100644 lib/test-parse-integer.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ba2b0c8..35224ca 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1628,6 +1628,9 @@ config TEST_HEXDUMP
 config TEST_STRING_HELPERS
        tristate "Test functions located in the string_helpers module at 
runtime"
 
+config TEST_PARSE_INTEGER
+       tristate "Test parse_integer() function at runtime"
+
 config TEST_KSTRTOX
        tristate "Test kstrto*() family of functions at runtime"
 
diff --git a/lib/Makefile b/lib/Makefile
index e69b356..1925810 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,6 +36,7 @@ obj-y += parse-integer.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
 obj-$(CONFIG_TEST_KASAN) += test_kasan.o
+obj-$(CONFIG_TEST_PARSE_INTEGER) += test-parse-integer.o
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 obj-$(CONFIG_TEST_LKM) += test_module.o
 obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
diff --git a/lib/test-parse-integer.c b/lib/test-parse-integer.c
new file mode 100644
index 0000000..4274603
--- /dev/null
+++ b/lib/test-parse-integer.c
@@ -0,0 +1,563 @@
+#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");
-- 
2.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to