Skip to content

Commit 896d3fc

Browse files
committed
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
2 parents 4b768bf + 5496b9b commit 896d3fc

File tree

10 files changed

+121
-38
lines changed

10 files changed

+121
-38
lines changed

include/kunit/test.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ struct kunit {
301301
struct list_head resources; /* Protected by lock. */
302302

303303
char status_comment[KUNIT_STATUS_COMMENT_SIZE];
304+
/* Saves the last seen test. Useful to help with faults. */
305+
struct kunit_loc last_seen;
304306
};
305307

306308
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,
567569
#define kunit_err(test, fmt, ...) \
568570
kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
569571

572+
/*
573+
* Must be called at the beginning of each KUNIT_*_ASSERTION().
574+
* Cf. KUNIT_CURRENT_LOC.
575+
*/
576+
#define _KUNIT_SAVE_LOC(test) do { \
577+
WRITE_ONCE(test->last_seen.file, __FILE__); \
578+
WRITE_ONCE(test->last_seen.line, __LINE__); \
579+
} while (0)
580+
570581
/**
571582
* KUNIT_SUCCEED() - A no-op expectation. Only exists for code clarity.
572583
* @test: The test context object.
@@ -575,7 +586,7 @@ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt,
575586
* words, it does nothing and only exists for code clarity. See
576587
* KUNIT_EXPECT_TRUE() for more information.
577588
*/
578-
#define KUNIT_SUCCEED(test) do {} while (0)
589+
#define KUNIT_SUCCEED(test) _KUNIT_SAVE_LOC(test)
579590

580591
void __noreturn __kunit_abort(struct kunit *test);
581592

@@ -601,14 +612,16 @@ void __printf(6, 7) __kunit_do_failed_assertion(struct kunit *test,
601612
} while (0)
602613

603614

604-
#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) \
615+
#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) do { \
616+
_KUNIT_SAVE_LOC(test); \
605617
_KUNIT_FAILED(test, \
606618
assert_type, \
607619
kunit_fail_assert, \
608620
kunit_fail_assert_format, \
609621
{}, \
610622
fmt, \
611-
##__VA_ARGS__)
623+
##__VA_ARGS__); \
624+
} while (0)
612625

613626
/**
614627
* 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,
637650
fmt, \
638651
...) \
639652
do { \
653+
_KUNIT_SAVE_LOC(test); \
640654
if (likely(!!(condition_) == !!expected_true_)) \
641655
break; \
642656
\
@@ -698,6 +712,7 @@ do { \
698712
.right_text = #right, \
699713
}; \
700714
\
715+
_KUNIT_SAVE_LOC(test); \
701716
if (likely(__left op __right)) \
702717
break; \
703718
\
@@ -758,6 +773,7 @@ do { \
758773
.right_text = #right, \
759774
}; \
760775
\
776+
_KUNIT_SAVE_LOC(test); \
761777
if (likely((__left) && (__right) && (strcmp(__left, __right) op 0))) \
762778
break; \
763779
\
@@ -791,6 +807,7 @@ do { \
791807
.right_text = #right, \
792808
}; \
793809
\
810+
_KUNIT_SAVE_LOC(test); \
794811
if (likely(__left && __right)) \
795812
if (likely(memcmp(__left, __right, __size) op 0)) \
796813
break; \
@@ -815,6 +832,7 @@ do { \
815832
do { \
816833
const typeof(ptr) __ptr = (ptr); \
817834
\
835+
_KUNIT_SAVE_LOC(test); \
818836
if (!IS_ERR_OR_NULL(__ptr)) \
819837
break; \
820838
\

include/kunit/try-catch.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@
1414

1515
typedef void (*kunit_try_catch_func_t)(void *);
1616

17-
struct completion;
1817
struct kunit;
1918

2019
/**
2120
* struct kunit_try_catch - provides a generic way to run code which might fail.
2221
* @test: The test case that is currently being executed.
23-
* @try_completion: Completion that the control thread waits on while test runs.
2422
* @try_result: Contains any errno obtained while running test case.
2523
* @try: The function, the test case, to attempt to run.
2624
* @catch: The function called if @try bails out.
@@ -46,7 +44,6 @@ struct kunit;
4644
struct kunit_try_catch {
4745
/* private: internal use only. */
4846
struct kunit *test;
49-
struct completion *try_completion;
5047
int try_result;
5148
kunit_try_catch_func_t try;
5249
kunit_try_catch_func_t catch;

