LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v1 0/4] hexdump: amend the hex_dump_to_buffer()
@ 2014-12-29 11:50 Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 1/4] hexdump: introduce test suite Andy Shevchenko
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Andy Shevchenko @ 2014-12-29 11:50 UTC (permalink / raw)
  To: linux-kernel, Joe Perches, Andrew Morton; +Cc: Andy Shevchenko

This series is targeted to amend hex_dump_to_buffer() function. It consists
test suite, fix for output format and features the function by adding return
code.

With those changes the function would be used for seq_file API.

Andy Shevchenko (4):
  hexdump: introduce test suite
  hexdump: fix ascii column for the tail of a dump
  hexdump: do few calculations ahead
  hexdump: makes it return amount of bytes placed in buffer

 include/linux/printk.h |   6 +-
 lib/Kconfig.debug      |   3 +
 lib/Makefile           |   4 +-
 lib/hexdump.c          | 105 ++++++++++++++++++-----------
 lib/test-hexdump.c     | 180 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 253 insertions(+), 45 deletions(-)
 create mode 100644 lib/test-hexdump.c

-- 
2.1.3


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v1 1/4] hexdump: introduce test suite
  2014-12-29 11:50 [PATCH v1 0/4] hexdump: amend the hex_dump_to_buffer() Andy Shevchenko
