linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules
@ 2019-11-15 10:16 Alan Maguire
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit Alan Maguire
                   ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire

The current kunit execution model is to provide base kunit functionality
and tests built-in to the kernel.  The aim of this series is to allow
building kunit itself and tests as modules.  This in turn allows a
simple form of selective execution; load the module you wish to test.
In doing so, kunit itself (if also built as a module) will be loaded as
an implicit dependency.

Because this requires a core API modification - if a module delivers
multiple suites, they must be declared with the kunit_test_suites()
macro - we're proposing this patch set as a candidate to be applied to the
test tree before too many kunit consumers appear.  We attempt to deal
with existing consumers in patch 3.

Changes since v3:
 - removed symbol lookup patch for separate submission later
 - removed use of sysctl_hung_task_timeout_seconds (patch 4, as discussed
   with Brendan and Stephen)
 - disabled build of string-stream-test when CONFIG_KUNIT_TEST=m; this
   is to avoid having to deal with symbol lookup issues
 - changed string-stream-impl.h back to string-stream.h (Brendan)
 - added module build support to new list, ext4 tests

Changes since v2:
 - moved string-stream.h header to lib/kunit/string-stream-impl.h (Brendan)
   (patch 1)
 - split out non-exported interfaces in try-catch-impl.h (Brendan)
   (patch 2)
 - added kunit_find_symbol() and KUNIT_INIT_SYMBOL to lookup non-exported
   symbols (patches 3, 4)
 - removed #ifdef MODULE around module licenses (Randy, Brendan, Andy)
   (patch 4)
 - replaced kunit_test_suite() with kunit_test_suites() rather than
   supporting both (Brendan) (patch 4)
 - lookup sysctl_hung_task_timeout_secs as kunit may be built as a module
   and the symbol may not be available (patch 5)

Alan Maguire (6):
  kunit: move string-stream.h to lib/kunit
  kunit: hide unexported try-catch interface in try-catch-impl.h
  kunit: allow kunit tests to be loaded as a module
  kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds
  kunit: allow kunit to be loaded as a module
  kunit: update documentation to describe module-based build

 Documentation/dev-tools/kunit/faq.rst   |   3 +-
 Documentation/dev-tools/kunit/index.rst |   3 +
 Documentation/dev-tools/kunit/usage.rst |  16 ++
 fs/ext4/Kconfig                         |   2 +-
 fs/ext4/Makefile                        |   5 +
 fs/ext4/inode-test.c                    |   4 +-
 include/kunit/assert.h                  |   3 +-
 include/kunit/string-stream.h           |  51 -----
 include/kunit/test.h                    |  35 +++-
 include/kunit/try-catch.h               |  10 -
 kernel/sysctl-test.c                    |   4 +-
 lib/Kconfig.debug                       |   4 +-
 lib/kunit/Kconfig                       |   6 +-
 lib/kunit/Makefile                      |  14 +-
 lib/kunit/assert.c                      |  10 +
 lib/kunit/example-test.c                |  88 ---------
 lib/kunit/kunit-example-test.c          |  90 +++++++++
 lib/kunit/kunit-test.c                  | 334 ++++++++++++++++++++++++++++++++
 lib/kunit/string-stream-test.c          |   5 +-
 lib/kunit/string-stream.c               |   3 +-
 lib/kunit/string-stream.h               |  51 +++++
 lib/kunit/test-test.c                   | 331 -------------------------------
 lib/kunit/test.c                        |  25 ++-
 lib/kunit/try-catch-impl.h              |  28 +++
 lib/kunit/try-catch.c                   |  37 +---
 lib/list-test.c                         |   4 +-
 26 files changed, 628 insertions(+), 538 deletions(-)
 delete mode 100644 include/kunit/string-stream.h
 delete mode 100644 lib/kunit/example-test.c
 create mode 100644 lib/kunit/kunit-example-test.c
 create mode 100644 lib/kunit/kunit-test.c
 create mode 100644 lib/kunit/string-stream.h
 delete mode 100644 lib/kunit/test-test.c
 create mode 100644 lib/kunit/try-catch-impl.h

-- 
1.8.3.1


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

* [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit
  2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
@ 2019-11-15 10:16 ` Alan Maguire
  2019-11-17  1:33   ` Stephen Boyd
  2019-11-19 18:39   ` Brendan Higgins
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h Alan Maguire
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire, Knut Omang

string-stream interfaces are not intended for external use;
move them from include/kunit to lib/kunit accordingly.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
---
 include/kunit/assert.h         |  3 ++-
 include/kunit/string-stream.h  | 51 ------------------------------------------
 lib/kunit/assert.c             |  2 ++
 lib/kunit/string-stream-test.c |  3 ++-
 lib/kunit/string-stream.c      |  3 ++-
 lib/kunit/string-stream.h      | 51 ++++++++++++++++++++++++++++++++++++++++++
 lib/kunit/test.c               |  2 ++
 7 files changed, 61 insertions(+), 54 deletions(-)
 delete mode 100644 include/kunit/string-stream.h
 create mode 100644 lib/kunit/string-stream.h

diff --git a/include/kunit/assert.h b/include/kunit/assert.h
index db6a0fc..ad889b5 100644
--- a/include/kunit/assert.h
+++ b/include/kunit/assert.h
@@ -9,10 +9,11 @@
 #ifndef _KUNIT_ASSERT_H
 #define _KUNIT_ASSERT_H
 
-#include <kunit/string-stream.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 
 struct kunit;
+struct string_stream;
 
 /**
  * enum kunit_assert_type - Type of expectation/assertion.
diff --git a/include/kunit/string-stream.h b/include/kunit/string-stream.h
deleted file mode 100644
index fe98a00..0000000
--- a/include/kunit/string-stream.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * C++ stream style string builder used in KUnit for building messages.
- *
- * Copyright (C) 2019, Google LLC.
- * Author: Brendan Higgins <brendanhiggins@google.com>
- */
-
-#ifndef _KUNIT_STRING_STREAM_H
-#define _KUNIT_STRING_STREAM_H
-
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <stdarg.h>
-
-struct string_stream_fragment {
-	struct kunit *test;
-	struct list_head node;
-	char *fragment;
-};
-
-struct string_stream {
-	size_t length;
-	struct list_head fragments;
-	/* length and fragments are protected by this lock */
-	spinlock_t lock;
-	struct kunit *test;
-	gfp_t gfp;
-};
-
-struct kunit;
-
-struct string_stream *alloc_string_stream(struct kunit *test, gfp_t gfp);
-
-int __printf(2, 3) string_stream_add(struct string_stream *stream,
-				     const char *fmt, ...);
-
-int string_stream_vadd(struct string_stream *stream,
-		       const char *fmt,
-		       va_list args);
-
-char *string_stream_get_string(struct string_stream *stream);
-
-int string_stream_append(struct string_stream *stream,
-			 struct string_stream *other);
-
-bool string_stream_is_empty(struct string_stream *stream);
-
-int string_stream_destroy(struct string_stream *stream);
-
-#endif /* _KUNIT_STRING_STREAM_H */
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
index 86013d4..9aca71c 100644
--- a/lib/kunit/assert.c
+++ b/lib/kunit/assert.c
@@ -7,6 +7,8 @@
  */
 #include <kunit/assert.h>
 
+#include "string-stream.h"
+
 void kunit_base_assert_format(const struct kunit_assert *assert,
 			      struct string_stream *stream)
 {
diff --git a/lib/kunit/string-stream-test.c b/lib/kunit/string-stream-test.c
index 76cc05e..6c70dc8 100644
--- a/lib/kunit/string-stream-test.c
+++ b/lib/kunit/string-stream-test.c
@@ -6,10 +6,11 @@
  * Author: Brendan Higgins <brendanhiggins@google.com>
  */
 
-#include <kunit/string-stream.h>
 #include <kunit/test.h>
 #include <linux/slab.h>
 
+#include "string-stream.h"
+
 static void string_stream_test_empty_on_creation(struct kunit *test)
 {
 	struct string_stream *stream = alloc_string_stream(test, GFP_KERNEL);
diff --git a/lib/kunit/string-stream.c b/lib/kunit/string-stream.c
index e6d17aa..3503920 100644
--- a/lib/kunit/string-stream.c
+++ b/lib/kunit/string-stream.c
@@ -6,11 +6,12 @@
  * Author: Brendan Higgins <brendanhiggins@google.com>
  */
 
-#include <kunit/string-stream.h>
 #include <kunit/test.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 
+#include "string-stream.h"
+
 struct string_stream_fragment_alloc_context {
 	struct kunit *test;
 	int len;
diff --git a/lib/kunit/string-stream.h b/lib/kunit/string-stream.h
new file mode 100644
index 0000000..fe98a00
--- /dev/null
+++ b/lib/kunit/string-stream.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * C++ stream style string builder used in KUnit for building messages.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@google.com>
+ */
+
+#ifndef _KUNIT_STRING_STREAM_H
+#define _KUNIT_STRING_STREAM_H
+
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <stdarg.h>
+
+struct string_stream_fragment {
+	struct kunit *test;
+	struct list_head node;
+	char *fragment;
+};
+
+struct string_stream {
+	size_t length;
+	struct list_head fragments;
+	/* length and fragments are protected by this lock */
+	spinlock_t lock;
+	struct kunit *test;
+	gfp_t gfp;
+};
+
+struct kunit;
+
+struct string_stream *alloc_string_stream(struct kunit *test, gfp_t gfp);
+
+int __printf(2, 3) string_stream_add(struct string_stream *stream,
+				     const char *fmt, ...);
+
+int string_stream_vadd(struct string_stream *stream,
+		       const char *fmt,
+		       va_list args);
+
+char *string_stream_get_string(struct string_stream *stream);
+
+int string_stream_append(struct string_stream *stream,
+			 struct string_stream *other);
+
+bool string_stream_is_empty(struct string_stream *stream);
+
+int string_stream_destroy(struct string_stream *stream);
+
+#endif /* _KUNIT_STRING_STREAM_H */
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index c83c0fa..36ebf47 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -11,6 +11,8 @@
 #include <linux/kernel.h>
 #include <linux/sched/debug.h>
 
+#include "string-stream.h"
+
 static void kunit_set_failure(struct kunit *test)
 {
 	WRITE_ONCE(test->success, false);
-- 
1.8.3.1


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

* [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h
  2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit Alan Maguire
@ 2019-11-15 10:16 ` Alan Maguire
  2019-11-17  1:36   ` Stephen Boyd
  2019-11-19 18:48   ` Brendan Higgins
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module Alan Maguire
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire

Define function as static inline in try-catch-impl.h to allow it to
be used in kunit itself and tests.  Also remove unused
kunit_generic_try_catch

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 include/kunit/try-catch.h  | 10 ----------
 lib/kunit/test-test.c      |  2 ++
 lib/kunit/test.c           |  2 +-
 lib/kunit/try-catch-impl.h | 28 ++++++++++++++++++++++++++++
 lib/kunit/try-catch.c      | 13 ++-----------
 5 files changed, 33 insertions(+), 22 deletions(-)
 create mode 100644 lib/kunit/try-catch-impl.h

diff --git a/include/kunit/try-catch.h b/include/kunit/try-catch.h
index 404f336..c507dd4 100644
--- a/include/kunit/try-catch.h
+++ b/include/kunit/try-catch.h
@@ -53,11 +53,6 @@ struct kunit_try_catch {
 	void *context;
 };
 
-void kunit_try_catch_init(struct kunit_try_catch *try_catch,
-			  struct kunit *test,
-			  kunit_try_catch_func_t try,
-			  kunit_try_catch_func_t catch);
-
 void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
 
 void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch);
