@@ -15,23 +15,89 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
15
15
#if IS_BUILTIN (CONFIG_KUNIT )
16
16
17
17
static char * filter_glob_param ;
18
+ static char * action_param ;
19
+
18
20
module_param_named (filter_glob , filter_glob_param , charp , 0 );
19
21
MODULE_PARM_DESC (filter_glob ,
20
- "Filter which KUnit test suites run at boot-time, e.g. list*" );
22
+ "Filter which KUnit test suites/tests run at boot-time, e.g. list* or list*.*del_test" );
23
+ module_param_named (action , action_param , charp , 0 );
24
+ MODULE_PARM_DESC (action ,
25
+ "Changes KUnit executor behavior, valid values are:\n"
26
+ "<none>: run the tests like normal\n"
27
+ "'list' to list test names instead of running them.\n" );
28
+
29
+ /* glob_match() needs NULL terminated strings, so we need a copy of filter_glob_param. */
30
+ struct kunit_test_filter {
31
+ char * suite_glob ;
32
+ char * test_glob ;
33
+ };
34
+
35
+ /* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */
36
+ static void kunit_parse_filter_glob (struct kunit_test_filter * parsed ,
37
+ const char * filter_glob )
38
+ {
39
+ const int len = strlen (filter_glob );
40
+ const char * period = strchr (filter_glob , '.' );
41
+
42
+ if (!period ) {
43
+ parsed -> suite_glob = kzalloc (len + 1 , GFP_KERNEL );
44
+ parsed -> test_glob = NULL ;
45
+ strcpy (parsed -> suite_glob , filter_glob );
46
+ return ;
47
+ }
48
+
49
+ parsed -> suite_glob = kzalloc (period - filter_glob + 1 , GFP_KERNEL );
50
+ parsed -> test_glob = kzalloc (len - (period - filter_glob ) + 1 , GFP_KERNEL );
51
+
52
+ strncpy (parsed -> suite_glob , filter_glob , period - filter_glob );
53
+ strncpy (parsed -> test_glob , period + 1 , len - (period - filter_glob ));
54
+ }
55
+
56
+ /* Create a copy of suite with only tests that match test_glob. */
57
+ static struct kunit_suite *
58
+ kunit_filter_tests (struct kunit_suite * const suite , const char * test_glob )
59
+ {
60
+ int n = 0 ;
61
+ struct kunit_case * filtered , * test_case ;
62
+ struct kunit_suite * copy ;
63
+
64
+ kunit_suite_for_each_test_case (suite , test_case ) {
65
+ if (!test_glob || glob_match (test_glob , test_case -> name ))
66
+ ++ n ;
67
+ }
68
+
69
+ if (n == 0 )
70
+ return NULL ;
71
+
72
+ /* Use memcpy to workaround copy->name being const. */
73
+ copy = kmalloc (sizeof (* copy ), GFP_KERNEL );
74
+ memcpy (copy , suite , sizeof (* copy ));
75
+
76
+ filtered = kcalloc (n + 1 , sizeof (* filtered ), GFP_KERNEL );
77
+
78
+ n = 0 ;
79
+ kunit_suite_for_each_test_case (suite , test_case ) {
80
+ if (!test_glob || glob_match (test_glob , test_case -> name ))
81
+ filtered [n ++ ] = * test_case ;
82
+ }
83
+
84
+ copy -> test_cases = filtered ;
85
+ return copy ;
86
+ }
21
87
22
88
static char * kunit_shutdown ;
23
89
core_param (kunit_shutdown , kunit_shutdown , charp , 0644 );
24
90
25
91
static struct kunit_suite * const *
26
92
kunit_filter_subsuite (struct kunit_suite * const * const subsuite ,
27
- const char * filter_glob )
93
+ struct kunit_test_filter * filter )
28
94
{
29
95
int i , n = 0 ;
30
- struct kunit_suite * * filtered ;
96
+ struct kunit_suite * * filtered , * filtered_suite ;
31
97
32
98
n = 0 ;
33
- for (i = 0 ; subsuite [i ] != NULL ; ++ i ) {
34
- if (glob_match (filter_glob , subsuite [i ]-> name ))
99
+ for (i = 0 ; subsuite [i ]; ++ i ) {
100
+ if (glob_match (filter -> suite_glob , subsuite [i ]-> name ))
35
101
++ n ;
36
102
}
37
103
@@ -44,8 +110,11 @@ kunit_filter_subsuite(struct kunit_suite * const * const subsuite,
44
110
45
111
n = 0 ;
46
112
for (i = 0 ; subsuite [i ] != NULL ; ++ i ) {
47
- if (glob_match (filter_glob , subsuite [i ]-> name ))
48
- filtered [n ++ ] = subsuite [i ];
113
+ if (!glob_match (filter -> suite_glob , subsuite [i ]-> name ))
114
+ continue ;
115
+ filtered_suite = kunit_filter_tests (subsuite [i ], filter -> test_glob );
116
+ if (filtered_suite )
117
+ filtered [n ++ ] = filtered_suite ;
49
118
}
50
119
filtered [n ] = NULL ;
51
120
@@ -57,12 +126,32 @@ struct suite_set {
57
126
struct kunit_suite * const * const * end ;
58
127
};
59
128
129
+ static void kunit_free_subsuite (struct kunit_suite * const * subsuite )
130
+ {
131
+ unsigned int i ;
132
+
133
+ for (i = 0 ; subsuite [i ]; i ++ )
134
+ kfree (subsuite [i ]);
135
+
136
+ kfree (subsuite );
137
+ }
138
+
139
+ static void kunit_free_suite_set (struct suite_set suite_set )
140
+ {
141
+ struct kunit_suite * const * const * suites ;
142
+
143
+ for (suites = suite_set .start ; suites < suite_set .end ; suites ++ )
144
+ kunit_free_subsuite (* suites );
145
+ kfree (suite_set .start );
146
+ }
147
+
60
148
static struct suite_set kunit_filter_suites (const struct suite_set * suite_set ,
61
149
const char * filter_glob )
62
150
{
63
151
int i ;
64
152
struct kunit_suite * const * * copy , * const * filtered_subsuite ;
65
153
struct suite_set filtered ;
154
+ struct kunit_test_filter filter ;
66
155
67
156
const size_t max = suite_set -> end - suite_set -> start ;
68
157
@@ -73,12 +162,17 @@ static struct suite_set kunit_filter_suites(const struct suite_set *suite_set,
73
162
return filtered ;
74
163
}
75
164
165
+ kunit_parse_filter_glob (& filter , filter_glob );
166
+
76
167
for (i = 0 ; i < max ; ++ i ) {
77
- filtered_subsuite = kunit_filter_subsuite (suite_set -> start [i ], filter_glob );
168
+ filtered_subsuite = kunit_filter_subsuite (suite_set -> start [i ], & filter );
78
169
if (filtered_subsuite )
79
170
* copy ++ = filtered_subsuite ;
80
171
}
81
172
filtered .end = copy ;
173
+
174
+ kfree (filter .suite_glob );
175
+ kfree (filter .test_glob );
82
176
return filtered ;
83
177
}
84
178
@@ -109,9 +203,35 @@ static void kunit_print_tap_header(struct suite_set *suite_set)
109
203
pr_info ("1..%d\n" , num_of_suites );
110
204
}
111
205
112
- int kunit_run_all_tests (void )
206
+ static void kunit_exec_run_tests (struct suite_set * suite_set )
207
+ {
208
+ struct kunit_suite * const * const * suites ;
209
+
210
+ kunit_print_tap_header (suite_set );
211
+
212
+ for (suites = suite_set -> start ; suites < suite_set -> end ; suites ++ )
213
+ __kunit_test_suites_init (* suites );
214
+ }
215
+
216
+ static void kunit_exec_list_tests (struct suite_set * suite_set )
113
217
{
218
+ unsigned int i ;
114
219
struct kunit_suite * const * const * suites ;
220
+ struct kunit_case * test_case ;
221
+
222
+ /* Hack: print a tap header so kunit.py can find the start of KUnit output. */
223
+ pr_info ("TAP version 14\n" );
224
+
225
+ for (suites = suite_set -> start ; suites < suite_set -> end ; suites ++ )
226
+ for (i = 0 ; (* suites )[i ] != NULL ; i ++ ) {
227
+ kunit_suite_for_each_test_case ((* suites )[i ], test_case ) {
228
+ pr_info ("%s.%s\n" , (* suites )[i ]-> name , test_case -> name );
229
+ }
230
+ }
231
+ }
232
+
233
+ int kunit_run_all_tests (void )
234
+ {
115
235
struct suite_set suite_set = {
116
236
.start = __kunit_suites_start ,
117
237
.end = __kunit_suites_end ,
@@ -120,15 +240,15 @@ int kunit_run_all_tests(void)
120
240
if (filter_glob_param )
121
241
suite_set = kunit_filter_suites (& suite_set , filter_glob_param );
122
242
123
- kunit_print_tap_header (& suite_set );
124
-
125
- for (suites = suite_set .start ; suites < suite_set .end ; suites ++ )
126
- __kunit_test_suites_init (* suites );
243
+ if (!action_param )
244
+ kunit_exec_run_tests (& suite_set );
245
+ else if (strcmp (action_param , "list" ) == 0 )
246
+ kunit_exec_list_tests (& suite_set );
247
+ else
248
+ pr_err ("kunit executor: unknown action '%s'\n" , action_param );
127
249
128
250
if (filter_glob_param ) { /* a copy was made of each array */
129
- for (suites = suite_set .start ; suites < suite_set .end ; suites ++ )
130
- kfree (* suites );
131
- kfree (suite_set .start );
251
+ kunit_free_suite_set (suite_set );
132
252
}
133
253
134
254
kunit_handle_shutdown ();
0 commit comments