@ 2014-12-29 11:50 ` Andy Shevchenko
  2015-01-12 15:08   ` Paul Gortmaker
  2014-12-29 11:50 ` [PATCH v1 2/4] hexdump: fix ascii column for the tail of a dump Andy Shevchenko
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Andy Shevchenko @ 2014-12-29 11:50 UTC (permalink / raw)
  To: linux-kernel, Joe Perches, Andrew Morton; +Cc: Andy Shevchenko

Test different scenarios of function calls located in lib/hexdump.c.

Currently hex_dump_to_buffer() is only tested and test data is provided for
little endian CPUs.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 lib/Kconfig.debug  |   3 ++
 lib/Makefile       |   4 +-
 lib/test-hexdump.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+), 1 deletion(-)
 create mode 100644 lib/test-hexdump.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a4a6d9a..5fe0a71 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1580,6 +1580,9 @@ config ASYNC_RAID6_TEST
 
 	  If unsure, say N.
 
+config TEST_HEXDUMP
+	tristate "Test functions located in the hexdump module at runtime"
+
 config TEST_STRING_HELPERS
 	tristate "Test functions located in the string_helpers module at runtime"
 
diff --git a/lib/Makefile b/lib/Makefile
index f42838a..3dca86f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -23,12 +23,14 @@ lib-y	+= kobject.o klist.o
 obj-y	+= lockref.o
 
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
-	 bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
+	 bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
 	 gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \
 	 bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \
 	 percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o
 obj-y += string_helpers.o
 obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
+obj-y += hexdump.o
+obj-$(CONFIG_TEST_HEXDUMP) += test-hexdump.o
 obj-y += kstrtox.o
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 obj-$(CONFIG_TEST_LKM) += test_module.o
diff --git a/lib/test-hexdump.c b/lib/test-hexdump.c
new file mode 100644
index 0000000..9d3bd1e
--- /dev/null
+++ b/lib/test-hexdump.c
@@ -0,0 +1,135 @@
+/*
+ * Test cases for lib/hexdump.c module.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/string.h>
+
+static const unsigned char data_b[] = {
+	'\xbe', '\x32', '\xdb', '\x7b', '\x0a', '\x18', '\x93', '\xb2',	/* 00 - 07 */
+	'\x70', '\xba', '\xc4', '\x24', '\x7d', '\x83', '\x34', '\x9b',	/* 08 - 0f */
+	'\xa6', '\x9c', '\x31', '\xad', '\x9c', '\x0f', '\xac', '\xe9',	/* 10 - 17 */
+	'\x4c', '\xd1', '\x19', '\x99', '\x43', '\xb1', '\xaf', '\x0c',	/* 18 - 1f */
+};
+
+static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
+
+static const char *test_data_1_le[] __initconst = {
+	"be", "32", "db", "7b", "0a", "18", "93", "b2",
+	"70", "ba", "c4", "24", "7d", "83", "34", "9b",
+	"a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
+	"4c", "d1", "19", "99", "43", "b1", "af", "0c",
+};
+
+static const char *test_data_2_le[] __initconst = {
+	"32be", "7bdb", "180a", "b293",
+	"ba70", "24c4", "837d", "9b34",
+	"9ca6", "ad31", "0f9c", "e9ac",
+	"d14c", "9919", "b143", "0caf",
+};
+
+static const char *test_data_4_le[] __initconst = {
+	"7bdb32be", "b293180a", "24c4ba70", "9b34837d",
+	"ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
+};
+
+static const char *test_data_8_le[] __initconst = {
+	"b293180a7bdb32be", "9b34837d24c4ba70",
+	"e9ac0f9cad319ca6", "0cafb1439919d14c",
+};
+
+static void __init test_hexdump(size_t len, int rowsize, int groupsize,
+				bool ascii)
+{
+	char test[32 * 3 + 2 + 32 + 1];
+	char real[32 * 3 + 2 + 32 + 1];
+	char *p;
+	const char **result;
+	size_t l = len;
+	int gs = groupsize, rs = rowsize;
+	unsigned int i;
+
+	hex_dump_to_buffer(data_b, l, rs, gs, real, sizeof(real), ascii);
+
+	if (rs != 16 && rs != 32)
+		rs = 16;
+
+	if (l > rs)
+		l = rs;
+
+	if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
+		gs = 1;
+
+	if (gs == 8)
+		result = test_data_8_le;
+	else if (gs == 4)
+		result = test_data_4_le;
+	else if (gs == 2)
+		result = test_data_2_le;
+	else
+		result = test_data_1_le;
+
+	memset(test, ' ', sizeof(test));
+
+	/* hex dump */
+	p = test;
+	for (i = 0; i < l / gs; i++) {
+		const char *q = *result++;
+		size_t amount = strlen(q);
+
+		strncpy(p, q, amount);
+		p += amount + 1;
+	}
+	if (i)
+		p--;
+
+	/* ASCII part */
+	if (ascii) {
+		p = test + rs * 2 + rs / gs + 1;
+		strncpy(p, data_a, l);
+		p += l;
+	}
+
+	*p = '\0';
+
+	if (strcmp(test, real)) {
+		pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
+		pr_err("Result: '%s'\n", real);
+		pr_err("Expect: '%s'\n", test);
+	}
+}
+
+static void __init test_hexdump_set(int rowsize, bool ascii)
+{
+	size_t d = min_t(size_t, sizeof(data_b), rowsize);
+	size_t len = get_random_int() % d + 1;
+
+	test_hexdump(len, rowsize, 4, ascii);
+	test_hexdump(len, rowsize, 2, ascii);
+	test_hexdump(len, rowsize, 8, ascii);
+	test_hexdump(len, rowsize, 1, ascii);
+}
+
+static int __init test_hexdump_init(void)
+{
+	unsigned int i;
+	int rowsize;
+
+	pr_info("Running tests...\n");
+
+	rowsize = (get_random_int() % 2 + 1) * 16;
+	for (i = 0; i < 16; i++)
+		test_hexdump_set(rowsize, false);
+
+	rowsize = (get_random_int() % 2 + 1) * 16;
+	for (i = 0; i < 16; i++)
+		test_hexdump_set(rowsize, true);
+
+	return -EINVAL;
+}
+module_init(test_hexdump_init);
+MODULE_LICENSE("Dual BSD/GPL");
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v1 2/4] hexdump: fix ascii column for the tail of a dump
  2014-12-29 11:50 [PATCH v1 0/4] hexdump: amend the hex_dump_to_buffer() Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 1/4] hexdump: introduce test suite Andy Shevchenko
@ 2014-12-29 11:50 ` Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 3/4] hexdump: do few calculations ahead Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 4/4] hexdump: makes it return amount of bytes placed in buffer Andy Shevchenko
  3 siblings, 0 replies; 6+ messages in thread