kernel/kthread.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ void __noreturn kthread_exit(long result)
315315
kthread->result = result;
316316
do_exit(0);
317317
}
318+
EXPORT_SYMBOL(kthread_exit);
318319

319320
/**
320321
* kthread_complete_and_exit - Exit the current kthread.

lib/kunit/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ config KUNIT_DEBUGFS
2424
test suite, which allow users to see results of the last test suite
2525
run that occurred.
2626

27+
config KUNIT_FAULT_TEST
28+
bool "Enable KUnit tests which print BUG stacktraces"
29+
depends on KUNIT_TEST
30+
depends on !UML
31+
default y
32+
help
33+
Enables fault handling tests for the KUnit framework. These tests may
34+
trigger a kernel BUG(), and the associated stack trace, even when they
35+
pass. If this conflicts with your test infrastrcture (or is confusing
36+
or annoying), they can be disabled by setting this to N.
37+
2738
config KUNIT_TEST
2839
tristate "KUnit test for KUnit" if !KUNIT_ALL_TESTS
2940
default KUNIT_ALL_TESTS

lib/kunit/device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ int kunit_bus_init(void)
5151

5252
error = bus_register(&kunit_bus_type);
5353
if (error)
54-
bus_unregister(&kunit_bus_type);
54+
root_device_unregister(kunit_bus_device);
5555
return error;
5656
}
5757

lib/kunit/kunit-test.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,48 @@ static struct kunit_suite kunit_try_catch_test_suite = {
109109
.test_cases = kunit_try_catch_test_cases,
110110
};
111111

112+
#if IS_ENABLED(CONFIG_KUNIT_FAULT_TEST)
113+
114+
static void kunit_test_null_dereference(void *data)
115+
{
116+
struct kunit *test = data;
117+
int *null = NULL;
118+
119+
*null = 0;
120+
121+
KUNIT_FAIL(test, "This line should never be reached\n");
122+
}
123+
124+
static void kunit_test_fault_null_dereference(struct kunit *test)
125+
{
126+
struct kunit_try_catch_test_context *ctx = test->priv;
127+
struct kunit_try_catch *try_catch = ctx->try_catch;
128+
129+
kunit_try_catch_init(try_catch,
130+
test,
131+
kunit_test_null_dereference,
132+
kunit_test_catch);
133+
kunit_try_catch_run(try_catch, test);
134+
135+
KUNIT_EXPECT_EQ(test, try_catch->try_result, -EINTR);
136+
KUNIT_EXPECT_TRUE(test, ctx->function_called);
137+
}
138+
139+
#endif /* CONFIG_KUNIT_FAULT_TEST */
140+
141+
static struct kunit_case kunit_fault_test_cases[] = {
142+
#if IS_ENABLED(CONFIG_KUNIT_FAULT_TEST)
143+
KUNIT_CASE(kunit_test_fault_null_dereference),
144+
#endif /* CONFIG_KUNIT_FAULT_TEST */
145+
{}
146+
};
147+
148+
static struct kunit_suite kunit_fault_test_suite = {
149+
.name = "kunit_fault",
150+
.init = kunit_try_catch_test_init,
151+
.test_cases = kunit_fault_test_cases,
152+
};
153+
112154
/*
113155
* Context for testing test managed resources
114156
* is_resource_initialized is used to test arbitrary resources
@@ -826,6 +868,7 @@ static struct kunit_suite kunit_current_test_suite = {
826868

827869
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
828870
&kunit_log_test_suite, &kunit_status_test_suite,
829-
&kunit_current_test_suite, &kunit_device_test_suite);
871+
&kunit_current_test_suite, &kunit_device_test_suite,
872+
&kunit_fault_test_suite);
830873

831874
MODULE_LICENSE("GPL v2");

lib/kunit/string-stream-test.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,10 @@ struct string_stream_test_priv {
2222
};
2323

2424
/* Avoids a cast warning if kfree() is passed direct to kunit_add_action(). */
25-
static void kfree_wrapper(void *p)
26-
{
27-
kfree(p);
28-
}
25+
KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
2926

