]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - lib/kunit/test.c
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-hirsute-kernel.git] / lib / kunit / test.c
CommitLineData
914cc63e
BH
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Base unit test (KUnit) API.
4 *
5 * Copyright (C) 2019, Google LLC.
6 * Author: Brendan Higgins <brendanhiggins@google.com>
7 */
8
9#include <kunit/test.h>
10#include <linux/kernel.h>
5f3e0620 11#include <linux/sched/debug.h>
914cc63e 12
109fb06f 13#include "string-stream.h"
9bbb11c6 14#include "try-catch-impl.h"
109fb06f 15
914cc63e
BH
16static void kunit_set_failure(struct kunit *test)
17{
18 WRITE_ONCE(test->success, false);
19}
20
914cc63e
BH
21static void kunit_print_tap_version(void)
22{
23 static bool kunit_has_printed_tap_version;
24
25 if (!kunit_has_printed_tap_version) {
741a98d0 26 pr_info("TAP version 14\n");
914cc63e
BH
27 kunit_has_printed_tap_version = true;
28 }
29}
30
31static size_t kunit_test_cases_len(struct kunit_case *test_cases)
32{
33 struct kunit_case *test_case;
34 size_t len = 0;
35
36 for (test_case = test_cases; test_case->run_case; test_case++)
37 len++;
38
39 return len;
40}
41
42static void kunit_print_subtest_start(struct kunit_suite *suite)
43{
44 kunit_print_tap_version();
741a98d0
BH
45 pr_info("\t# Subtest: %s\n", suite->name);
46 pr_info("\t1..%zd\n", kunit_test_cases_len(suite->test_cases));
914cc63e
BH
47}
48
49static void kunit_print_ok_not_ok(bool should_indent,
50 bool is_ok,
51 size_t test_number,
52 const char *description)
53{
54 const char *indent, *ok_not_ok;
55
56 if (should_indent)
57 indent = "\t";
58 else
59 indent = "";
60
61 if (is_ok)
62 ok_not_ok = "ok";
63 else
64 ok_not_ok = "not ok";
65
741a98d0 66 pr_info("%s%s %zd - %s\n", indent, ok_not_ok, test_number, description);
914cc63e
BH
67}
68
69static bool kunit_suite_has_succeeded(struct kunit_suite *suite)
70{
71 const struct kunit_case *test_case;
72
73 for (test_case = suite->test_cases; test_case->run_case; test_case++)
74 if (!test_case->success)
75 return false;
76
77 return true;
78}
79
80static void kunit_print_subtest_end(struct kunit_suite *suite)
81{
82 static size_t kunit_suite_counter = 1;
83
84 kunit_print_ok_not_ok(false,
85 kunit_suite_has_succeeded(suite),
86 kunit_suite_counter++,
87 suite->name);
88}
89
90static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case,
91 size_t test_number)
92{
93 kunit_print_ok_not_ok(true,
94 test_case->success,
95 test_number,
96 test_case->name);
97}
98
73cda7bb
BH
99static void kunit_print_string_stream(struct kunit *test,
100 struct string_stream *stream)
101{
102 struct string_stream_fragment *fragment;
103 char *buf;
104
105 buf = string_stream_get_string(stream);
106 if (!buf) {
107 kunit_err(test,
108 "Could not allocate buffer, dumping stream:\n");
109 list_for_each_entry(fragment, &stream->fragments, node) {
741a98d0 110 kunit_err(test, "%s", fragment->fragment);
73cda7bb
BH
111 }
112 kunit_err(test, "\n");
113 } else {
741a98d0 114 kunit_err(test, "%s", buf);
73cda7bb
BH
115 kunit_kfree(test, buf);
116 }
117}
118
119static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
120{
121 struct string_stream *stream;
122
123 kunit_set_failure(test);
124
125 stream = alloc_string_stream(test, GFP_KERNEL);
126 if (!stream) {
127 WARN(true,
128 "Could not allocate stream to print failed assertion in %s:%d\n",
129 assert->file,
130 assert->line);
131 return;
132 }
133
134 assert->format(assert, stream);
135
136 kunit_print_string_stream(test, stream);
137
138 WARN_ON(string_stream_destroy(stream));
139}
140
5f3e0620
BH
141static void __noreturn kunit_abort(struct kunit *test)
142{
143 kunit_try_catch_throw(&test->try_catch); /* Does not return. */
144
145 /*
146 * Throw could not abort from test.
147 *
148 * XXX: we should never reach this line! As kunit_try_catch_throw is
149 * marked __noreturn.
150 */
151 WARN_ONCE(true, "Throw could not abort from test!\n");
152}
153
73cda7bb
BH
154void kunit_do_assertion(struct kunit *test,
155 struct kunit_assert *assert,
156 bool pass,
157 const char *fmt, ...)
158{
159 va_list args;
160
161 if (pass)
162 return;
163
164 va_start(args, fmt);
165
166 assert->message.fmt = fmt;
167 assert->message.va = &args;
168
169 kunit_fail(test, assert);
170
171 va_end(args);
5f3e0620
BH
172
173 if (assert->type == KUNIT_ASSERTION)
174 kunit_abort(test);
73cda7bb 175}
c475c77d 176EXPORT_SYMBOL_GPL(kunit_do_assertion);
73cda7bb 177
914cc63e
BH
178void kunit_init_test(struct kunit *test, const char *name)
179{
0a756853
BH
180 spin_lock_init(&test->lock);
181 INIT_LIST_HEAD(&test->resources);
914cc63e
BH
182 test->name = name;
183 test->success = true;
184}
c475c77d 185EXPORT_SYMBOL_GPL(kunit_init_test);
914cc63e
BH
186
187/*
5f3e0620 188 * Initializes and runs test case. Does not clean up or do post validations.
914cc63e 189 */
5f3e0620
BH
190static void kunit_run_case_internal(struct kunit *test,
191 struct kunit_suite *suite,
192 struct kunit_case *test_case)
914cc63e 193{
914cc63e
BH
194 if (suite->init) {
195 int ret;
196
5f3e0620 197 ret = suite->init(test);
914cc63e 198 if (ret) {
5f3e0620
BH
199 kunit_err(test, "failed to initialize: %d\n", ret);
200 kunit_set_failure(test);
914cc63e
BH
201 return;
202 }
203 }
204
5f3e0620
BH
205 test_case->run_case(test);
206}
207
208static void kunit_case_internal_cleanup(struct kunit *test)
209{
210 kunit_cleanup(test);
211}
914cc63e 212
5f3e0620
BH
213/*
214 * Performs post validations and cleanup after a test case was run.
215 * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!
216 */
217static void kunit_run_case_cleanup(struct kunit *test,
218 struct kunit_suite *suite)
219{
914cc63e 220 if (suite->exit)
5f3e0620
BH
221 suite->exit(test);
222
223 kunit_case_internal_cleanup(test);
224}
225
226struct kunit_try_catch_context {
227 struct kunit *test;
228 struct kunit_suite *suite;
229 struct kunit_case *test_case;
230};
231
232static void kunit_try_run_case(void *data)
233{
234 struct kunit_try_catch_context *ctx = data;
235 struct kunit *test = ctx->test;
236 struct kunit_suite *suite = ctx->suite;
237 struct kunit_case *test_case = ctx->test_case;
238
239 /*
240 * kunit_run_case_internal may encounter a fatal error; if it does,
241 * abort will be called, this thread will exit, and finally the parent
242 * thread will resume control and handle any necessary clean up.
243 */
244 kunit_run_case_internal(test, suite, test_case);
245 /* This line may never be reached. */
246 kunit_run_case_cleanup(test, suite);
247}
248
249static void kunit_catch_run_case(void *data)
250{
251 struct kunit_try_catch_context *ctx = data;
252 struct kunit *test = ctx->test;
253 struct kunit_suite *suite = ctx->suite;
254 int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
255
256 if (try_exit_code) {
257 kunit_set_failure(test);
258 /*
259 * Test case could not finish, we have no idea what state it is
260 * in, so don't do clean up.
261 */
262 if (try_exit_code == -ETIMEDOUT) {
263 kunit_err(test, "test case timed out\n");
264 /*
265 * Unknown internal error occurred preventing test case from
266 * running, so there is nothing to clean up.
267 */
268 } else {
269 kunit_err(test, "internal error occurred preventing test case from running: %d\n",
270 try_exit_code);
271 }
272 return;
273 }
274
275 /*
276 * Test case was run, but aborted. It is the test case's business as to
277 * whether it failed or not, we just need to clean up.
278 */
279 kunit_run_case_cleanup(test, suite);
280}
281
282/*
283 * Performs all logic to run a test case. It also catches most errors that
284 * occur in a test case and reports them as failures.
285 */
286static void kunit_run_case_catch_errors(struct kunit_suite *suite,
287 struct kunit_case *test_case)
288{
289 struct kunit_try_catch_context context;
290 struct kunit_try_catch *try_catch;
291 struct kunit test;
292
293 kunit_init_test(&test, test_case->name);
294 try_catch = &test.try_catch;
914cc63e 295
5f3e0620
BH
296 kunit_try_catch_init(try_catch,
297 &test,
298 kunit_try_run_case,
299 kunit_catch_run_case);
300 context.test = &test;
301 context.suite = suite;
302 context.test_case = test_case;
303 kunit_try_catch_run(try_catch, &context);
0a756853 304
914cc63e
BH
305 test_case->success = test.success;
306}
307
308int kunit_run_tests(struct kunit_suite *suite)
309{
310 struct kunit_case *test_case;
311 size_t test_case_count = 1;
312
313 kunit_print_subtest_start(suite);
314
315 for (test_case = suite->test_cases; test_case->run_case; test_case++) {
5f3e0620 316 kunit_run_case_catch_errors(suite, test_case);
914cc63e
BH
317 kunit_print_test_case_ok_not_ok(test_case, test_case_count++);
318 }
319
320 kunit_print_subtest_end(suite);
321
322 return 0;
323}
c475c77d 324EXPORT_SYMBOL_GPL(kunit_run_tests);
914cc63e 325
0a756853
BH
326struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
327 kunit_resource_init_t init,
328 kunit_resource_free_t free,
329 gfp_t internal_gfp,
330 void *context)
331{
332 struct kunit_resource *res;
333 int ret;
334
335 res = kzalloc(sizeof(*res), internal_gfp);
336 if (!res)
337 return NULL;
338
339 ret = init(res, context);
340 if (ret)
341 return NULL;
342
343 res->free = free;
344 spin_lock(&test->lock);
345 list_add_tail(&res->node, &test->resources);
346 spin_unlock(&test->lock);
347
348 return res;
349}
c475c77d 350EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
0a756853
BH
351
352static void kunit_resource_free(struct kunit *test, struct kunit_resource *res)
353{
354 res->free(res);
355 kfree(res);
356}
357
358static struct kunit_resource *kunit_resource_find(struct kunit *test,
359 kunit_resource_match_t match,
360 kunit_resource_free_t free,
361 void *match_data)
362{
363 struct kunit_resource *resource;
364
365 lockdep_assert_held(&test->lock);
366
367 list_for_each_entry_reverse(resource, &test->resources, node) {
368 if (resource->free != free)
369 continue;
370 if (match(test, resource->allocation, match_data))
371 return resource;
372 }
373
374 return NULL;
375}
376
377static struct kunit_resource *kunit_resource_remove(
378 struct kunit *test,
379 kunit_resource_match_t match,
380 kunit_resource_free_t free,
381 void *match_data)
382{
383 struct kunit_resource *resource;
384
385 spin_lock(&test->lock);
386 resource = kunit_resource_find(test, match, free, match_data);
387 if (resource)
388 list_del(&resource->node);
389 spin_unlock(&test->lock);
390
391 return resource;
392}
393
394int kunit_resource_destroy(struct kunit *test,
395 kunit_resource_match_t match,
396 kunit_resource_free_t free,
397 void *match_data)
398{
399 struct kunit_resource *resource;
400
401 resource = kunit_resource_remove(test, match, free, match_data);
402
403 if (!resource)
404 return -ENOENT;
405
406 kunit_resource_free(test, resource);
407 return 0;
408}
c475c77d 409EXPORT_SYMBOL_GPL(kunit_resource_destroy);
0a756853
BH
410
411struct kunit_kmalloc_params {
412 size_t size;
413 gfp_t gfp;
414};
415
416static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
417{
418 struct kunit_kmalloc_params *params = context;
419
420 res->allocation = kmalloc(params->size, params->gfp);
421 if (!res->allocation)
422 return -ENOMEM;
423
424 return 0;
425}
426
427static void kunit_kmalloc_free(struct kunit_resource *res)
428{
429 kfree(res->allocation);
430}
431
432void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
433{
434 struct kunit_kmalloc_params params = {
435 .size = size,
436 .gfp = gfp
437 };
438
439 return kunit_alloc_resource(test,
440 kunit_kmalloc_init,
441 kunit_kmalloc_free,
442 gfp,
443 &params);
444}
c475c77d 445EXPORT_SYMBOL_GPL(kunit_kmalloc);
0a756853
BH
446
447void kunit_kfree(struct kunit *test, const void *ptr)
448{
449 int rc;
450
451 rc = kunit_resource_destroy(test,
452 kunit_resource_instance_match,
453 kunit_kmalloc_free,
454 (void *)ptr);
455
456 WARN_ON(rc);
457}
c475c77d 458EXPORT_SYMBOL_GPL(kunit_kfree);
0a756853
BH
459
460void kunit_cleanup(struct kunit *test)
461{
462 struct kunit_resource *resource;
463
464 /*
465 * test->resources is a stack - each allocation must be freed in the
466 * reverse order from which it was added since one resource may depend
467 * on another for its entire lifetime.
468 * Also, we cannot use the normal list_for_each constructs, even the
469 * safe ones because *arbitrary* nodes may be deleted when
470 * kunit_resource_free is called; the list_for_each_safe variants only
471 * protect against the current node being deleted, not the next.
472 */
473 while (true) {
474 spin_lock(&test->lock);
475 if (list_empty(&test->resources)) {
476 spin_unlock(&test->lock);
477 break;
478 }
479 resource = list_last_entry(&test->resources,
480 struct kunit_resource,
481 node);
482 list_del(&resource->node);
483 spin_unlock(&test->lock);
484
485 kunit_resource_free(test, resource);
486 }
487}
c475c77d 488EXPORT_SYMBOL_GPL(kunit_cleanup);
9fe124bf
AM
489
490static int __init kunit_init(void)
491{
492 return 0;
493}
494late_initcall(kunit_init);
495
496static void __exit kunit_exit(void)
497{
498}
499module_exit(kunit_exit);
500
501MODULE_LICENSE("GPL v2");