@@ -67,9 +62,4 @@ static inline int kunit_try_catch_get_result(struct kunit_try_catch *try_catch)
 	return try_catch->try_result;
 }
 
-/*
- * Exposed for testing only.
- */
-void kunit_generic_try_catch_init(struct kunit_try_catch *try_catch);
-
 #endif /* _KUNIT_TRY_CATCH_H */
diff --git a/lib/kunit/test-test.c b/lib/kunit/test-test.c
index 5ebe059..5a6cc04 100644
--- a/lib/kunit/test-test.c
+++ b/lib/kunit/test-test.c
@@ -7,6 +7,8 @@
  */
 #include <kunit/test.h>
 
+#include "try-catch-impl.h"
+
 struct kunit_try_catch_test_context {
 	struct kunit_try_catch *try_catch;
 	bool function_called;
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 36ebf47..58a6227 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -7,11 +7,11 @@
  */
 
 #include <kunit/test.h>
-#include <kunit/try-catch.h>
 #include <linux/kernel.h>
 #include <linux/sched/debug.h>
 
 #include "string-stream.h"
+#include "try-catch-impl.h"
 
 static void kunit_set_failure(struct kunit *test)
 {
diff --git a/lib/kunit/try-catch-impl.h b/lib/kunit/try-catch-impl.h
new file mode 100644
index 0000000..e308d5c
--- /dev/null
+++ b/lib/kunit/try-catch-impl.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * An API to allow a function, that may fail, to be executed, and recover in a
+ * controlled manner.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@google.com>
+ */
+
+#ifndef _KUNIT_TRY_CATCH_IMPL_H
+#define _KUNIT_TRY_CATCH_IMPL_H
+
+#include <kunit/try-catch.h>
+#include <linux/types.h>
+
+struct kunit;
+
+static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
+					struct kunit *test,
+					kunit_try_catch_func_t try,
+					kunit_try_catch_func_t catch)
+{
+	try_catch->test = test;
+	try_catch->try = try;
+	try_catch->catch = catch;
+}
+
+#endif /* _KUNIT_TRY_CATCH_IMPL_H */
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index 55686839..4a66d16 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -8,12 +8,13 @@
  */
 
 #include <kunit/test.h>
-#include <kunit/try-catch.h>
 #include <linux/completion.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/sched/sysctl.h>
 
+#include "try-catch-impl.h"
+
 void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
 {
 	try_catch->try_result = -EFAULT;
@@ -106,13 +107,3 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
 
 	try_catch->catch(try_catch->context);
 }
-
-void kunit_try_catch_init(struct kunit_try_catch *try_catch,
-			  struct kunit *test,
-			  kunit_try_catch_func_t try,
-			  kunit_try_catch_func_t catch)
-{
-	try_catch->test = test;
-	try_catch->try = try;
-	try_catch->catch = catch;
-}
-- 
1.8.3.1


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

* [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module
  2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit Alan Maguire
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h Alan Maguire
@ 2019-11-15 10:16 ` Alan Maguire
  2019-11-19 19:16   ` Brendan Higgins
  2019-11-19 21:05   ` Stephen Boyd
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds Alan Maguire
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire, Knut Omang

As tests are added to kunit, it will become less feasible to execute
all built tests together.  By supporting modular tests we provide
a simple way to do selective execution on a running system; specifying

CONFIG_KUNIT=y
CONFIG_KUNIT_EXAMPLE_TEST=m

...means we can simply "insmod example-test.ko" to run the tests.

To achieve this we need to do the following:

o export the required symbols in kunit
o string-stream tests utilize non-exported symbols so for now we skip
  building them when CONFIG_KUNIT_TEST=m.
o support a new way of declaring test suites.  Because a module cannot
  do multiple late_initcall()s, we provide a kunit_test_suites() macro
  to declare multiple suites within the same module at once.
o some test module names would have been too general ("test-test"
  and "example-test" for kunit tests, "inode-test" for ext4 tests);
  rename these as appropriate ("kunit-test", "kunit-example-test"
  and "ext4-inode-test" respectively).

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
---
 fs/ext4/Kconfig                |   2 +-
 fs/ext4/Makefile               |   5 +
 fs/ext4/inode-test.c           |   4 +-
 include/kunit/test.h           |  35 +++--
 kernel/sysctl-test.c           |   4 +-
 lib/Kconfig.debug              |   4 +-
 lib/kunit/Kconfig              |   4 +-
 lib/kunit/Makefile             |  10 +-
 lib/kunit/assert.c             |   8 +
 lib/kunit/example-test.c       |  88 -----------
 lib/kunit/kunit-example-test.c |  90 +++++++++++
 lib/kunit/kunit-test.c         | 334 +++++++++++++++++++++++++++++++++++++++++
 lib/kunit/string-stream-test.c |   2 +-
 lib/kunit/test-test.c          | 333 ----------------------------------------
 lib/kunit/test.c               |   8 +
 lib/kunit/try-catch.c          |   2 +
 lib/list-test.c                |   4 +-
 17 files changed, 494 insertions(+), 443 deletions(-)
 delete mode 100644 lib/kunit/example-test.c
 create mode 100644 lib/kunit/kunit-example-test.c
 create mode 100644 lib/kunit/kunit-test.c
 delete mode 100644 lib/kunit/test-test.c

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index ef42ab0..435510f 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -108,7 +108,7 @@ config EXT4_DEBUG
 		echo 1 > /sys/module/ext4/parameters/mballoc_debug
 
 config EXT4_KUNIT_TESTS
-	bool "KUnit tests for ext4"
+	tristate "KUnit tests for ext4"
 	select EXT4_FS
 	depends on KUNIT
 	help
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 840b91d..1e72ef6 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -13,5 +13,10 @@ ext4-y	:= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
 ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+ifeq ($(CONFIG_EXT4_KUNIT_TESTS),y)
 ext4-$(CONFIG_EXT4_KUNIT_TESTS)		+= inode-test.o
+else
+obj-$(CONFIG_EXT4_KUNIT_TESTS)		+= ext4-inode-test.o
+ext4-inode-test-objs			+= inode-test.o
+endif
 ext4-$(CONFIG_FS_VERITY)		+= verity.o
diff --git a/fs/ext4/inode-test.c b/fs/ext4/inode-test.c
index 92a9da1..5a59978 100644
--- a/fs/ext4/inode-test.c
+++ b/fs/ext4/inode-test.c
@@ -269,4 +269,6 @@ static void inode_test_xtimestamp_decoding(struct kunit *test)
 	.test_cases = ext4_inode_test_cases,
 };
 
-kunit_test_suite(ext4_inode_test_suite);
+kunit_test_suites(&ext4_inode_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/include/kunit/test.h b/include/kunit/test.h
index dba4830..4e21a36 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -12,6 +12,7 @@
 #include <kunit/assert.h>
 #include <kunit/try-catch.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 
@@ -197,31 +198,45 @@ struct kunit {
 int kunit_run_tests(struct kunit_suite *suite);
 
 /**
- * kunit_test_suite() - used to register a &struct kunit_suite with KUnit.
+ * kunit_test_suites() - used to register one or more &struct kunit_suite
+ *			 with KUnit.
  *
- * @suite: a statically allocated &struct kunit_suite.
+ * @suites: a statically allocated list of &struct kunit_suite.
  *
- * Registers @suite with the test framework. See &struct kunit_suite for
+ * Registers @suites with the test framework. See &struct kunit_suite for
  * more information.
  *
- * NOTE: Currently KUnit tests are all run as late_initcalls; this means
+ * 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.
  */
-#define kunit_test_suite(suite)						       \
-	static int kunit_suite_init##suite(void)			       \
-	{								       \
-		return kunit_run_tests(&suite);				       \
-	}								       \
-	late_initcall(kunit_suite_init##suite)
+#define kunit_test_suites(...)						\
+	static struct kunit_suite *suites[] = { __VA_ARGS__, NULL};	\
+	static int kunit_test_suites_init(void)				\
+	{								\
+		unsigned int i;						\
+		for (i = 0; suites[i] != NULL; i++)			\
+			kunit_run_tests(suites[i]);			\
+		return 0;						\
+	}								\
+	late_initcall(kunit_test_suites_init);				\
+	static void __exit kunit_test_suites_exit(void)			\
+	{								\
+		return;							\
+	}								\
+	module_exit(kunit_test_suites_exit)
 
 /*
  * Like kunit_alloc_resource() below, but returns the struct kunit_resource
diff --git a/kernel/sysctl-test.c b/kernel/sysctl-test.c
index 2a63241..98d3e4e 100644
--- a/kernel/sysctl-test.c
+++ b/kernel/sysctl-test.c
@@ -389,4 +389,6 @@ static void sysctl_test_api_dointvec_write_single_greater_int_max(
 	.test_cases = sysctl_test_cases,
 };
 
-kunit_test_suite(sysctl_test_suite);
+kunit_test_suites(&sysctl_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 6c1be61..4b25bef 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1951,7 +1951,7 @@ config TEST_SYSCTL
 	  If unsure, say N.
 
 config SYSCTL_KUNIT_TEST
-	bool "KUnit test for sysctl"
+	tristate "KUnit test for sysctl"
 	depends on KUNIT
 	help
 	  This builds the proc sysctl unit test, which runs on boot.
@@ -1962,7 +1962,7 @@ config SYSCTL_KUNIT_TEST
 	  If unsure, say N.
 
 config LIST_KUNIT_TEST
-	bool "KUnit Test for Kernel Linked-list structures"
+	tristate "KUnit Test for Kernel Linked-list structures"
 	depends on KUNIT
 	help
 	  This builds the linked list KUnit test suite.
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index af37016..9ebd5e6 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -15,7 +15,7 @@ menuconfig KUNIT
 if KUNIT
 
 config KUNIT_TEST
-	bool "KUnit test for KUnit"
+	tristate "KUnit test for KUnit"
 	help
 	  Enables the unit tests for the KUnit test framework. These tests test
 	  the KUnit test framework itself; the tests are both written using
@@ -24,7 +24,7 @@ config KUNIT_TEST
 	  expected.
 
 config KUNIT_EXAMPLE_TEST
-	bool "Example test for KUnit"
+	tristate "Example test for KUnit"
 	help
 	  Enables an example unit test that illustrates some of the basic
 	  features of KUnit. This test only exists to help new users understand
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 769d940..bc6e5e54 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -3,7 +3,11 @@ obj-$(CONFIG_KUNIT) +=			test.o \
 					assert.o \
 					try-catch.o
 
-obj-$(CONFIG_KUNIT_TEST) +=		test-test.o \
-					string-stream-test.o
+obj-$(CONFIG_KUNIT_TEST) +=		kunit-test.o
 
-obj-$(CONFIG_KUNIT_EXAMPLE_TEST) +=	example-test.o
+# string-stream-test compiles built-in only.
+ifeq ($(CONFIG_KUNIT_TEST),y)
+obj-$(CONFIG_KUNIT_TEST) +=		string-stream-test.o
+endif
+
+obj-$(CONFIG_KUNIT_EXAMPLE_TEST) +=	kunit-example-test.o
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
index 9aca71c..b24bebc 100644
--- a/lib/kunit/assert.c
+++ b/lib/kunit/assert.c
@@ -26,6 +26,7 @@ void kunit_base_assert_format(const struct kunit_assert *assert,
 	string_stream_add(stream, "%s FAILED at %s:%d\n",
 			 expect_or_assert, assert->file, assert->line);
 }
+EXPORT_SYMBOL_GPL(kunit_base_assert_format);
 
 void kunit_assert_print_msg(const struct kunit_assert *assert,
 			    struct string_stream *stream)
@@ -33,6 +34,7 @@ void kunit_assert_print_msg(const struct kunit_assert *assert,
 	if (assert->message.fmt)
 		string_stream_add(stream, "\n%pV", &assert->message);
 }
+EXPORT_SYMBOL_GPL(kunit_assert_print_msg);
 
 void kunit_fail_assert_format(const struct kunit_assert *assert,
 			      struct string_stream *stream)
@@ -40,6 +42,7 @@ void kunit_fail_assert_format(const struct kunit_assert *assert,
 	kunit_base_assert_format(assert, stream);
 	string_stream_add(stream, "%pV", &assert->message);
 }
+EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
 
 void kunit_unary_assert_format(const struct kunit_assert *assert,
 			       struct string_stream *stream)
@@ -58,6 +61,7 @@ void kunit_unary_assert_format(const struct kunit_assert *assert,
 				 unary_assert->condition);
 	kunit_assert_print_msg(assert, stream);
 }
+EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
 
 void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
 				     struct string_stream *stream)
@@ -78,6 +82,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
 	}
 	kunit_assert_print_msg(assert, stream);
 }
+EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
 
 void kunit_binary_assert_format(const struct kunit_assert *assert,
 				struct string_stream *stream)
@@ -99,6 +104,7 @@ void kunit_binary_assert_format(const struct kunit_assert *assert,
 			 binary_assert->right_value);
 	kunit_assert_print_msg(assert, stream);
 }
+EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
 
 void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
 				    struct string_stream *stream)
@@ -120,6 +126,7 @@ void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
 			 binary_assert->right_value);
 	kunit_assert_print_msg(assert, stream);
 }
+EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
 
 void kunit_binary_str_assert_format(const struct kunit_assert *assert,
 				    struct string_stream *stream)
@@ -141,3 +148,4 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
 			 binary_assert->right_value);
 	kunit_assert_print_msg(assert, stream);
 }
+EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
diff --git a/lib/kunit/example-test.c b/lib/kunit/example-test.c
deleted file mode 100644
index f64a829..0000000
--- a/lib/kunit/example-test.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Example KUnit test to show how to use KUnit.
- *
- * Copyright (C) 2019, Google LLC.
- * Author: Brendan Higgins <brendanhiggins@google.com>
- */
-
-#include <kunit/test.h>
-
-/*
- * This is the most fundamental element of KUnit, the test case. A test case
- * makes a set EXPECTATIONs and ASSERTIONs about the behavior of some code; if
- * any expectations or assertions are not met, the test fails; otherwise, the
- * test passes.
- *
- * In KUnit, a test case is just a function with the signature
- * `void (*)(struct kunit *)`. `struct kunit` is a context object that stores
- * information about the current test.
- */
-static void example_simple_test(struct kunit *test)
-{
-	/*
-	 * This is an EXPECTATION; it is how KUnit tests things. When you want
-	 * to test a piece of code, you set some expectations about what the
-	 * code should do. KUnit then runs the test and verifies that the code's
-	 * behavior matched what was expected.
-	 */
-	KUNIT_EXPECT_EQ(test, 1 + 1, 2);
-}
-
-/*
- * This is run once before each test case, see the comment on
- * example_test_suite for more information.
- */
-static int example_test_init(struct kunit *test)
-{
-	kunit_info(test, "initializing\n");
-
-	return 0;
-}
-
-/*
- * Here we make a list of all the test cases we want to add to the test suite
- * below.
- */
-static struct kunit_case example_test_cases[] = {
-	/*
-	 * This is a helper to create a test case object from a test case
-	 * function; its exact function is not important to understand how to
-	 * use KUnit, just know that this is how you associate test cases with a
-	 * test suite.
-	 */
-	KUNIT_CASE(example_simple_test),
-	{}
-};
-
-/*
- * This defines a suite or grouping of tests.
- *
- * Test cases are defined as belonging to the suite by adding them to
- * `kunit_cases`.
- *
- * Often it is desirable to run some function which will set up things which
- * will be used by every test; this is accomplished with an `init` function
- * which runs before each test case is invoked. Similarly, an `exit` function
- * may be specified which runs after every test case and can be used to for
- * cleanup. For clarity, running tests in a test suite would behave as follows:
- *
- * suite.init(test);
- * suite.test_case[0](test);
- * suite.exit(test);
- * suite.init(test);
- * suite.test_case[1](test);
- * suite.exit(test);
- * ...;
- */
-static struct kunit_suite example_test_suite = {
-	.name = "example",
-	.init = example_test_init,
-	.test_cases = example_test_cases,
-};
-
-/*
- * This registers the above test suite telling KUnit that this is a suite of
- * tests that need to be run.
- */
-kunit_test_suite(example_test_suite);
diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c
new file mode 100644
index 0000000..ff930e0
--- /dev/null
+++ b/lib/kunit/kunit-example-test.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Example KUnit test to show how to use KUnit.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@google.com>
+ */
+
+#include <kunit/test.h>
+
+/*
+ * This is the most fundamental element of KUnit, the test case. A test case
+ * makes a set EXPECTATIONs and ASSERTIONs about the behavior of some code; if
+ * any expectations or assertions are not met, the test fails; otherwise, the
+ * test passes.
+ *
+ * In KUnit, a test case is just a function with the signature
+ * `void (*)(struct kunit *)`. `struct kunit` is a context object that stores
+ * information about the current test.
+ */
+static void example_simple_test(struct kunit *test)
+{
+	/*
+	 * This is an EXPECTATION; it is how KUnit tests things. When you want
+	 * to test a piece of code, you set some expectations about what the
+	 * code should do. KUnit then runs the test and verifies that the code's
+	 * behavior matched what was expected.
+	 */
+	KUNIT_EXPECT_EQ(test, 1 + 1, 2);
+}
+
+/*
+ * This is run once before each test case, see the comment on
+ * example_test_suite for more information.
+ */
+static int example_test_init(struct kunit *test)
+{
+	kunit_info(test, "initializing\n");
+
+	return 0;
+}
+
+/*
+ * Here we make a list of all the test cases we want to add to the test suite
+ * below.
+ */
+static struct kunit_case example_test_cases[] = {
+	/*
+	 * This is a helper to create a test case object from a test case
+	 * function; its exact function is not important to understand how to
+	 * use KUnit, just know that this is how you associate test cases with a
+	 * test suite.
+	 */
+	KUNIT_CASE(example_simple_test),
+	{}
+};
+
+/*
+ * This defines a suite or grouping of tests.
+ *
+ * Test cases are defined as belonging to the suite by adding them to
+ * `kunit_cases`.
+ *
+ * Often it is desirable to run some function which will set up things which
+ * will be used by every test; this is accomplished with an `init` function
+ * which runs before each test case is invoked. Similarly, an `exit` function
+ * may be specified which runs after every test case and can be used to for
+ * cleanup. For clarity, running tests in a test suite would behave as follows:
+ *
+ * suite.init(test);
+ * suite.test_case[0](test);
+ * suite.exit(test);
+ * suite.init(test);
+ * suite.test_case[1](test);
+ * suite.exit(test);
+ * ...;
+ */
+static struct kunit_suite example_test_suite = {
+	.name = "example",
+	.init = example_test_init,
+	.test_cases = example_test_cases,
+};
+
+/*
+ * This registers the above test suite telling KUnit that this is a suite of
+ * tests that need to be run.
+ */
+kunit_test_suites(&example_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c
new file mode 100644
index 0000000..1f5942e
--- /dev/null
+++ b/lib/kunit/kunit-test.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for core test infrastructure.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@google.com>
+ */
+#include <kunit/test.h>
+
+#include "try-catch-impl.h"
+
+struct kunit_try_catch_test_context {
+	struct kunit_try_catch *try_catch;
+	bool function_called;
+};
+
+static void kunit_test_successful_try(void *data)
+{
+	struct kunit *test = data;
+	struct kunit_try_catch_test_context *ctx = test->priv;
+
+	ctx->function_called = true;
+}
+
+static void kunit_test_no_catch(void *data)
+{
+	struct kunit *test = data;
+
+	KUNIT_FAIL(test, "Catch should not be called\n");
+}
+
+static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
+{
+	struct kunit_try_catch_test_context *ctx = test->priv;
+	struct kunit_try_catch *try_catch = ctx->try_catch;
+
+	kunit_try_catch_init(try_catch,
+			     test,
+			     kunit_test_successful_try,
+			     kunit_test_no_catch);
+	kunit_try_catch_run(try_catch, test);
+
+	KUNIT_EXPECT_TRUE(test, ctx->function_called);
+}
+
+static void kunit_test_unsuccessful_try(void *data)
+{
+	struct kunit *test = data;
+	struct kunit_try_catch_test_context *ctx = test->priv;
+	struct kunit_try_catch *try_catch = ctx->try_catch;
+
+	kunit_try_catch_throw(try_catch);
+	KUNIT_FAIL(test, "This line should never be reached\n");
+}
+
+static void kunit_test_catch(void *data)
+{
+	struct kunit *test = data;
+	struct kunit_try_catch_test_context *ctx = test->priv;
+
+	ctx->function_called = true;
+}
+
+static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
+{
+	struct kunit_try_catch_test_context *ctx = test->priv;
+	struct kunit_try_catch *try_catch = ctx->try_catch;
+
+	kunit_try_catch_init(try_catch,
+			     test,
+			     kunit_test_unsuccessful_try,
+			     kunit_test_catch);
+	kunit_try_catch_run(try_catch, test);
+
+	KUNIT_EXPECT_TRUE(test, ctx->function_called);
+}
+
+static int kunit_try_catch_test_init(struct kunit *test)
+{
+	struct kunit_try_catch_test_context *ctx;
+
+	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+	test->priv = ctx;
+
+	ctx->try_catch = kunit_kmalloc(test,
+				       sizeof(*ctx->try_catch),
+				       GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
+
+	return 0;
+}
+
+static struct kunit_case kunit_try_catch_test_cases[] = {
+	KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
+	KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
+	{}
+};
+
+static struct kunit_suite kunit_try_catch_test_suite = {
+	.name = "kunit-try-catch-test",
+	.init = kunit_try_catch_test_init,
+	.test_cases = kunit_try_catch_test_cases,
+};
+
+/*
+ * Context for testing test managed resources
+ * is_resource_initialized is used to test arbitrary resources
+ */
+struct kunit_test_resource_context {
+	struct kunit test;
+	bool is_resource_initialized;
+	int allocate_order[2];
+	int free_order[2];
+};
+
+static int fake_resource_init(struct kunit_resource *res, void *context)
+{
+	struct kunit_test_resource_context *ctx = context;
+
+	res->allocation = &ctx->is_resource_initialized;
+	ctx->is_resource_initialized = true;
+	return 0;
+}
+
+static void fake_resource_free(struct kunit_resource *res)
+{
+	bool *is_resource_initialized = res->allocation;
+
+	*is_resource_initialized = false;
+}
+
+static void kunit_resource_test_init_resources(struct kunit *test)
+{
+	struct kunit_test_resource_context *ctx = test->priv;
+
+	kunit_init_test(&ctx->test, "testing_test_init_test");
+
+	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
+}
+
+static void kunit_resource_test_alloc_resource(struct kunit *test)
+{
+	struct kunit_test_resource_context *ctx = test->priv;
+	struct kunit_resource *res;
+	kunit_resource_free_t free = fake_resource_free;
+
+	res = kunit_alloc_and_get_resource(&ctx->test,
+					   fake_resource_init,
+					   fake_resource_free,
+					   GFP_KERNEL,
+					   ctx);
+
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
+	KUNIT_EXPECT_PTR_EQ(test,
+			    &ctx->is_resource_initialized,
+			    (bool *) res->allocation);
+	KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
+	KUNIT_EXPECT_PTR_EQ(test, free, res->free);
+}
+
+static void kunit_resource_test_destroy_resource(struct kunit *test)
+{
+	struct kunit_test_resource_context *ctx = test->priv;
+	struct kunit_resource *res = kunit_alloc_and_get_resource(
+			&ctx->test,
+			fake_resource_init,
+			fake_resource_free,
+			GFP_KERNEL,
+			ctx);
+
+	KUNIT_ASSERT_FALSE(test,
+			   kunit_resource_destroy(&ctx->test,
+						  kunit_resource_instance_match,
+						  res->free,
+						  res->allocation));
+
+	KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
+	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
+}
+
+static void kunit_resource_test_cleanup_resources(struct kunit *test)
+{
+	int i;
+	struct kunit_test_resource_context *ctx = test->priv;
+	struct kunit_resource *resources[5];
+
+	for (i = 0; i < ARRAY_SIZE(resources); i++) {
+		resources[i] = kunit_alloc_and_get_resource(&ctx->test,
+							    fake_resource_init,
+							    fake_resource_free,
+							    GFP_KERNEL,
+							    ctx);
+	}
+
+	kunit_cleanup(&ctx->test);
+
+	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
+}
+
+static void kunit_resource_test_mark_order(int order_array[],
+					   size_t order_size,
+					   int key)
+{
+	int i;
+
+	for (i = 0; i < order_size && order_array[i]; i++)
+		;
+
+	order_array[i] = key;
+}
+
+#define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key)		       \
+		kunit_resource_test_mark_order(ctx->order_field,	       \
+					       ARRAY_SIZE(ctx->order_field),   \
+					       key)
+
+static int fake_resource_2_init(struct kunit_resource *res, void *context)
+{
+	struct kunit_test_resource_context *ctx = context;
+
+	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
+
+	res->allocation = ctx;
+
+	return 0;
+}
+
+static void fake_resource_2_free(struct kunit_resource *res)
+{
+	struct kunit_test_resource_context *ctx = res->allocation;
+
+	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
+}
+
+static int fake_resource_1_init(struct kunit_resource *res, void *context)
+{
+	struct kunit_test_resource_context *ctx = context;
+
+	kunit_alloc_and_get_resource(&ctx->test,
+				     fake_resource_2_init,
+				     fake_resource_2_free,
+				     GFP_KERNEL,
+				     ctx);
+
+	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
+
+	res->allocation = ctx;
+
+	return 0;
+}
+
+static void fake_resource_1_free(struct kunit_resource *res)
+{
+	struct kunit_test_resource_context *ctx = res->allocation;
+
+	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
+}
+
+/*
+ * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
+ * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
+ * to assert allocation and freeing order when the feature becomes available.
+ */
+static void kunit_resource_test_proper_free_ordering(struct kunit *test)
+{
+	struct kunit_test_resource_context *ctx = test->priv;
+
+	/* fake_resource_1 allocates a fake_resource_2 in its init. */
+	kunit_alloc_and_get_resource(&ctx->test,
+				     fake_resource_1_init,
+				     fake_resource_1_free,
+				     GFP_KERNEL,
+				     ctx);
+
+	/*
+	 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
+	 * before returning to fake_resource_1_init, it should be the first to
+	 * put its key in the allocate_order array.
+	 */
+	KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
+	KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
+
+	kunit_cleanup(&ctx->test);
+
+	/*
+	 * Because fake_resource_2 finishes allocation before fake_resource_1,
+	 * fake_resource_1 should be freed first since it could depend on
+	 * fake_resource_2.
+	 */
+	KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
+	KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
+}
+
+static int kunit_resource_test_init(struct kunit *test)
+{
+	struct kunit_test_resource_context *ctx =
+			kzalloc(sizeof(*ctx), GFP_KERNEL);
+
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+	test->priv = ctx;
+
+	kunit_init_test(&ctx->test, "test_test_context");
+
+	return 0;
+}
+
+static void kunit_resource_test_exit(struct kunit *test)
+{
+	struct kunit_test_resource_context *ctx = test->priv;
+
+	kunit_cleanup(&ctx->test);
+	kfree(ctx);
+}
+
+static struct kunit_case kunit_resource_test_cases[] = {
+	KUNIT_CASE(kunit_resource_test_init_resources),
+	KUNIT_CASE(kunit_resource_test_alloc_resource),
+	KUNIT_CASE(kunit_resource_test_destroy_resource),
+	KUNIT_CASE(kunit_resource_test_cleanup_resources),
+	KUNIT_CASE(kunit_resource_test_proper_free_ordering),
+	{}
+};
+
+static struct kunit_suite kunit_resource_test_suite = {
+	.name = "kunit-resource-test",
+	.init = kunit_resource_test_init,
+	.exit = kunit_resource_test_exit,
+	.test_cases = kunit_resource_test_cases,
+};
+kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/lib/kunit/string-stream-test.c b/lib/kunit/string-stream-test.c
index 6c70dc8..110f3a9 100644
--- a/lib/kunit/string-stream-test.c
+++ b/lib/kunit/string-stream-test.c
@@ -50,4 +50,4 @@ static void string_stream_test_get_string(struct kunit *test)
 	.name = "string-stream-test",
 	.test_cases = string_stream_test_cases
 };
-kunit_test_suite(string_stream_test_suite);
+kunit_test_suites(&string_stream_test_suite);
diff --git a/lib/kunit/test-test.c b/lib/kunit/test-test.c
deleted file mode 100644
index 5a6cc04..0000000
--- a/lib/kunit/test-test.c
+++ /dev/null
@@ -1,333 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * KUnit test for core test infrastructure.
- *
- * Copyright (C) 2019, Google LLC.
- * Author: Brendan Higgins <brendanhiggins@google.com>
- */
-#include <kunit/test.h>
-
-#include "try-catch-impl.h"
-
-struct kunit_try_catch_test_context {
-	struct kunit_try_catch *try_catch;
-	bool function_called;
-};
-
-static void kunit_test_successful_try(void *data)
-{
-	struct kunit *test = data;
-	struct kunit_try_catch_test_context *ctx = test->priv;
-
-	ctx->function_called = true;
-}
-
-static void kunit_test_no_catch(void *data)
-{
-	struct kunit *test = data;
-
-	KUNIT_FAIL(test, "Catch should not be called\n");
-}
-
-static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
-{
-	struct kunit_try_catch_test_context *ctx = test->priv;
-	struct kunit_try_catch *try_catch = ctx->try_catch;
-
-	kunit_try_catch_init(try_catch,
-			     test,
-			     kunit_test_successful_try,
-			     kunit_test_no_catch);
-	kunit_try_catch_run(try_catch, test);
-
-	KUNIT_EXPECT_TRUE(test, ctx->function_called);
-}
-
-static void kunit_test_unsuccessful_try(void *data)
-{
-	struct kunit *test = data;
-	struct kunit_try_catch_test_context *ctx = test->priv;
-	struct kunit_try_catch *try_catch = ctx->try_catch;
-
-	kunit_try_catch_throw(try_catch);
-	KUNIT_FAIL(test, "This line should never be reached\n");
-}
-
-static void kunit_test_catch(void *data)
-{
-	struct kunit *test = data;
-	struct kunit_try_catch_test_context *ctx = test->priv;
-
-	ctx->function_called = true;
-}
-
-static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
-{
-	struct kunit_try_catch_test_context *ctx = test->priv;
-	struct kunit_try_catch *try_catch = ctx->try_catch;
-
-	kunit_try_catch_init(try_catch,
-			     test,
-			     kunit_test_unsuccessful_try,
-			     kunit_test_catch);
-	kunit_try_catch_run(try_catch, test);
-
-	KUNIT_EXPECT_TRUE(test, ctx->function_called);
-}
-
-static int kunit_try_catch_test_init(struct kunit *test)
-{
-	struct kunit_try_catch_test_context *ctx;
-
-	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
-	test->priv = ctx;
-
-	ctx->try_catch = kunit_kmalloc(test,
-				       sizeof(*ctx->try_catch),
-				       GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
-
-	return 0;
-}
-
-static struct kunit_case kunit_try_catch_test_cases[] = {
-	KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
-	KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
-	{}
-};
-
-static struct kunit_suite kunit_try_catch_test_suite = {
-	.name = "kunit-try-catch-test",
-	.init = kunit_try_catch_test_init,
-	.test_cases = kunit_try_catch_test_cases,
-};
-kunit_test_suite(kunit_try_catch_test_suite);
-
-/*
- * Context for testing test managed resources
- * is_resource_initialized is used to test arbitrary resources
- */
-struct kunit_test_resource_context {
-	struct kunit test;
-	bool is_resource_initialized;
-	int allocate_order[2];
-	int free_order[2];
-};
-
-static int fake_resource_init(struct kunit_resource *res, void *context)
-{
-	struct kunit_test_resource_context *ctx = context;
-
-	res->allocation = &ctx->is_resource_initialized;
-	ctx->is_resource_initialized = true;
-	return 0;
-}
-
-static void fake_resource_free(struct kunit_resource *res)
-{
-	bool *is_resource_initialized = res->allocation;
-
-	*is_resource_initialized = false;
-}
-
-static void kunit_resource_test_init_resources(struct kunit *test)
-{
-	struct kunit_test_resource_context *ctx = test->priv;
-
-	kunit_init_test(&ctx->test, "testing_test_init_test");
-
-	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
-}
-
-static void kunit_resource_test_alloc_resource(struct kunit *test)
-{
-	struct kunit_test_resource_context *ctx = test->priv;
-	struct kunit_resource *res;
-	kunit_resource_free_t free = fake_resource_free;
-
-	res = kunit_alloc_and_get_resource(&ctx->test,
-					   fake_resource_init,
-					   fake_resource_free,
-					   GFP_KERNEL,
-					   ctx);
-
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
-	KUNIT_EXPECT_PTR_EQ(test,
-			    &ctx->is_resource_initialized,
-			    (bool *) res->allocation);
-	KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
-	KUNIT_EXPECT_PTR_EQ(test, free, res->free);
-}
-
-static void kunit_resource_test_destroy_resource(struct kunit *test)
-{
-	struct kunit_test_resource_context *ctx = test->priv;
-	struct kunit_resource *res = kunit_alloc_and_get_resource(
-			&ctx->test,
-			fake_resource_init,
-			fake_resource_free,
-			GFP_KERNEL,
-			ctx);
-
-	KUNIT_ASSERT_FALSE(test,
-			   kunit_resource_destroy(&ctx->test,
-						  kunit_resource_instance_match,
-						  res->free,
-						  res->allocation));
-
-	KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
-	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
-}
-
-static void kunit_resource_test_cleanup_resources(struct kunit *test)
-{
-	int i;
-	struct kunit_test_resource_context *ctx = test->priv;
-	struct kunit_resource *resources[5];
-
-	for (i = 0; i < ARRAY_SIZE(resources); i++) {
-		resources[i] = kunit_alloc_and_get_resource(&ctx->test,
-							    fake_resource_init,
-							    fake_resource_free,
-							    GFP_KERNEL,
-							    ctx);
-	}
-
-	kunit_cleanup(&ctx->test);
-
-	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
-}
-
-static void kunit_resource_test_mark_order(int order_array[],
-					   size_t order_size,
-					   int key)
-{
-	int i;
-
-	for (i = 0; i < order_size && order_array[i]; i++)
-		;
-
-	order_array[i] = key;
-}
-
-#define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key)		       \
-		kunit_resource_test_mark_order(ctx->order_field,	       \
-					       ARRAY_SIZE(ctx->order_field),   \
-					       key)
-
-static int fake_resource_2_init(struct kunit_resource *res, void *context)
-{
-	struct kunit_test_resource_context *ctx = context;
-
-	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
-
-	res->allocation = ctx;
-
-	return 0;
-}
-
-static void fake_resource_2_free(struct kunit_resource *res)
-{
-	struct kunit_test_resource_context *ctx = res->allocation;
-
-	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
-}
-
-static int fake_resource_1_init(struct kunit_resource *res, void *context)
-{
-	struct kunit_test_resource_context *ctx = context;
-
-	kunit_alloc_and_get_resource(&ctx->test,
-				     fake_resource_2_init,
-				     fake_resource_2_free,
-				     GFP_KERNEL,
-				     ctx);
-
-	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
-
-	res->allocation = ctx;
-
-	return 0;
-}
-
-static void fake_resource_1_free(struct kunit_resource *res)
-{
-	struct kunit_test_resource_context *ctx = res->allocation;
-
-	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
-}
-
-/*
- * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
- * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
- * to assert allocation and freeing order when the feature becomes available.
- */
-static void kunit_resource_test_proper_free_ordering(struct kunit *test)
-{
-	struct kunit_test_resource_context *ctx = test->priv;
-
-	/* fake_resource_1 allocates a fake_resource_2 in its init. */
-	kunit_alloc_and_get_resource(&ctx->test,
-				     fake_resource_1_init,
-				     fake_resource_1_free,
-				     GFP_KERNEL,
-				     ctx);
-
-	/*
-	 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
-	 * before returning to fake_resource_1_init, it should be the first to
-	 * put its key in the allocate_order array.
-	 */
-	KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
-	KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
-
-	kunit_cleanup(&ctx->test);
-
-	/*
-	 * Because fake_resource_2 finishes allocation before fake_resource_1,
-	 * fake_resource_1 should be freed first since it could depend on
-	 * fake_resource_2.
-	 */
-	KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
-	KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
-}
-
-static int kunit_resource_test_init(struct kunit *test)
-{
-	struct kunit_test_resource_context *ctx =
-			kzalloc(sizeof(*ctx), GFP_KERNEL);
-
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
-
-	test->priv = ctx;
-
-	kunit_init_test(&ctx->test, "test_test_context");
-
-	return 0;
-}
-
-static void kunit_resource_test_exit(struct kunit *test)
-{
-	struct kunit_test_resource_context *ctx = test->priv;
-
-	kunit_cleanup(&ctx->test);
-	kfree(ctx);
-}
-
-static struct kunit_case kunit_resource_test_cases[] = {
-	KUNIT_CASE(kunit_resource_test_init_resources),
-	KUNIT_CASE(kunit_resource_test_alloc_resource),
-	KUNIT_CASE(kunit_resource_test_destroy_resource),
-	KUNIT_CASE(kunit_resource_test_cleanup_resources),
-	KUNIT_CASE(kunit_resource_test_proper_free_ordering),
-	{}
-};
-
-static struct kunit_suite kunit_resource_test_suite = {
-	.name = "kunit-resource-test",
-	.init = kunit_resource_test_init,
-	.exit = kunit_resource_test_exit,
-	.test_cases = kunit_resource_test_cases,
-};
-kunit_test_suite(kunit_resource_test_suite);
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 58a6227..87b5cf1 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -173,6 +173,7 @@ void kunit_do_assertion(struct kunit *test,
 	if (assert->type == KUNIT_ASSERTION)
 		kunit_abort(test);
 }
+EXPORT_SYMBOL_GPL(kunit_do_assertion);
 
 void kunit_init_test(struct kunit *test, const char *name)
 {
@@ -181,6 +182,7 @@ void kunit_init_test(struct kunit *test, const char *name)
 	test->name = name;
 	test->success = true;
 }
+EXPORT_SYMBOL_GPL(kunit_init_test);
 
 /*
  * Initializes and runs test case. Does not clean up or do post validations.
@@ -319,6 +321,7 @@ int kunit_run_tests(struct kunit_suite *suite)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(kunit_run_tests);
 
 struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
 						    kunit_resource_init_t init,
@@ -344,6 +347,7 @@ struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
 
 	return res;
 }
+EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
 
 static void kunit_resource_free(struct kunit *test, struct kunit_resource *res)
 {
@@ -402,6 +406,7 @@ int kunit_resource_destroy(struct kunit *test,
 	kunit_resource_free(test, resource);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(kunit_resource_destroy);
 
 struct kunit_kmalloc_params {
 	size_t size;
@@ -437,6 +442,7 @@ void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
 				    gfp,
 				    &params);
 }
+EXPORT_SYMBOL_GPL(kunit_kmalloc);
 
 void kunit_kfree(struct kunit *test, const void *ptr)
 {
@@ -449,6 +455,7 @@ void kunit_kfree(struct kunit *test, const void *ptr)
 
 	WARN_ON(rc);
 }
+EXPORT_SYMBOL_GPL(kunit_kfree);
 
 void kunit_cleanup(struct kunit *test)
 {
@@ -478,3 +485,4 @@ void kunit_cleanup(struct kunit *test)
 		kunit_resource_free(test, resource);
 	}
 }
+EXPORT_SYMBOL_GPL(kunit_cleanup);
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index 4a66d16..0247a28 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -20,6 +20,7 @@ void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
 	try_catch->try_result = -EFAULT;
 	complete_and_exit(try_catch->try_completion, -EFAULT);
 }
+EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
 
 static int kunit_generic_run_threadfn_adapter(void *data)
 {
@@ -107,3 +108,4 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
 
 	try_catch->catch(try_catch->context);
 }
+EXPORT_SYMBOL_GPL(kunit_try_catch_run);
diff --git a/lib/list-test.c b/lib/list-test.c
index 363c600..4c31a91 100644
--- a/lib/list-test.c
+++ b/lib/list-test.c
@@ -743,4 +743,6 @@ static void list_test_list_for_each_entry_reverse(struct kunit *test)
 	.test_cases = list_test_cases,
 };
 
-kunit_test_suite(list_test_module);
+kunit_test_suites(&list_test_module);
+
+MODULE_LICENSE("GPL");
-- 
1.8.3.1


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

* [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds
  2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
                   ` (2 preceding siblings ...)
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module Alan Maguire
@ 2019-11-15 10:16 ` Alan Maguire
  2019-11-18 22:09   ` Luis Chamberlain
  2019-11-19 21:06   ` Stephen Boyd
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module Alan Maguire
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 6/6] kunit: update documentation to describe module-based build Alan Maguire
  5 siblings, 2 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire, Knut Omang

In discussion of how to handle timeouts, it was noted that if
sysctl_hung_task_timeout_seconds is exceeded for a kunit test,
the test task will be killed and an oops generated.  This should
suffice as a means of debugging such timeout issues for now.

Hence remove use of sysctl_hung_task_timeout_secs, which has the
added benefit of avoiding the need to export that symbol from
the core kernel.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
---
 lib/kunit/try-catch.c | 22 ++++------------------
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index 0247a28..0dd434e 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -11,7 +11,6 @@
 #include <linux/completion.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
-#include <linux/sched/sysctl.h>
 
 #include "try-catch-impl.h"
 
@@ -33,8 +32,6 @@ static int kunit_generic_run_threadfn_adapter(void *data)
 
 static unsigned long kunit_test_timeout(void)
 {
-	unsigned long timeout_msecs;
-
 	/*
 	 * TODO(brendanhiggins@google.com): We should probably have some type of
 	 * variable timeout here. The only question is what that timeout value
@@ -51,22 +48,11 @@ static unsigned long kunit_test_timeout(void)
 	 *
 	 * For more background on this topic, see:
 	 * https://mike-bland.com/2011/11/01/small-medium-large.html
+	 *
+	 * If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
+	 * the task will be killed and an oops generated.
 	 */
-	if (sysctl_hung_task_timeout_secs) {
-		/*
-		 * If sysctl_hung_task is active, just set the timeout to some
-		 * value less than that.
-		 *
-		 * In regards to the above TODO, if we decide on variable
-		 * timeouts, this logic will likely need to change.
-		 */
-		timeout_msecs = (sysctl_hung_task_timeout_secs - 1) *
-				MSEC_PER_SEC;
-	} else {
-		timeout_msecs = 300 * MSEC_PER_SEC; /* 5 min */
-	}
-
-	return timeout_msecs;
+	return 300 * MSEC_PER_SEC; /* 5 min */
 }
 
 void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
-- 
1.8.3.1


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

* [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module
  2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
                   ` (3 preceding siblings ...)
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds Alan Maguire
@ 2019-11-15 10:16 ` Alan Maguire
  2019-11-19 21:13   ` Stephen Boyd
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 6/6] kunit: update documentation to describe module-based build Alan Maguire
  5 siblings, 1 reply; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire, Knut Omang

Making kunit itself buildable as a module allows for "always-on"
kunit configuration; specifying CONFIG_KUNIT=m means the module
is built but only used when loaded.  Kunit test modules will load
kunit.ko as an implicit dependency, so simply running
"modprobe my-kunit-tests" will load the tests along with the kunit
module and run them.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
---
 lib/kunit/Kconfig  |  2 +-
 lib/kunit/Makefile |  4 +++-
 lib/kunit/test.c   | 13 +++++++++++++
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index 9ebd5e6..065aa16 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig KUNIT
-	bool "KUnit - Enable support for unit tests"
+	tristate "KUnit - Enable support for unit tests"
 	help
 	  Enables support for kernel unit tests (KUnit), a lightweight unit
 	  testing and mocking framework for the Linux kernel. These tests are
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index bc6e5e54..fab5564 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -1,4 +1,6 @@
-obj-$(CONFIG_KUNIT) +=			test.o \
+obj-$(CONFIG_KUNIT) +=			kunit.o
+
+kunit-objs +=				test.o \
 					string-stream.o \
 					assert.o \
 					try-catch.o
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 87b5cf1..41ef71a 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -486,3 +486,16 @@ void kunit_cleanup(struct kunit *test)
 	}
 }
 EXPORT_SYMBOL_GPL(kunit_cleanup);
