[PATCH v8 03/10] lib: test-kstrtox: add tests for kstrntoull()

Rodrigo Alencar via B4 Relay posted 10 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH v8 03/10] lib: test-kstrtox: add tests for kstrntoull()
Posted by Rodrigo Alencar via B4 Relay 1 month, 1 week ago
From: Rodrigo Alencar <rodrigo.alencar@analog.com>

Add test cases for the new kstrntoull() function which converts a string
to unsigned long long with a maximum character limit.

The OK tests cover basic decimal conversion, max_chars truncation, octal
and hex with both autodetection and explicit base, stop-at-non-digit
behavior, and chained conversions where the return value is used to
advance through a compound string (e.g. "192.168.1.0", "123::456").

The fail tests cover overflow for decimal, hex, and octal, prefix
consumed entirely by max_chars, zero max_chars, empty string, and bare
hex prefix.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
---
 lib/test-kstrtox.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/lib/test-kstrtox.c b/lib/test-kstrtox.c
index ee87fef66cb5..c3fe2a3bc142 100644
--- a/lib/test-kstrtox.c
+++ b/lib/test-kstrtox.c
@@ -703,6 +703,124 @@ static void __init test_kstrtos8_fail(void)
 	TEST_FAIL(kstrtos8, s8, "%hhd", test_s8_fail);
 }
 
+static void __init test_kstrntoull_ok(void)
+{
+	struct test_ntoull {
+		const char *str;
+		size_t step;
+		unsigned int base;
+		size_t max_chars;
+		ssize_t expected_rv;
+		unsigned long long expected_res;
+	};
+	static const struct test_ntoull test[] __initconst = {
+		/* basic decimal */
+		{"0",		0,	10,	1,	1,	0ULL},
+		{"1",		0,	10,	1,	1,	1ULL},
+		{"123",		0,	10,	3,	3,	123ULL},
+		{"123",		0,	10,	10,	3,	123ULL},
+		/* max_chars truncation */
+		{"1234567",	0,	10,	1,	1,	1ULL},
+		{"1234567",	0,	10,	3,	3,	123ULL},
+		{"1234567",	0,	10,	5,	5,	12345ULL},
+		/* octal with base autodetection */
+		{"0177",	0,	0,	4,	4,	0177ULL},
+		{"0177",	0,	0,	3,	3,	017ULL},
+		{"0177",	0,	0,	2,	2,	01ULL},
+		/* octal with explicit base */
+		{"01777",	0,	8,	4,	4,	0177ULL},
+		{"01777",	0,	8,	3,	3,	017ULL},
+		/* hex with base autodetection */
+		{"0xff",	0,	0,	4,	4,	0xffULL},
+		{"0xffff",	0,	0,	4,	4,	0xffULL},
+		{"0xffff",	0,	0,	6,	6,	0xffffULL},
+		{"0xFF",	0,	0,	4,	4,	0xffULL},
+		/* hex with explicit base */
+		{"0xff",	0,	16,	4,	4,	0xffULL},
+		{"ff",		0,	16,	2,	2,	0xffULL},
+		/* stop at non-digit */
+		{"12abc",	0,	10,	5,	2,	12ULL},
+		/* large values */
+		{"18446744073709551615", 0, 10, 20, 20, 18446744073709551615ULL},
+		{"ffffffffffffffff", 0, 16, 16, 16, 0xffffffffffffffffULL},
+		/* chained tests */
+		{"123::456",	0,	10,	10,	3,	123ULL},
+		{NULL,		2,	10,	10,	3,	456ULL},
+		{"192.168.1.0",	0,	10,	10,	3,	192ULL},
+		{NULL,		1,	10,	10,	3,	168ULL},
+		{NULL,		1,	10,	10,	1,	1ULL},
+		{NULL,		1,	10,	10,	1,	0ULL},
+		{"123-beef",	0,	10,	10,	3,	123ULL},
+		{NULL,		1,	16,	10,	4,	0xBEEFULL},
+		{"12345678",	0,	10,	5,	5,	12345ULL},
+		{NULL,		0,	10,	5,	3,	678ULL},
+	};
+	unsigned int i;
+	const char *s = NULL;
+
+	for_each_test(i, test) {
+		const struct test_ntoull *t = &test[i];
+		unsigned long long res = ~0ULL;
+		ssize_t rv;
+
+		if (t->str)
+			s = t->str;
+		s += t->step;
+
+		rv = kstrntoull(s, t->base, &res, t->max_chars);
+		if (rv != t->expected_rv) {
+			WARN(1, "str '%s', base %u, max_chars %zu, expected rv %zd, got %zd\n",
+			     s, t->base, t->max_chars, t->expected_rv, rv);
+			continue;
+		}
+		if (rv >= 0 && res != t->expected_res) {
+			WARN(1, "str '%s', base %u, max_chars %zu, expected %llu, got %llu\n",
+			     s, t->base, t->max_chars, t->expected_res, res);
+			continue;
+		}
+		s += rv;
+	}
+}
+
+static void __init test_kstrntoull_fail(void)
+{
+	struct test_ntoull_fail {
+		const char *str;
+		unsigned int base;
+		size_t max_chars;
+		ssize_t expected_rv;
+	};
+	static const struct test_ntoull_fail test[] __initconst = {
+		/* overflow */
+		{"18446744073709551616",	10,	20,	-ERANGE},
+		{"10000000000000000",		16,	17,	-ERANGE},
+		{"2000000000000000000000",	8,	22,	-ERANGE},
+		/* max_chars is too small */
+		{"123",		10,	0,	-EINVAL},
+		{"0xff",	0,	1,	-EINVAL},
+		{"0xff",	0,	2,	-EINVAL},
+		{"0xff",	16,	1,	-EINVAL},
+		{"0xff",	16,	2,	-EINVAL},
+		/* empty string */
+		{"",		10,	10,	-EINVAL},
+		{"0x",		16,	10,	-EINVAL},
+	};
+	unsigned int i;
+
+	for_each_test(i, test) {
+		const struct test_ntoull_fail *t = &test[i];
+		unsigned long long res = 0;
+		ssize_t rv;
+
+		rv = kstrntoull(t->str, t->base, &res, t->max_chars);
+		if (rv != t->expected_rv) {
+			WARN(1, "str '%s', base %u, max_chars %zu, expected %zd, got %zd\n",
+			     t->str, t->base, t->max_chars, t->expected_rv, rv);
+			continue;
+		}
+	}
+}
+
 static int __init test_kstrtox_init(void)
 {
 	test_kstrtoull_ok();
@@ -729,6 +847,9 @@ static int __init test_kstrtox_init(void)
 	test_kstrtou8_fail();
 	test_kstrtos8_ok();
 	test_kstrtos8_fail();
+
+	test_kstrntoull_ok();
+	test_kstrntoull_fail();
 	return -EINVAL;
 }
 module_init(test_kstrtox_init);

-- 
2.43.0