## TL;DR
This patchset adds a centralized executor to dispatch tests rather than relying on late_initcall to schedule each test suite separately along with a couple of new features that depend on it.
Also, sorry for the delay in getting this new revision out. I have been really busy for the past couple weeks.
## What am I trying to do?
Conceptually, I am trying to provide a mechanism by which test suites can be grouped together so that they can be reasoned about collectively. The last two of three patches in this series add features which depend on this:
PATCH 5/7 Prints out a test plan[1] right before KUnit tests are run; this is valuable because it makes it possible for a test harness to detect whether the number of tests run matches the number of tests expected to be run, ensuring that no tests silently failed. The test plan includes a count of tests that will run. With the centralized executor, the tests are located in a single data structure and thus can be counted.
PATCH 6/7 Add a new kernel command-line option which allows the user to specify that the kernel poweroff, halt, or reboot after completing all KUnit tests; this is very handy for running KUnit tests on UML or a VM so that the UML/VM process exits cleanly immediately after running all tests without needing a special initramfs. The centralized executor provides a definitive point when all tests have completed and the poweroff, halt, or reboot could occur.
In addition, by dispatching tests from a single location, we can guarantee that all KUnit tests run after late_init is complete, which was a concern during the initial KUnit patchset review (this has not been a problem in practice, but resolving with certainty is nevertheless desirable).
Other use cases for this exist, but the above features should provide an idea of the value that this could provide.
## Changes since last revision: - On patch 7/7, I added some additional wording around the kunit_shutdown command line option explaining that it runs after built-in tests as suggested by Frank. - On the coverletter, I improved some wording and added a missing link. I also specified the base-commit for the series. - Frank asked for some changes to the documentation; however, David is taking care of that in a separate patch[2], so I did not make those changes here. There will be some additional changes necessary after David's patch is applied.
Alan Maguire (1): kunit: test: create a single centralized executor for all tests
Brendan Higgins (5): vmlinux.lds.h: add linker section for KUnit test suites arch: um: add linker section for KUnit test suites init: main: add KUnit to kernel init kunit: test: add test plan to KUnit TAP format Documentation: Add kunit_shutdown to kernel-parameters.txt
David Gow (1): kunit: Add 'kunit_shutdown' option
.../admin-guide/kernel-parameters.txt | 8 ++ arch/um/include/asm/common.lds.S | 4 + include/asm-generic/vmlinux.lds.h | 8 ++ include/kunit/test.h | 82 ++++++++++++------- init/main.c | 4 + lib/kunit/Makefile | 3 +- lib/kunit/executor.c | 71 ++++++++++++++++ lib/kunit/test.c | 11 --- tools/testing/kunit/kunit_kernel.py | 2 +- tools/testing/kunit/kunit_parser.py | 76 ++++++++++++++--- .../test_is_test_passed-all_passed.log | 1 + .../test_data/test_is_test_passed-crash.log | 1 + .../test_data/test_is_test_passed-failure.log | 1 + 13 files changed, 218 insertions(+), 54 deletions(-) create mode 100644 lib/kunit/executor.c
base-commit: a2f0b878c3ca531a1706cb2a8b079cea3b17bafc
[1] https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-s... [2] https://patchwork.kernel.org/patch/11383635/
Add a linker section where KUnit can put references to its test suites. This patch is the first step in transitioning to dispatching all KUnit tests from a centralized executor rather than having each as its own separate late_initcall.
Co-developed-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- include/asm-generic/vmlinux.lds.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index e00f41aa8ec4f..99a866f49cb3d 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -856,6 +856,13 @@ KEEP(*(.con_initcall.init)) \ __con_initcall_end = .;
+/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ +#define KUNIT_TEST_SUITES \ + . = ALIGN(8); \ + __kunit_suites_start = .; \ + KEEP(*(.kunit_test_suites)) \ + __kunit_suites_end = .; + #ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ @@ -1024,6 +1031,7 @@ INIT_CALLS \ CON_INITCALL \ INIT_RAM_FS \ + KUNIT_TEST_SUITES \ }
#define BSS_SECTION(sbss_align, bss_align, stop_align) \
On Thu, Feb 27, 2020 at 5:20 PM Brendan Higgins brendanhiggins@google.com wrote:
Add a linker section where KUnit can put references to its test suites. This patch is the first step in transitioning to dispatching all KUnit tests from a centralized executor rather than having each as its own separate late_initcall.
Co-developed-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org
include/asm-generic/vmlinux.lds.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index e00f41aa8ec4f..99a866f49cb3d 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -856,6 +856,13 @@ KEEP(*(.con_initcall.init)) \ __con_initcall_end = .;
+/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ +#define KUNIT_TEST_SUITES \
. = ALIGN(8); \
After posting this, I saw I had gotten an email from 0day[1]. After some investigation, I discovered that this 8 byte alignment works for x86 64 bit fine, but only *sometimes* for 32 bit. 4 byte alignment seems to work in all cases (so far). I am not sure why we went with such a large alignment in hindsight. In any case, I should have a fixed revision out pretty soon.
__kunit_suites_start = .; \
KEEP(*(.kunit_test_suites)) \
__kunit_suites_end = .;
#ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ @@ -1024,6 +1031,7 @@ INIT_CALLS \ CON_INITCALL \ INIT_RAM_FS \
KUNIT_TEST_SUITES \ }
#define BSS_SECTION(sbss_align, bss_align, stop_align) \
[1] https://lists.01.org/hyperkitty/list/lkp@lists.01.org/thread/4I4UW4OAT63ETMI...
We went with this alignment precisely because it's the largest that any supported arch may possibly need. The problem as I understood it was that the compiler, seeing a bunch of pointers decided to put them at the memory-access efficient alignment rather than at the section start. Remember that the section start used to be unaligned for some reason. Note that the alignment that is a multiple of smaller alignment is still aligned wrt the smaller alignment, so the compiler shouldn't need to put the pointers elsewhere. I wonder if there's a more robust way of forcing the compiler to put the pointers right at the section start and insert no gaps between them than playing with alignment.
On Thu, Feb 27, 2020 at 11:22 PM Brendan Higgins brendanhiggins@google.com wrote:
On Thu, Feb 27, 2020 at 5:20 PM Brendan Higgins brendanhiggins@google.com wrote:
Add a linker section where KUnit can put references to its test suites. This patch is the first step in transitioning to dispatching all KUnit tests from a centralized executor rather than having each as its own separate late_initcall.
Co-developed-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org
include/asm-generic/vmlinux.lds.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index e00f41aa8ec4f..99a866f49cb3d 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -856,6 +856,13 @@ KEEP(*(.con_initcall.init)) \ __con_initcall_end = .;
+/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ +#define KUNIT_TEST_SUITES \
. = ALIGN(8); \
After posting this, I saw I had gotten an email from 0day[1]. After some investigation, I discovered that this 8 byte alignment works for x86 64 bit fine, but only *sometimes* for 32 bit. 4 byte alignment seems to work in all cases (so far). I am not sure why we went with such a large alignment in hindsight. In any case, I should have a fixed revision out pretty soon.
__kunit_suites_start = .; \
KEEP(*(.kunit_test_suites)) \
__kunit_suites_end = .;
#ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ @@ -1024,6 +1031,7 @@ INIT_CALLS \ CON_INITCALL \ INIT_RAM_FS \
KUNIT_TEST_SUITES \ }
#define BSS_SECTION(sbss_align, bss_align, stop_align) \
[1] https://lists.01.org/hyperkitty/list/lkp@lists.01.org/thread/4I4UW4OAT63ETMI...
Add a linker section to UML where KUnit can put references to its test suites. This patch is an early step in transitioning to dispatching all KUnit tests from a centralized executor rather than having each as its own separate late_initcall.
Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- arch/um/include/asm/common.lds.S | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S index eca6c452a41bd..9a9c97f45694c 100644 --- a/arch/um/include/asm/common.lds.S +++ b/arch/um/include/asm/common.lds.S @@ -52,6 +52,10 @@ CON_INITCALL }
+ .kunit_test_suites : { + KUNIT_TEST_SUITES + } + .exitcall : { __exitcall_begin = .; *(.exitcall.exit)
From: Alan Maguire alan.maguire@oracle.com
Add a centralized executor to dispatch tests rather than relying on late_initcall to schedule each test suite separately. Centralized execution is for built-in tests only; modules will execute tests when loaded.
Signed-off-by: Alan Maguire alan.maguire@oracle.com Co-developed-by: Iurii Zaikin yzaikin@google.com Signed-off-by: Iurii Zaikin yzaikin@google.com Co-developed-by: Brendan Higgins brendanhiggins@google.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- include/kunit/test.h | 73 +++++++++++++++++++++++++++----------------- lib/kunit/Makefile | 3 +- lib/kunit/executor.c | 36 ++++++++++++++++++++++ 3 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 lib/kunit/executor.c
diff --git a/include/kunit/test.h b/include/kunit/test.h index 2dfb550c6723a..8a02f93a6b505 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -197,46 +197,63 @@ void kunit_init_test(struct kunit *test, const char *name);
int kunit_run_tests(struct kunit_suite *suite);
-/** - * kunit_test_suites() - used to register one or more &struct kunit_suite - * with KUnit. - * - * @suites: a statically allocated list of &struct kunit_suite. - * - * Registers @suites with the test framework. See &struct kunit_suite for - * more information. - * - * When builtin, KUnit tests are all run as late_initcalls; this means - * that they cannot test anything where tests must run at a different init - * phase. One significant restriction resulting from this is that KUnit - * cannot reliably test anything that is initialize in the late_init phase; - * another is that KUnit is useless to test things that need to be run in - * an earlier init phase. - * - * An alternative is to build the tests as a module. Because modules - * do not support multiple late_initcall()s, we need to initialize an - * array of suites for a module. - * - * TODO(brendanhiggins@google.com): Don't run all KUnit tests as - * late_initcalls. I have some future work planned to dispatch all KUnit - * tests from the same place, and at the very least to do so after - * everything else is definitely initialized. +/* + * If a test suite is built-in, module_init() gets translated into + * an initcall which we don't want as the idea is that for builtins + * the executor will manage execution. So ensure we do not define + * module_{init|exit} functions for the builtin case when registering + * suites via kunit_test_suites() below. */ -#define kunit_test_suites(...) \ - static struct kunit_suite *suites[] = { __VA_ARGS__, NULL}; \ - static int kunit_test_suites_init(void) \ +#ifdef MODULE +#define kunit_test_suites_for_module(__suites) \ + static int __init kunit_test_suites_init(void) \ { \ + struct kunit_suite *suites[] = (__suites); \ unsigned int i; \ + \ for (i = 0; suites[i] != NULL; i++) \ kunit_run_tests(suites[i]); \ return 0; \ } \ - late_initcall(kunit_test_suites_init); \ + module_init(kunit_test_suites_init); \ + \ static void __exit kunit_test_suites_exit(void) \ { \ return; \ } \ module_exit(kunit_test_suites_exit) +#else +#define kunit_test_suites_for_module(__suites) +#endif /* MODULE */ + +#define __kunit_test_suites(unique_array, unique_suites, ...) \ + static struct kunit_suite *unique_array[] = { __VA_ARGS__, NULL }; \ + kunit_test_suites_for_module(unique_array); \ + static struct kunit_suite **unique_suites \ + __used __aligned(8) __section(.kunit_test_suites) = unique_array + +/** + * kunit_test_suites() - used to register one or more &struct kunit_suite + * with KUnit. + * + * @suites: a statically allocated list of &struct kunit_suite. + * + * Registers @suites with the test framework. See &struct kunit_suite for + * more information. + * + * When builtin, KUnit tests are all run via executor; this is done + * by placing the array of struct kunit_suite * in the .kunit_test_suites + * ELF section. + * + * An alternative is to build the tests as a module. Because modules do not + * support multiple initcall()s, we need to initialize an array of suites for a + * module. + * + */ +#define kunit_test_suites(...) \ + __kunit_test_suites(__UNIQUE_ID(array), \ + __UNIQUE_ID(suites), \ + __VA_ARGS__)
#define kunit_test_suite(suite) kunit_test_suites(&suite)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile index fab55649b69a5..c282f02ca066b 100644 --- a/lib/kunit/Makefile +++ b/lib/kunit/Makefile @@ -3,7 +3,8 @@ obj-$(CONFIG_KUNIT) += kunit.o kunit-objs += test.o \ string-stream.o \ assert.o \ - try-catch.o + try-catch.o \ + executor.o
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c new file mode 100644 index 0000000000000..6429927d598a5 --- /dev/null +++ b/lib/kunit/executor.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <kunit/test.h> + +/* + * These symbols point to the .kunit_test_suites section and are defined in + * include/asm-generic/vmlinux.lds.h, and consequently must be extern. + */ +extern struct kunit_suite * const * const __kunit_suites_start[]; +extern struct kunit_suite * const * const __kunit_suites_end[]; + +#if IS_BUILTIN(CONFIG_KUNIT) + +static int kunit_run_all_tests(void) +{ + struct kunit_suite * const * const *suites, * const *subsuite; + bool has_test_failed = false; + + for (suites = __kunit_suites_start; + suites < __kunit_suites_end; + suites++) { + for (subsuite = *suites; *subsuite != NULL; subsuite++) { + if (kunit_run_tests(*subsuite)) + has_test_failed = true; + } + } + + if (has_test_failed) + return -EFAULT; + + return 0; +} + +late_initcall(kunit_run_all_tests); + +#endif /* IS_BUILTIN(CONFIG_KUNIT) */
Remove KUnit from init calls entirely, instead call directly from kernel_init().
Co-developed-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- include/kunit/test.h | 9 +++++++++ init/main.c | 4 ++++ lib/kunit/executor.c | 4 +--- 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h index 8a02f93a6b505..8689dd1459844 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -197,6 +197,15 @@ void kunit_init_test(struct kunit *test, const char *name);
int kunit_run_tests(struct kunit_suite *suite);
+#if IS_BUILTIN(CONFIG_KUNIT) +int kunit_run_all_tests(void); +#else +static inline int kunit_run_all_tests(void) +{ + return 0; +} +#endif /* IS_BUILTIN(CONFIG_KUNIT) */ + /* * If a test suite is built-in, module_init() gets translated into * an initcall which we don't want as the idea is that for builtins diff --git a/init/main.c b/init/main.c index ee4947af823f3..7875a5c486dc4 100644 --- a/init/main.c +++ b/init/main.c @@ -104,6 +104,8 @@ #define CREATE_TRACE_POINTS #include <trace/events/initcall.h>
+#include <kunit/test.h> + static int kernel_init(void *);
extern void init_IRQ(void); @@ -1444,6 +1446,8 @@ static noinline void __init kernel_init_freeable(void)
do_basic_setup();
+ kunit_run_all_tests(); + console_on_rootfs();
/* diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 6429927d598a5..b75a46c560847 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -11,7 +11,7 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
-static int kunit_run_all_tests(void) +int kunit_run_all_tests(void) { struct kunit_suite * const * const *suites, * const *subsuite; bool has_test_failed = false; @@ -31,6 +31,4 @@ static int kunit_run_all_tests(void) return 0; }
-late_initcall(kunit_run_all_tests); - #endif /* IS_BUILTIN(CONFIG_KUNIT) */
On 2/27/20 7:20 PM, Brendan Higgins wrote:
Remove KUnit from init calls entirely, instead call directly from kernel_init().
Co-developed-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org
include/kunit/test.h | 9 +++++++++ init/main.c | 4 ++++ lib/kunit/executor.c | 4 +--- 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h index 8a02f93a6b505..8689dd1459844 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -197,6 +197,15 @@ void kunit_init_test(struct kunit *test, const char *name); int kunit_run_tests(struct kunit_suite *suite); +#if IS_BUILTIN(CONFIG_KUNIT)
I suspected this would not work if a unittest was builtin but CONFIG_KUNIT was set to module.
So I decided to experiment a bit to verify my assumptions (before applying this patch series). I tried to set CONFIG_KUNIT to module, then set CONFIG_KUNIT_EXAMPLE_TEST to built in. Kconfig does not let me do this because KUNIT_EXAMPLE_TEST is inside a 'if KUNIT' in lib/kunit/Kconfig, but instead switches KUNIT_EXAMPLE_TEST to a module, and warns that it has done so. This was a bit of a surprise, but seems reasonable.
So my next assumption is that the architecture of KUnit expects each individual unit test config option to depend upon CONFIG_KUNIT. If this is the case, please clearly document that requirement in the KUnit documentation.
+int kunit_run_all_tests(void); +#else +static inline int kunit_run_all_tests(void) +{
- return 0;
+} +#endif /* IS_BUILTIN(CONFIG_KUNIT) */
/*
- If a test suite is built-in, module_init() gets translated into
- an initcall which we don't want as the idea is that for builtins
diff --git a/init/main.c b/init/main.c index ee4947af823f3..7875a5c486dc4 100644 --- a/init/main.c +++ b/init/main.c @@ -104,6 +104,8 @@ #define CREATE_TRACE_POINTS #include <trace/events/initcall.h> +#include <kunit/test.h>
static int kernel_init(void *); extern void init_IRQ(void); @@ -1444,6 +1446,8 @@ static noinline void __init kernel_init_freeable(void) do_basic_setup();
- kunit_run_all_tests();
- console_on_rootfs();
/* diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 6429927d598a5..b75a46c560847 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -11,7 +11,7 @@ extern struct kunit_suite * const * const __kunit_suites_end[]; #if IS_BUILTIN(CONFIG_KUNIT) -static int kunit_run_all_tests(void) +int kunit_run_all_tests(void) { struct kunit_suite * const * const *suites, * const *subsuite; bool has_test_failed = false; @@ -31,6 +31,4 @@ static int kunit_run_all_tests(void) return 0; } -late_initcall(kunit_run_all_tests);
#endif /* IS_BUILTIN(CONFIG_KUNIT) */
On Mon, Mar 2, 2020 at 11:13 AM Frank Rowand frowand.list@gmail.com wrote:
Sorry it took so long to respond. I am reviving this patchset now, about to send out a new revision and I just saw this comment.
On 2/27/20 7:20 PM, Brendan Higgins wrote:
Remove KUnit from init calls entirely, instead call directly from kernel_init().
Co-developed-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org
include/kunit/test.h | 9 +++++++++ init/main.c | 4 ++++ lib/kunit/executor.c | 4 +--- 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h index 8a02f93a6b505..8689dd1459844 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -197,6 +197,15 @@ void kunit_init_test(struct kunit *test, const char *name);
int kunit_run_tests(struct kunit_suite *suite);
+#if IS_BUILTIN(CONFIG_KUNIT)
I suspected this would not work if a unittest was builtin but CONFIG_KUNIT was set to module.
So I decided to experiment a bit to verify my assumptions (before applying this patch series). I tried to set CONFIG_KUNIT to module, then set CONFIG_KUNIT_EXAMPLE_TEST to built in. Kconfig does not let me do this because KUNIT_EXAMPLE_TEST is inside a 'if KUNIT' in lib/kunit/Kconfig, but instead switches KUNIT_EXAMPLE_TEST to a module, and warns that it has done so. This was a bit of a surprise, but seems reasonable.
So my next assumption is that the architecture of KUnit expects each individual unit test config option to depend upon CONFIG_KUNIT. If this is the case, please clearly document that requirement in the KUnit documentation.
Your assumption is correct. I will fix this in the Kconfig documentation in a separate patch.
+int kunit_run_all_tests(void); +#else +static inline int kunit_run_all_tests(void) +{
return 0;
+} +#endif /* IS_BUILTIN(CONFIG_KUNIT) */
/*
- If a test suite is built-in, module_init() gets translated into
- an initcall which we don't want as the idea is that for builtins
diff --git a/init/main.c b/init/main.c index ee4947af823f3..7875a5c486dc4 100644 --- a/init/main.c +++ b/init/main.c @@ -104,6 +104,8 @@ #define CREATE_TRACE_POINTS #include <trace/events/initcall.h>
+#include <kunit/test.h>
static int kernel_init(void *);
extern void init_IRQ(void); @@ -1444,6 +1446,8 @@ static noinline void __init kernel_init_freeable(void)
do_basic_setup();
kunit_run_all_tests();
console_on_rootfs(); /*
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 6429927d598a5..b75a46c560847 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -11,7 +11,7 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
-static int kunit_run_all_tests(void) +int kunit_run_all_tests(void) { struct kunit_suite * const * const *suites, * const *subsuite; bool has_test_failed = false; @@ -31,6 +31,4 @@ static int kunit_run_all_tests(void) return 0; }
-late_initcall(kunit_run_all_tests);
#endif /* IS_BUILTIN(CONFIG_KUNIT) */
On 2/27/20 7:20 PM, Brendan Higgins wrote:
Remove KUnit from init calls entirely, instead call directly from kernel_init().
Co-developed-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org [...] diff --git a/init/main.c b/init/main.c index ee4947af823f3..7875a5c486dc4 100644 --- a/init/main.c +++ b/init/main.c @@ -104,6 +104,8 @@ #define CREATE_TRACE_POINTS #include <trace/events/initcall.h> +#include <kunit/test.h>
static int kernel_init(void *); extern void init_IRQ(void); @@ -1444,6 +1446,8 @@ static noinline void __init kernel_init_freeable(void) do_basic_setup();
- kunit_run_all_tests();
- console_on_rootfs();
/*
I'm nervous about this happening before two key pieces of the kernel setup, which might lead to weird timing-sensitive bugs or false positives: async_synchronize_full() mark_readonly()
Now, I realize kunit tests _should_ be self-contained, but this seems like a possible robustness problem. Is there any reason this can't be moved after rcu_end_inkernel_boot() in kernel_init() instead?
On Mon, Mar 2, 2020 at 2:45 PM Kees Cook keescook@chromium.org wrote:
Sorry it took so long to respond. I am reviving this patchset now, about to send out a new revision and I just saw this comment.
On 2/27/20 7:20 PM, Brendan Higgins wrote:
Remove KUnit from init calls entirely, instead call directly from kernel_init().
Co-developed-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Alan Maguire alan.maguire@oracle.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org [...] diff --git a/init/main.c b/init/main.c index ee4947af823f3..7875a5c486dc4 100644 --- a/init/main.c +++ b/init/main.c @@ -104,6 +104,8 @@ #define CREATE_TRACE_POINTS #include <trace/events/initcall.h>
+#include <kunit/test.h>
static int kernel_init(void *);
extern void init_IRQ(void); @@ -1444,6 +1446,8 @@ static noinline void __init kernel_init_freeable(void)
do_basic_setup();
kunit_run_all_tests();
console_on_rootfs(); /*
I'm nervous about this happening before two key pieces of the kernel setup, which might lead to weird timing-sensitive bugs or false positives: async_synchronize_full() mark_readonly()
Now, I realize kunit tests _should_ be self-contained, but this seems like a possible robustness problem. Is there any reason this can't be moved after rcu_end_inkernel_boot() in kernel_init() instead?
I tried that, but it doesn't work without an initramfs. We could add an initramfs for KUnit at some point if highly desired, but I think that is outside the scope of this patchset. Additionally, this patch actually moves running tests to later in the init process, which is still an improvement over the way KUnit works today.
There are some other reasons I wouldn't want to make that change right now, which will become apparent in a patch that I will send out in short order.
Cheers
On Wed, Jun 24, 2020 at 01:20:35PM -0700, Brendan Higgins wrote:
On Mon, Mar 2, 2020 at 2:45 PM Kees Cook keescook@chromium.org wrote:
Now, I realize kunit tests _should_ be self-contained, but this seems like a possible robustness problem. Is there any reason this can't be moved after rcu_end_inkernel_boot() in kernel_init() instead?
I tried that, but it doesn't work without an initramfs. We could add
I'm curious to know what happened. To me it looks like it would be possible to do it in here:
system_state = SYSTEM_RUNNING; numa_default_policy();
rcu_end_inkernel_boot();
do_sysctl_args();
put it here?
if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command);
That should be before anything happens with an initramfs. (i.e. boot the kernel without an initrd and it won't be required...)
an initramfs for KUnit at some point if highly desired, but I think that is outside the scope of this patchset. Additionally, this patch actually moves running tests to later in the init process, which is still an improvement over the way KUnit works today.
Later is better! :)
There are some other reasons I wouldn't want to make that change right now, which will become apparent in a patch that I will send out in short order.
Cool; I'll look for it.
TAP 14 allows an optional test plan to be emitted before the start of the start of testing[1]; this is valuable because it makes it possible for a test harness to detect whether the number of tests run matches the number of tests expected to be run, ensuring that no tests silently failed.
Link[1]: https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-s... Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- lib/kunit/executor.c | 17 +++++ lib/kunit/test.c | 11 --- tools/testing/kunit/kunit_parser.py | 74 ++++++++++++++++--- .../test_is_test_passed-all_passed.log | 1 + .../test_data/test_is_test_passed-crash.log | 1 + .../test_data/test_is_test_passed-failure.log | 1 + 6 files changed, 82 insertions(+), 23 deletions(-)
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index b75a46c560847..7fd16feff157e 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -11,11 +11,28 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
+static void kunit_print_tap_header(void) +{ + struct kunit_suite * const * const *suites, * const *subsuite; + int num_of_suites = 0; + + for (suites = __kunit_suites_start; + suites < __kunit_suites_end; + suites++) + for (subsuite = *suites; *subsuite != NULL; subsuite++) + num_of_suites++; + + pr_info("TAP version 14\n"); + pr_info("1..%d\n", num_of_suites); +} + int kunit_run_all_tests(void) { struct kunit_suite * const * const *suites, * const *subsuite; bool has_test_failed = false;
+ kunit_print_tap_header(); + for (suites = __kunit_suites_start; suites < __kunit_suites_end; suites++) { diff --git a/lib/kunit/test.c b/lib/kunit/test.c index 9242f932896c7..da56b94261b43 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -18,16 +18,6 @@ static void kunit_set_failure(struct kunit *test) WRITE_ONCE(test->success, false); }
-static void kunit_print_tap_version(void) -{ - static bool kunit_has_printed_tap_version; - - if (!kunit_has_printed_tap_version) { - pr_info("TAP version 14\n"); - kunit_has_printed_tap_version = true; - } -} - static size_t kunit_test_cases_len(struct kunit_case *test_cases) { struct kunit_case *test_case; @@ -41,7 +31,6 @@ static size_t kunit_test_cases_len(struct kunit_case *test_cases)
static void kunit_print_subtest_start(struct kunit_suite *suite) { - kunit_print_tap_version(); pr_info("\t# Subtest: %s\n", suite->name); pr_info("\t1..%zd\n", kunit_test_cases_len(suite->test_cases)); } diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py index 4ffbae0f67325..78b3bdd03b1e4 100644 --- a/tools/testing/kunit/kunit_parser.py +++ b/tools/testing/kunit/kunit_parser.py @@ -45,6 +45,7 @@ class TestStatus(Enum): FAILURE = auto() TEST_CRASHED = auto() NO_TESTS = auto() + FAILURE_TO_PARSE_TESTS = auto()
kunit_start_re = re.compile(r'^TAP version [0-9]+$') kunit_end_re = re.compile('List of all partitions:') @@ -106,7 +107,7 @@ OkNotOkResult = namedtuple('OkNotOkResult', ['is_ok','description', 'text'])
OK_NOT_OK_SUBTEST = re.compile(r'^\t(ok|not ok) [0-9]+ - (.*)$')
-OK_NOT_OK_MODULE = re.compile(r'^(ok|not ok) [0-9]+ - (.*)$') +OK_NOT_OK_MODULE = re.compile(r'^(ok|not ok) ([0-9]+) - (.*)$')
def parse_ok_not_ok_test_case(lines: List[str], test_case: TestCase, @@ -196,7 +197,9 @@ def max_status(left: TestStatus, right: TestStatus) -> TestStatus: else: return TestStatus.SUCCESS
-def parse_ok_not_ok_test_suite(lines: List[str], test_suite: TestSuite) -> bool: +def parse_ok_not_ok_test_suite(lines: List[str], + test_suite: TestSuite, + expected_suite_index: int) -> bool: consume_non_diagnositic(lines) if not lines: test_suite.status = TestStatus.TEST_CRASHED @@ -209,6 +212,12 @@ def parse_ok_not_ok_test_suite(lines: List[str], test_suite: TestSuite) -> bool: test_suite.status = TestStatus.SUCCESS else: test_suite.status = TestStatus.FAILURE + suite_index = int(match.group(2)) + if suite_index != expected_suite_index: + print_with_timestamp( + red('[ERROR] ') + 'expected_suite_index ' + + str(expected_suite_index) + ', but got ' + + str(suite_index)) return True else: return False @@ -221,7 +230,7 @@ def bubble_up_test_case_errors(test_suite: TestSuite) -> TestStatus: max_test_case_status = bubble_up_errors(lambda x: x.status, test_suite.cases) return max_status(max_test_case_status, test_suite.status)
-def parse_test_suite(lines: List[str]) -> TestSuite: +def parse_test_suite(lines: List[str], expected_suite_index: int) -> TestSuite: if not lines: return None consume_non_diagnositic(lines) @@ -240,7 +249,7 @@ def parse_test_suite(lines: List[str]) -> TestSuite: test_suite.cases.append(test_case) test_case = parse_test_case(lines, expected_test_case_num > 0) expected_test_case_num -= 1 - if parse_ok_not_ok_test_suite(lines, test_suite): + if parse_ok_not_ok_test_suite(lines, test_suite, expected_suite_index): test_suite.status = bubble_up_test_case_errors(test_suite) return test_suite elif not lines: @@ -260,6 +269,17 @@ def parse_tap_header(lines: List[str]) -> bool: else: return False
+TEST_PLAN = re.compile(r'[0-9]+..([0-9]+)') + +def parse_test_plan(lines: List[str]) -> int: + consume_non_diagnositic(lines) + match = TEST_PLAN.match(lines[0]) + if match: + lines.pop(0) + return int(match.group(1)) + else: + return None + def bubble_up_suite_errors(test_suite_list: List[TestSuite]) -> TestStatus: return bubble_up_errors(lambda x: x.status, test_suite_list)
@@ -268,19 +288,34 @@ def parse_test_result(lines: List[str]) -> TestResult: return TestResult(TestStatus.NO_TESTS, [], lines) consume_non_diagnositic(lines) if not parse_tap_header(lines): - return None + return TestResult(TestStatus.NO_TESTS, [], lines) + expected_test_suite_num = parse_test_plan(lines) + if not expected_test_suite_num: + return TestResult(TestStatus.FAILURE_TO_PARSE_TESTS, [], lines) test_suites = [] - test_suite = parse_test_suite(lines) - while test_suite: - test_suites.append(test_suite) - test_suite = parse_test_suite(lines) - return TestResult(bubble_up_suite_errors(test_suites), test_suites, lines) + for i in range(1, expected_test_suite_num + 1): + test_suite = parse_test_suite(lines, i) + if test_suite: + test_suites.append(test_suite) + else: + print_with_timestamp( + red('[ERROR] ') + ' expected ' + + str(expected_test_suite_num) + + ' test suites, but got ' + str(i - 2)) + break + test_suite = parse_test_suite(lines, -1) + if test_suite: + print_with_timestamp(red('[ERROR] ') + + 'got unexpected test suite: ' + test_suite.name) + if test_suites: + return TestResult(bubble_up_suite_errors(test_suites), test_suites, lines) + else: + return TestResult(TestStatus.NO_TESTS, [], lines)
-def parse_run_tests(kernel_output) -> TestResult: +def print_and_count_results(test_result: TestResult) -> None: total_tests = 0 failed_tests = 0 crashed_tests = 0 - test_result = parse_test_result(list(isolate_kunit_output(kernel_output))) for test_suite in test_result.suites: if test_suite.status == TestStatus.SUCCESS: print_suite_divider(green('[PASSED] ') + test_suite.name) @@ -302,6 +337,21 @@ def parse_run_tests(kernel_output) -> TestResult: print_with_timestamp(red('[FAILED] ') + test_case.name) print_log(map(yellow, test_case.log)) print_with_timestamp('') + return total_tests, failed_tests, crashed_tests + +def parse_run_tests(kernel_output) -> TestResult: + total_tests = 0 + failed_tests = 0 + crashed_tests = 0 + test_result = parse_test_result(list(isolate_kunit_output(kernel_output))) + if test_result.status == TestStatus.NO_TESTS: + print(red('[ERROR] ') + yellow('no tests run!')) + elif test_result.status == TestStatus.FAILURE_TO_PARSE_TESTS: + print(red('[ERROR] ') + yellow('could not parse test results!')) + else: + (total_tests, + failed_tests, + crashed_tests) = print_and_count_results(test_result) print_with_timestamp(DIVIDER) fmt = green if test_result.status == TestStatus.SUCCESS else red print_with_timestamp( diff --git a/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log b/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log index 62ebc0288355c..bc0dc8fe35b76 100644 --- a/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log +++ b/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log @@ -1,4 +1,5 @@ TAP version 14 +1..2 # Subtest: sysctl_test 1..8 # sysctl_test_dointvec_null_tbl_data: sysctl_test_dointvec_null_tbl_data passed diff --git a/tools/testing/kunit/test_data/test_is_test_passed-crash.log b/tools/testing/kunit/test_data/test_is_test_passed-crash.log index 0b249870c8be4..4d97f6708c4a5 100644 --- a/tools/testing/kunit/test_data/test_is_test_passed-crash.log +++ b/tools/testing/kunit/test_data/test_is_test_passed-crash.log @@ -1,6 +1,7 @@ printk: console [tty0] enabled printk: console [mc-1] enabled TAP version 14 +1..2 # Subtest: sysctl_test 1..8 # sysctl_test_dointvec_null_tbl_data: sysctl_test_dointvec_null_tbl_data passed diff --git a/tools/testing/kunit/test_data/test_is_test_passed-failure.log b/tools/testing/kunit/test_data/test_is_test_passed-failure.log index 9e89d32d5667a..7a416497e3bec 100644 --- a/tools/testing/kunit/test_data/test_is_test_passed-failure.log +++ b/tools/testing/kunit/test_data/test_is_test_passed-failure.log @@ -1,4 +1,5 @@ TAP version 14 +1..2 # Subtest: sysctl_test 1..8 # sysctl_test_dointvec_null_tbl_data: sysctl_test_dointvec_null_tbl_data passed
From: David Gow davidgow@google.com
Add a new kernel command-line option, 'kunit_shutdown', which allows the user to specify that the kernel poweroff, halt, or reboot after completing all KUnit tests; this is very handy for running KUnit tests on UML or a VM so that the UML/VM process exits cleanly immediately after running all tests without needing a special initramfs.
Signed-off-by: David Gow davidgow@google.com Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- lib/kunit/executor.c | 20 ++++++++++++++++++++ tools/testing/kunit/kunit_kernel.py | 2 +- tools/testing/kunit/kunit_parser.py | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 7fd16feff157e..a93821116ccec 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0
+#include <linux/reboot.h> #include <kunit/test.h>
/* @@ -11,6 +12,23 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
+static char *kunit_shutdown; +core_param(kunit_shutdown, kunit_shutdown, charp, 0644); + +static void kunit_handle_shutdown(void) +{ + if (!kunit_shutdown) + return; + + if (!strcmp(kunit_shutdown, "poweroff")) + kernel_power_off(); + else if (!strcmp(kunit_shutdown, "halt")) + kernel_halt(); + else if (!strcmp(kunit_shutdown, "reboot")) + kernel_restart(NULL); + +} + static void kunit_print_tap_header(void) { struct kunit_suite * const * const *suites, * const *subsuite; @@ -42,6 +60,8 @@ int kunit_run_all_tests(void) } }
+ kunit_handle_shutdown(); + if (has_test_failed) return -EFAULT;
diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py index d99ae75ef72fa..6cf0697c788b6 100644 --- a/tools/testing/kunit/kunit_kernel.py +++ b/tools/testing/kunit/kunit_kernel.py @@ -145,7 +145,7 @@ class LinuxSourceTree(object): return self.validate_config(build_dir)
def run_kernel(self, args=[], timeout=None, build_dir=''): - args.extend(['mem=256M']) + args.extend(['mem=256M', 'kunit_shutdown=halt']) process = self._ops.linux_bin(args, timeout, build_dir) with open(os.path.join(build_dir, 'test.log'), 'w') as f: for line in process.stdout: diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py index 78b3bdd03b1e4..633811dd9bce8 100644 --- a/tools/testing/kunit/kunit_parser.py +++ b/tools/testing/kunit/kunit_parser.py @@ -48,7 +48,7 @@ class TestStatus(Enum): FAILURE_TO_PARSE_TESTS = auto()
kunit_start_re = re.compile(r'^TAP version [0-9]+$') -kunit_end_re = re.compile('List of all partitions:') +kunit_end_re = re.compile(r'reboot: System halted')
def isolate_kunit_output(kernel_output): started = False
Add kunit_shutdown, an option to specify that the kernel shutsdown after running KUnit tests, to the kernel-parameters.txt documentation.
Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org --- Documentation/admin-guide/kernel-parameters.txt | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index dbc22d6846275..6ad63e98916f9 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2099,6 +2099,14 @@ 0: force disabled 1: force enabled
+ kunit_shutdown [KERNEL UNIT TESTING FRAMEWORK] Shutdown kernel after + running built-in tests. Tests configured as modules will + not be run. + Default: (flag not present) don't shutdown + poweroff: poweroff the kernel after running tests + halt: halt the kernel after running tests + reboot: reboot the kernel after running tests + kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs. Default is 0 (don't ignore, but inject #GP)
On 2/27/20 5:20 PM, Brendan Higgins wrote:
Add kunit_shutdown, an option to specify that the kernel shutsdown after running KUnit tests, to the kernel-parameters.txt documentation.
Signed-off-by: Brendan Higgins brendanhiggins@google.com Reviewed-by: Stephen Boyd sboyd@kernel.org
Hi Brendan,
To be consistent with other parameters in this file:
Documentation/admin-guide/kernel-parameters.txt | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index dbc22d6846275..6ad63e98916f9 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2099,6 +2099,14 @@ 0: force disabled 1: force enabled
- kunit_shutdown [KERNEL UNIT TESTING FRAMEWORK] Shutdown kernel after
that line should have an '=' sign after the param name: kunit_shutdown=
running built-in tests. Tests configured as modules will
not be run.
Default: (flag not present) don't shutdown
poweroff: poweroff the kernel after running tests
halt: halt the kernel after running tests
reboot: reboot the kernel after running tests
- kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs. Default is 0 (don't ignore, but inject #GP)
thanks.
On 2/27/20 7:20 PM, Brendan Higgins wrote:
## TL;DR
This patchset adds a centralized executor to dispatch tests rather than relying on late_initcall to schedule each test suite separately along with a couple of new features that depend on it.
Also, sorry for the delay in getting this new revision out. I have been really busy for the past couple weeks.
## What am I trying to do?
Conceptually, I am trying to provide a mechanism by which test suites can be grouped together so that they can be reasoned about collectively. The last two of three patches in this series add features which depend on this:
PATCH 5/7 Prints out a test plan[1] right before KUnit tests are run; this is valuable because it makes it possible for a test harness to detect whether the number of tests run matches the number of tests expected to be run, ensuring that no tests silently failed. The test plan includes a count of tests that will run. With the centralized executor, the tests are located in a single data structure and thus can be counted.
PATCH 6/7 Add a new kernel command-line option which allows the user to specify that the kernel poweroff, halt, or reboot after completing all KUnit tests; this is very handy for running KUnit tests on UML or a VM so that the UML/VM process exits cleanly immediately after running all tests without needing a special initramfs. The centralized executor provides a definitive point when all tests have completed and the poweroff, halt, or reboot could occur.
In addition, by dispatching tests from a single location, we can guarantee that all KUnit tests run after late_init is complete, which was a concern during the initial KUnit patchset review (this has not been a problem in practice, but resolving with certainty is nevertheless desirable).
Other use cases for this exist, but the above features should provide an idea of the value that this could provide.
## Changes since last revision:
- On patch 7/7, I added some additional wording around the kunit_shutdown command line option explaining that it runs after built-in tests as suggested by Frank.
- On the coverletter, I improved some wording and added a missing link. I also specified the base-commit for the series.
- Frank asked for some changes to the documentation; however, David is taking care of that in a separate patch[2], so I did not make those changes here. There will be some additional changes necessary after David's patch is applied.
Making the documentation changes after David's patches sounds like a good plan to me.
-Frank
Alan Maguire (1): kunit: test: create a single centralized executor for all tests
Brendan Higgins (5): vmlinux.lds.h: add linker section for KUnit test suites arch: um: add linker section for KUnit test suites init: main: add KUnit to kernel init kunit: test: add test plan to KUnit TAP format Documentation: Add kunit_shutdown to kernel-parameters.txt
David Gow (1): kunit: Add 'kunit_shutdown' option
.../admin-guide/kernel-parameters.txt | 8 ++ arch/um/include/asm/common.lds.S | 4 + include/asm-generic/vmlinux.lds.h | 8 ++ include/kunit/test.h | 82 ++++++++++++------- init/main.c | 4 + lib/kunit/Makefile | 3 +- lib/kunit/executor.c | 71 ++++++++++++++++ lib/kunit/test.c | 11 --- tools/testing/kunit/kunit_kernel.py | 2 +- tools/testing/kunit/kunit_parser.py | 76 ++++++++++++++--- .../test_is_test_passed-all_passed.log | 1 + .../test_data/test_is_test_passed-crash.log | 1 + .../test_data/test_is_test_passed-failure.log | 1 + 13 files changed, 218 insertions(+), 54 deletions(-) create mode 100644 lib/kunit/executor.c
base-commit: a2f0b878c3ca531a1706cb2a8b079cea3b17bafc
[1] https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-s... [2] https://patchwork.kernel.org/patch/11383635/
Guenter,
are you still running your cross-architecture tests? If so any chance you can try this for your build tests?
Brendan, do you have this code in a branch which can be merged into linux-next by any chance?
Luis
On Mon, Mar 02, 2020 at 08:03:37PM +0000, Luis Chamberlain wrote:
Guenter,
are you still running your cross-architecture tests? If so any chance
Yes
you can try this for your build tests?
I didn't have KUNIT_TEST enabled to start with. I did that now, and started a test run on mainline a minute ago. We'll see how that goes.
Afterwards, sure, I can run the series in a test branch. It would be great if I can pick it up from a repository somewhere.
Guenter
On Mon, Mar 2, 2020 at 1:16 PM Guenter Roeck linux@roeck-us.net wrote:
On Mon, Mar 02, 2020 at 08:03:37PM +0000, Luis Chamberlain wrote:
Guenter,
are you still running your cross-architecture tests? If so any chance
Yes
you can try this for your build tests?
I didn't have KUNIT_TEST enabled to start with. I did that now, and started a test run on mainline a minute ago. We'll see how that goes.
FYI, kbuild already found some architectures for which this change doesn't work.
So far, I need to fix: - arm64 (32 bit seems to work fine) - i386 in some cases.
Afterwards, sure, I can run the series in a test branch. It would be great if I can pick it up from a repository somewhere.
Cool, I will post my next revision to a branch somewhere.
Thanks!
linux-kselftest-mirror@lists.linaro.org