+
+static int kunit_init(void)
+{
+	return 0;
+}
+late_initcall(kunit_init);
+
+static void __exit kunit_exit(void)
+{
+}
+module_exit(kunit_exit);
+
+MODULE_LICENSE("GPL");
-- 
1.8.3.1


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

* [PATCH v4 linux-kselftest-test 6/6] kunit: update documentation to describe module-based build
  2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
                   ` (4 preceding siblings ...)
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module Alan Maguire
@ 2019-11-15 10:16 ` Alan Maguire
  2019-11-19 21:15   ` Stephen Boyd
  5 siblings, 1 reply; 22+ messages in thread
From: Alan Maguire @ 2019-11-15 10:16 UTC (permalink / raw)
  To: brendanhiggins, skhan, linux-kselftest
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	sboyd, Alan Maguire, Knut Omang

Documentation should describe how to build kunit and tests as
modules.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
---
 Documentation/dev-tools/kunit/faq.rst   |  3 ++-
 Documentation/dev-tools/kunit/index.rst |  3 +++
 Documentation/dev-tools/kunit/usage.rst | 16 ++++++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/Documentation/dev-tools/kunit/faq.rst b/Documentation/dev-tools/kunit/faq.rst
index bf20951..ea55b24 100644
--- a/Documentation/dev-tools/kunit/faq.rst
+++ b/Documentation/dev-tools/kunit/faq.rst
@@ -29,7 +29,8 @@ Yes, well, mostly.
 
 For the most part, the KUnit core framework (what you use to write the tests)
 can compile to any architecture; it compiles like just another part of the
-kernel and runs when the kernel boots. However, there is some infrastructure,
+kernel and runs when the kernel boots, or when built as a module, when the
+module is loaded.  However, there is some infrastructure,
 like the KUnit Wrapper (``tools/testing/kunit/kunit.py``) that does not support
 other architectures.
 
diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst
index 26ffb46..7ddc385 100644
--- a/Documentation/dev-tools/kunit/index.rst
+++ b/Documentation/dev-tools/kunit/index.rst
@@ -48,6 +48,9 @@ to a standalone program that can be run like any other program directly inside
 of a host operating system; to be clear, it does not require any virtualization
 support; it is just a regular program.
 
+Alternatively, kunit and kunit tests can be built as modules and tests will
+run when the test module is loaded.
+
 KUnit is fast. Excluding build time, from invocation to completion KUnit can run
 several dozen tests in only 10 to 20 seconds; this might not sound like a big
 deal to some people, but having such fast and easy to run tests fundamentally
diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst
index c6e6963..82f9213 100644
--- a/Documentation/dev-tools/kunit/usage.rst
+++ b/Documentation/dev-tools/kunit/usage.rst
@@ -539,6 +539,22 @@ Interspersed in the kernel logs you might see the following:
 
 Congratulations, you just ran a KUnit test on the x86 architecture!
 
+In a similar manner, kunit and kunit tests can also be built as modules,
+so if you wanted to run tests in this way you might add the following config
+options to your ``.config``:
+
+.. code-block:: none
+
+	CONFIG_KUNIT=m
+	CONFIG_KUNIT_EXAMPLE_TEST=m
+
+Once the kernel is built and installed, a simple
+
+.. code-block:: bash
+	modprobe example-test
+
+...will run the tests.
+
 Writing new tests for other architectures
 -----------------------------------------
 
-- 
1.8.3.1


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

* Re: [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit Alan Maguire
@ 2019-11-17  1:33   ` Stephen Boyd
  2019-11-19 18:36     ` Brendan Higgins
  2019-11-19 18:39   ` Brendan Higgins
  1 sibling, 1 reply; 22+ messages in thread