From: Andy Shevchenko @ 2014-12-29 11:50 UTC (permalink / raw)
  To: linux-kernel, Joe Perches, Andrew Morton; +Cc: Andy Shevchenko

In current implementation we have floating ascii column in the tail of the
dump.

For example, for row size equal to 16 the ascii column as in following table

group size \ length	8	12	16
	1		50	50	50
	2		22	32	42
	4		20	29	38
	8		19	-	36

This patch makes it the same independently of amount of bytes dumped.

The change is safe since all current users, which use ASCII part of the dump,
rely on the group size equal to 1. The patch doesn't change behaviour for such
group size (see the table above).

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 lib/hexdump.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/hexdump.c b/lib/hexdump.c
index 270773b..a61cb6b 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -126,7 +126,7 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 					"%s%16.16llx", j ? " " : "",
 					(unsigned long long)*(ptr8 + j));
-		ascii_column = 17 * ngroups + 2;
+		ascii_column = rowsize * 2 + rowsize / 8 + 2;
 		break;
 	}
 
@@ -137,7 +137,7 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 		for (j = 0; j < ngroups; j++)
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 					"%s%8.8x", j ? " " : "", *(ptr4 + j));
-		ascii_column = 9 * ngroups + 2;
+		ascii_column = rowsize * 2 + rowsize / 4 + 2;
 		break;
 	}
 
@@ -148,7 +148,7 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 		for (j = 0; j < ngroups; j++)
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 					"%s%4.4x", j ? " " : "", *(ptr2 + j));
-		ascii_column = 5 * ngroups + 2;
+		ascii_column = rowsize * 2 + rowsize / 2 + 2;
 		break;
 	}
 
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v1 3/4] hexdump: do few calculations ahead
  2014-12-29 11:50 [PATCH v1 0/4] hexdump: amend the hex_dump_to_buffer() Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 1/4] hexdump: introduce test suite Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 2/4] hexdump: fix ascii column for the tail of a dump Andy Shevchenko
@ 2014-12-29 11:50 ` Andy Shevchenko
  2014-12-29 11:50 ` [PATCH v1 4/4] hexdump: makes it return amount of bytes placed in buffer Andy Shevchenko
  3 siblings, 0 replies; 6+ messages in thread
From: Andy Shevchenko @ 2014-12-29 11:50 UTC (permalink / raw)
  To: linux-kernel, Joe Perches, Andrew Morton; +Cc: Andy Shevchenko

Instead of doing calculations in each case of different groupsize let's do them
beforehand. While here, change the switch by if-else-if construction.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 lib/hexdump.c | 34 ++++++++++------------------------
 1 file changed, 10 insertions(+), 24 deletions(-)

diff --git a/lib/hexdump.c b/lib/hexdump.c
index a61cb6b..4af53f7 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -103,6 +103,7 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 			bool ascii)
 {
 	const u8 *ptr = buf;
+	int ngroups;
 	u8 ch;
 	int j, lx = 0;
 	int ascii_column;
@@ -114,45 +115,33 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 		goto nil;
 	if (len > rowsize)		/* limit to one line at a time */
 		len = rowsize;
+	if (!is_power_of_2(groupsize) || groupsize > 8)
+		groupsize = 1;
 	if ((len % groupsize) != 0)	/* no mixed size output */
 		groupsize = 1;
 
-	switch (groupsize) {
-	case 8: {
+	ngroups = len / groupsize;
+	ascii_column = rowsize * 2 + rowsize / groupsize + 1;
+	if (groupsize == 8) {
 		const u64 *ptr8 = buf;
-		int ngroups = len / groupsize;
 
 		for (j = 0; j < ngroups; j++)
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 					"%s%16.16llx", j ? " " : "",
 					(unsigned long long)*(ptr8 + j));
-		ascii_column = rowsize * 2 + rowsize / 8 + 2;
-		break;
-	}
-
-	case 4: {
+	} else if (groupsize == 4) {
 		const u32 *ptr4 = buf;
-		int ngroups = len / groupsize;
 
 		for (j = 0; j < ngroups; j++)
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 					"%s%8.8x", j ? " " : "", *(ptr4 + j));
-		ascii_column = rowsize * 2 + rowsize / 4 + 2;
-		break;
-	}
-
-	case 2: {
+	} else if (groupsize == 2) {
 		const u16 *ptr2 = buf;
-		int ngroups = len / groupsize;
 
 		for (j = 0; j < ngroups; j++)
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 					"%s%4.4x", j ? " " : "", *(ptr2 + j));
-		ascii_column = rowsize * 2 + rowsize / 2 + 2;
-		break;
-	}
-
-	default:
+	} else {
 		for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
 			ch = ptr[j];
 			linebuf[lx++] = hex_asc_hi(ch);
@@ -161,14 +150,11 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 		}
 		if (j)
 			lx--;