3027
/* Avoids a cast warning if string_stream_destroy() is passed direct to kunit_add_action(). */
31-
static void cleanup_raw_stream(void *p)
32-
{
33-
struct string_stream *stream = p;
34-
35-
string_stream_destroy(stream);
36-
}
28+
KUNIT_DEFINE_ACTION_WRAPPER(cleanup_raw_stream, string_stream_destroy, struct string_stream *);
3729

3830
static char *get_concatenated_string(struct kunit *test, struct string_stream *stream)
3931
{

lib/kunit/test.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_
712712
{
713713
unsigned int i;
714714

715+
if (num_suites == 0)
716+
return 0;
717+
715718
if (!kunit_enabled() && num_suites > 0) {
716719
pr_info("kunit: disabled\n");
717720
return 0;

lib/kunit/try-catch.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,27 @@
1111
#include <linux/completion.h>
1212
#include <linux/kernel.h>
1313
#include <linux/kthread.h>
14+
#include <linux/sched/task.h>
1415

1516
#include "try-catch-impl.h"
1617

1718
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
1819
{
1920
try_catch->try_result = -EFAULT;
20-
kthread_complete_and_exit(try_catch->try_completion, -EFAULT);
21+
kthread_exit(0);
2122
}
2223
EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
2324

2425
static int kunit_generic_run_threadfn_adapter(void *data)
2526
{
2627
struct kunit_try_catch *try_catch = data;
2728

29+
try_catch->try_result = -EINTR;
2830
try_catch->try(try_catch->context);
31+
if (try_catch->try_result == -EINTR)
32+
try_catch->try_result = 0;
2933

30-
kthread_complete_and_exit(try_catch->try_completion, 0);
34+
return 0;
3135
}
3236

3337
static unsigned long kunit_test_timeout(void)
@@ -57,39 +61,53 @@ static unsigned long kunit_test_timeout(void)
5761

5862
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
5963
{
60-
DECLARE_COMPLETION_ONSTACK(try_completion);
6164
struct kunit *test = try_catch->test;
6265
struct task_struct *task_struct;
66+
struct completion *task_done;
6367
int exit_code, time_remaining;
6468

6569
try_catch->context = context;
66-
try_catch->try_completion = &try_completion;
6770
try_catch->try_result = 0;
68-
task_struct = kthread_run(kunit_generic_run_threadfn_adapter,
69-
try_catch,
70-
"kunit_try_catch_thread");
71+
task_struct = kthread_create(kunit_generic_run_threadfn_adapter,
72+
try_catch, "kunit_try_catch_thread");
7173
if (IS_ERR(task_struct)) {
74+
try_catch->try_result = PTR_ERR(task_struct);
7275
try_catch->catch(try_catch->context);
7376
return;
7477
}
78+
get_task_struct(task_struct);
79+
/*
80+
* As for a vfork(2), task_struct->vfork_done (pointing to the
81+
* underlying kthread->exited) can be used to wait for the end of a
82+
* kernel thread. It is set to NULL when the thread exits, so we
83+
* keep a copy here.
84+
*/
85+
task_done = task_struct->vfork_done;
86+
wake_up_process(task_struct);
7587

76-
time_remaining = wait_for_completion_timeout(&try_completion,
88+
time_remaining = wait_for_completion_timeout(task_done,
7789
kunit_test_timeout());
7890
if (time_remaining == 0) {
79-
kunit_err(test, "try timed out\n");
8091
try_catch->try_result = -ETIMEDOUT;
8192
kthread_stop(task_struct);
8293
}
8394

95+
put_task_struct(task_struct);
8496
exit_code = try_catch->try_result;
8597

8698
if (!exit_code)
8799
return;
88100

89101
if (exit_code == -EFAULT)
90102
try_catch->try_result = 0;
91-
else if (exit_code == -EINTR)
92-
kunit_err(test, "wake_up_process() was never called\n");
103+
else if (exit_code == -EINTR) {
104+
if (test->last_seen.file)
105+
kunit_err(test, "try faulted: last line seen %s:%d\n",
106+
test->last_seen.file, test->last_seen.line);
107+
else
108+
kunit_err(test, "try faulted\n");
109+
} else if (exit_code == -ETIMEDOUT)
110+
kunit_err(test, "try timed out\n");
93111
else if (exit_code)
94112
kunit_err(test, "Unknown error: %d\n", exit_code);
95113

0 commit comments

Comments
 (0)