]> asedeno.scripts.mit.edu Git - linux.git/blob - lib/kunit/test.c
Merge tag 'acpi-5.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux.git] / lib / kunit / test.c
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>
11 #include <linux/sched/debug.h>
12
13 #include "string-stream.h"
14 #include "try-catch-impl.h"
15
16 static void kunit_set_failure(struct kunit *test)
17 {
18         WRITE_ONCE(test->success, false);
19 }
20
21 static void kunit_print_tap_version(void)
22 {
23         static bool kunit_has_printed_tap_version;
24
25         if (!kunit_has_printed_tap_version) {
26                 pr_info("TAP version 14\n");
27                 kunit_has_printed_tap_version = true;
28         }
29 }
30
31 static 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
42 static void kunit_print_subtest_start(struct kunit_suite *suite)
43 {
44         kunit_print_tap_version();
45         pr_info("\t# Subtest: %s\n", suite->name);
46         pr_info("\t1..%zd\n", kunit_test_cases_len(suite->test_cases));
47 }
48
49 static 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
66         pr_info("%s%s %zd - %s\n", indent, ok_not_ok, test_number, description);
67 }
68
69 static 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
80 static 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
90 static 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
99 static 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) {
110                         kunit_err(test, "%s", fragment->fragment);
111                 }
112                 kunit_err(test, "\n");
113         } else {
114                 kunit_err(test, "%s", buf);
115                 kunit_kfree(test, buf);
116         }
117 }
118
119 static 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
141 static 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
154 void 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);
172
173         if (assert->type == KUNIT_ASSERTION)
174                 kunit_abort(test);
175 }
176 EXPORT_SYMBOL_GPL(kunit_do_assertion);
177
178 void kunit_init_test(struct kunit *test, const char *name)
179 {
180         spin_lock_init(&test->lock);
181         INIT_LIST_HEAD(&test->resources);
182         test->name = name;
183         test->success = true;
184 }
185 EXPORT_SYMBOL_GPL(kunit_init_test);
186
187 /*
188  * Initializes and runs test case. Does not clean up or do post validations.
189  */
190 static void kunit_run_case_internal(struct kunit *test,
191                                     struct kunit_suite *suite,
192                                     struct kunit_case *test_case)
193 {
194         if (suite->init) {
195                 int ret;
196
197                 ret = suite->init(test);
198                 if (ret) {
199                         kunit_err(test, "failed to initialize: %d\n", ret);
200                         kunit_set_failure(test);
201                         return;
202                 }
203         }
204
205         test_case->run_case(test);
206 }
207
208 static void kunit_case_internal_cleanup(struct kunit *test)
209 {
210         kunit_cleanup(test);
211 }
212
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  */
217 static void kunit_run_case_cleanup(struct kunit *test,
218                                    struct kunit_suite *suite)
219 {
220         if (suite->exit)
221                 suite->exit(test);
222
223         kunit_case_internal_cleanup(test);
224 }
225
226 struct kunit_try_catch_context {
227         struct kunit *test;
228         struct kunit_suite *suite;
229         struct kunit_case *test_case;
230 };
231
232 static 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
249 static 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  */
286 static 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;
295
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);
304
305         test_case->success = test.success;
306 }
307
308 int 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++) {
316                 kunit_run_case_catch_errors(suite, test_case);
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 }
324 EXPORT_SYMBOL_GPL(kunit_run_tests);
325
326 struct 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 }
350 EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
351
352 static void kunit_resource_free(struct kunit *test, struct kunit_resource *res)
353 {
354         res->free(res);
355         kfree(res);
356 }
357
358 static 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
377 static 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
394 int 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 }
409 EXPORT_SYMBOL_GPL(kunit_resource_destroy);
410
411 struct kunit_kmalloc_params {
412         size_t size;
413         gfp_t gfp;
414 };
415
416 static 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
427 static void kunit_kmalloc_free(struct kunit_resource *res)
428 {
429         kfree(res->allocation);
430 }
431
432 void *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 }
445 EXPORT_SYMBOL_GPL(kunit_kmalloc);
446
447 void 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 }
458 EXPORT_SYMBOL_GPL(kunit_kfree);
459
460 void 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 }
488 EXPORT_SYMBOL_GPL(kunit_cleanup);
489
490 static int __init kunit_init(void)
491 {
492         return 0;
493 }
494 late_initcall(kunit_init);
495
496 static void __exit kunit_exit(void)
497 {
498 }
499 module_exit(kunit_exit);
500
501 MODULE_LICENSE("GPL v2");