-
-		ascii_column = 3 * rowsize + 2;
-		break;
 	}
 	if (!ascii)
 		goto nil;
 
-	while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
+	while (lx < (linebuflen - 1) && lx < ascii_column)
 		linebuf[lx++] = ' ';
 	for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) {
 		ch = ptr[j];
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v1 4/4] hexdump: makes it return amount of bytes placed in buffer
  2014-12-29 11:50 [PATCH v1 0/4] hexdump: amend the hex_dump_to_buffer() Andy Shevchenko
                   ` (2 preceding siblings ...)
  2014-12-29 11:50 ` [PATCH v1 3/4] hexdump: do few calculations ahead Andy Shevchenko
@ 2014-12-29 11:50 ` Andy Shevchenko
  3 siblings, 0 replies; 6+ messages in thread
From: Andy Shevchenko @ 2014-12-29 11:50 UTC (permalink / raw)
  To: linux-kernel, Joe Perches, Andrew Morton; +Cc: Andy Shevchenko

This patch makes hexdump to return amount of bytes placed in the buffer
excluding trailing NUL. In case of overflow it returns desired amount of bytes
to place entire dump. Thus, it mimics snprintf().

This will be useful for users that would like to repeat with bigger buffer.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 include/linux/printk.h |  6 ++---
 lib/hexdump.c          | 73 +++++++++++++++++++++++++++++++++++++-------------
 lib/test-hexdump.c     | 45 +++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+), 21 deletions(-)

diff --git a/include/linux/printk.h b/include/linux/printk.h
index c8f1703..aeb9d7f 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -408,9 +408,9 @@ enum {
 	DUMP_PREFIX_ADDRESS,
 	DUMP_PREFIX_OFFSET
 };
-extern void hex_dump_to_buffer(const void *buf, size_t len,
-			       int rowsize, int groupsize,
-			       char *linebuf, size_t linebuflen, bool ascii);
+extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+			      int groupsize, char *linebuf, size_t linebuflen,
+			      bool ascii);
 #ifdef CONFIG_PRINTK
 extern void print_hex_dump(const char *level, const char *prefix_str,
 			   int prefix_type, int rowsize, int groupsize,
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 4af53f7..7ea0969 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -97,22 +97,26 @@ EXPORT_SYMBOL(bin2hex);
  *
  * example output buffer:
  * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
+ *
+ * Return:
+ * The amount of bytes placed in the buffer without terminating NUL. If the
+ * output was truncated, then the return value is the number of bytes
+ * (excluding the terminating NUL) which would have been written to the final
+ * string if enough space had been available.
  */
-void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
-			int groupsize, char *linebuf, size_t linebuflen,
-			bool ascii)
+int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
+		       char *linebuf, size_t linebuflen, bool ascii)
 {
 	const u8 *ptr = buf;
 	int ngroups;
 	u8 ch;
 	int j, lx = 0;
 	int ascii_column;
+	int ret;
 
 	if (rowsize != 16 && rowsize != 32)
 		rowsize = 16;
 
-	if (!len)
-		goto nil;
 	if (len > rowsize)		/* limit to one line at a time */
 		len = rowsize;
 	if (!is_power_of_2(groupsize) || groupsize > 8)
@@ -122,27 +126,50 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 
 	ngroups = len / groupsize;
 	ascii_column = rowsize * 2 + rowsize / groupsize + 1;
+
+	if (!linebuflen)
+		goto overflow1;
+
+	if (!len)
+		goto nil;
+
 	if (groupsize == 8) {
 		const u64 *ptr8 = buf;
 
-		for (j = 0; j < ngroups; j++)
-			lx += scnprintf(linebuf + lx, linebuflen - lx,
-					"%s%16.16llx", j ? " " : "",
-					(unsigned long long)*(ptr8 + j));
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%16.16llx", j ? " " : "",
+				       (unsigned long long)*(ptr8 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
 	} else if (groupsize == 4) {
 		const u32 *ptr4 = buf;
 
-		for (j = 0; j < ngroups; j++)
-			lx += scnprintf(linebuf + lx, linebuflen - lx,
-					"%s%8.8x", j ? " " : "", *(ptr4 + j));
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%8.8x", j ? " " : "",
+				       *(ptr4 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
 	} else if (groupsize == 2) {
 		const u16 *ptr2 = buf;
 
-		for (j = 0; j < ngroups; j++)
-			lx += scnprintf(linebuf + lx, linebuflen - lx,
-					"%s%4.4x", j ? " " : "", *(ptr2 + j));
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%4.4x", j ? " " : "",
+				       *(ptr2 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
 	} else {
-		for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
+		for (j = 0; j < len; j++) {
+			if (linebuflen < lx + 3)
+				goto overflow2;
 			ch = ptr[j];
 			linebuf[lx++] = hex_asc_hi(ch);
 			linebuf[lx++] = hex_asc_lo(ch);
@@ -154,14 +181,24 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 	if (!ascii)
 		goto nil;
 
-	while (lx < (linebuflen - 1) && lx < ascii_column)
+	while (lx < ascii_column) {
+		if (linebuflen < lx + 2)
+			goto overflow2;
 		linebuf[lx++] = ' ';
-	for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) {
+	}
+	for (j = 0; j < len; j++) {
+		if (linebuflen < lx + 2)
+			goto overflow2;
 		ch = ptr[j];
 		linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
 	}
 nil:
+	linebuf[lx] = '\0';
+	return lx;
+overflow2:
 	linebuf[lx++] = '\0';
+overflow1:
+	return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
 }
 EXPORT_SYMBOL(hex_dump_to_buffer);
 
diff --git a/lib/test-hexdump.c b/lib/test-hexdump.c
index 9d3bd1e..d10f90b 100644
--- a/lib/test-hexdump.c
+++ b/lib/test-hexdump.c
@@ -114,6 +114,45 @@ static void __init test_hexdump_set(int rowsize, bool ascii)
 	test_hexdump(len, rowsize, 1, ascii);
 }
 
+static void __init test_hexdump_overflow(bool ascii)
+{
+	char buf[56];
+	const char *t = test_data_1_le[0];
+	size_t l = get_random_int() % sizeof(buf);
+	bool a;
+	int e, r;
+
+	memset(buf, ' ', sizeof(buf));
+
+	r = hex_dump_to_buffer(data_b, 1, 16, 1, buf, l, ascii);
+
+	if (ascii)
+		e = 50;
+	else
+		e = 2;
+	buf[e + 2] = '\0';
+
+	if (!l) {
+		a = r == e && buf[0] == ' ';
+	} else if (l < 3) {
+		a = r == e && buf[0] == '\0';
+	} else if (l < 4) {
+		a = r == e && !strcmp(buf, t);
+	} else if (ascii) {
+		if (l < 51)
+			a = r == e && buf[l - 1] == '\0' && buf[l - 2] == ' ';
+		else
+			a = r == e && buf[50] == '\0' && buf[49] == '.';
+	} else {
+		a = r == e && buf[e] == '\0';
+	}
+
+	if (!a) {
+		pr_err("Len: %zu rc: %zu strlen: %zu\n", l, r, strlen(buf));
+		pr_err("Result: '%s'\n", buf);
+	}
+}
+
 static int __init test_hexdump_init(void)
 {
 	unsigned int i;
@@ -129,6 +168,12 @@ static int __init test_hexdump_init(void)
 	for (i = 0; i < 16; i++)
 		test_hexdump_set(rowsize, true);
 
+	for (i = 0; i < 16; i++)
+		test_hexdump_overflow(false);
+
+	for (i = 0; i < 16; i++)
+		test_hexdump_overflow(true);
+
 	return -EINVAL;
 }
 module_init(test_hexdump_init);
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v1 1/4] hexdump: introduce test suite
  2014-12-29 11:50 ` [PATCH v1 1/4] hexdump: introduce test suite Andy Shevchenko