From: Stephen Boyd @ 2019-11-17  1:33 UTC (permalink / raw)
  To: Alan Maguire, brendanhiggins, linux-kselftest, skhan
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	Alan Maguire, Knut Omang

Quoting Alan Maguire (2019-11-15 02:16:07)
> string-stream interfaces are not intended for external use;
> move them from include/kunit to lib/kunit accordingly.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>

The sign off chain is incorrect here. Is Knut tag supposed to be
Co-developed-by? 

> diff --git a/include/kunit/assert.h b/include/kunit/assert.h
> index db6a0fc..ad889b5 100644
> --- a/include/kunit/assert.h
> +++ b/include/kunit/assert.h
> @@ -9,10 +9,11 @@
>  #ifndef _KUNIT_ASSERT_H
>  #define _KUNIT_ASSERT_H
>  
> -#include <kunit/string-stream.h>
>  #include <linux/err.h>
> +#include <linux/kernel.h>

Why is this included now?

>  
>  struct kunit;
> +struct string_stream;
>  
>  /**
>   * enum kunit_assert_type - Type of expectation/assertion.

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

* Re: [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h Alan Maguire
@ 2019-11-17  1:36   ` Stephen Boyd
  2019-11-18 17:30     ` Alan Maguire
  2019-11-19 18:48   ` Brendan Higgins
  1 sibling, 1 reply; 22+ messages in thread
From: Stephen Boyd @ 2019-11-17  1:36 UTC (permalink / raw)
  To: Alan Maguire, brendanhiggins, linux-kselftest, skhan
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	Alan Maguire

Quoting Alan Maguire (2019-11-15 02:16:08)
> diff --git a/lib/kunit/try-catch-impl.h b/lib/kunit/try-catch-impl.h
> new file mode 100644
> index 0000000..e308d5c
> --- /dev/null
> +++ b/lib/kunit/try-catch-impl.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * An API to allow a function, that may fail, to be executed, and recover in a

This file is not an API. Maybe just say "Internal kunit try catch
implementation details to be shared with tests".

> + * controlled manner.
> + *
> + * Copyright (C) 2019, Google LLC.
> + * Author: Brendan Higgins <brendanhiggins@google.com>
> + */
> +
> +#ifndef _KUNIT_TRY_CATCH_IMPL_H
> +#define _KUNIT_TRY_CATCH_IMPL_H
> +
> +#include <kunit/try-catch.h>
> +#include <linux/types.h>
> +
> +struct kunit;
> +
> +static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
> +                                       struct kunit *test,
> +                                       kunit_try_catch_func_t try,

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

