summaryrefslogtreecommitdiff
path: root/lib/kunit
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2022-08-02 10:06:12 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2022-08-02 10:06:12 -0700
commit8bb5e7f4dcd9b9ef22a3ea25c9066a8a968f12dd (patch)
tree0f1383880607a227142f9388a066959926233ff1 /lib/kunit
parent2a96271fb66c499e4a89d76a89d3d01170c10bef (diff)
parent7c744d00990ea999d27f306f6db5ccb61b1304b2 (diff)
Merge branch 'next' into for-linus
Prepare input updates for 5.20 (or 6.0) merge window.
Diffstat (limited to 'lib/kunit')
-rw-r--r--lib/kunit/Makefile1
-rw-r--r--lib/kunit/assert.c80
-rw-r--r--lib/kunit/debugfs.c2
-rw-r--r--lib/kunit/executor.c32
-rw-r--r--lib/kunit/executor_test.c4
-rw-r--r--lib/kunit/kunit-example-test.c58
-rw-r--r--lib/kunit/kunit-test.c37
-rw-r--r--lib/kunit/resource.c79
-rw-r--r--lib/kunit/test.c176
-rw-r--r--lib/kunit/try-catch.c3
10 files changed, 285 insertions, 187 deletions
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index c49f4ffb6273..29aff6562b42 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_KUNIT) += kunit.o
kunit-objs += test.o \
+ resource.o \
string-stream.o \
assert.o \
try-catch.o \
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
index b972bda61c0c..d00d6d181ee8 100644
--- a/lib/kunit/assert.c
+++ b/lib/kunit/assert.c
@@ -10,12 +10,13 @@
#include "string-stream.h"
-void kunit_base_assert_format(const struct kunit_assert *assert,
+void kunit_assert_prologue(const struct kunit_loc *loc,
+ enum kunit_assert_type type,
struct string_stream *stream)
{
const char *expect_or_assert = NULL;
- switch (assert->type) {
+ switch (type) {
case KUNIT_EXPECTATION:
expect_or_assert = "EXPECTATION";
break;
@@ -25,34 +26,33 @@ 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);
+ expect_or_assert, loc->file, loc->line);
}
-EXPORT_SYMBOL_GPL(kunit_base_assert_format);
+EXPORT_SYMBOL_GPL(kunit_assert_prologue);
-void kunit_assert_print_msg(const struct kunit_assert *assert,
- struct string_stream *stream)
+static void kunit_assert_print_msg(const struct va_format *message,
+ struct string_stream *stream)
{
- if (assert->message.fmt)
- string_stream_add(stream, "\n%pV", &assert->message);
+ if (message->fmt)
+ string_stream_add(stream, "\n%pV", message);
}
-EXPORT_SYMBOL_GPL(kunit_assert_print_msg);
void kunit_fail_assert_format(const struct kunit_assert *assert,
+ const struct va_format *message,
struct string_stream *stream)
{
- kunit_base_assert_format(assert, stream);
- string_stream_add(stream, "%pV", &assert->message);
+ string_stream_add(stream, "%pV", message);
}
EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
void kunit_unary_assert_format(const struct kunit_assert *assert,
+ const struct va_format *message,
struct string_stream *stream)
{
struct kunit_unary_assert *unary_assert;
unary_assert = container_of(assert, struct kunit_unary_assert, assert);
- kunit_base_assert_format(assert, stream);
if (unary_assert->expected_true)
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
@@ -61,11 +61,12 @@ void kunit_unary_assert_format(const struct kunit_assert *assert,
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
unary_assert->condition);
- kunit_assert_print_msg(assert, stream);
+ kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
+ const struct va_format *message,
struct string_stream *stream)
{
struct kunit_ptr_not_err_assert *ptr_assert;
@@ -73,7 +74,6 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,
assert);
- kunit_base_assert_format(assert, stream);
if (!ptr_assert->value) {
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
@@ -84,7 +84,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
ptr_assert->text,
PTR_ERR(ptr_assert->value));
}
- kunit_assert_print_msg(assert, stream);
+ kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
@@ -112,6 +112,7 @@ static bool is_literal(struct kunit *test, const char *text, long long value,
}
void kunit_binary_assert_format(const struct kunit_assert *assert,
+ const struct va_format *message,
struct string_stream *stream)
{
struct kunit_binary_assert *binary_assert;
@@ -119,27 +120,27 @@ void kunit_binary_assert_format(const struct kunit_assert *assert,
binary_assert = container_of(assert, struct kunit_binary_assert,
assert);
- kunit_base_assert_format(assert, stream);
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
- binary_assert->left_text,
- binary_assert->operation,
- binary_assert->right_text);
- if (!is_literal(stream->test, binary_assert->left_text,
+ binary_assert->text->left_text,
+ binary_assert->text->operation,
+ binary_assert->text->right_text);
+ if (!is_literal(stream->test, binary_assert->text->left_text,
binary_assert->left_value, stream->gfp))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld\n",
- binary_assert->left_text,
+ binary_assert->text->left_text,
binary_assert->left_value);
- if (!is_literal(stream->test, binary_assert->right_text,
+ if (!is_literal(stream->test, binary_assert->text->right_text,
binary_assert->right_value, stream->gfp))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld",
- binary_assert->right_text,
+ binary_assert->text->right_text,
binary_assert->right_value);
- kunit_assert_print_msg(assert, stream);
+ kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
+ const struct va_format *message,
struct string_stream *stream)
{
struct kunit_binary_ptr_assert *binary_assert;
@@ -147,19 +148,18 @@ void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
binary_assert = container_of(assert, struct kunit_binary_ptr_assert,
assert);
- kunit_base_assert_format(assert, stream);
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
- binary_assert->left_text,
- binary_assert->operation,
- binary_assert->right_text);
+ binary_assert->text->left_text,
+ binary_assert->text->operation,
+ binary_assert->text->right_text);
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",
- binary_assert->left_text,
+ binary_assert->text->left_text,
binary_assert->left_value);
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",
- binary_assert->right_text,
+ binary_assert->text->right_text,
binary_assert->right_value);
- kunit_assert_print_msg(assert, stream);
+ kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
@@ -180,6 +180,7 @@ static bool is_str_literal(const char *text, const char *value)
}
void kunit_binary_str_assert_format(const struct kunit_assert *assert,
+ const struct va_format *message,
struct string_stream *stream)
{
struct kunit_binary_str_assert *binary_assert;
@@ -187,20 +188,19 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
binary_assert = container_of(assert, struct kunit_binary_str_assert,
assert);
- kunit_base_assert_format(assert, stream);
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
- binary_assert->left_text,
- binary_assert->operation,
- binary_assert->right_text);
- if (!is_str_literal(binary_assert->left_text, binary_assert->left_value))
+ binary_assert->text->left_text,
+ binary_assert->text->operation,
+ binary_assert->text->right_text);
+ if (!is_str_literal(binary_assert->text->left_text, binary_assert->left_value))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n",
- binary_assert->left_text,
+ binary_assert->text->left_text,
binary_assert->left_value);
- if (!is_str_literal(binary_assert->right_text, binary_assert->right_value))
+ if (!is_str_literal(binary_assert->text->right_text, binary_assert->right_value))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"",
- binary_assert->right_text,
+ binary_assert->text->right_text,
binary_assert->right_value);
- kunit_assert_print_msg(assert, stream);
+ kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
diff --git a/lib/kunit/debugfs.c b/lib/kunit/debugfs.c
index b71db0abc12b..1048ef1b8d6e 100644
--- a/lib/kunit/debugfs.c
+++ b/lib/kunit/debugfs.c
@@ -52,7 +52,7 @@ static void debugfs_print_result(struct seq_file *seq,
static int debugfs_print_results(struct seq_file *seq, void *v)
{
struct kunit_suite *suite = (struct kunit_suite *)seq->private;
- bool success = kunit_suite_has_succeeded(suite);
+ enum kunit_status success = kunit_suite_has_succeeded(suite);
struct kunit_case *test_case;
if (!suite || !suite->log)
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
index 22640c9ee819..96f96e42ce06 100644
--- a/lib/kunit/executor.c
+++ b/lib/kunit/executor.c
@@ -71,9 +71,13 @@ kunit_filter_tests(struct kunit_suite *const suite, const char *test_glob)
/* Use memcpy to workaround copy->name being const. */
copy = kmalloc(sizeof(*copy), GFP_KERNEL);
+ if (!copy)
+ return ERR_PTR(-ENOMEM);
memcpy(copy, suite, sizeof(*copy));
filtered = kcalloc(n + 1, sizeof(*filtered), GFP_KERNEL);
+ if (!filtered)
+ return ERR_PTR(-ENOMEM);
n = 0;
kunit_suite_for_each_test_case(suite, test_case) {
@@ -106,14 +110,16 @@ kunit_filter_subsuite(struct kunit_suite * const * const subsuite,
filtered = kmalloc_array(n + 1, sizeof(*filtered), GFP_KERNEL);
if (!filtered)
- return NULL;
+ return ERR_PTR(-ENOMEM);
n = 0;
for (i = 0; subsuite[i] != NULL; ++i) {
if (!glob_match(filter->suite_glob, subsuite[i]->name))
continue;
filtered_suite = kunit_filter_tests(subsuite[i], filter->test_glob);
- if (filtered_suite)
+ if (IS_ERR(filtered_suite))
+ return ERR_CAST(filtered_suite);
+ else if (filtered_suite)
filtered[n++] = filtered_suite;
}
filtered[n] = NULL;
@@ -146,7 +152,8 @@ static void kunit_free_suite_set(struct suite_set suite_set)
}
static struct suite_set kunit_filter_suites(const struct suite_set *suite_set,
- const char *filter_glob)
+ const char *filter_glob,
+ int *err)
{
int i;
struct kunit_suite * const **copy, * const *filtered_subsuite;
@@ -166,6 +173,10 @@ static struct suite_set kunit_filter_suites(const struct suite_set *suite_set,
for (i = 0; i < max; ++i) {
filtered_subsuite = kunit_filter_subsuite(suite_set->start[i], &filter);
+ if (IS_ERR(filtered_subsuite)) {
+ *err = PTR_ERR(filtered_subsuite);
+ return filtered;
+ }
if (filtered_subsuite)
*copy++ = filtered_subsuite;
}
@@ -236,9 +247,15 @@ int kunit_run_all_tests(void)
.start = __kunit_suites_start,
.end = __kunit_suites_end,
};
+ int err = 0;
- if (filter_glob_param)
- suite_set = kunit_filter_suites(&suite_set, filter_glob_param);
+ if (filter_glob_param) {
+ suite_set = kunit_filter_suites(&suite_set, filter_glob_param, &err);
+ if (err) {
+ pr_err("kunit executor: error filtering suites: %d\n", err);
+ goto out;
+ }
+ }
if (!action_param)
kunit_exec_run_tests(&suite_set);
@@ -251,9 +268,10 @@ int kunit_run_all_tests(void)
kunit_free_suite_set(suite_set);
}
- kunit_handle_shutdown();
- return 0;
+out:
+ kunit_handle_shutdown();
+ return err;
}
#if IS_BUILTIN(CONFIG_KUNIT_TEST)
diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c
index 4ed57fd94e42..eac6ff480273 100644
--- a/lib/kunit/executor_test.c
+++ b/lib/kunit/executor_test.c
@@ -137,14 +137,16 @@ static void filter_suites_test(struct kunit *test)
.end = suites + 2,
};
struct suite_set filtered = {.start = NULL, .end = NULL};
+ int err = 0;
/* Emulate two files, each having one suite */
subsuites[0][0] = alloc_fake_suite(test, "suite0", dummy_test_cases);
subsuites[1][0] = alloc_fake_suite(test, "suite1", dummy_test_cases);
/* Filter out suite1 */
- filtered = kunit_filter_suites(&suite_set, "suite0");
+ filtered = kunit_filter_suites(&suite_set, "suite0", &err);
kfree_subsuites_at_end(test, &filtered); /* let us use ASSERTs without leaking */
+ KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_ASSERT_EQ(test, filtered.end - filtered.start, (ptrdiff_t)1);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start);
diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c
index 51099b0ca29c..f8fe582c9e36 100644
--- a/lib/kunit/kunit-example-test.c
+++ b/lib/kunit/kunit-example-test.c
@@ -41,6 +41,17 @@ static int example_test_init(struct kunit *test)
}
/*
+ * This is run once before all test cases in the suite.
+ * See the comment on example_test_suite for more information.
+ */
+static int example_test_init_suite(struct kunit_suite *suite)
+{
+ kunit_info(suite, "initializing suite\n");
+
+ return 0;
+}
+
+/*
* This test should always be skipped.
*/
static void example_skip_test(struct kunit *test)
@@ -69,6 +80,49 @@ static void example_mark_skipped_test(struct kunit *test)
/* This line should run */
kunit_info(test, "You should see this line.");
}
+
+/*
+ * This test shows off all the types of KUNIT_EXPECT macros.
+ */
+static void example_all_expect_macros_test(struct kunit *test)
+{
+ /* Boolean assertions */
+ KUNIT_EXPECT_TRUE(test, true);
+ KUNIT_EXPECT_FALSE(test, false);
+
+ /* Integer assertions */
+ KUNIT_EXPECT_EQ(test, 1, 1); /* check == */
+ KUNIT_EXPECT_GE(test, 1, 1); /* check >= */
+ KUNIT_EXPECT_LE(test, 1, 1); /* check <= */
+ KUNIT_EXPECT_NE(test, 1, 0); /* check != */
+ KUNIT_EXPECT_GT(test, 1, 0); /* check > */
+ KUNIT_EXPECT_LT(test, 0, 1); /* check < */
+
+ /* Pointer assertions */
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, test);
+ KUNIT_EXPECT_PTR_EQ(test, NULL, NULL);
+ KUNIT_EXPECT_PTR_NE(test, test, NULL);
+ KUNIT_EXPECT_NULL(test, NULL);
+ KUNIT_EXPECT_NOT_NULL(test, test);
+
+ /* String assertions */
+ KUNIT_EXPECT_STREQ(test, "hi", "hi");
+ KUNIT_EXPECT_STRNEQ(test, "hi", "bye");
+
+ /*
+ * There are also ASSERT variants of all of the above that abort test
+ * execution if they fail. Useful for memory allocations, etc.
+ */
+ KUNIT_ASSERT_GT(test, sizeof(char), 0);
+
+ /*
+ * There are also _MSG variants of all of the above that let you include
+ * additional text on failure.
+ */
+ KUNIT_EXPECT_GT_MSG(test, sizeof(int), 0, "Your ints are 0-bit?!");
+ KUNIT_ASSERT_GT_MSG(test, sizeof(int), 0, "Your ints are 0-bit?!");
+}
+
/*
* Here we make a list of all the test cases we want to add to the test suite
* below.
@@ -83,6 +137,7 @@ static struct kunit_case example_test_cases[] = {
KUNIT_CASE(example_simple_test),
KUNIT_CASE(example_skip_test),
KUNIT_CASE(example_mark_skipped_test),
+ KUNIT_CASE(example_all_expect_macros_test),
{}
};
@@ -98,17 +153,20 @@ static struct kunit_case example_test_cases[] = {
* 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.suite_init(suite);
* suite.init(test);
* suite.test_case[0](test);
* suite.exit(test);
* suite.init(test);
* suite.test_case[1](test);
* suite.exit(test);
+ * suite.suite_exit(suite);
* ...;
*/
static struct kunit_suite example_test_suite = {
.name = "example",
.init = example_test_init,
+ .suite_init = example_test_init_suite,
.test_cases = example_test_cases,
};
diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c
index 555601d17f79..13d0bd8b07a9 100644
--- a/lib/kunit/kunit-test.c
+++ b/lib/kunit/kunit-test.c
@@ -190,6 +190,40 @@ static void kunit_resource_test_destroy_resource(struct kunit *test)
KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
}
+static void kunit_resource_test_remove_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);
+
+ /* The resource is in the list */
+ KUNIT_EXPECT_FALSE(test, list_empty(&ctx->test.resources));
+
+ /* Remove the resource. The pointer is still valid, but it can't be
+ * found.
+ */
+ kunit_remove_resource(test, res);
+ KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
+ /* We haven't been freed yet. */
+ KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized);
+
+ /* Removing the resource multiple times is valid. */
+ kunit_remove_resource(test, res);
+ KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
+ /* Despite having been removed twice (from only one reference), the
+ * resource still has not been freed.
+ */
+ KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized);
+
+ /* Free the resource. */
+ kunit_put_resource(res);
+ KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
+}
+
static void kunit_resource_test_cleanup_resources(struct kunit *test)
{
int i;
@@ -387,6 +421,7 @@ 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_remove_resource),
KUNIT_CASE(kunit_resource_test_cleanup_resources),
KUNIT_CASE(kunit_resource_test_proper_free_ordering),
KUNIT_CASE(kunit_resource_test_static),
@@ -435,7 +470,7 @@ static void kunit_log_test(struct kunit *test)
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
strstr(suite.log, "along with this."));
#else
- KUNIT_EXPECT_PTR_EQ(test, test->log, (char *)NULL);
+ KUNIT_EXPECT_NULL(test, test->log);
#endif
}
diff --git a/lib/kunit/resource.c b/lib/kunit/resource.c
new file mode 100644
index 000000000000..c414df922f34
--- /dev/null
+++ b/lib/kunit/resource.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit resource API for test managed resources (allocations, etc.).
+ *
+ * Copyright (C) 2022, Google LLC.
+ * Author: Daniel Latypov <dlatypov@google.com>
+ */
+
+#include <kunit/resource.h>
+#include <kunit/test.h>
+#include <linux/kref.h>
+
+/*
+ * Used for static resources and when a kunit_resource * has been created by
+ * kunit_alloc_resource(). When an init function is supplied, @data is passed
+ * into the init function; otherwise, we simply set the resource data field to
+ * the data value passed in. Doesn't initialize res->should_kfree.
+ */
+int __kunit_add_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ struct kunit_resource *res,
+ void *data)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ res->free = free;
+ kref_init(&res->refcount);
+
+ if (init) {
+ ret = init(res, data);
+ if (ret)
+ return ret;
+ } else {
+ res->data = data;
+ }
+
+ spin_lock_irqsave(&test->lock, flags);
+ list_add_tail(&res->node, &test->resources);
+ /* refcount for list is established by kref_init() */
+ spin_unlock_irqrestore(&test->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__kunit_add_resource);
+
+void kunit_remove_resource(struct kunit *test, struct kunit_resource *res)
+{
+ unsigned long flags;
+ bool was_linked;
+
+ spin_lock_irqsave(&test->lock, flags);
+ was_linked = !list_empty(&res->node);
+ list_del_init(&res->node);
+ spin_unlock_irqrestore(&test->lock, flags);
+
+ if (was_linked)
+ kunit_put_resource(res);
+}
+EXPORT_SYMBOL_GPL(kunit_remove_resource);
+
+int kunit_destroy_resource(struct kunit *test, kunit_resource_match_t match,
+ void *match_data)
+{
+ struct kunit_resource *res = kunit_find_resource(test, match,
+ match_data);
+
+ if (!res)
+ return -ENOENT;
+
+ kunit_remove_resource(test, res);
+
+ /* We have a reference also via _find(); drop it. */
+ kunit_put_resource(res);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kunit_destroy_resource);
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index c7ed4aabec04..a5053a07409f 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -6,10 +6,10 @@
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
+#include <kunit/resource.h>
#include <kunit/test.h>
#include <kunit/test-bug.h>
#include <linux/kernel.h>
-#include <linux/kref.h>
#include <linux/moduleparam.h>
#include <linux/sched/debug.h>
#include <linux/sched.h>
@@ -134,7 +134,7 @@ size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
}
EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
-static void kunit_print_subtest_start(struct kunit_suite *suite)
+static void kunit_print_suite_start(struct kunit_suite *suite)
{
kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
suite->name);
@@ -179,6 +179,9 @@ enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)
const struct kunit_case *test_case;
enum kunit_status status = KUNIT_SKIPPED;
+ if (suite->suite_init_err)
+ return KUNIT_FAILURE;
+
kunit_suite_for_each_test_case(suite, test_case) {
if (test_case->status == KUNIT_FAILURE)
return KUNIT_FAILURE;
@@ -192,7 +195,7 @@ EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
static size_t kunit_suite_counter = 1;
-static void kunit_print_subtest_end(struct kunit_suite *suite)
+static void kunit_print_suite_end(struct kunit_suite *suite)
{
kunit_print_ok_not_ok((void *)suite, false,
kunit_suite_has_succeeded(suite),
@@ -240,7 +243,9 @@ static void kunit_print_string_stream(struct kunit *test,
}
}
-static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
+static void kunit_fail(struct kunit *test, const struct kunit_loc *loc,
+ enum kunit_assert_type type, const struct kunit_assert *assert,
+ const struct va_format *message)
{
struct string_stream *stream;
@@ -250,12 +255,13 @@ static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
if (!stream) {
WARN(true,
"Could not allocate stream to print failed assertion in %s:%d\n",
- assert->file,
- assert->line);
+ loc->file,
+ loc->line);
return;
}
- assert->format(assert, stream);
+ kunit_assert_prologue(loc, type, stream);
+ assert->format(assert, message, stream);
kunit_print_string_stream(test, stream);
@@ -275,29 +281,27 @@ static void __noreturn kunit_abort(struct kunit *test)
WARN_ONCE(true, "Throw could not abort from test!\n");
}
-void kunit_do_assertion(struct kunit *test,
- struct kunit_assert *assert,
- bool pass,
- const char *fmt, ...)
+void kunit_do_failed_assertion(struct kunit *test,
+ const struct kunit_loc *loc,
+ enum kunit_assert_type type,
+ const struct kunit_assert *assert,
+ const char *fmt, ...)
{
va_list args;
-
- if (pass)
- return;
-
+ struct va_format message;
va_start(args, fmt);
- assert->message.fmt = fmt;
- assert->message.va = &args;
+ message.fmt = fmt;
+ message.va = &args;
- kunit_fail(test, assert);
+ kunit_fail(test, loc, type, assert, &message);
va_end(args);
- if (assert->type == KUNIT_ASSERTION)
+ if (type == KUNIT_ASSERTION)
kunit_abort(test);
}
-EXPORT_SYMBOL_GPL(kunit_do_assertion);
+EXPORT_SYMBOL_GPL(kunit_do_failed_assertion);
void kunit_init_test(struct kunit *test, const char *name, char *log)
{
@@ -497,7 +501,16 @@ int kunit_run_tests(struct kunit_suite *suite)
struct kunit_result_stats suite_stats = { 0 };
struct kunit_result_stats total_stats = { 0 };
- kunit_print_subtest_start(suite);
+ if (suite->suite_init) {
+ suite->suite_init_err = suite->suite_init(suite);
+ if (suite->suite_init_err) {
+ kunit_err(suite, KUNIT_SUBTEST_INDENT
+ "# failed to initialize (%d)", suite->suite_init_err);
+ goto suite_end;
+ }
+ }
+
+ kunit_print_suite_start(suite);
kunit_suite_for_each_test_case(suite, test_case) {
struct kunit test = { .param_value = NULL, .param_index = 0 };
@@ -550,8 +563,12 @@ int kunit_run_tests(struct kunit_suite *suite)
kunit_accumulate_stats(&total_stats, param_stats);
}
+ if (suite->suite_exit)
+ suite->suite_exit(suite);
+
kunit_print_suite_stats(suite, suite_stats, total_stats);
- kunit_print_subtest_end(suite);
+suite_end:
+ kunit_print_suite_end(suite);
return 0;
}
@@ -561,6 +578,7 @@ static void kunit_init_suite(struct kunit_suite *suite)
{
kunit_debugfs_create_suite(suite);
suite->status_comment[0] = '\0';
+ suite->suite_init_err = 0;
}
int __kunit_test_suites_init(struct kunit_suite * const * const suites)
@@ -591,120 +609,6 @@ void __kunit_test_suites_exit(struct kunit_suite **suites)
}
EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
-/*
- * Used for static resources and when a kunit_resource * has been created by
- * kunit_alloc_resource(). When an init function is supplied, @data is passed
- * into the init function; otherwise, we simply set the resource data field to
- * the data value passed in.
- */
-int kunit_add_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- struct kunit_resource *res,
- void *data)
-{
- int ret = 0;
- unsigned long flags;
-
- res->free = free;
- kref_init(&res->refcount);
-
- if (init) {
- ret = init(res, data);
- if (ret)
- return ret;
- } else {
- res->data = data;
- }
-
- spin_lock_irqsave(&test->lock, flags);
- list_add_tail(&res->node, &test->resources);
- /* refcount for list is established by kref_init() */
- spin_unlock_irqrestore(&test->lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(kunit_add_resource);
-
-int kunit_add_named_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- struct kunit_resource *res,
- const char *name,
- void *data)
-{
- struct kunit_resource *existing;
-
- if (!name)
- return -EINVAL;
-
- existing = kunit_find_named_resource(test, name);
- if (existing) {
- kunit_put_resource(existing);
- return -EEXIST;
- }
-
- res->name = name;
-
- return kunit_add_resource(test, init, free, res, data);
-}
-EXPORT_SYMBOL_GPL(kunit_add_named_resource);
-
-struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- gfp_t internal_gfp,
- void *data)
-{
- struct kunit_resource *res;
- int ret;
-
- res = kzalloc(sizeof(*res), internal_gfp);
- if (!res)
- return NULL;
-
- ret = kunit_add_resource(test, init, free, res, data);
- if (!ret) {
- /*
- * bump refcount for get; kunit_resource_put() should be called
- * when done.
- */
- kunit_get_resource(res);
- return res;
- }
- return NULL;
-}
-EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
-
-void kunit_remove_resource(struct kunit *test, struct kunit_resource *res)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&test->lock, flags);
- list_del(&res->node);
- spin_unlock_irqrestore(&test->lock, flags);
- kunit_put_resource(res);
-}
-EXPORT_SYMBOL_GPL(kunit_remove_resource);
-
-int kunit_destroy_resource(struct kunit *test, kunit_resource_match_t match,
- void *match_data)
-{
- struct kunit_resource *res = kunit_find_resource(test, match,
- match_data);
-
- if (!res)
- return -ENOENT;
-
- kunit_remove_resource(test, res);
-
- /* We have a reference also via _find(); drop it. */
- kunit_put_resource(res);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(kunit_destroy_resource);
-
struct kunit_kmalloc_array_params {
size_t n;
size_t size;
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index be38a2c5ecc2..f7825991d576 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -52,7 +52,7 @@ static unsigned long kunit_test_timeout(void)
* If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
* the task will be killed and an oops generated.
*/
- return 300 * MSEC_PER_SEC; /* 5 min */
+ return 300 * msecs_to_jiffies(MSEC_PER_SEC); /* 5 min */
}
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
@@ -78,6 +78,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
if (time_remaining == 0) {
kunit_err(test, "try timed out\n");
try_catch->try_result = -ETIMEDOUT;
+ kthread_stop(task_struct);
}
exit_code = try_catch->try_result;