@ 2015-01-12 15:08   ` Paul Gortmaker
  0 siblings, 0 replies; 6+ messages in thread
From: Paul Gortmaker @ 2015-01-12 15:08 UTC (permalink / raw)
  To: Andy Shevchenko; +Cc: LKML, Joe Perches, Andrew Morton

On Mon, Dec 29, 2014 at 6:50 AM, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> Test different scenarios of function calls located in lib/hexdump.c.
>
> Currently hex_dump_to_buffer() is only tested and test data is provided for
> little endian CPUs.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  lib/Kconfig.debug  |   3 ++
>  lib/Makefile       |   4 +-
>  lib/test-hexdump.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 141 insertions(+), 1 deletion(-)
>  create mode 100644 lib/test-hexdump.c
>
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index a4a6d9a..5fe0a71 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -1580,6 +1580,9 @@ config ASYNC_RAID6_TEST
>
>           If unsure, say N.
>
> +config TEST_HEXDUMP
> +       tristate "Test functions located in the hexdump module at runtime"
> +

I just happened across this as it appeared in linux-next and came
up in "make oldconfig".  I realize that there are other options like
the one immediately below in the context that have no help text,
but I don't think that makes it a good reason to add more w/o any
help text.   Just filling in the blanks in something as simple as:

   The hexdump module provides library functions like ....
   that are primarily used by the ...   Enabling this option will
   build a simple test run at boot/module insertion that checks...

   If unsure, say N.

Thanks,
Paul.
--

>  config TEST_STRING_HELPERS
>         tristate "Test functions located in the string_helpers module at runtime"
>
> diff --git a/lib/Makefile b/lib/Makefile
> index f42838a..3dca86f 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -23,12 +23,14 @@ lib-y       += kobject.o klist.o
>  obj-y  += lockref.o
>
>  obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
> -        bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
> +        bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
>          gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \
>          bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \
>          percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o
>  obj-y += string_helpers.o
>  obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
> +obj-y += hexdump.o
> +obj-$(CONFIG_TEST_HEXDUMP) += test-hexdump.o
>  obj-y += kstrtox.o
>  obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
>  obj-$(CONFIG_TEST_LKM) += test_module.o
> diff --git a/lib/test-hexdump.c b/lib/test-hexdump.c
> new file mode 100644
> index 0000000..9d3bd1e
> --- /dev/null
> +++ b/lib/test-hexdump.c
> @@ -0,0 +1,135 @@
> +/*
> + * Test cases for lib/hexdump.c module.
> + */
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/random.h>
> +#include <linux/string.h>
> +
> +static const unsigned char data_b[] = {
> +       '\xbe', '\x32', '\xdb', '\x7b', '\x0a', '\x18', '\x93', '\xb2', /* 00 - 07 */
> +       '\x70', '\xba', '\xc4', '\x24', '\x7d', '\x83', '\x34', '\x9b', /* 08 - 0f */
> +       '\xa6', '\x9c', '\x31', '\xad', '\x9c', '\x0f', '\xac', '\xe9', /* 10 - 17 */
> +       '\x4c', '\xd1', '\x19', '\x99', '\x43', '\xb1', '\xaf', '\x0c', /* 18 - 1f */
> +};
> +
> +static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
> +
> +static const char *test_data_1_le[] __initconst = {
> +       "be", "32", "db", "7b", "0a", "18", "93", "b2",
> +       "70", "ba", "c4", "24", "7d", "83", "34", "9b",
> +       "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
> +       "4c", "d1", "19", "99", "43", "b1", "af", "0c",
> +};
> +
> +static const char *test_data_2_le[] __initconst = {
> +       "32be", "7bdb", "180a", "b293",
> +       "ba70", "24c4", "837d", "9b34",
> +       "9ca6", "ad31", "0f9c", "e9ac",
> +       "d14c", "9919", "b143", "0caf",
> +};
> +
> +static const char *test_data_4_le[] __initconst = {
> +       "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
> +       "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
> +};
> +
> +static const char *test_data_8_le[] __initconst = {
> +       "b293180a7bdb32be", "9b34837d24c4ba70",
> +       "e9ac0f9cad319ca6", "0cafb1439919d14c",
> +};
> +
> +static void __init test_hexdump(size_t len, int rowsize, int groupsize,
> +                               bool ascii)
> +{
> +       char test[32 * 3 + 2 + 32 + 1];
> +       char real[32 * 3 + 2 + 32 + 1];
> +       char *p;
> +       const char **result;
> +       size_t l = len;
> +       int gs = groupsize, rs = rowsize;
> +       unsigned int i;
> +
> +       hex_dump_to_buffer(data_b, l, rs, gs, real, sizeof(real), ascii);
> +
> +       if (rs != 16 && rs != 32)
> +               rs = 16;
> +
> +       if (l > rs)
> +               l = rs;
> +
> +       if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
> +               gs = 1;
> +
> +       if (gs == 8)
> +               result = test_data_8_le;
> +       else if (gs == 4)
> +               result = test_data_4_le;
> +       else if (gs == 2)
> +               result = test_data_2_le;
> +       else
> +               result = test_data_1_le;
> +
> +       memset(test, ' ', sizeof(test));
> +
> +       /* hex dump */
> +       p = test;
> +       for (i = 0; i < l / gs; i++) {
> +               const char *q = *result++;
> +               size_t amount = strlen(q);
> +
> +               strncpy(p, q, amount);
> +               p += amount + 1;
> +       }
> +       if (i)
> +               p--;
> +
> +       /* ASCII part */
> +       if (ascii) {
> +               p = test + rs * 2 + rs / gs + 1;
> +               strncpy(p, data_a, l);
> +               p += l;
> +       }
> +
> +       *p = '\0';
> +
> +       if (strcmp(test, real)) {
> +               pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
> +               pr_err("Result: '%s'\n", real);
> +               pr_err("Expect: '%s'\n", test);
> +       }
> +}
> +
> +static void __init test_hexdump_set(int rowsize, bool ascii)
> +{
> +       size_t d = min_t(size_t, sizeof(data_b), rowsize);
> +       size_t len = get_random_int() % d + 1;
> +
> +       test_hexdump(len, rowsize, 4, ascii);
> +       test_hexdump(len, rowsize, 2, ascii);
> +       test_hexdump(len, rowsize, 8, ascii);
> +       test_hexdump(len, rowsize, 1, ascii);
> +}
> +
> +static int __init test_hexdump_init(void)
> +{
> +       unsigned int i;
> +       int rowsize;
> +
> +       pr_info("Running tests...\n");
> +
> +       rowsize = (get_random_int() % 2 + 1) * 16;
> +       for (i = 0; i < 16; i++)
> +               test_hexdump_set(rowsize, false);
> +
> +       rowsize = (get_random_int() % 2 + 1) * 16;
> +       for (i = 0; i < 16; i++)
> +               test_hexdump_set(rowsize, true);
> +
> +       return -EINVAL;
> +}
> +module_init(test_hexdump_init);
> +MODULE_LICENSE("Dual BSD/GPL");
> --
> 2.1.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-01-12 15:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-29 11:50 [PATCH v1 0/4] hexdump: amend the hex_dump_to_buffer() Andy Shevchenko
2014-12-29 11:50 ` [PATCH v1 1/4] hexdump: introduce test suite Andy Shevchenko
2015-01-12 15:08   ` Paul Gortmaker
2014-12-29 11:50 ` [PATCH v1 2/4] hexdump: fix ascii column for the tail of a dump Andy Shevchenko
2014-12-29 11:50 ` [PATCH v1 3/4] hexdump: do few calculations ahead Andy Shevchenko
2014-12-29 11:50 ` [PATCH v1 4/4] hexdump: makes it return amount of bytes placed in buffer Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).