From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Rouven Czerwinski <r.czerwinski@pengutronix.de>,
Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH v3 08/13] test: self: port Linux printf kselftest
Date: Wed, 2 Jun 2021 16:34:48 +0200 [thread overview]
Message-ID: <20210602143453.23097-9-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20210602143453.23097-1-a.fatoum@pengutronix.de>
Port over the Linux v5.11 selftest for printf sans the parts we don't
support. This can be used to catch regressions if changes affecting the
printf code are made.
Acked-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/stdlib.h | 5 +
test/self/Kconfig | 6 +
test/self/Makefile | 1 +
test/self/core.c | 2 +-
test/self/printf.c | 302 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 315 insertions(+), 1 deletion(-)
create mode 100644 test/self/printf.c
diff --git a/include/stdlib.h b/include/stdlib.h
index d4056087243d..8eb419e111f0 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -25,4 +25,9 @@ static inline u32 random32(void)
return ret;
}
+static inline u32 prandom_u32_max(u32 ep_ro)
+{
+ return (u32)(((u64) random32() * ep_ro) >> 32);
+}
+
#endif /* __STDLIB_H */
diff --git a/test/self/Kconfig b/test/self/Kconfig
index 720abeffc51b..73dc6c7b4f03 100644
--- a/test/self/Kconfig
+++ b/test/self/Kconfig
@@ -27,7 +27,13 @@ config SELFTEST_AUTORUN
config SELFTEST_ENABLE_ALL
bool "Enable all self-tests"
+ select SELFTEST_PRINTF
help
Selects all self-tests compatible with current configuration
+config SELFTEST_PRINTF
+ bool "printf selftest"
+ help
+ Tests barebox vsnprintf() functionality
+
endif
diff --git a/test/self/Makefile b/test/self/Makefile
index 78f738c8e210..b4aa49d6f817 100644
--- a/test/self/Makefile
+++ b/test/self/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SELFTEST) += core.o
+obj-$(CONFIG_SELFTEST_PRINTF) += printf.o
diff --git a/test/self/core.c b/test/self/core.c
index 5a309fc8f18d..caa4c27f6def 100644
--- a/test/self/core.c
+++ b/test/self/core.c
@@ -7,7 +7,7 @@
LIST_HEAD(selftests);
-int selftests_run(void)
+void selftests_run(void)
{
struct selftest *test;
int err = 0;
diff --git a/test/self/printf.c b/test/self/printf.c
new file mode 100644
index 000000000000..52fe6ac0faf9
--- /dev/null
+++ b/test/self/printf.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for printf facility.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <common.h>
+#include <bselftest.h>
+#include <linux/kernel.h>
+#include <module.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/string.h>
+#include <errno.h>
+
+#include <linux/bitmap.h>
+
+#define BUF_SIZE 256
+#define PAD_SIZE 16
+#define FILL_CHAR '$'
+
+BSELFTEST_GLOBALS();
+
+static char *test_buffer __initdata;
+static char *alloced_buffer __initdata;
+
+static int __printf(4, 0) __init
+do_test(int bufsize, const char *expect, int elen,
+ const char *fmt, va_list ap)
+{
+ va_list aq;
+ int ret, written;
+
+ total_tests++;
+
+ memset(alloced_buffer, FILL_CHAR, BUF_SIZE + 2*PAD_SIZE);
+ va_copy(aq, ap);
+ ret = vsnprintf(test_buffer, bufsize, fmt, aq);
+ va_end(aq);
+
+ if (ret != elen) {
+ pr_warn("vsnprintf(buf, %d, \"%s\", ...) returned %d, expected %d\n",
+ bufsize, fmt, ret, elen);
+ pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n",
+ bufsize, fmt, test_buffer, ret, expect);
+ return 1;
+ }
+
+ if (memchr_inv(alloced_buffer, FILL_CHAR, PAD_SIZE)) {
+ pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote before buffer\n", bufsize, fmt);
+ return 1;
+ }
+
+ if (!bufsize) {
+ if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE + PAD_SIZE)) {
+ pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n",
+ fmt);
+ return 1;
+ }
+ return 0;
+ }
+
+ written = min(bufsize-1, elen);
+ if (test_buffer[written]) {
+ pr_warn("vsnprintf(buf, %d, \"%s\", ...) did not nul-terminate buffer\n",
+ bufsize, fmt);
+ return 1;
+ }
+
+ if (memchr_inv(test_buffer + written + 1, FILL_CHAR, BUF_SIZE + PAD_SIZE - (written + 1))) {
+ pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n",
+ bufsize, fmt);
+ return 1;
+ }
+
+ if (memcmp(test_buffer, expect, written)) {
+ pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n",
+ bufsize, fmt, test_buffer, written, expect);
+ return 1;
+ }
+ return 0;
+}
+
+static void __printf(3, 4) __init
+__test(const char *expect, int elen, const char *fmt, ...)
+{
+ va_list ap;
+ int rand;
+ char *p;
+
+ if (elen >= BUF_SIZE) {
+ pr_err("error in test suite: expected output length %d too long. Format was '%s'.\n",
+ elen, fmt);
+ failed_tests++;
+ return;
+ }
+
+ va_start(ap, fmt);
+
+ /*
+ * Every fmt+args is subjected to four tests: Three where we
+ * tell vsnprintf varying buffer sizes (plenty, not quite
+ * enough and 0), and then we also test that bvasprintf would
+ * be able to print it as expected.
+ */
+ failed_tests += do_test(BUF_SIZE, expect, elen, fmt, ap);
+ rand = 1 + prandom_u32_max(elen+1);
+ /* Since elen < BUF_SIZE, we have 1 <= rand <= BUF_SIZE. */
+ failed_tests += do_test(rand, expect, elen, fmt, ap);
+ failed_tests += do_test(0, expect, elen, fmt, ap);
+
+ p = bvasprintf(fmt, ap);
+ if (p) {
+ total_tests++;
+ if (memcmp(p, expect, elen+1)) {
+ pr_warn("bvasprintf(..., \"%s\", ...) returned '%s', expected '%s'\n",
+ fmt, p, expect);
+ failed_tests++;
+ }
+ kfree(p);
+ }
+ va_end(ap);
+}
+
+#define test(expect, fmt, ...) \
+ __test(expect, strlen(expect), fmt, ##__VA_ARGS__)
+
+static void __init
+test_basic(void)
+{
+ /* Work around annoying "warning: zero-length gnu_printf format string". */
+ char nul = '\0';
+
+ test("", &nul);
+ test("100%", "100%%");
+ test("xxx%yyy", "xxx%cyyy", '%');
+ __test("xxx\0yyy", 7, "xxx%cyyy", '\0');
+}
+
+static void __init
+test_number(void)
+{
+ signed char val;
+
+ test("0x1234abcd ", "%#-12x", 0x1234abcd);
+ test(" 0x1234abcd", "%#12x", 0x1234abcd);
+ test("0|001| 12|+123| 1234|-123|-1234", "%d|%03d|%3d|%+d|% d|%+d|% d", 0, 1, 12, 123, 1234, -123, -1234);
+ test("0|1|1|32768|65535", "%hu|%hu|%hu|%hu|%hu", 0, 1, 65537, 32768, -1);
+ test("0|1|1|-32768|-1", "%hd|%hd|%hd|%hd|%hd", 0, 1, 65537, 32768, -1);
+ test("2015122420151225", "%ho%ho%#ho", 1037, 5282, -11627);
+
+ test("2015122420151225", "%ho%ho%#ho", 1037, 5282, -11627);
+
+ /*
+ * POSIX/C99: »The result of converting zero with an explicit
+ * precision of zero shall be no characters.« Hence the output
+ * from the below test should really be "00|0||| ". However,
+ * the kernel's printf also produces a single 0 in that
+ * case. This test case simply documents the current
+ * behaviour.
+ */
+ test("00|0|0|0|0", "%.2d|%.1d|%.0d|%.*d|%1.0d", 0, 0, 0, 0, 0, 0);
+
+ val = -16;
+ test("0xfffffff0|0xf0|0xf0", "%#02x|%#02x|%#02x", val, val & 0xff, (u8)val);
+
+ /* On some platforms, test failure here indicates a misaligned stack */
+ test("0x0807060504030201", "0x%016llx", 0x0807060504030201ULL);
+}
+
+static void __init
+test_string(void)
+{
+ test("", "%s%.0s", "", "123");
+ test("ABCD|abc|123", "%s|%.3s|%.*s", "ABCD", "abcdef", 3, "123456");
+ test("1 | 2|3 | 4|5 ", "%-3s|%3s|%-*s|%*s|%*s", "1", "2", 3, "3", 3, "4", -3, "5");
+ test("1234 ", "%-10.4s", "123456");
+ test(" 1234", "%10.4s", "123456");
+}
+
+#if BITS_PER_LONG == 64
+
+#define PTR_WIDTH 16
+#define PTR ((void *)0xffff0123456789abUL)
+#define PTR_STR "ffff0123456789ab"
+#define PTR_VAL_NO_CRNG "(____ptrval____)"
+#define ZEROS "00000000" /* hex 32 zero bits */
+#define ONES "ffffffff" /* hex 32 one bits */
+
+#else
+
+#define PTR_WIDTH 8
+#define PTR ((void *)0x456789ab)
+#define PTR_STR "456789ab"
+#define PTR_VAL_NO_CRNG "(ptrval)"
+#define ZEROS ""
+#define ONES ""
+
+#endif /* BITS_PER_LONG == 64 */
+
+/*
+ * NULL pointers aren't hashed.
+ */
+static void __init
+null_pointer(void)
+{
+ test(ZEROS "00000000", "%p", NULL);
+ test(ZEROS "00000000", "%px", NULL);
+}
+
+/*
+ * Error pointers aren't hashed.
+ */
+static void __init
+error_pointer(void)
+{
+ test(ONES "fffffff5", "%p", ERR_PTR(-11));
+ test(ONES "fffffff5", "%px", ERR_PTR(-11));
+}
+
+#define PTR_INVALID ((void *)0x000000ab)
+
+static void __init
+invalid_pointer(void)
+{
+ test(ZEROS "000000ab", "%px", PTR_INVALID);
+}
+
+static void __init
+ip4(void)
+{
+ IPaddr_t ip = cpu_to_be32(0x7f000001);
+
+ test("127.0.0.1", "%pI4", &ip);
+}
+
+static void __init
+ip(void)
+{
+ ip4();
+}
+
+static void __init
+uuid(void)
+{
+ const char uuid[16] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+
+ if (!IS_ENABLED(CONFIG_PRINTF_UUID))
+ return;
+
+ test("00010203-0405-0607-0809-0a0b0c0d0e0f", "%pUb", uuid);
+ test("00010203-0405-0607-0809-0A0B0C0D0E0F", "%pUB", uuid);
+ test("03020100-0504-0706-0809-0a0b0c0d0e0f", "%pUl", uuid);
+ test("03020100-0504-0706-0809-0A0B0C0D0E0F", "%pUL", uuid);
+}
+
+static void __init
+errptr(void)
+{
+ test("error 1234", "%pe", ERR_PTR(-1234));
+ test(sizeof(void *) == 8 ? "00000000000004d2" : "000004d2", "%pe", ERR_PTR(1234));
+
+ /* Check that %pe with a non-ERR_PTR gets treated as ordinary %p. */
+ BUILD_BUG_ON(IS_ERR(PTR));
+
+ if (!IS_ENABLED(CONFIG_ERRNO_MESSAGES))
+ return;
+ test("(Operation not permitted)", "(%pe)", ERR_PTR(-EPERM));
+ test("Requested probe deferral", "%pe", ERR_PTR(-EPROBE_DEFER));
+}
+
+static void __init
+test_pointer(void)
+{
+ null_pointer();
+ error_pointer();
+ invalid_pointer();
+ ip();
+ uuid();
+ errptr();
+}
+
+static void __init test_printf(void)
+{
+ alloced_buffer = malloc(BUF_SIZE + 2*PAD_SIZE);
+ if (!alloced_buffer)
+ return;
+ test_buffer = alloced_buffer + PAD_SIZE;
+
+ test_basic();
+ test_number();
+ test_string();
+ test_pointer();
+
+ free(alloced_buffer);
+}
+
+bselftest(core, test_printf);
+MODULE_AUTHOR("Rasmus Villemoes <linux@rasmusvillemoes.dk>");
+MODULE_LICENSE("GPL");
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2021-06-02 14:41 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-02 14:34 [PATCH v3 00/13] add barebox in-tree testing infrastructure Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 01/13] kbuild: add install target Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 02/13] kbuild: add ARCH={i386, x86_64} as aliases for x86 Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 03/13] kbuild: add ARCH=um alias for sandbox Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 04/13] MIPS: qemu-malta: generate swapped image as part of multi-image build Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 05/13] openrisc: set default KBUILD_IMAGE Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 06/13] Documentation: boards: RISC-V: update TinyEMU support Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 07/13] test: add basic barebox self-test infrastructure Ahmad Fatoum
2021-06-02 14:34 ` Ahmad Fatoum [this message]
2021-06-02 14:34 ` [PATCH v3 09/13] test: add labgrid configs for some emulated targets Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 10/13] test: add first sample tests Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 11/13] test: add emulate.pl, a runner for barebox on emulated targets Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 12/13] test: self: run selftests as part of the pytest suite Ahmad Fatoum
2021-06-02 14:34 ` [PATCH v3 13/13] test: add bthread test Ahmad Fatoum
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210602143453.23097-9-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
--cc=r.czerwinski@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox