Skip to content

Commit c72a870

Browse files
rmr167shuahkh
authored andcommitted
kunit: add ability to run tests after boot using debugfs
Add functionality to run built-in tests after boot by writing to a debugfs file. Add a new debugfs file labeled "run" for each test suite to use for this purpose. As an example, write to the file using the following: echo "any string" > /sys/kernel/debugfs/kunit/<testsuite>/run This will trigger the test suite to run and will print results to the kernel log. To guard against running tests concurrently with this feature, add a mutex lock around running kunit. This supports the current practice of not allowing tests to be run concurrently on the same kernel. This new functionality could be used to design a parameter injection feature in the future. Fixed up merge conflict duing rebase to Linux 6.7-rc6 Signed-off-by: Shuah Khan <[email protected]> Reviewed-by: David Gow <[email protected]> Signed-off-by: Rae Moar <[email protected]> Signed-off-by: Shuah Khan <[email protected]>
1 parent 6c4ea2f commit c72a870

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

lib/kunit/debugfs.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@
88
#include <linux/module.h>
99

1010
#include <kunit/test.h>
11+
#include <kunit/test-bug.h>
1112

1213
#include "string-stream.h"
1314
#include "debugfs.h"
1415

1516
#define KUNIT_DEBUGFS_ROOT "kunit"
1617
#define KUNIT_DEBUGFS_RESULTS "results"
18+
#define KUNIT_DEBUGFS_RUN "run"
1719

1820
/*
1921
* Create a debugfs representation of test suites:
2022
*
2123
* Path Semantics
2224
* /sys/kernel/debug/kunit/<testsuite>/results Show results of last run for
2325
* testsuite
26+
* /sys/kernel/debug/kunit/<testsuite>/run Write to this file to trigger
27+
* testsuite to run
2428
*
2529
*/
2630

@@ -101,18 +105,75 @@ static int debugfs_results_open(struct inode *inode, struct file *file)
101105
return single_open(file, debugfs_print_results, suite);
102106
}
103107

108+
/*
109+
* Print a usage message to the debugfs "run" file
110+
* (/sys/kernel/debug/kunit/<testsuite>/run) if opened.
111+
*/
112+
static int debugfs_print_run(struct seq_file *seq, void *v)
113+
{
114+
struct kunit_suite *suite = (struct kunit_suite *)seq->private;
115+
116+
seq_puts(seq, "Write to this file to trigger the test suite to run.\n");
117+
seq_printf(seq, "usage: echo \"any string\" > /sys/kernel/debugfs/kunit/%s/run\n",
118+
suite->name);
119+
return 0;
120+
}
121+
122+
/*
123+
* The debugfs "run" file (/sys/kernel/debug/kunit/<testsuite>/run)
124+
* contains no information. Write to the file to trigger the test suite
125+
* to run.
126+
*/
127+
static int debugfs_run_open(struct inode *inode, struct file *file)
128+
{
129+
struct kunit_suite *suite;
130+
131+
suite = (struct kunit_suite *)inode->i_private;
132+
133+
return single_open(file, debugfs_print_run, suite);
134+
}
135+
136+
/*
137+
* Trigger a test suite to run by writing to the suite's "run" debugfs
138+
* file found at: /sys/kernel/debug/kunit/<testsuite>/run
139+
*
140+
* Note: what is written to this file will not be saved.
141+
*/
142+
static ssize_t debugfs_run(struct file *file,
143+
const char __user *buf, size_t count, loff_t *ppos)
144+
{
145+
struct inode *f_inode = file->f_inode;
146+
struct kunit_suite *suite = (struct kunit_suite *) f_inode->i_private;
147+
148+
__kunit_test_suites_init(&suite, 1);
149+
150+
return count;
151+
}
152+
104153
static const struct file_operations debugfs_results_fops = {
105154
.open = debugfs_results_open,
106155
.read = seq_read,
107156
.llseek = seq_lseek,
108157
.release = debugfs_release,
109158
};
110159

160+
static const struct file_operations debugfs_run_fops = {
161+
.open = debugfs_run_open,
162+
.read = seq_read,
163+
.write = debugfs_run,
164+
.llseek = seq_lseek,
165+
.release = debugfs_release,
166+
};
167+
111168
void kunit_debugfs_create_suite(struct kunit_suite *suite)
112169
{
113170
struct kunit_case *test_case;
114171
struct string_stream *stream;
115172

173+
/* If suite log already allocated, do not create new debugfs files. */
174+
if (suite->log)
175+
return;
176+
116177
/*
117178
* Allocate logs before creating debugfs representation.
118179
* The suite->log and test_case->log pointer are expected to be NULL
@@ -140,6 +201,13 @@ void kunit_debugfs_create_suite(struct kunit_suite *suite)
140201
debugfs_create_file(KUNIT_DEBUGFS_RESULTS, S_IFREG | 0444,
141202
suite->debugfs,
142203
suite, &debugfs_results_fops);
204+
205+
/* Do not create file to re-run test if test runs on init */
206+
if (!suite->is_init) {
207+
debugfs_create_file(KUNIT_DEBUGFS_RUN, S_IFREG | 0644,
208+
suite->debugfs,
209+
suite, &debugfs_run_fops);
210+
}
143211
return;
144212

145213
err:

lib/kunit/test.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/kernel.h>
1414
#include <linux/module.h>
1515
#include <linux/moduleparam.h>
16+
#include <linux/mutex.h>
1617
#include <linux/panic.h>
1718
#include <linux/sched/debug.h>
1819
#include <linux/sched.h>
@@ -22,6 +23,8 @@
2223
#include "string-stream.h"
2324
#include "try-catch-impl.h"
2425

26+
static DEFINE_MUTEX(kunit_run_lock);
27+
2528
/*
2629
* Hook to fail the current test and print an error message to the log.
2730
*/
@@ -692,6 +695,7 @@ static void kunit_init_suite(struct kunit_suite *suite)
692695
kunit_debugfs_create_suite(suite);
693696
suite->status_comment[0] = '\0';
694697
suite->suite_init_err = 0;
698+
string_stream_clear(suite->log);
695699
}
696700

697701
bool kunit_enabled(void)
@@ -710,6 +714,11 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_
710714

711715
kunit_suite_counter = 1;
712716

717+
/* Use mutex lock to guard against running tests concurrently. */
718+
if (mutex_lock_interruptible(&kunit_run_lock)) {
719+
pr_err("kunit: test interrupted\n");
720+
return -EINTR;
721+
}
713722
static_branch_inc(&kunit_running);
714723

715724
for (i = 0; i < num_suites; i++) {
@@ -718,6 +727,7 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_
718727
}
719728

720729
static_branch_dec(&kunit_running);
730+
mutex_unlock(&kunit_run_lock);
721731
return 0;
722732
}
723733
EXPORT_SYMBOL_GPL(__kunit_test_suites_init);

0 commit comments

Comments
 (0)