Skip to content

Commit

Permalink
UPSTREAM: kunit: allow kunit tests to be loaded as a module
Browse files Browse the repository at this point in the history
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 drivers/base/power/qos-test.c contains a few unexported interface
  references, namely freq_qos_read_value() and freq_constraints_init().
  Both of these could be potentially defined as static inline functions
  in include/linux/pm_qos.h, but for now we simply avoid supporting
  module build for that test suite.
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).

Also define kunit_test_suite() via kunit_test_suites()
as callers in other trees may need the old definition.

Co-developed-by: Knut Omang <knut.omang@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Acked-by: Theodore Ts'o <tytso@mit.edu> # for ext4 bits
Acked-by: David Gow <davidgow@google.com> # For list-test
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
(cherry picked from commit c475c77)
Bug: 179135338
Test: run cuttlefish with KUNIT_ALL_TESTS enabled
Signed-off-by: Alexander Potapenko <glider@google.com>
Change-Id: I6d11cf8165c7cb256136757ddca79c7334b3e206
  • Loading branch information
alan-maguire authored and adelva1984 committed Feb 10, 2021
1 parent 418b37d commit 7678fa7
Show file tree
Hide file tree
Showing 16 changed files with 76 additions and 27 deletions.
2 changes: 1 addition & 1 deletion drivers/base/power/qos-test.c
Expand Up @@ -114,4 +114,4 @@ static struct kunit_suite pm_qos_test_module = {
.name = "qos-kunit-test",
.test_cases = pm_qos_test_cases,
};
kunit_test_suite(pm_qos_test_module);
kunit_test_suites(&pm_qos_test_module);
2 changes: 1 addition & 1 deletion fs/ext4/Kconfig
Expand Up @@ -109,7 +109,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
Expand Down
3 changes: 2 additions & 1 deletion fs/ext4/Makefile
Expand Up @@ -13,5 +13,6 @@ 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
ext4-$(CONFIG_EXT4_KUNIT_TESTS) += inode-test.o
ext4-inode-test-objs += inode-test.o
obj-$(CONFIG_EXT4_KUNIT_TESTS) += ext4-inode-test.o
ext4-$(CONFIG_FS_VERITY) += verity.o
4 changes: 3 additions & 1 deletion fs/ext4/inode-test.c
Expand Up @@ -269,4 +269,6 @@ static struct kunit_suite ext4_inode_test_suite = {
.test_cases = ext4_inode_test_cases,
};

kunit_test_suite(ext4_inode_test_suite);
kunit_test_suites(&ext4_inode_test_suite);

MODULE_LICENSE("GPL v2");
37 changes: 27 additions & 10 deletions include/kunit/test.h
Expand Up @@ -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>

Expand Down Expand Up @@ -197,31 +198,47 @@ void kunit_init_test(struct kunit *test, const char *name);
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)

#define kunit_test_suite(suite) kunit_test_suites(&suite)

/*
* Like kunit_alloc_resource() below, but returns the struct kunit_resource
Expand Down
4 changes: 3 additions & 1 deletion kernel/sysctl-test.c
Expand Up @@ -389,4 +389,6 @@ static struct kunit_suite sysctl_test_suite = {
.test_cases = sysctl_test_cases,
};

kunit_test_suite(sysctl_test_suite);
kunit_test_suites(&sysctl_test_suite);

MODULE_LICENSE("GPL v2");
4 changes: 2 additions & 2 deletions lib/Kconfig.debug
Expand Up @@ -1955,7 +1955,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.
Expand All @@ -1966,7 +1966,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.
Expand Down
4 changes: 2 additions & 2 deletions lib/kunit/Kconfig
Expand Up @@ -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
Expand All @@ -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
Expand Down
10 changes: 7 additions & 3 deletions lib/kunit/Makefile
Expand Up @@ -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
8 changes: 8 additions & 0 deletions lib/kunit/assert.c
Expand Up @@ -26,20 +26,23 @@ 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)
{
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)
{
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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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);
4 changes: 3 additions & 1 deletion lib/kunit/example-test.c → lib/kunit/kunit-example-test.c
Expand Up @@ -85,4 +85,6 @@ static struct kunit_suite example_test_suite = {
* 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);
kunit_test_suites(&example_test_suite);

MODULE_LICENSE("GPL v2");
5 changes: 3 additions & 2 deletions lib/kunit/test-test.c → lib/kunit/kunit-test.c
Expand Up @@ -102,7 +102,6 @@ static struct kunit_suite kunit_try_catch_test_suite = {
.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
Expand Down Expand Up @@ -330,4 +329,6 @@ static struct kunit_suite kunit_resource_test_suite = {
.exit = kunit_resource_test_exit,
.test_cases = kunit_resource_test_cases,
};
kunit_test_suite(kunit_resource_test_suite);
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite);

MODULE_LICENSE("GPL v2");
2 changes: 1 addition & 1 deletion lib/kunit/string-stream-test.c
Expand Up @@ -50,4 +50,4 @@ static struct kunit_suite string_stream_test_suite = {
.name = "string-stream-test",
.test_cases = string_stream_test_cases
};
kunit_test_suite(string_stream_test_suite);
kunit_test_suites(&string_stream_test_suite);
8 changes: 8 additions & 0 deletions lib/kunit/test.c
Expand Up @@ -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)
{
Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
{
Expand Down Expand Up @@ -478,3 +485,4 @@ void kunit_cleanup(struct kunit *test)
kunit_resource_free(test, resource);
}
}
EXPORT_SYMBOL_GPL(kunit_cleanup);
2 changes: 2 additions & 0 deletions lib/kunit/try-catch.c
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
4 changes: 3 additions & 1 deletion lib/list-test.c
Expand Up @@ -743,4 +743,6 @@ static struct kunit_suite list_test_module = {
.test_cases = list_test_cases,
};

kunit_test_suite(list_test_module);
kunit_test_suites(&list_test_module);

MODULE_LICENSE("GPL v2");

0 comments on commit 7678fa7

Please sign in to comment.