mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
Merge tag 'linux-kselftest-kunit-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull KUnit updates from Shuah Khan: - kunit_add_action() API to defer a call until test exit - Update document to add kunit_add_action() usage notes - Changes to always run cleanup from a test kthread - Documentation updates to clarify cleanup usage (assertions should not be used in cleanup) - Documentation update to clearly indicate that exit functions should run even if init fails - Several fixes and enhancements to existing tests * tag 'linux-kselftest-kunit-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: MAINTAINERS: Add source tree entry for kunit Documentation: kunit: Rename references to kunit_abort() kunit: Move kunit_abort() call out of kunit_do_failed_assertion() kunit: Fix obsolete name in documentation headers (func->action) Documentation: Kunit: add MODULE_LICENSE to sample code kunit: Update kunit_print_ok_not_ok function kunit: Fix reporting of the skipped parameterized tests kunit/test: Add example test showing parameterized testing Documentation: kunit: Add usage notes for kunit_add_action() kunit: kmalloc_array: Use kunit_add_action() kunit: executor_test: Use kunit_add_action() kunit: Add kunit_add_action() to defer a call until test exit kunit: example: Provide example exit functions Documentation: kunit: Warn that exit functions run even if init fails Documentation: kunit: Note that assertions should not be used in cleanup kunit: Always run cleanup from a test kthread Documentation: kunit: Modular tests should not depend on KUNIT=y kunit: tool: undo type subscripts for subprocess.Popen
This commit is contained in:
@@ -125,11 +125,6 @@ kunit_test_suites(&executor_test_suite);
|
||||
|
||||
/* Test helpers */
|
||||
|
||||
static void kfree_res_free(struct kunit_resource *res)
|
||||
{
|
||||
kfree(res->data);
|
||||
}
|
||||
|
||||
/* Use the resource API to register a call to kfree(to_free).
|
||||
* Since we never actually use the resource, it's safe to use on const data.
|
||||
*/
|
||||
@@ -138,8 +133,10 @@ static void kfree_at_end(struct kunit *test, const void *to_free)
|
||||
/* kfree() handles NULL already, but avoid allocating a no-op cleanup. */
|
||||
if (IS_ERR_OR_NULL(to_free))
|
||||
return;
|
||||
kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL,
|
||||
(void *)to_free);
|
||||
|
||||
kunit_add_action(test,
|
||||
(kunit_action_t *)kfree,
|
||||
(void *)to_free);
|
||||
}
|
||||
|
||||
static struct kunit_suite *alloc_fake_suite(struct kunit *test,
|
||||
|
@@ -41,6 +41,16 @@ static int example_test_init(struct kunit *test)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is run once after each test case, see the comment on
|
||||
* example_test_suite for more information.
|
||||
*/
|
||||
static void example_test_exit(struct kunit *test)
|
||||
{
|
||||
kunit_info(test, "cleaning up\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is run once before all test cases in the suite.
|
||||
* See the comment on example_test_suite for more information.
|
||||
@@ -52,6 +62,16 @@ static int example_test_init_suite(struct kunit_suite *suite)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is run once after all test cases in the suite.
|
||||
* See the comment on example_test_suite for more information.
|
||||
*/
|
||||
static void example_test_exit_suite(struct kunit_suite *suite)
|
||||
{
|
||||
kunit_info(suite, "exiting suite\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This test should always be skipped.
|
||||
*/
|
||||
@@ -167,6 +187,39 @@ static void example_static_stub_test(struct kunit *test)
|
||||
KUNIT_EXPECT_EQ(test, add_one(1), 2);
|
||||
}
|
||||
|
||||
static const struct example_param {
|
||||
int value;
|
||||
} example_params_array[] = {
|
||||
{ .value = 2, },
|
||||
{ .value = 1, },
|
||||
{ .value = 0, },
|
||||
};
|
||||
|
||||
static void example_param_get_desc(const struct example_param *p, char *desc)
|
||||
{
|
||||
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "example value %d", p->value);
|
||||
}
|
||||
|
||||
KUNIT_ARRAY_PARAM(example, example_params_array, example_param_get_desc);
|
||||
|
||||
/*
|
||||
* This test shows the use of params.
|
||||
*/
|
||||
static void example_params_test(struct kunit *test)
|
||||
{
|
||||
const struct example_param *param = test->param_value;
|
||||
|
||||
/* By design, param pointer will not be NULL */
|
||||
KUNIT_ASSERT_NOT_NULL(test, param);
|
||||
|
||||
/* Test can be skipped on unsupported param values */
|
||||
if (!param->value)
|
||||
kunit_skip(test, "unsupported param value");
|
||||
|
||||
/* You can use param values for parameterized testing */
|
||||
KUNIT_EXPECT_EQ(test, param->value % param->value, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we make a list of all the test cases we want to add to the test suite
|
||||
* below.
|
||||
@@ -183,6 +236,7 @@ static struct kunit_case example_test_cases[] = {
|
||||
KUNIT_CASE(example_mark_skipped_test),
|
||||
KUNIT_CASE(example_all_expect_macros_test),
|
||||
KUNIT_CASE(example_static_stub_test),
|
||||
KUNIT_CASE_PARAM(example_params_test, example_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -211,7 +265,9 @@ static struct kunit_case example_test_cases[] = {
|
||||
static struct kunit_suite example_test_suite = {
|
||||
.name = "example",
|
||||
.init = example_test_init,
|
||||
.exit = example_test_exit,
|
||||
.suite_init = example_test_init_suite,
|
||||
.suite_exit = example_test_exit_suite,
|
||||
.test_cases = example_test_cases,
|
||||
};
|
||||
|
||||
|
@@ -112,7 +112,7 @@ struct kunit_test_resource_context {
|
||||
struct kunit test;
|
||||
bool is_resource_initialized;
|
||||
int allocate_order[2];
|
||||
int free_order[2];
|
||||
int free_order[4];
|
||||
};
|
||||
|
||||
static int fake_resource_init(struct kunit_resource *res, void *context)
|
||||
@@ -403,6 +403,88 @@ static void kunit_resource_test_named(struct kunit *test)
|
||||
KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
|
||||
}
|
||||
|
||||
static void increment_int(void *ctx)
|
||||
{
|
||||
int *i = (int *)ctx;
|
||||
(*i)++;
|
||||
}
|
||||
|
||||
static void kunit_resource_test_action(struct kunit *test)
|
||||
{
|
||||
int num_actions = 0;
|
||||
|
||||
kunit_add_action(test, increment_int, &num_actions);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 0);
|
||||
kunit_cleanup(test);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 1);
|
||||
|
||||
/* Once we've cleaned up, the action queue is empty. */
|
||||
kunit_cleanup(test);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 1);
|
||||
|
||||
/* Check the same function can be deferred multiple times. */
|
||||
kunit_add_action(test, increment_int, &num_actions);
|
||||
kunit_add_action(test, increment_int, &num_actions);
|
||||
kunit_cleanup(test);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 3);
|
||||
}
|
||||
static void kunit_resource_test_remove_action(struct kunit *test)
|
||||
{
|
||||
int num_actions = 0;
|
||||
|
||||
kunit_add_action(test, increment_int, &num_actions);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 0);
|
||||
|
||||
kunit_remove_action(test, increment_int, &num_actions);
|
||||
kunit_cleanup(test);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 0);
|
||||
}
|
||||
static void kunit_resource_test_release_action(struct kunit *test)
|
||||
{
|
||||
int num_actions = 0;
|
||||
|
||||
kunit_add_action(test, increment_int, &num_actions);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 0);
|
||||
/* Runs immediately on trigger. */
|
||||
kunit_release_action(test, increment_int, &num_actions);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 1);
|
||||
|
||||
/* Doesn't run again on test exit. */
|
||||
kunit_cleanup(test);
|
||||
KUNIT_EXPECT_EQ(test, num_actions, 1);
|
||||
}
|
||||
static void action_order_1(void *ctx)
|
||||
{
|
||||
struct kunit_test_resource_context *res_ctx = (struct kunit_test_resource_context *)ctx;
|
||||
|
||||
KUNIT_RESOURCE_TEST_MARK_ORDER(res_ctx, free_order, 1);
|
||||
kunit_log(KERN_INFO, current->kunit_test, "action_order_1");
|
||||
}
|
||||
static void action_order_2(void *ctx)
|
||||
{
|
||||
struct kunit_test_resource_context *res_ctx = (struct kunit_test_resource_context *)ctx;
|
||||
|
||||
KUNIT_RESOURCE_TEST_MARK_ORDER(res_ctx, free_order, 2);
|
||||
kunit_log(KERN_INFO, current->kunit_test, "action_order_2");
|
||||
}
|
||||
static void kunit_resource_test_action_ordering(struct kunit *test)
|
||||
{
|
||||
struct kunit_test_resource_context *ctx = test->priv;
|
||||
|
||||
kunit_add_action(test, action_order_1, ctx);
|
||||
kunit_add_action(test, action_order_2, ctx);
|
||||
kunit_add_action(test, action_order_1, ctx);
|
||||
kunit_add_action(test, action_order_2, ctx);
|
||||
kunit_remove_action(test, action_order_1, ctx);
|
||||
kunit_release_action(test, action_order_2, ctx);
|
||||
kunit_cleanup(test);
|
||||
|
||||
/* [2 is triggered] [2], [(1 is cancelled)] [1] */
|
||||
KUNIT_EXPECT_EQ(test, ctx->free_order[0], 2);
|
||||
KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
|
||||
KUNIT_EXPECT_EQ(test, ctx->free_order[2], 1);
|
||||
}
|
||||
|
||||
static int kunit_resource_test_init(struct kunit *test)
|
||||
{
|
||||
struct kunit_test_resource_context *ctx =
|
||||
@@ -434,6 +516,10 @@ static struct kunit_case kunit_resource_test_cases[] = {
|
||||
KUNIT_CASE(kunit_resource_test_proper_free_ordering),
|
||||
KUNIT_CASE(kunit_resource_test_static),
|
||||
KUNIT_CASE(kunit_resource_test_named),
|
||||
KUNIT_CASE(kunit_resource_test_action),
|
||||
KUNIT_CASE(kunit_resource_test_remove_action),
|
||||
KUNIT_CASE(kunit_resource_test_release_action),
|
||||
KUNIT_CASE(kunit_resource_test_action_ordering),
|
||||
{}
|
||||
};
|
||||
|
||||
|
@@ -77,3 +77,102 @@ int kunit_destroy_resource(struct kunit *test, kunit_resource_match_t match,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_destroy_resource);
|
||||
|
||||
struct kunit_action_ctx {
|
||||
struct kunit_resource res;
|
||||
kunit_action_t *func;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
static void __kunit_action_free(struct kunit_resource *res)
|
||||
{
|
||||
struct kunit_action_ctx *action_ctx = container_of(res, struct kunit_action_ctx, res);
|
||||
|
||||
action_ctx->func(action_ctx->ctx);
|
||||
}
|
||||
|
||||
|
||||
int kunit_add_action(struct kunit *test, void (*action)(void *), void *ctx)
|
||||
{
|
||||
struct kunit_action_ctx *action_ctx;
|
||||
|
||||
KUNIT_ASSERT_NOT_NULL_MSG(test, action, "Tried to action a NULL function!");
|
||||
|
||||
action_ctx = kzalloc(sizeof(*action_ctx), GFP_KERNEL);
|
||||
if (!action_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
action_ctx->func = action;
|
||||
action_ctx->ctx = ctx;
|
||||
|
||||
action_ctx->res.should_kfree = true;
|
||||
/* As init is NULL, this cannot fail. */
|
||||
__kunit_add_resource(test, NULL, __kunit_action_free, &action_ctx->res, action_ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_add_action);
|
||||
|
||||
int kunit_add_action_or_reset(struct kunit *test, void (*action)(void *),
|
||||
void *ctx)
|
||||
{
|
||||
int res = kunit_add_action(test, action, ctx);
|
||||
|
||||
if (res)
|
||||
action(ctx);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_add_action_or_reset);
|
||||
|
||||
static bool __kunit_action_match(struct kunit *test,
|
||||
struct kunit_resource *res, void *match_data)
|
||||
{
|
||||
struct kunit_action_ctx *match_ctx = (struct kunit_action_ctx *)match_data;
|
||||
struct kunit_action_ctx *res_ctx = container_of(res, struct kunit_action_ctx, res);
|
||||
|
||||
/* Make sure this is a free function. */
|
||||
if (res->free != __kunit_action_free)
|
||||
return false;
|
||||
|
||||
/* Both the function and context data should match. */
|
||||
return (match_ctx->func == res_ctx->func) && (match_ctx->ctx == res_ctx->ctx);
|
||||
}
|
||||
|
||||
void kunit_remove_action(struct kunit *test,
|
||||
kunit_action_t *action,
|
||||
void *ctx)
|
||||
{
|
||||
struct kunit_action_ctx match_ctx;
|
||||
struct kunit_resource *res;
|
||||
|
||||
match_ctx.func = action;
|
||||
match_ctx.ctx = ctx;
|
||||
|
||||
res = kunit_find_resource(test, __kunit_action_match, &match_ctx);
|
||||
if (res) {
|
||||
/* Remove the free function so we don't run the action. */
|
||||
res->free = NULL;
|
||||
kunit_remove_resource(test, res);
|
||||
kunit_put_resource(res);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_remove_action);
|
||||
|
||||
void kunit_release_action(struct kunit *test,
|
||||
kunit_action_t *action,
|
||||
void *ctx)
|
||||
{
|
||||
struct kunit_action_ctx match_ctx;
|
||||
struct kunit_resource *res;
|
||||
|
||||
match_ctx.func = action;
|
||||
match_ctx.ctx = ctx;
|
||||
|
||||
res = kunit_find_resource(test, __kunit_action_match, &match_ctx);
|
||||
if (res) {
|
||||
kunit_remove_resource(test, res);
|
||||
/* We have to put() this here, else free won't be called. */
|
||||
kunit_put_resource(res);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_release_action);
|
||||
|
161
lib/kunit/test.c
161
lib/kunit/test.c
@@ -185,16 +185,28 @@ static void kunit_print_suite_start(struct kunit_suite *suite)
|
||||
kunit_suite_num_test_cases(suite));
|
||||
}
|
||||
|
||||
static void kunit_print_ok_not_ok(void *test_or_suite,
|
||||
bool is_test,
|
||||
/* Currently supported test levels */
|
||||
enum {
|
||||
KUNIT_LEVEL_SUITE = 0,
|
||||
KUNIT_LEVEL_CASE,
|
||||
KUNIT_LEVEL_CASE_PARAM,
|
||||
};
|
||||
|
||||
static void kunit_print_ok_not_ok(struct kunit *test,
|
||||
unsigned int test_level,
|
||||
enum kunit_status status,
|
||||
size_t test_number,
|
||||
const char *description,
|
||||
const char *directive)
|
||||
{
|
||||
struct kunit_suite *suite = is_test ? NULL : test_or_suite;
|
||||
struct kunit *test = is_test ? test_or_suite : NULL;
|
||||
const char *directive_header = (status == KUNIT_SKIPPED) ? " # SKIP " : "";
|
||||
const char *directive_body = (status == KUNIT_SKIPPED) ? directive : "";
|
||||
|
||||
/*
|
||||
* When test is NULL assume that results are from the suite
|
||||
* and today suite results are expected at level 0 only.
|
||||
*/
|
||||
WARN(!test && test_level, "suite test level can't be %u!\n", test_level);
|
||||
|
||||
/*
|
||||
* We do not log the test suite results as doing so would
|
||||
@@ -203,17 +215,18 @@ static void kunit_print_ok_not_ok(void *test_or_suite,
|
||||
* separately seq_printf() the suite results for the debugfs
|
||||
* representation.
|
||||
*/
|
||||
if (suite)
|
||||
if (!test)
|
||||
pr_info("%s %zd %s%s%s\n",
|
||||
kunit_status_to_ok_not_ok(status),
|
||||
test_number, description, directive_header,
|
||||
(status == KUNIT_SKIPPED) ? directive : "");
|
||||
directive_body);
|
||||
else
|
||||
kunit_log(KERN_INFO, test,
|
||||
KUNIT_SUBTEST_INDENT "%s %zd %s%s%s",
|
||||
"%*s%s %zd %s%s%s",
|
||||
KUNIT_INDENT_LEN * test_level, "",
|
||||
kunit_status_to_ok_not_ok(status),
|
||||
test_number, description, directive_header,
|
||||
(status == KUNIT_SKIPPED) ? directive : "");
|
||||
directive_body);
|
||||
}
|
||||
|
||||
enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)
|
||||
@@ -239,7 +252,7 @@ static size_t kunit_suite_counter = 1;
|
||||
|
||||
static void kunit_print_suite_end(struct kunit_suite *suite)
|
||||
{
|
||||
kunit_print_ok_not_ok((void *)suite, false,
|
||||
kunit_print_ok_not_ok(NULL, KUNIT_LEVEL_SUITE,
|
||||
kunit_suite_has_succeeded(suite),
|
||||
kunit_suite_counter++,
|
||||
suite->name,
|
||||
@@ -310,7 +323,7 @@ static void kunit_fail(struct kunit *test, const struct kunit_loc *loc,
|
||||
string_stream_destroy(stream);
|
||||
}
|
||||
|
||||
static void __noreturn kunit_abort(struct kunit *test)
|
||||
void __noreturn __kunit_abort(struct kunit *test)
|
||||
{
|
||||
kunit_try_catch_throw(&test->try_catch); /* Does not return. */
|
||||
|
||||
@@ -322,8 +335,9 @@ static void __noreturn kunit_abort(struct kunit *test)
|
||||
*/
|
||||
WARN_ONCE(true, "Throw could not abort from test!\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__kunit_abort);
|
||||
|
||||
void kunit_do_failed_assertion(struct kunit *test,
|
||||
void __kunit_do_failed_assertion(struct kunit *test,
|
||||
const struct kunit_loc *loc,
|
||||
enum kunit_assert_type type,
|
||||
const struct kunit_assert *assert,
|
||||
@@ -340,11 +354,8 @@ void kunit_do_failed_assertion(struct kunit *test,
|
||||
kunit_fail(test, loc, type, assert, assert_format, &message);
|
||||
|
||||
va_end(args);
|
||||
|
||||
if (type == KUNIT_ASSERTION)
|
||||
kunit_abort(test);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_do_failed_assertion);
|
||||
EXPORT_SYMBOL_GPL(__kunit_do_failed_assertion);
|
||||
|
||||
void kunit_init_test(struct kunit *test, const char *name, char *log)
|
||||
{
|
||||
@@ -419,15 +430,54 @@ static void kunit_try_run_case(void *data)
|
||||
* thread will resume control and handle any necessary clean up.
|
||||
*/
|
||||
kunit_run_case_internal(test, suite, test_case);
|
||||
/* This line may never be reached. */
|
||||
}
|
||||
|
||||
static void kunit_try_run_case_cleanup(void *data)
|
||||
{
|
||||
struct kunit_try_catch_context *ctx = data;
|
||||
struct kunit *test = ctx->test;
|
||||
struct kunit_suite *suite = ctx->suite;
|
||||
|
||||
current->kunit_test = test;
|
||||
|
||||
kunit_run_case_cleanup(test, suite);
|
||||
}
|
||||
|
||||
static void kunit_catch_run_case_cleanup(void *data)
|
||||
{
|
||||
struct kunit_try_catch_context *ctx = data;
|
||||
struct kunit *test = ctx->test;
|
||||
int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
|
||||
|
||||
/* It is always a failure if cleanup aborts. */
|
||||
kunit_set_failure(test);
|
||||
|
||||
if (try_exit_code) {
|
||||
/*
|
||||
* Test case could not finish, we have no idea what state it is
|
||||
* in, so don't do clean up.
|
||||
*/
|
||||
if (try_exit_code == -ETIMEDOUT) {
|
||||
kunit_err(test, "test case cleanup timed out\n");
|
||||
/*
|
||||
* Unknown internal error occurred preventing test case from
|
||||
* running, so there is nothing to clean up.
|
||||
*/
|
||||
} else {
|
||||
kunit_err(test, "internal error occurred during test case cleanup: %d\n",
|
||||
try_exit_code);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
kunit_err(test, "test aborted during cleanup. continuing without cleaning up\n");
|
||||
}
|
||||
|
||||
|
||||
static void kunit_catch_run_case(void *data)
|
||||
{
|
||||
struct kunit_try_catch_context *ctx = data;
|
||||
struct kunit *test = ctx->test;
|
||||
struct kunit_suite *suite = ctx->suite;
|
||||
int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
|
||||
|
||||
if (try_exit_code) {
|
||||
@@ -448,12 +498,6 @@ static void kunit_catch_run_case(void *data)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test case was run, but aborted. It is the test case's business as to
|
||||
* whether it failed or not, we just need to clean up.
|
||||
*/
|
||||
kunit_run_case_cleanup(test, suite);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -478,6 +522,13 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
|
||||
context.test_case = test_case;
|
||||
kunit_try_catch_run(try_catch, &context);
|
||||
|
||||
/* Now run the cleanup */
|
||||
kunit_try_catch_init(try_catch,
|
||||
test,
|
||||
kunit_try_run_case_cleanup,
|
||||
kunit_catch_run_case_cleanup);
|
||||
kunit_try_catch_run(try_catch, &context);
|
||||
|
||||
/* Propagate the parameter result to the test case. */
|
||||
if (test->status == KUNIT_FAILURE)
|
||||
test_case->status = KUNIT_FAILURE;
|
||||
@@ -585,11 +636,11 @@ int kunit_run_tests(struct kunit_suite *suite)
|
||||
"param-%d", test.param_index);
|
||||
}
|
||||
|
||||
kunit_log(KERN_INFO, &test,
|
||||
KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
|
||||
"%s %d %s",
|
||||
kunit_status_to_ok_not_ok(test.status),
|
||||
test.param_index + 1, param_desc);
|
||||
kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE_PARAM,
|
||||
test.status,
|
||||
test.param_index + 1,
|
||||
param_desc,
|
||||
test.status_comment);
|
||||
|
||||
/* Get next param. */
|
||||
param_desc[0] = '\0';
|
||||
@@ -603,7 +654,7 @@ int kunit_run_tests(struct kunit_suite *suite)
|
||||
|
||||
kunit_print_test_stats(&test, param_stats);
|
||||
|
||||
kunit_print_ok_not_ok(&test, true, test_case->status,
|
||||
kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE, test_case->status,
|
||||
kunit_test_case_num(suite, test_case),
|
||||
test_case->name,
|
||||
test.status_comment);
|
||||
@@ -712,58 +763,28 @@ static struct notifier_block kunit_mod_nb = {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct kunit_kmalloc_array_params {
|
||||
size_t n;
|
||||
size_t size;
|
||||
gfp_t gfp;
|
||||
};
|
||||
|
||||
static int kunit_kmalloc_array_init(struct kunit_resource *res, void *context)
|
||||
{
|
||||
struct kunit_kmalloc_array_params *params = context;
|
||||
|
||||
res->data = kmalloc_array(params->n, params->size, params->gfp);
|
||||
if (!res->data)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kunit_kmalloc_array_free(struct kunit_resource *res)
|
||||
{
|
||||
kfree(res->data);
|
||||
}
|
||||
|
||||
void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)
|
||||
{
|
||||
struct kunit_kmalloc_array_params params = {
|
||||
.size = size,
|
||||
.n = n,
|
||||
.gfp = gfp
|
||||
};
|
||||
void *data;
|
||||
|
||||
return kunit_alloc_resource(test,
|
||||
kunit_kmalloc_array_init,
|
||||
kunit_kmalloc_array_free,
|
||||
gfp,
|
||||
¶ms);
|
||||
data = kmalloc_array(n, size, gfp);
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
if (kunit_add_action_or_reset(test, (kunit_action_t *)kfree, data) != 0)
|
||||
return NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_kmalloc_array);
|
||||
|
||||
static inline bool kunit_kfree_match(struct kunit *test,
|
||||
struct kunit_resource *res, void *match_data)
|
||||
{
|
||||
/* Only match resources allocated with kunit_kmalloc() and friends. */
|
||||
return res->free == kunit_kmalloc_array_free && res->data == match_data;
|
||||
}
|
||||
|
||||
void kunit_kfree(struct kunit *test, const void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
if (kunit_destroy_resource(test, kunit_kfree_match, (void *)ptr))
|
||||
KUNIT_FAIL(test, "kunit_kfree: %px already freed or not allocated by kunit", ptr);
|
||||
kunit_release_action(test, (kunit_action_t *)kfree, (void *)ptr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_kfree);
|
||||
|
||||
|
Reference in New Issue
Block a user