From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>, rcz@pengutronix.de
Subject: [PATCH 09/17] test: add basic barebox self-test infrastructure
Date: Mon, 12 Apr 2021 09:16:43 +0200 [thread overview]
Message-ID: <20210412071651.8769-10-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20210412071651.8769-1-a.fatoum@pengutronix.de>
Self tests is code written to run within barebox to exercise
functionality. They offer flexibility to test specific units of barebox
instead of the program as a whole. Add a very simple infrastructure
for registering and executing self-tests. THis is based on the Linux
kselftest modules. We don't utilize modules for this, however, because
we only have module support on ARM, but we need a generic solution.
Selftests can be enabled individually and even tested without shell
support to allow tests to happen for size-restricted barebox images
as well.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
Kconfig | 1 +
Makefile | 2 +-
commands/Makefile | 1 +
commands/selftest.c | 88 +++++++++++++++++++++++++++++++++++++++++++++
include/bselftest.h | 70 ++++++++++++++++++++++++++++++++++++
test/Kconfig | 8 +++++
test/Makefile | 1 +
test/self/Kconfig | 33 +++++++++++++++++
test/self/Makefile | 3 ++
test/self/core.c | 39 ++++++++++++++++++++
10 files changed, 245 insertions(+), 1 deletion(-)
create mode 100644 commands/selftest.c
create mode 100644 include/bselftest.h
create mode 100644 test/Kconfig
create mode 100644 test/Makefile
create mode 100644 test/self/Kconfig
create mode 100644 test/self/Makefile
create mode 100644 test/self/core.c
diff --git a/Kconfig b/Kconfig
index 29c32463fb43..7c4cf36881b4 100644
--- a/Kconfig
+++ b/Kconfig
@@ -15,3 +15,4 @@ source "lib/Kconfig"
source "crypto/Kconfig"
source "firmware/Kconfig"
source "scripts/Kconfig"
+source "test/Kconfig"
diff --git a/Makefile b/Makefile
index f6c0c4817046..0a93915cf347 100644
--- a/Makefile
+++ b/Makefile
@@ -581,7 +581,7 @@ endif
include $(srctree)/scripts/Makefile.lib
# Objects we will link into barebox / subdirs we need to visit
-common-y := common/ drivers/ commands/ lib/ crypto/ net/ fs/ firmware/
+common-y := common/ drivers/ commands/ lib/ crypto/ net/ fs/ firmware/ test/
include $(srctree)/arch/$(SRCARCH)/Makefile
diff --git a/commands/Makefile b/commands/Makefile
index 447349fd157d..4b45d266fd56 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -130,5 +130,6 @@ obj-$(CONFIG_CMD_SEED) += seed.o
obj-$(CONFIG_CMD_IP_ROUTE_GET) += ip-route-get.o
obj-$(CONFIG_CMD_BTHREAD) += bthread.o
obj-$(CONFIG_CMD_UBSAN) += ubsan.o
+obj-$(CONFIG_CMD_SELFTEST) += selftest.o
UBSAN_SANITIZE_ubsan.o := y
diff --git a/commands/selftest.c b/commands/selftest.c
new file mode 100644
index 000000000000..de5d100de04a
--- /dev/null
+++ b/commands/selftest.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#define pr_fmt(fmt) "selftest: " fmt
+
+#include <common.h>
+#include <command.h>
+#include <getopt.h>
+#include <bselftest.h>
+#include <complete.h>
+
+static int run_selftest(const char *match, bool list)
+{
+ struct selftest *test;
+ int matches = 0;
+ int err = 0;
+
+ list_for_each_entry(test, &selftests, list) {
+ if (list) {
+ printf("%s\n", test->name);
+ matches++;
+ continue;
+ }
+
+ if (match && strcmp(test->name, match))
+ continue;
+
+ err |= test->func();
+ matches++;
+ }
+
+ if (!matches) {
+ if (match)
+ printf("No tests matching '%s' found.\n", match);
+ else
+ printf("No matching tests found.\n");
+
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int do_selftest(int argc, char *argv[])
+{
+ bool list = false;
+ int i, err = 0;
+ int opt;
+
+ while((opt = getopt(argc, argv, "l")) > 0) {
+ switch(opt) {
+ case 'l':
+ list = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind == argc) {
+ err = run_selftest(NULL, list);
+ } else {
+ for (i = optind; i < argc; i++) {
+ err = run_selftest(argv[i], list);
+ if (err)
+ goto out;
+ }
+ }
+
+out:
+ return err ? COMMAND_ERROR : COMMAND_SUCCESS;
+}
+
+BAREBOX_CMD_HELP_START(selftest)
+BAREBOX_CMD_HELP_TEXT("Run enabled barebox self-tests")
+BAREBOX_CMD_HELP_TEXT("If run without arguments, all tests are run")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-l", "list available tests")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(selftest)
+ .cmd = do_selftest,
+ BAREBOX_CMD_DESC("Run selftests")
+ BAREBOX_CMD_OPTS("[-l] [tests..]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+ BAREBOX_CMD_HELP(cmd_selftest_help)
+BAREBOX_CMD_END
diff --git a/include/bselftest.h b/include/bselftest.h
new file mode 100644
index 000000000000..9a639608e35b
--- /dev/null
+++ b/include/bselftest.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef __BSELFTEST_H
+#define __BSELFTEST_H
+
+#include <linux/compiler.h>
+#include <linux/list.h>
+#include <init.h>
+
+enum bselftest_group {
+ BSELFTEST_core
+};
+
+struct selftest {
+ enum bselftest_group group;
+ const char *name;
+ int (*func)(void);
+ struct list_head list;
+};
+
+static inline int selftest_report(unsigned int total_tests, unsigned int failed_tests,
+ unsigned int skipped_tests)
+{
+ if (failed_tests == 0) {
+ if (skipped_tests) {
+ pr_info("skipped %u tests\n", skipped_tests);
+ pr_info("remaining %u tests passed\n", total_tests);
+ } else
+ pr_info("all %u tests passed\n", total_tests);
+ } else
+ pr_err("failed %u out of %u tests\n", failed_tests, total_tests);
+
+ return failed_tests ? -EINVAL : 0;
+}
+
+extern struct list_head selftests;
+
+#define BSELFTEST_GLOBALS() \
+static unsigned int total_tests __initdata; \
+static unsigned int failed_tests __initdata; \
+static unsigned int skipped_tests __initdata
+
+#ifdef CONFIG_SELFTEST
+#define __bselftest_initcall(func) late_initcall(func)
+#else
+#define __bselftest_initcall(func)
+#endif
+
+#define bselftest(_group, _func) \
+ static int __bselftest_##_func(void) \
+ { \
+ total_tests = failed_tests = skipped_tests = 0; \
+ _func(); \
+ return selftest_report(total_tests, \
+ failed_tests, \
+ skipped_tests); \
+ } \
+ static __maybe_unused \
+ int __init _func##_bselftest_register(void) \
+ { \
+ static struct selftest this = { \
+ .group = BSELFTEST_##_group, \
+ .name = KBUILD_MODNAME, \
+ .func = __bselftest_##_func, \
+ }; \
+ list_add_tail(&this.list, &selftests); \
+ return 0; \
+ } \
+ __bselftest_initcall(_func##_bselftest_register);
+
+#endif
diff --git a/test/Kconfig b/test/Kconfig
new file mode 100644
index 000000000000..eece702e68aa
--- /dev/null
+++ b/test/Kconfig
@@ -0,0 +1,8 @@
+menuconfig TEST
+ bool "Testing"
+
+if TEST
+
+source "test/self/Kconfig"
+
+endif
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 000000000000..1b9eb2171a82
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1 @@
+obj-y += self/
diff --git a/test/self/Kconfig b/test/self/Kconfig
new file mode 100644
index 000000000000..720abeffc51b
--- /dev/null
+++ b/test/self/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config SELFTEST
+ bool "Self-tests"
+ help
+ Configures support for in-barebox testing
+
+if SELFTEST
+
+config CMD_SELFTEST
+ bool "selftest command"
+ depends on COMMAND_SUPPORT
+ help
+ Command to run enabled barebox self-tests.
+ If run without arguments, all tests are run
+
+ Usage: selftest [-l] [tests...]
+
+ Options:
+ -l list available tests
+
+config SELFTEST_AUTORUN
+ bool "Run self-tests on startup"
+ help
+ Self tests are run automatically after initcalls are done,
+ but before barebox_main (shell or board-specific startup).
+
+config SELFTEST_ENABLE_ALL
+ bool "Enable all self-tests"
+ help
+ Selects all self-tests compatible with current configuration
+
+endif
diff --git a/test/self/Makefile b/test/self/Makefile
new file mode 100644
index 000000000000..78f738c8e210
--- /dev/null
+++ b/test/self/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SELFTEST) += core.o
diff --git a/test/self/core.c b/test/self/core.c
new file mode 100644
index 000000000000..d8c6e5d271ba
--- /dev/null
+++ b/test/self/core.c
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#define pr_fmt(fmt) "bselftest: " fmt
+
+#include <common.h>
+#include <bselftest.h>
+
+LIST_HEAD(selftests);
+
+static int (*old_main)(void);
+
+static int run_selftests(void)
+{
+ struct selftest *test;
+ int err = 0;
+
+ pr_notice("Configured tests will run now\n");
+
+ list_for_each_entry(test, &selftests, list)
+ err |= test->func();
+
+ if (err)
+ pr_err("Some selftests failed\n");
+
+ barebox_main = old_main;
+ return barebox_main();
+}
+
+static int init_selftests(void)
+{
+ if (!IS_ENABLED(CONFIG_SELFTEST_AUTORUN))
+ return 0;
+
+ old_main = barebox_main;
+ barebox_main = run_selftests;
+
+ return 0;
+}
+postenvironment_initcall(init_selftests);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2021-04-12 7:20 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-12 7:16 [PATCH 00/17] add barebox in-tree testing infrastructure Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 01/17] kbuild: add install target Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 02/17] kbuild: add ARCH={i386, x86_64} as aliases for x86 Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 03/17] kbuild: add ARCH=um alias for sandbox Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 04/17] MIPS: qemu-malta: generate swapped image as part of multi-image build Ahmad Fatoum
2021-04-12 9:27 ` Jules Maselbas
2021-04-12 9:45 ` Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 05/17] MIPS: qemu-malta: replace board code with syscon-reboot Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 06/17] MIPS: configs: qemu-malta: enable Virt I/O Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 07/17] openrisc: set default KBUILD_IMAGE Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 08/17] Documentation: boards: RISC-V: update TinyEMU support Ahmad Fatoum
2021-04-12 7:16 ` Ahmad Fatoum [this message]
2021-04-12 10:12 ` [PATCH 09/17] test: add basic barebox self-test infrastructure Jules Maselbas
2021-04-12 7:16 ` [PATCH 10/17] test: self: port Linux printf kselftest Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 11/17] test: add labgrid configs for some emulated targets Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 12/17] test: add first sample tests Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 13/17] test: support running labgrid-pytest from out-of-tree build directory Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 14/17] test: add emulate.pl, a runner for barebox on emulated targets Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 15/17] test: self: run selftests as part of the pytest suite Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 16/17] test: add bthread test Ahmad Fatoum
2021-04-12 7:16 ` [PATCH 17/17] [RFC] test: run ./test/emulate.pl in Github action 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=20210412071651.8769-10-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
--cc=rcz@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