mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
linux_kselftest-kunit-6.10-rc1
This kunit update for Linux 6.10-rc1 consists of: - fix to race condition in try-catch completion - change to __kunit_test_suites_init() to exit early if there is nothing to test - change to string-stream-test to use KUNIT_DEFINE_ACTION_WRAPPER - moving fault tests behind KUNIT_FAULT_TEST Kconfig option - kthread test fixes and improvements - iov_iter test fixes -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAmZCNsAACgkQCwJExA0N Qxx03w/9EmjF3T16LPaeuerdoypWDcroDT6gpoFXGrvf3lDrna8uDNija5Pb1yMn l97wla3IJ1EZRMTy1jgWGQiiGIdkV8hcze65HZMi19qx/49TUbhA/pTmpYC56cp9 sk2fBjOHz8iI4kdL4eCMr9MpSiwOIDcfWOr1Lh/AP2LHOU1pRdFZbwO6iZ3wyGlJ JH4D1CwmfgMGEau4qUo0jvuRbFAf33S+yEI9gr8CskPItljFVO4jVz4lprnTbU9i qAOivHzwcHyYc0upb6q2vIlp8vhmDygG/m07lnwfF7ZHsYo+3zV4FkxHspN2+jGA frH7Y0X9zt6YjRRMb9NcNnI67VTiSNzdCvB7urUhKlbXoZ2gjtgB7zHeQtAhlXRo XVa4QgWBI5ExKBuLI+0yKo4wEO8M0quXxhbX+2Q+tsRnoYmhwb0G8AUyl/26bt2g RelGrArDS5eMrlxl97rjMGFrB5Uan2MR751tl+aZPgyNRW3tRKJnQLZmM1z8aFQp vGReT6POzCnQ1wLUkcj6mnObbv9XuuYY1BQgKCtmJflvRToEuwpLOKK8Uca7ou3p TbVarGIn0jdHv4zGkXrAkt/mhcxanBXhVKLfh/MqQ7fCZBULkSrjJFLhCpvvHwIV nckaP2sZWls6FTDuawFOUxrr/+LjJchMmHhFy9MiDaVoieiTg6U= =3QIa -----END PGP SIGNATURE----- Merge tag 'linux_kselftest-kunit-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest Pull kunit updates from Shuah Khan: - fix race condition in try-catch completion - change __kunit_test_suites_init() to exit early if there is nothing to test - change string-stream-test to use KUNIT_DEFINE_ACTION_WRAPPER - move fault tests behind KUNIT_FAULT_TEST Kconfig option - kthread test fixes and improvements - iov_iter test fixes * tag 'linux_kselftest-kunit-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: kunit: bail out early in __kunit_test_suites_init() if there are no suites to test kunit: string-stream-test: use KUNIT_DEFINE_ACTION_WRAPPER kunit: test: Move fault tests behind KUNIT_FAULT_TEST Kconfig option kunit: unregister the device on error kunit: Fix race condition in try-catch completion kunit: Add tests for fault kunit: Print last test location on fault kunit: Fix KUNIT_SUCCESS() calls in iov_iter tests kunit: Handle test faults kunit: Fix timeout message kunit: Fix kthread reference kunit: Handle thread creation error
This commit is contained in:
commit
896d3fce84
@ -301,6 +301,8 @@ struct kunit {
|
||||
struct list_head resources; /* Protected by lock. */
|
||||
|
||||
char status_comment[KUNIT_STATUS_COMMENT_SIZE];
|
||||
/* Saves the last seen test. Useful to help with faults. */
|
||||
struct kunit_loc last_seen;
|
||||
};
|
||||
|
||||
static inline void kunit_set_failure(struct kunit *test)
|
||||
@ -567,6 +569,15 @@ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt,
|
||||
#define kunit_err(test, fmt, ...) \
|
||||
kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Must be called at the beginning of each KUNIT_*_ASSERTION().
|
||||
* Cf. KUNIT_CURRENT_LOC.
|
||||
*/
|
||||
#define _KUNIT_SAVE_LOC(test) do { \
|
||||
WRITE_ONCE(test->last_seen.file, __FILE__); \
|
||||
WRITE_ONCE(test->last_seen.line, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* KUNIT_SUCCEED() - A no-op expectation. Only exists for code clarity.
|
||||
* @test: The test context object.
|
||||
@ -575,7 +586,7 @@ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt,
|
||||
* words, it does nothing and only exists for code clarity. See
|
||||
* KUNIT_EXPECT_TRUE() for more information.
|
||||
*/
|
||||
#define KUNIT_SUCCEED(test) do {} while (0)
|
||||
#define KUNIT_SUCCEED(test) _KUNIT_SAVE_LOC(test)
|
||||
|
||||
void __noreturn __kunit_abort(struct kunit *test);
|
||||
|
||||
@ -601,14 +612,16 @@ void __printf(6, 7) __kunit_do_failed_assertion(struct kunit *test,
|
||||
} while (0)
|
||||
|
||||
|
||||
#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) \
|
||||
#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) do { \
|
||||
_KUNIT_SAVE_LOC(test); \
|
||||
_KUNIT_FAILED(test, \
|
||||
assert_type, \
|
||||
kunit_fail_assert, \
|
||||
kunit_fail_assert_format, \
|
||||
{}, \
|
||||
fmt, \
|
||||
##__VA_ARGS__)
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* KUNIT_FAIL() - Always causes a test to fail when evaluated.
|
||||
@ -637,6 +650,7 @@ void __printf(6, 7) __kunit_do_failed_assertion(struct kunit *test,
|
||||
fmt, \
|
||||
...) \
|
||||
do { \
|
||||
_KUNIT_SAVE_LOC(test); \
|
||||
if (likely(!!(condition_) == !!expected_true_)) \
|
||||
break; \
|
||||
\
|
||||
@ -698,6 +712,7 @@ do { \
|
||||
.right_text = #right, \
|
||||
}; \
|
||||
\
|
||||
_KUNIT_SAVE_LOC(test); \
|
||||
if (likely(__left op __right)) \
|
||||
break; \
|
||||
\
|
||||
@ -758,6 +773,7 @@ do { \
|
||||
.right_text = #right, \
|
||||
}; \
|
||||
\
|
||||
_KUNIT_SAVE_LOC(test); \
|
||||
if (likely((__left) && (__right) && (strcmp(__left, __right) op 0))) \
|
||||
break; \
|
||||
\
|
||||
@ -791,6 +807,7 @@ do { \
|
||||
.right_text = #right, \
|
||||
}; \
|
||||
\
|
||||
_KUNIT_SAVE_LOC(test); \
|
||||
if (likely(__left && __right)) \
|
||||
if (likely(memcmp(__left, __right, __size) op 0)) \
|
||||
break; \
|
||||
@ -815,6 +832,7 @@ do { \
|
||||
do { \
|
||||
const typeof(ptr) __ptr = (ptr); \
|
||||
\
|
||||
_KUNIT_SAVE_LOC(test); \
|
||||
if (!IS_ERR_OR_NULL(__ptr)) \
|
||||
break; \
|
||||
\
|
||||
|
@ -14,13 +14,11 @@
|
||||
|
||||
typedef void (*kunit_try_catch_func_t)(void *);
|
||||
|
||||
struct completion;
|
||||
struct kunit;
|
||||
|
||||
/**
|
||||
* struct kunit_try_catch - provides a generic way to run code which might fail.
|
||||
* @test: The test case that is currently being executed.
|
||||
* @try_completion: Completion that the control thread waits on while test runs.
|
||||
* @try_result: Contains any errno obtained while running test case.
|
||||
* @try: The function, the test case, to attempt to run.
|
||||
* @catch: The function called if @try bails out.
|
||||
@ -46,7 +44,6 @@ struct kunit;
|
||||
struct kunit_try_catch {
|
||||
/* private: internal use only. */
|
||||
struct kunit *test;
|
||||
struct completion *try_completion;
|
||||
int try_result;
|
||||
kunit_try_catch_func_t try;
|
||||
kunit_try_catch_func_t catch;
|
||||
|
@ -315,6 +315,7 @@ void __noreturn kthread_exit(long result)
|
||||
kthread->result = result;
|
||||
do_exit(0);
|
||||
}
|
||||
EXPORT_SYMBOL(kthread_exit);
|
||||
|
||||
/**
|
||||
* kthread_complete_and_exit - Exit the current kthread.
|
||||
|
@ -24,6 +24,17 @@ config KUNIT_DEBUGFS
|
||||
test suite, which allow users to see results of the last test suite
|
||||
run that occurred.
|
||||
|
||||
config KUNIT_FAULT_TEST
|
||||
bool "Enable KUnit tests which print BUG stacktraces"
|
||||
depends on KUNIT_TEST
|
||||
depends on !UML
|
||||
default y
|
||||
help
|
||||
Enables fault handling tests for the KUnit framework. These tests may
|
||||
trigger a kernel BUG(), and the associated stack trace, even when they
|
||||
pass. If this conflicts with your test infrastrcture (or is confusing
|
||||
or annoying), they can be disabled by setting this to N.
|
||||
|
||||
config KUNIT_TEST
|
||||
tristate "KUnit test for KUnit" if !KUNIT_ALL_TESTS
|
||||
default KUNIT_ALL_TESTS
|
||||
|
@ -51,7 +51,7 @@ int kunit_bus_init(void)
|
||||
|
||||
error = bus_register(&kunit_bus_type);
|
||||
if (error)
|
||||
bus_unregister(&kunit_bus_type);
|
||||
root_device_unregister(kunit_bus_device);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,48 @@ static struct kunit_suite kunit_try_catch_test_suite = {
|
||||
.test_cases = kunit_try_catch_test_cases,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_KUNIT_FAULT_TEST)
|
||||
|
||||
static void kunit_test_null_dereference(void *data)
|
||||
{
|
||||
struct kunit *test = data;
|
||||
int *null = NULL;
|
||||
|
||||
*null = 0;
|
||||
|
||||
KUNIT_FAIL(test, "This line should never be reached\n");
|
||||
}
|
||||
|
||||
static void kunit_test_fault_null_dereference(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_null_dereference,
|
||||
kunit_test_catch);
|
||||
kunit_try_catch_run(try_catch, test);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, try_catch->try_result, -EINTR);
|
||||
KUNIT_EXPECT_TRUE(test, ctx->function_called);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KUNIT_FAULT_TEST */
|
||||
|
||||
static struct kunit_case kunit_fault_test_cases[] = {
|
||||
#if IS_ENABLED(CONFIG_KUNIT_FAULT_TEST)
|
||||
KUNIT_CASE(kunit_test_fault_null_dereference),
|
||||
#endif /* CONFIG_KUNIT_FAULT_TEST */
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite kunit_fault_test_suite = {
|
||||
.name = "kunit_fault",
|
||||
.init = kunit_try_catch_test_init,
|
||||
.test_cases = kunit_fault_test_cases,
|
||||
};
|
||||
|
||||
/*
|
||||
* Context for testing test managed resources
|
||||
* is_resource_initialized is used to test arbitrary resources
|
||||
@ -826,6 +868,7 @@ static struct kunit_suite kunit_current_test_suite = {
|
||||
|
||||
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
|
||||
&kunit_log_test_suite, &kunit_status_test_suite,
|
||||
&kunit_current_test_suite, &kunit_device_test_suite);
|
||||
&kunit_current_test_suite, &kunit_device_test_suite,
|
||||
&kunit_fault_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -22,18 +22,10 @@ struct string_stream_test_priv {
|
||||
};
|
||||
|
||||
/* Avoids a cast warning if kfree() is passed direct to kunit_add_action(). */
|
||||
static void kfree_wrapper(void *p)
|
||||
{
|
||||
kfree(p);
|
||||
}
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
|
||||
|
||||
/* Avoids a cast warning if string_stream_destroy() is passed direct to kunit_add_action(). */
|
||||
static void cleanup_raw_stream(void *p)
|
||||
{
|
||||
struct string_stream *stream = p;
|
||||
|
||||
string_stream_destroy(stream);
|
||||
}
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(cleanup_raw_stream, string_stream_destroy, struct string_stream *);
|
||||
|
||||
static char *get_concatenated_string(struct kunit *test, struct string_stream *stream)
|
||||
{
|
||||
|
@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (num_suites == 0)
|
||||
return 0;
|
||||
|
||||
if (!kunit_enabled() && num_suites > 0) {
|
||||
pr_info("kunit: disabled\n");
|
||||
return 0;
|
||||
|
@ -11,13 +11,14 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched/task.h>
|
||||
|
||||
#include "try-catch-impl.h"
|
||||
|
||||
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
|
||||
{
|
||||
try_catch->try_result = -EFAULT;
|
||||
kthread_complete_and_exit(try_catch->try_completion, -EFAULT);
|
||||
kthread_exit(0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
|
||||
|
||||
@ -25,9 +26,12 @@ static int kunit_generic_run_threadfn_adapter(void *data)
|
||||
{
|
||||
struct kunit_try_catch *try_catch = data;
|
||||
|
||||
try_catch->try_result = -EINTR;
|
||||
try_catch->try(try_catch->context);
|
||||
if (try_catch->try_result == -EINTR)
|
||||
try_catch->try_result = 0;
|
||||
|
||||
kthread_complete_and_exit(try_catch->try_completion, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long kunit_test_timeout(void)
|
||||
@ -57,30 +61,38 @@ static unsigned long kunit_test_timeout(void)
|
||||
|
||||
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(try_completion);
|
||||
struct kunit *test = try_catch->test;
|
||||
struct task_struct *task_struct;
|
||||
struct completion *task_done;
|
||||
int exit_code, time_remaining;
|
||||
|
||||
try_catch->context = context;
|
||||
try_catch->try_completion = &try_completion;
|
||||
try_catch->try_result = 0;
|
||||
task_struct = kthread_run(kunit_generic_run_threadfn_adapter,
|
||||
try_catch,
|
||||
"kunit_try_catch_thread");
|
||||
task_struct = kthread_create(kunit_generic_run_threadfn_adapter,
|
||||
try_catch, "kunit_try_catch_thread");
|
||||
if (IS_ERR(task_struct)) {
|
||||
try_catch->try_result = PTR_ERR(task_struct);
|
||||
try_catch->catch(try_catch->context);
|
||||
return;
|
||||
}
|
||||
get_task_struct(task_struct);
|
||||
/*
|
||||
* As for a vfork(2), task_struct->vfork_done (pointing to the
|
||||
* underlying kthread->exited) can be used to wait for the end of a
|
||||
* kernel thread. It is set to NULL when the thread exits, so we
|
||||
* keep a copy here.
|
||||
*/
|
||||
task_done = task_struct->vfork_done;
|
||||
wake_up_process(task_struct);
|
||||
|
||||
time_remaining = wait_for_completion_timeout(&try_completion,
|
||||
time_remaining = wait_for_completion_timeout(task_done,
|
||||
kunit_test_timeout());
|
||||
if (time_remaining == 0) {
|
||||
kunit_err(test, "try timed out\n");
|
||||
try_catch->try_result = -ETIMEDOUT;
|
||||
kthread_stop(task_struct);
|
||||
}
|
||||
|
||||
put_task_struct(task_struct);
|
||||
exit_code = try_catch->try_result;
|
||||
|
||||
if (!exit_code)
|
||||
@ -88,8 +100,14 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
|
||||
|
||||
if (exit_code == -EFAULT)
|
||||
try_catch->try_result = 0;
|
||||
else if (exit_code == -EINTR)
|
||||
kunit_err(test, "wake_up_process() was never called\n");
|
||||
else if (exit_code == -EINTR) {
|
||||
if (test->last_seen.file)
|
||||
kunit_err(test, "try faulted: last line seen %s:%d\n",
|
||||
test->last_seen.file, test->last_seen.line);
|
||||
else
|
||||
kunit_err(test, "try faulted\n");
|
||||
} else if (exit_code == -ETIMEDOUT)
|
||||
kunit_err(test, "try timed out\n");
|
||||
else if (exit_code)
|
||||
kunit_err(test, "Unknown error: %d\n", exit_code);
|
||||
|
||||
|
@ -139,7 +139,7 @@ static void __init iov_kunit_copy_to_kvec(struct kunit *test)
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -194,7 +194,7 @@ static void __init iov_kunit_copy_from_kvec(struct kunit *test)
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
struct bvec_test_range {
|
||||
@ -302,7 +302,7 @@ static void __init iov_kunit_copy_to_bvec(struct kunit *test)
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -359,7 +359,7 @@ static void __init iov_kunit_copy_from_bvec(struct kunit *test)
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
static void iov_kunit_destroy_xarray(void *data)
|
||||
@ -453,7 +453,7 @@ static void __init iov_kunit_copy_to_xarray(struct kunit *test)
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -516,7 +516,7 @@ static void __init iov_kunit_copy_from_xarray(struct kunit *test)
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -596,7 +596,7 @@ static void __init iov_kunit_extract_pages_kvec(struct kunit *test)
|
||||
stop:
|
||||
KUNIT_EXPECT_EQ(test, size, 0);
|
||||
KUNIT_EXPECT_EQ(test, iter.count, 0);
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -674,7 +674,7 @@ static void __init iov_kunit_extract_pages_bvec(struct kunit *test)
|
||||
stop:
|
||||
KUNIT_EXPECT_EQ(test, size, 0);
|
||||
KUNIT_EXPECT_EQ(test, iter.count, 0);
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -753,7 +753,7 @@ static void __init iov_kunit_extract_pages_xarray(struct kunit *test)
|
||||
}
|
||||
|
||||
stop:
|
||||
KUNIT_SUCCEED();
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
static struct kunit_case __refdata iov_kunit_cases[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user