[PATCH 03/12] parse_integer: add runtime testsuite

From: Alexey Dobriyan
Date: Fri May 08 2015 - 14:32:09 EST


Use with CONFIG_PARSE_INTEGER=y.

Signed-off-by: Alexey Dobriyan <adobriyan@xxxxxxxxx>
---
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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/