* Re: [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h
  2019-11-17  1:36   ` Stephen Boyd
@ 2019-11-18 17:30     ` Alan Maguire
  0 siblings, 0 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-18 17:30 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Alan Maguire, brendanhiggins, linux-kselftest, skhan,
	linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc

On Sat, 16 Nov 2019, Stephen Boyd wrote:
> Quoting Alan Maguire (2019-11-15 02:16:08)
> > diff --git a/lib/kunit/try-catch-impl.h b/lib/kunit/try-catch-impl.h
> > new file mode 100644
> > index 0000000..e308d5c
> > --- /dev/null
> > +++ b/lib/kunit/try-catch-impl.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * An API to allow a function, that may fail, to be executed, and recover in a
> 
> This file is not an API. Maybe just say "Internal kunit try catch
> implementation details to be shared with tests".
>

Thanks for the review! Will fix this, along with adding the
"Co-developed-by:" for Knut and will remove the unneeded
#include of linux/kernel.h in v5 mentioned in the patch
1 review. Thanks again!

Alan

> > + * controlled manner.
> > + *
> > + * Copyright (C) 2019, Google LLC.
> > + * Author: Brendan Higgins <brendanhiggins@google.com>
> > + */
> > +
> > +#ifndef _KUNIT_TRY_CATCH_IMPL_H
> > +#define _KUNIT_TRY_CATCH_IMPL_H
> > +
> > +#include <kunit/try-catch.h>
> > +#include <linux/types.h>
> > +
> > +struct kunit;
> > +
> > +static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
> > +                                       struct kunit *test,
> > +                                       kunit_try_catch_func_t try,
> 

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

* Re: [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds Alan Maguire
@ 2019-11-18 22:09   ` Luis Chamberlain
  2019-11-19  1:24     ` Brendan Higgins
  2019-11-19 21:06   ` Stephen Boyd
  1 sibling, 1 reply; 22+ messages in thread
From: Luis Chamberlain @ 2019-11-18 22:09 UTC (permalink / raw)
  To: Alan Maguire
  Cc: brendanhiggins, skhan, linux-kselftest, linux-kernel, kunit-dev,
	keescook, yzaikin, akpm, yamada.masahiro, catalin.marinas,
	joe.lawrence, penguin-kernel, schowdary, urezki,
	andriy.shevchenko, corbet, tytso, adilger.kernel, changbin.du,
	linux-ext4, linux-doc, sboyd, Knut Omang

On Fri, Nov 15, 2019 at 10:16:10AM +0000, Alan Maguire wrote:
> In discussion of how to handle timeouts, it was noted that if
> sysctl_hung_task_timeout_seconds is exceeded for a kunit test,
> the test task will be killed and an oops generated.  This should
> suffice as a means of debugging such timeout issues for now.
> 
> Hence remove use of sysctl_hung_task_timeout_secs, which has the
> added benefit of avoiding the need to export that symbol from
> the core kernel.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>

This seems like a workaround for sysctl_hung_task_timeout_secs not being
exported. If true, this can be addressed by creating a symbol namespace
(new) and using that namespace on this path.

  Luis

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

* Re: [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds
  2019-11-18 22:09   ` Luis Chamberlain
@ 2019-11-19  1:24     ` Brendan Higgins
  0 siblings, 0 replies; 22+ messages in thread
From: Brendan Higgins @ 2019-11-19  1:24 UTC (permalink / raw)
  To: Luis Chamberlain
  Cc: Alan Maguire, Shuah Khan, open list:KERNEL SELFTEST FRAMEWORK,
	Linux Kernel Mailing List, KUnit Development, Kees Cook,
	Iurii Zaikin, Andrew Morton, Masahiro Yamada, catalin.marinas,
	joe.lawrence, penguin-kernel, schowdary, urezki,
	andriy.shevchenko, Jonathan Corbet, Theodore Ts'o,
	adilger.kernel, changbin.du, linux-ext4, open list:DOCUMENTATION,
	Stephen Boyd, Knut Omang

On Mon, Nov 18, 2019 at 2:10 PM Luis Chamberlain <mcgrof@kernel.org> wrote:
>
> On Fri, Nov 15, 2019 at 10:16:10AM +0000, Alan Maguire wrote:
> > In discussion of how to handle timeouts, it was noted that if
> > sysctl_hung_task_timeout_seconds is exceeded for a kunit test,
> > the test task will be killed and an oops generated.  This should
> > suffice as a means of debugging such timeout issues for now.
> >
> > Hence remove use of sysctl_hung_task_timeout_secs, which has the
> > added benefit of avoiding the need to export that symbol from
> > the core kernel.
> >
> > Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> > Signed-off-by: Knut Omang <knut.omang@oracle.com>
>
> This seems like a workaround for sysctl_hung_task_timeout_secs not being
> exported. If true, this can be addressed by creating a symbol namespace
> (new) and using that namespace on this path.

It is; as discussed on in v3[1]. I don't really feel strongly one way
or the other, I can see arguments for either side. Still, I don't want
to give Alan the run-around. I think this is the 3rd or 4th time he
has tried to address this issue.

[1] https://lore.kernel.org/linux-kselftest/CAFd5g44esDP6WFmkjOiH+my_4iBeqMpFoScMCm_hQ0aFwNS9qw@mail.gmail.com/

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

* Re: [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit
  2019-11-17  1:33   ` Stephen Boyd
@ 2019-11-19 18:36     ` Brendan Higgins
  0 siblings, 0 replies; 22+ messages in thread
From: Brendan Higgins @ 2019-11-19 18:36 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Alan Maguire, open list:KERNEL SELFTEST FRAMEWORK, Shuah Khan,
	Linux Kernel Mailing List, KUnit Development, Kees Cook,
	Iurii Zaikin, Andrew Morton, Masahiro Yamada, catalin.marinas,
	joe.lawrence, penguin-kernel, schowdary, urezki,
	andriy.shevchenko, Jonathan Corbet, Theodore Ts'o,
	adilger.kernel, Luis Chamberlain, changbin.du, linux-ext4,
	open list:DOCUMENTATION, Knut Omang

On Sat, Nov 16, 2019 at 5:33 PM Stephen Boyd <sboyd@kernel.org> wrote:
>
> Quoting Alan Maguire (2019-11-15 02:16:07)
> > string-stream interfaces are not intended for external use;
> > move them from include/kunit to lib/kunit accordingly.
> >
> > Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> > Signed-off-by: Knut Omang <knut.omang@oracle.com>
>
> The sign off chain is incorrect here. Is Knut tag supposed to be
> Co-developed-by?

I am not sure what the relationship between Alan and Knut on this
patch. Nevertheless, Signed-off-by is required either way, but it
seems that Co-developed-by is optional depending on how Alan and Knut
would like to share credit for this patch, at least that is based on
my reading of the submitting patches guide:

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by

> > diff --git a/include/kunit/assert.h b/include/kunit/assert.h
> > index db6a0fc..ad889b5 100644
> > --- a/include/kunit/assert.h
> > +++ b/include/kunit/assert.h
> > @@ -9,10 +9,11 @@
> >  #ifndef _KUNIT_ASSERT_H
> >  #define _KUNIT_ASSERT_H
> >
> > -#include <kunit/string-stream.h>
> >  #include <linux/err.h>
> > +#include <linux/kernel.h>
>
> Why is this included now?

Nice catch! I think I would have missed that.

> >
> >  struct kunit;
> > +struct string_stream;
> >
> >  /**
> >   * enum kunit_assert_type - Type of expectation/assertion.

Cheers!

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

* Re: [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit Alan Maguire
  2019-11-17  1:33   ` Stephen Boyd
@ 2019-11-19 18:39   ` Brendan Higgins
  1 sibling, 0 replies; 22+ messages in thread
From: Brendan Higgins @ 2019-11-19 18:39 UTC (permalink / raw)
  To: Alan Maguire
  Cc: Shuah Khan, open list:KERNEL SELFTEST FRAMEWORK,
	Linux Kernel Mailing List, KUnit Development, Kees Cook,
	Iurii Zaikin, Andrew Morton, Masahiro Yamada, catalin.marinas,
	joe.lawrence, penguin-kernel, schowdary, urezki,
	andriy.shevchenko, Jonathan Corbet, Theodore Ts'o,
	adilger.kernel, Luis Chamberlain, changbin.du, linux-ext4,
	open list:DOCUMENTATION, Stephen Boyd, Knut Omang

On Fri, Nov 15, 2019 at 2:17 AM Alan Maguire <alan.maguire@oracle.com> wrote:
>
> string-stream interfaces are not intended for external use;
> move them from include/kunit to lib/kunit accordingly.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>

Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Tested-by: Brendan Higgins <brendanhiggins@google.com>

Stephen pointed out a couple of nits, but beyond that this looks good to me.

Thanks for all your hard work!

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

* Re: [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h Alan Maguire
  2019-11-17  1:36   ` Stephen Boyd
@ 2019-11-19 18:48   ` Brendan Higgins
  1 sibling, 0 replies; 22+ messages in thread
From: Brendan Higgins @ 2019-11-19 18:48 UTC (permalink / raw)
  To: Alan Maguire
  Cc: Shuah Khan, open list:KERNEL SELFTEST FRAMEWORK,
	Linux Kernel Mailing List, KUnit Development, Kees Cook,
	Iurii Zaikin, Andrew Morton, Masahiro Yamada, catalin.marinas,
	joe.lawrence, penguin-kernel, schowdary, urezki,
	andriy.shevchenko, Jonathan Corbet, Theodore Ts'o,
	adilger.kernel, Luis Chamberlain, changbin.du, linux-ext4,
	open list:DOCUMENTATION, Stephen Boyd

On Fri, Nov 15, 2019 at 2:17 AM Alan Maguire <alan.maguire@oracle.com> wrote:
>
> Define function as static inline in try-catch-impl.h to allow it to
> be used in kunit itself and tests.  Also remove unused
> kunit_generic_try_catch
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Tested-by: Brendan Higgins <brendanhiggins@google.com>

Aside from Stephen's comment, this looks good to me.

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

* Re: [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module Alan Maguire
@ 2019-11-19 19:16   ` Brendan Higgins
  2019-11-20 13:56     ` Alan Maguire
  2019-11-19 21:05   ` Stephen Boyd
  1 sibling, 1 reply; 22+ messages in thread
From: Brendan Higgins @ 2019-11-19 19:16 UTC (permalink / raw)
  To: Alan Maguire, David Gow, Iurii Zaikin, Theodore Ts'o, Kees Cook
  Cc: Shuah Khan, open list:KERNEL SELFTEST FRAMEWORK,
	Linux Kernel Mailing List, KUnit Development, Andrew Morton,
	Masahiro Yamada, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, Jonathan Corbet,
	adilger.kernel, Luis Chamberlain, changbin.du, linux-ext4,
	open list:DOCUMENTATION, Stephen Boyd, Knut Omang

On Fri, Nov 15, 2019 at 2:16 AM Alan Maguire <alan.maguire@oracle.com> wrote:
>
> As tests are added to kunit, it will become less feasible to execute
> all built tests together.  By supporting modular tests we provide
> a simple way to do selective execution on a running system; specifying
>
> CONFIG_KUNIT=y
> CONFIG_KUNIT_EXAMPLE_TEST=m
>
> ...means we can simply "insmod example-test.ko" to run the tests.
>
> To achieve this we need to do the following:
>
> o export the required symbols in kunit
> o string-stream tests utilize non-exported symbols so for now we skip
>   building them when CONFIG_KUNIT_TEST=m.
> o support a new way of declaring test suites.  Because a module cannot
>   do multiple late_initcall()s, we provide a kunit_test_suites() macro
>   to declare multiple suites within the same module at once.
> o some test module names would have been too general ("test-test"
>   and "example-test" for kunit tests, "inode-test" for ext4 tests);
>   rename these as appropriate ("kunit-test", "kunit-example-test"
>   and "ext4-inode-test" respectively).

Hmm...should we maybe apply this naming scheme to all the tests then?
I think Kees might have suggested this. I am actually not sure whether
or not we should and would like to get other people's input.

It is a valid point that test-test or example-test are too general of
names for modules, but if this is the case, I think that inode-test is
probably too general as well. But if we are going that far, maybe we
should rename everything *-kunit-test.c.

> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>
> ---
>  fs/ext4/Kconfig                |   2 +-
>  fs/ext4/Makefile               |   5 +
>  fs/ext4/inode-test.c           |   4 +-
>  include/kunit/test.h           |  35 +++--
>  kernel/sysctl-test.c           |   4 +-
>  lib/Kconfig.debug              |   4 +-
>  lib/kunit/Kconfig              |   4 +-
>  lib/kunit/Makefile             |  10 +-
>  lib/kunit/assert.c             |   8 +
>  lib/kunit/example-test.c       |  88 -----------
>  lib/kunit/kunit-example-test.c |  90 +++++++++++
>  lib/kunit/kunit-test.c         | 334 +++++++++++++++++++++++++++++++++++++++++
>  lib/kunit/string-stream-test.c |   2 +-
>  lib/kunit/test-test.c          | 333 ----------------------------------------
>  lib/kunit/test.c               |   8 +
>  lib/kunit/try-catch.c          |   2 +
>  lib/list-test.c                |   4 +-
>  17 files changed, 494 insertions(+), 443 deletions(-)
>  delete mode 100644 lib/kunit/example-test.c
>  create mode 100644 lib/kunit/kunit-example-test.c
>  create mode 100644 lib/kunit/kunit-test.c
>  delete mode 100644 lib/kunit/test-test.c

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

* Re: [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module Alan Maguire
  2019-11-19 19:16   ` Brendan Higgins
@ 2019-11-19 21:05   ` Stephen Boyd
  1 sibling, 0 replies; 22+ messages in thread
From: Stephen Boyd @ 2019-11-19 21:05 UTC (permalink / raw)
  To: Alan Maguire, brendanhiggins, linux-kselftest, skhan
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	Alan Maguire, Knut Omang

Quoting Alan Maguire (2019-11-15 02:16:09)
> As tests are added to kunit, it will become less feasible to execute
> all built tests together.  By supporting modular tests we provide
> a simple way to do selective execution on a running system; specifying
> 
> CONFIG_KUNIT=y
> CONFIG_KUNIT_EXAMPLE_TEST=m
> 
> ...means we can simply "insmod example-test.ko" to run the tests.
> 
> To achieve this we need to do the following:
> 
> o export the required symbols in kunit
> o string-stream tests utilize non-exported symbols so for now we skip
>   building them when CONFIG_KUNIT_TEST=m.
> o support a new way of declaring test suites.  Because a module cannot
>   do multiple late_initcall()s, we provide a kunit_test_suites() macro
>   to declare multiple suites within the same module at once.
> o some test module names would have been too general ("test-test"
>   and "example-test" for kunit tests, "inode-test" for ext4 tests);
>   rename these as appropriate ("kunit-test", "kunit-example-test"
>   and "ext4-inode-test" respectively).
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>
> ---
>  fs/ext4/Kconfig                |   2 +-
>  fs/ext4/Makefile               |   5 +
>  fs/ext4/inode-test.c           |   4 +-
>  include/kunit/test.h           |  35 +++--
>  kernel/sysctl-test.c           |   4 +-
>  lib/Kconfig.debug              |   4 +-
>  lib/kunit/Kconfig              |   4 +-
>  lib/kunit/Makefile             |  10 +-
>  lib/kunit/assert.c             |   8 +
>  lib/kunit/example-test.c       |  88 -----------
>  lib/kunit/kunit-example-test.c |  90 +++++++++++
>  lib/kunit/kunit-test.c         | 334 +++++++++++++++++++++++++++++++++++++++++
>  lib/kunit/string-stream-test.c |   2 +-
>  lib/kunit/test-test.c          | 333 ----------------------------------------
>  lib/kunit/test.c               |   8 +
>  lib/kunit/try-catch.c          |   2 +
>  lib/list-test.c                |   4 +-

Can you generate your patches with -M or -C? Hopefully that will find
copies and only show us the diff between the two files.

>  17 files changed, 494 insertions(+), 443 deletions(-)
>  delete mode 100644 lib/kunit/example-test.c
>  create mode 100644 lib/kunit/kunit-example-test.c
>  create mode 100644 lib/kunit/kunit-test.c
>  delete mode 100644 lib/kunit/test-test.c

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

* Re: [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds Alan Maguire
  2019-11-18 22:09   ` Luis Chamberlain
@ 2019-11-19 21:06   ` Stephen Boyd
  1 sibling, 0 replies; 22+ messages in thread
From: Stephen Boyd @ 2019-11-19 21:06 UTC (permalink / raw)
  To: Alan Maguire, brendanhiggins, linux-kselftest, skhan
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	Alan Maguire, Knut Omang

Quoting Alan Maguire (2019-11-15 02:16:10)
> In discussion of how to handle timeouts, it was noted that if
> sysctl_hung_task_timeout_seconds is exceeded for a kunit test,
> the test task will be killed and an oops generated.  This should
> suffice as a means of debugging such timeout issues for now.
> 
> Hence remove use of sysctl_hung_task_timeout_secs, which has the
> added benefit of avoiding the need to export that symbol from
> the core kernel.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>
> ---

Reviewed-by: Stephen Boyd <sboyd@kernel.org>


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

* Re: [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module Alan Maguire
@ 2019-11-19 21:13   ` Stephen Boyd
  2019-11-20 13:46     ` Alan Maguire
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Boyd @ 2019-11-19 21:13 UTC (permalink / raw)
  To: Alan Maguire, brendanhiggins, linux-kselftest, skhan
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	Alan Maguire, Knut Omang

Quoting Alan Maguire (2019-11-15 02:16:11)
> diff --git a/lib/kunit/test.c b/lib/kunit/test.c
> index 87b5cf1..41ef71a 100644
> --- a/lib/kunit/test.c
> +++ b/lib/kunit/test.c
> @@ -486,3 +486,16 @@ void kunit_cleanup(struct kunit *test)
>         }
>  }
>  EXPORT_SYMBOL_GPL(kunit_cleanup);
> +
> +static int kunit_init(void)

Missing __init?

> +{
> +       return 0;
> +}
> +late_initcall(kunit_init);

It looks pretty weird that this doesn't do anything in the module init
or exit path. How does it work? And why does it need to be late init if
nothing is called from here?

> +
> +static void __exit kunit_exit(void)
> +{
> +}
> +module_exit(kunit_exit);
> +
> +MODULE_LICENSE("GPL");

I guess should be "GPL v2"?


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

* Re: [PATCH v4 linux-kselftest-test 6/6] kunit: update documentation to describe module-based build
  2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 6/6] kunit: update documentation to describe module-based build Alan Maguire
@ 2019-11-19 21:15   ` Stephen Boyd
  0 siblings, 0 replies; 22+ messages in thread
From: Stephen Boyd @ 2019-11-19 21:15 UTC (permalink / raw)
  To: Alan Maguire, brendanhiggins, linux-kselftest, skhan
  Cc: linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	schowdary, urezki, andriy.shevchenko, corbet, tytso,
	adilger.kernel, mcgrof, changbin.du, linux-ext4, linux-doc,
	Alan Maguire, Knut Omang

Quoting Alan Maguire (2019-11-15 02:16:12)
> Documentation should describe how to build kunit and tests as
> modules.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Knut Omang <knut.omang@oracle.com>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>


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

* Re: [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module
  2019-11-19 21:13   ` Stephen Boyd
@ 2019-11-20 13:46     ` Alan Maguire
  0 siblings, 0 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-20 13:46 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Alan Maguire, brendanhiggins, linux-kselftest, skhan,
	linux-kernel, kunit-dev, keescook, yzaikin, akpm,
	yamada.masahiro, catalin.marinas, joe.lawrence, penguin-kernel,
	urezki, andriy.shevchenko, corbet, tytso, adilger.kernel, mcgrof,
	linux-ext4, linux-doc, Knut Omang

On Tue, 19 Nov 2019, Stephen Boyd wrote:

> Quoting Alan Maguire (2019-11-15 02:16:11)
> > diff --git a/lib/kunit/test.c b/lib/kunit/test.c
> > index 87b5cf1..41ef71a 100644
> > --- a/lib/kunit/test.c
> > +++ b/lib/kunit/test.c
> > @@ -486,3 +486,16 @@ void kunit_cleanup(struct kunit *test)
> >         }
> >  }
> >  EXPORT_SYMBOL_GPL(kunit_cleanup);
> > +
> > +static int kunit_init(void)
> 
> Missing __init?
>

Oops, will fix.
 
> > +{
> > +       return 0;
> > +}
> > +late_initcall(kunit_init);
> 
> It looks pretty weird that this doesn't do anything in the module init
> or exit path. How does it work? And why does it need to be late init if
> nothing is called from here?
>

I used a late_initcall() here because if there is initialization code in 
the future (say setting up debugfs, sysctl tables etc), it will get run 
irrespective of whether kunit is built as a module or not.  For the module
case, we need init/exit to ensure the module can be unloaded 
successfully.

> > +
> > +static void __exit kunit_exit(void)
> > +{
> > +}
> > +module_exit(kunit_exit);
> > +
> > +MODULE_LICENSE("GPL");
> 
> I guess should be "GPL v2"?
> 

Good catch, will fix here and elsewhere, thanks!

BTW in replying to your review of patch 1 I made a mistake; we do in fact 
need to add the "#include <linux/kernel.h>" in assert.h as we are removing 
the "#include <kunit/string-stream.h>".  The latter indirectly includes 
linux/kernel.h which allows us to find definition for "struct va_format"
used in the struct kunit_assert definition. Apologies about this.

I'll have a go at generating v5 using -C as requested. Thanks again for 
the careful review!

Alan

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

* Re: [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module
  2019-11-19 19:16   ` Brendan Higgins
@ 2019-11-20 13:56     ` Alan Maguire
  0 siblings, 0 replies; 22+ messages in thread
From: Alan Maguire @ 2019-11-20 13:56 UTC (permalink / raw)
  To: Brendan Higgins
  Cc: Alan Maguire, David Gow, Iurii Zaikin, Theodore Ts'o,
	Kees Cook, Shuah Khan, open list:KERNEL SELFTEST FRAMEWORK,
	Linux Kernel Mailing List, KUnit Development, Andrew Morton,
	Masahiro Yamada, catalin.marinas, joe.lawrence, penguin-kernel,
	urezki, andriy.shevchenko, Jonathan Corbet, adilger.kernel,
	Luis Chamberlain, linux-ext4, open list:DOCUMENTATION,
	Stephen Boyd, Knut Omang

On Tue, 19 Nov 2019, Brendan Higgins wrote:

> On Fri, Nov 15, 2019 at 2:16 AM Alan Maguire <alan.maguire@oracle.com> wrote:
> >
> > As tests are added to kunit, it will become less feasible to execute
> > all built tests together.  By supporting modular tests we provide
> > a simple way to do selective execution on a running system; specifying
> >
> > CONFIG_KUNIT=y
> > CONFIG_KUNIT_EXAMPLE_TEST=m
> >
> > ...means we can simply "insmod example-test.ko" to run the tests.
> >
> > To achieve this we need to do the following:
> >
> > o export the required symbols in kunit
> > o string-stream tests utilize non-exported symbols so for now we skip
> >   building them when CONFIG_KUNIT_TEST=m.
> > o support a new way of declaring test suites.  Because a module cannot
> >   do multiple late_initcall()s, we provide a kunit_test_suites() macro
> >   to declare multiple suites within the same module at once.
> > o some test module names would have been too general ("test-test"
> >   and "example-test" for kunit tests, "inode-test" for ext4 tests);
> >   rename these as appropriate ("kunit-test", "kunit-example-test"
> >   and "ext4-inode-test" respectively).
> 
> Hmm...should we maybe apply this naming scheme to all the tests then?
> I think Kees might have suggested this. I am actually not sure whether
> or not we should and would like to get other people's input.
> 

I'd be interested in other opinions here too; the approach I took here was 
to apply the convention [subsystem]-[optional-suite]-test.ko. So for 
example kunit-test.ko because the subsystem under test is kunit, etc.
Implicit in this is the reasoning that the framework used isn't relevant 
to the naming of the test module, but I'm happy to tweak the naming 
scheme if another approach is preferred.  The current names from the 
patchset are:

kunit-test.ko		- tests for kunit itself
kunit-example-test.ko	- example test using the kunit framework
sysctl-test.ko		- sysctl kunit tests
list-test.ko		- list kunit tests
ext4-inode-test.ko	- ext4 kunit tests
 
> It is a valid point that test-test or example-test are too general of
> names for modules, but if this is the case, I think that inode-test is
> probably too general as well. But if we are going that far, maybe we
> should rename everything *-kunit-test.c.
> 

Yep, I figured inode-test.ko was too general also, so the Makefile 
builds ext4-inode-test.ko from inode-test.c. See fs/ext4/Makefile.

Thanks!

Alan

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

end of thread, other threads:[~2019-11-20 13:57 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-15 10:16 [PATCH v4 linux-kselftest-test 0/6] kunit: support building core/tests as modules Alan Maguire
2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 1/6] kunit: move string-stream.h to lib/kunit Alan Maguire
2019-11-17  1:33   ` Stephen Boyd
2019-11-19 18:36     ` Brendan Higgins
2019-11-19 18:39   ` Brendan Higgins
2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 2/6] kunit: hide unexported try-catch interface in try-catch-impl.h Alan Maguire
2019-11-17  1:36   ` Stephen Boyd
2019-11-18 17:30     ` Alan Maguire
2019-11-19 18:48   ` Brendan Higgins
2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 3/6] kunit: allow kunit tests to be loaded as a module Alan Maguire
2019-11-19 19:16   ` Brendan Higgins
2019-11-20 13:56     ` Alan Maguire
2019-11-19 21:05   ` Stephen Boyd
2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 4/6] kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds Alan Maguire
2019-11-18 22:09   ` Luis Chamberlain
2019-11-19  1:24     ` Brendan Higgins
2019-11-19 21:06   ` Stephen Boyd
2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 5/6] kunit: allow kunit to be loaded as a module Alan Maguire
2019-11-19 21:13   ` Stephen Boyd
2019-11-20 13:46     ` Alan Maguire
2019-11-15 10:16 ` [PATCH v4 linux-kselftest-test 6/6] kunit: update documentation to describe module-based build Alan Maguire
2019-11-19 21:15   ` Stephen Boyd

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).