• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <kunit/test-bug.h>
11 #include <linux/kernel.h>
12 #include <linux/kref.h>
13 #include <linux/moduleparam.h>
14 #include <linux/sched/debug.h>
15 #include <linux/sched.h>
16 
17 #include "debugfs.h"
18 #include "string-stream.h"
19 #include "try-catch-impl.h"
20 
21 #if IS_BUILTIN(CONFIG_KUNIT)
22 /*
23  * Fail the current test and print an error message to the log.
24  */
__kunit_fail_current_test(const char * file,int line,const char * fmt,...)25 void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...)
26 {
27 	va_list args;
28 	int len;
29 	char *buffer;
30 
31 	if (!current->kunit_test)
32 		return;
33 
34 	kunit_set_failure(current->kunit_test);
35 
36 	/* kunit_err() only accepts literals, so evaluate the args first. */
37 	va_start(args, fmt);
38 	len = vsnprintf(NULL, 0, fmt, args) + 1;
39 	va_end(args);
40 
41 	buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL);
42 	if (!buffer)
43 		return;
44 
45 	va_start(args, fmt);
46 	vsnprintf(buffer, len, fmt, args);
47 	va_end(args);
48 
49 	kunit_err(current->kunit_test, "%s:%d: %s", file, line, buffer);
50 	kunit_kfree(current->kunit_test, buffer);
51 }
52 EXPORT_SYMBOL_GPL(__kunit_fail_current_test);
53 #endif
54 
55 /*
56  * KUnit statistic mode:
57  * 0 - disabled
58  * 1 - only when there is more than one subtest
59  * 2 - enabled
60  */
61 static int kunit_stats_enabled = 1;
62 module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);
63 MODULE_PARM_DESC(stats_enabled,
64 		  "Print test stats: never (0), only for multiple subtests (1), or always (2)");
65 
66 struct kunit_result_stats {
67 	unsigned long passed;
68 	unsigned long skipped;
69 	unsigned long failed;
70 	unsigned long total;
71 };
72 
kunit_should_print_stats(struct kunit_result_stats stats)73 static bool kunit_should_print_stats(struct kunit_result_stats stats)
74 {
75 	if (kunit_stats_enabled == 0)
76 		return false;
77 
78 	if (kunit_stats_enabled == 2)
79 		return true;
80 
81 	return (stats.total > 1);
82 }
83 
kunit_print_test_stats(struct kunit * test,struct kunit_result_stats stats)84 static void kunit_print_test_stats(struct kunit *test,
85 				   struct kunit_result_stats stats)
86 {
87 	if (!kunit_should_print_stats(stats))
88 		return;
89 
90 	kunit_log(KERN_INFO, test,
91 		  KUNIT_SUBTEST_INDENT
92 		  "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
93 		  test->name,
94 		  stats.passed,
95 		  stats.failed,
96 		  stats.skipped,
97 		  stats.total);
98 }
99 
100 /*
101  * Append formatted message to log, size of which is limited to
102  * KUNIT_LOG_SIZE bytes (including null terminating byte).
103  */
kunit_log_append(char * log,const char * fmt,...)104 void kunit_log_append(char *log, const char *fmt, ...)
105 {
106 	char line[KUNIT_LOG_SIZE];
107 	va_list args;
108 	int len_left;
109 
110 	if (!log)
111 		return;
112 
113 	len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
114 	if (len_left <= 0)
115 		return;
116 
117 	va_start(args, fmt);
118 	vsnprintf(line, sizeof(line), fmt, args);
119 	va_end(args);
120 
121 	strncat(log, line, len_left);
122 }
123 EXPORT_SYMBOL_GPL(kunit_log_append);
124 
kunit_suite_num_test_cases(struct kunit_suite * suite)125 size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
126 {
127 	struct kunit_case *test_case;
128 	size_t len = 0;
129 
130 	kunit_suite_for_each_test_case(suite, test_case)
131 		len++;
132 
133 	return len;
134 }
135 EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
136 
kunit_print_subtest_start(struct kunit_suite * suite)137 static void kunit_print_subtest_start(struct kunit_suite *suite)
138 {
139 	kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
140 		  suite->name);
141 	kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
142 		  kunit_suite_num_test_cases(suite));
143 }
144 
kunit_print_ok_not_ok(void * test_or_suite,bool is_test,enum kunit_status status,size_t test_number,const char * description,const char * directive)145 static void kunit_print_ok_not_ok(void *test_or_suite,
146 				  bool is_test,
147 				  enum kunit_status status,
148 				  size_t test_number,
149 				  const char *description,
150 				  const char *directive)
151 {
152 	struct kunit_suite *suite = is_test ? NULL : test_or_suite;
153 	struct kunit *test = is_test ? test_or_suite : NULL;
154 	const char *directive_header = (status == KUNIT_SKIPPED) ? " # SKIP " : "";
155 
156 	/*
157 	 * We do not log the test suite results as doing so would
158 	 * mean debugfs display would consist of the test suite
159 	 * description and status prior to individual test results.
160 	 * Hence directly printk the suite status, and we will
161 	 * separately seq_printf() the suite status for the debugfs
162 	 * representation.
163 	 */
164 	if (suite)
165 		pr_info("%s %zd - %s%s%s\n",
166 			kunit_status_to_ok_not_ok(status),
167 			test_number, description, directive_header,
168 			(status == KUNIT_SKIPPED) ? directive : "");
169 	else
170 		kunit_log(KERN_INFO, test,
171 			  KUNIT_SUBTEST_INDENT "%s %zd - %s%s%s",
172 			  kunit_status_to_ok_not_ok(status),
173 			  test_number, description, directive_header,
174 			  (status == KUNIT_SKIPPED) ? directive : "");
175 }
176 
kunit_suite_has_succeeded(struct kunit_suite * suite)177 enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)
178 {
179 	const struct kunit_case *test_case;
180 	enum kunit_status status = KUNIT_SKIPPED;
181 
182 	kunit_suite_for_each_test_case(suite, test_case) {
183 		if (test_case->status == KUNIT_FAILURE)
184 			return KUNIT_FAILURE;
185 		else if (test_case->status == KUNIT_SUCCESS)
186 			status = KUNIT_SUCCESS;
187 	}
188 
189 	return status;
190 }
191 EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
192 
kunit_print_subtest_end(struct kunit_suite * suite)193 static void kunit_print_subtest_end(struct kunit_suite *suite)
194 {
195 	static size_t kunit_suite_counter = 1;
196 
197 	kunit_print_ok_not_ok((void *)suite, false,
198 			      kunit_suite_has_succeeded(suite),
199 			      kunit_suite_counter++,
200 			      suite->name,
201 			      suite->status_comment);
202 }
203 
kunit_test_case_num(struct kunit_suite * suite,struct kunit_case * test_case)204 unsigned int kunit_test_case_num(struct kunit_suite *suite,
205 				 struct kunit_case *test_case)
206 {
207 	struct kunit_case *tc;
208 	unsigned int i = 1;
209 
210 	kunit_suite_for_each_test_case(suite, tc) {
211 		if (tc == test_case)
212 			return i;
213 		i++;
214 	}
215 
216 	return 0;
217 }
218 EXPORT_SYMBOL_GPL(kunit_test_case_num);
219 
kunit_print_string_stream(struct kunit * test,struct string_stream * stream)220 static void kunit_print_string_stream(struct kunit *test,
221 				      struct string_stream *stream)
222 {
223 	struct string_stream_fragment *fragment;
224 	char *buf;
225 
226 	if (string_stream_is_empty(stream))
227 		return;
228 
229 	buf = string_stream_get_string(stream);
230 	if (!buf) {
231 		kunit_err(test,
232 			  "Could not allocate buffer, dumping stream:\n");
233 		list_for_each_entry(fragment, &stream->fragments, node) {
234 			kunit_err(test, "%s", fragment->fragment);
235 		}
236 		kunit_err(test, "\n");
237 	} else {
238 		kunit_err(test, "%s", buf);
239 		kunit_kfree(test, buf);
240 	}
241 }
242 
kunit_fail(struct kunit * test,struct kunit_assert * assert)243 static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
244 {
245 	struct string_stream *stream;
246 
247 	kunit_set_failure(test);
248 
249 	stream = alloc_string_stream(test, GFP_KERNEL);
250 	if (!stream) {
251 		WARN(true,
252 		     "Could not allocate stream to print failed assertion in %s:%d\n",
253 		     assert->file,
254 		     assert->line);
255 		return;
256 	}
257 
258 	assert->format(assert, stream);
259 
260 	kunit_print_string_stream(test, stream);
261 
262 	WARN_ON(string_stream_destroy(stream));
263 }
264 
kunit_abort(struct kunit * test)265 static void __noreturn kunit_abort(struct kunit *test)
266 {
267 	kunit_try_catch_throw(&test->try_catch); /* Does not return. */
268 
269 	/*
270 	 * Throw could not abort from test.
271 	 *
272 	 * XXX: we should never reach this line! As kunit_try_catch_throw is
273 	 * marked __noreturn.
274 	 */
275 	WARN_ONCE(true, "Throw could not abort from test!\n");
276 }
277 
kunit_do_assertion(struct kunit * test,struct kunit_assert * assert,bool pass,const char * fmt,...)278 void kunit_do_assertion(struct kunit *test,
279 			struct kunit_assert *assert,
280 			bool pass,
281 			const char *fmt, ...)
282 {
283 	va_list args;
284 
285 	if (pass)
286 		return;
287 
288 	va_start(args, fmt);
289 
290 	assert->message.fmt = fmt;
291 	assert->message.va = &args;
292 
293 	kunit_fail(test, assert);
294 
295 	va_end(args);
296 
297 	if (assert->type == KUNIT_ASSERTION)
298 		kunit_abort(test);
299 }
300 EXPORT_SYMBOL_GPL(kunit_do_assertion);
301 
kunit_init_test(struct kunit * test,const char * name,char * log)302 void kunit_init_test(struct kunit *test, const char *name, char *log)
303 {
304 	spin_lock_init(&test->lock);
305 	INIT_LIST_HEAD(&test->resources);
306 	test->name = name;
307 	test->log = log;
308 	if (test->log)
309 		test->log[0] = '\0';
310 	test->status = KUNIT_SUCCESS;
311 	test->status_comment[0] = '\0';
312 }
313 EXPORT_SYMBOL_GPL(kunit_init_test);
314 
315 /*
316  * Initializes and runs test case. Does not clean up or do post validations.
317  */
kunit_run_case_internal(struct kunit * test,struct kunit_suite * suite,struct kunit_case * test_case)318 static void kunit_run_case_internal(struct kunit *test,
319 				    struct kunit_suite *suite,
320 				    struct kunit_case *test_case)
321 {
322 	if (suite->init) {
323 		int ret;
324 
325 		ret = suite->init(test);
326 		if (ret) {
327 			kunit_err(test, "failed to initialize: %d\n", ret);
328 			kunit_set_failure(test);
329 			return;
330 		}
331 	}
332 
333 	test_case->run_case(test);
334 }
335 
kunit_case_internal_cleanup(struct kunit * test)336 static void kunit_case_internal_cleanup(struct kunit *test)
337 {
338 	kunit_cleanup(test);
339 }
340 
341 /*
342  * Performs post validations and cleanup after a test case was run.
343  * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!
344  */
kunit_run_case_cleanup(struct kunit * test,struct kunit_suite * suite)345 static void kunit_run_case_cleanup(struct kunit *test,
346 				   struct kunit_suite *suite)
347 {
348 	if (suite->exit)
349 		suite->exit(test);
350 
351 	kunit_case_internal_cleanup(test);
352 }
353 
354 struct kunit_try_catch_context {
355 	struct kunit *test;
356 	struct kunit_suite *suite;
357 	struct kunit_case *test_case;
358 };
359 
kunit_try_run_case(void * data)360 static void kunit_try_run_case(void *data)
361 {
362 	struct kunit_try_catch_context *ctx = data;
363 	struct kunit *test = ctx->test;
364 	struct kunit_suite *suite = ctx->suite;
365 	struct kunit_case *test_case = ctx->test_case;
366 
367 	current->kunit_test = test;
368 
369 	/*
370 	 * kunit_run_case_internal may encounter a fatal error; if it does,
371 	 * abort will be called, this thread will exit, and finally the parent
372 	 * thread will resume control and handle any necessary clean up.
373 	 */
374 	kunit_run_case_internal(test, suite, test_case);
375 	/* This line may never be reached. */
376 	kunit_run_case_cleanup(test, suite);
377 }
378 
kunit_catch_run_case(void * data)379 static void kunit_catch_run_case(void *data)
380 {
381 	struct kunit_try_catch_context *ctx = data;
382 	struct kunit *test = ctx->test;
383 	struct kunit_suite *suite = ctx->suite;
384 	int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
385 
386 	if (try_exit_code) {
387 		kunit_set_failure(test);
388 		/*
389 		 * Test case could not finish, we have no idea what state it is
390 		 * in, so don't do clean up.
391 		 */
392 		if (try_exit_code == -ETIMEDOUT) {
393 			kunit_err(test, "test case timed out\n");
394 		/*
395 		 * Unknown internal error occurred preventing test case from
396 		 * running, so there is nothing to clean up.
397 		 */
398 		} else {
399 			kunit_err(test, "internal error occurred preventing test case from running: %d\n",
400 				  try_exit_code);
401 		}
402 		return;
403 	}
404 
405 	/*
406 	 * Test case was run, but aborted. It is the test case's business as to
407 	 * whether it failed or not, we just need to clean up.
408 	 */
409 	kunit_run_case_cleanup(test, suite);
410 }
411 
412 /*
413  * Performs all logic to run a test case. It also catches most errors that
414  * occur in a test case and reports them as failures.
415  */
kunit_run_case_catch_errors(struct kunit_suite * suite,struct kunit_case * test_case,struct kunit * test)416 static void kunit_run_case_catch_errors(struct kunit_suite *suite,
417 					struct kunit_case *test_case,
418 					struct kunit *test)
419 {
420 	struct kunit_try_catch_context context;
421 	struct kunit_try_catch *try_catch;
422 
423 	kunit_init_test(test, test_case->name, test_case->log);
424 	try_catch = &test->try_catch;
425 
426 	kunit_try_catch_init(try_catch,
427 			     test,
428 			     kunit_try_run_case,
429 			     kunit_catch_run_case);
430 	context.test = test;
431 	context.suite = suite;
432 	context.test_case = test_case;
433 	kunit_try_catch_run(try_catch, &context);
434 
435 	/* Propagate the parameter result to the test case. */
436 	if (test->status == KUNIT_FAILURE)
437 		test_case->status = KUNIT_FAILURE;
438 	else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS)
439 		test_case->status = KUNIT_SUCCESS;
440 }
441 
kunit_print_suite_stats(struct kunit_suite * suite,struct kunit_result_stats suite_stats,struct kunit_result_stats param_stats)442 static void kunit_print_suite_stats(struct kunit_suite *suite,
443 				    struct kunit_result_stats suite_stats,
444 				    struct kunit_result_stats param_stats)
445 {
446 	if (kunit_should_print_stats(suite_stats)) {
447 		kunit_log(KERN_INFO, suite,
448 			  "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
449 			  suite->name,
450 			  suite_stats.passed,
451 			  suite_stats.failed,
452 			  suite_stats.skipped,
453 			  suite_stats.total);
454 	}
455 
456 	if (kunit_should_print_stats(param_stats)) {
457 		kunit_log(KERN_INFO, suite,
458 			  "# Totals: pass:%lu fail:%lu skip:%lu total:%lu",
459 			  param_stats.passed,
460 			  param_stats.failed,
461 			  param_stats.skipped,
462 			  param_stats.total);
463 	}
464 }
465 
kunit_update_stats(struct kunit_result_stats * stats,enum kunit_status status)466 static void kunit_update_stats(struct kunit_result_stats *stats,
467 			       enum kunit_status status)
468 {
469 	switch (status) {
470 	case KUNIT_SUCCESS:
471 		stats->passed++;
472 		break;
473 	case KUNIT_SKIPPED:
474 		stats->skipped++;
475 		break;
476 	case KUNIT_FAILURE:
477 		stats->failed++;
478 		break;
479 	}
480 
481 	stats->total++;
482 }
483 
kunit_accumulate_stats(struct kunit_result_stats * total,struct kunit_result_stats add)484 static void kunit_accumulate_stats(struct kunit_result_stats *total,
485 				   struct kunit_result_stats add)
486 {
487 	total->passed += add.passed;
488 	total->skipped += add.skipped;
489 	total->failed += add.failed;
490 	total->total += add.total;
491 }
492 
kunit_run_tests(struct kunit_suite * suite)493 int kunit_run_tests(struct kunit_suite *suite)
494 {
495 	char param_desc[KUNIT_PARAM_DESC_SIZE];
496 	struct kunit_case *test_case;
497 	struct kunit_result_stats suite_stats = { 0 };
498 	struct kunit_result_stats total_stats = { 0 };
499 
500 	kunit_print_subtest_start(suite);
501 
502 	kunit_suite_for_each_test_case(suite, test_case) {
503 		struct kunit test = { .param_value = NULL, .param_index = 0 };
504 		struct kunit_result_stats param_stats = { 0 };
505 		test_case->status = KUNIT_SKIPPED;
506 
507 		if (!test_case->generate_params) {
508 			/* Non-parameterised test. */
509 			kunit_run_case_catch_errors(suite, test_case, &test);
510 			kunit_update_stats(&param_stats, test.status);
511 		} else {
512 			/* Get initial param. */
513 			param_desc[0] = '\0';
514 			test.param_value = test_case->generate_params(NULL, param_desc);
515 
516 			while (test.param_value) {
517 				kunit_run_case_catch_errors(suite, test_case, &test);
518 
519 				if (param_desc[0] == '\0') {
520 					snprintf(param_desc, sizeof(param_desc),
521 						 "param-%d", test.param_index);
522 				}
523 
524 				kunit_log(KERN_INFO, &test,
525 					  KUNIT_SUBTEST_INDENT
526 					  "# %s: %s %d - %s",
527 					  test_case->name,
528 					  kunit_status_to_ok_not_ok(test.status),
529 					  test.param_index + 1, param_desc);
530 
531 				/* Get next param. */
532 				param_desc[0] = '\0';
533 				test.param_value = test_case->generate_params(test.param_value, param_desc);
534 				test.param_index++;
535 
536 				kunit_update_stats(&param_stats, test.status);
537 			}
538 		}
539 
540 
541 		kunit_print_test_stats(&test, param_stats);
542 
543 		kunit_print_ok_not_ok(&test, true, test_case->status,
544 				      kunit_test_case_num(suite, test_case),
545 				      test_case->name,
546 				      test.status_comment);
547 
548 		kunit_update_stats(&suite_stats, test_case->status);
549 		kunit_accumulate_stats(&total_stats, param_stats);
550 	}
551 
552 	kunit_print_suite_stats(suite, suite_stats, total_stats);
553 	kunit_print_subtest_end(suite);
554 
555 	return 0;
556 }
557 EXPORT_SYMBOL_GPL(kunit_run_tests);
558 
kunit_init_suite(struct kunit_suite * suite)559 static void kunit_init_suite(struct kunit_suite *suite)
560 {
561 	kunit_debugfs_create_suite(suite);
562 	suite->status_comment[0] = '\0';
563 }
564 
__kunit_test_suites_init(struct kunit_suite * const * const suites)565 int __kunit_test_suites_init(struct kunit_suite * const * const suites)
566 {
567 	unsigned int i;
568 
569 	for (i = 0; suites[i] != NULL; i++) {
570 		kunit_init_suite(suites[i]);
571 		kunit_run_tests(suites[i]);
572 	}
573 	return 0;
574 }
575 EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
576 
kunit_exit_suite(struct kunit_suite * suite)577 static void kunit_exit_suite(struct kunit_suite *suite)
578 {
579 	kunit_debugfs_destroy_suite(suite);
580 }
581 
__kunit_test_suites_exit(struct kunit_suite ** suites)582 void __kunit_test_suites_exit(struct kunit_suite **suites)
583 {
584 	unsigned int i;
585 
586 	for (i = 0; suites[i] != NULL; i++)
587 		kunit_exit_suite(suites[i]);
588 }
589 EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
590 
591 /*
592  * Used for static resources and when a kunit_resource * has been created by
593  * kunit_alloc_resource().  When an init function is supplied, @data is passed
594  * into the init function; otherwise, we simply set the resource data field to
595  * the data value passed in.
596  */
kunit_add_resource(struct kunit * test,kunit_resource_init_t init,kunit_resource_free_t free,struct kunit_resource * res,void * data)597 int kunit_add_resource(struct kunit *test,
598 		       kunit_resource_init_t init,
599 		       kunit_resource_free_t free,
600 		       struct kunit_resource *res,
601 		       void *data)
602 {
603 	int ret = 0;
604 	unsigned long flags;
605 
606 	res->free = free;
607 	kref_init(&res->refcount);
608 
609 	if (init) {
610 		ret = init(res, data);
611 		if (ret)
612 			return ret;
613 	} else {
614 		res->data = data;
615 	}
616 
617 	spin_lock_irqsave(&test->lock, flags);
618 	list_add_tail(&res->node, &test->resources);
619 	/* refcount for list is established by kref_init() */
620 	spin_unlock_irqrestore(&test->lock, flags);
621 
622 	return ret;
623 }
624 EXPORT_SYMBOL_GPL(kunit_add_resource);
625 
kunit_add_named_resource(struct kunit * test,kunit_resource_init_t init,kunit_resource_free_t free,struct kunit_resource * res,const char * name,void * data)626 int kunit_add_named_resource(struct kunit *test,
627 			     kunit_resource_init_t init,
628 			     kunit_resource_free_t free,
629 			     struct kunit_resource *res,
630 			     const char *name,
631 			     void *data)
632 {
633 	struct kunit_resource *existing;
634 
635 	if (!name)
636 		return -EINVAL;
637 
638 	existing = kunit_find_named_resource(test, name);
639 	if (existing) {
640 		kunit_put_resource(existing);
641 		return -EEXIST;
642 	}
643 
644 	res->name = name;
645 
646 	return kunit_add_resource(test, init, free, res, data);
647 }
648 EXPORT_SYMBOL_GPL(kunit_add_named_resource);
649 
kunit_alloc_and_get_resource(struct kunit * test,kunit_resource_init_t init,kunit_resource_free_t free,gfp_t internal_gfp,void * data)650 struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
651 						    kunit_resource_init_t init,
652 						    kunit_resource_free_t free,
653 						    gfp_t internal_gfp,
654 						    void *data)
655 {
656 	struct kunit_resource *res;
657 	int ret;
658 
659 	res = kzalloc(sizeof(*res), internal_gfp);
660 	if (!res)
661 		return NULL;
662 
663 	ret = kunit_add_resource(test, init, free, res, data);
664 	if (!ret) {
665 		/*
666 		 * bump refcount for get; kunit_resource_put() should be called
667 		 * when done.
668 		 */
669 		kunit_get_resource(res);
670 		return res;
671 	}
672 	return NULL;
673 }
674 EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
675 
kunit_remove_resource(struct kunit * test,struct kunit_resource * res)676 void kunit_remove_resource(struct kunit *test, struct kunit_resource *res)
677 {
678 	unsigned long flags;
679 
680 	spin_lock_irqsave(&test->lock, flags);
681 	list_del(&res->node);
682 	spin_unlock_irqrestore(&test->lock, flags);
683 	kunit_put_resource(res);
684 }
685 EXPORT_SYMBOL_GPL(kunit_remove_resource);
686 
kunit_destroy_resource(struct kunit * test,kunit_resource_match_t match,void * match_data)687 int kunit_destroy_resource(struct kunit *test, kunit_resource_match_t match,
688 			   void *match_data)
689 {
690 	struct kunit_resource *res = kunit_find_resource(test, match,
691 							 match_data);
692 
693 	if (!res)
694 		return -ENOENT;
695 
696 	kunit_remove_resource(test, res);
697 
698 	/* We have a reference also via _find(); drop it. */
699 	kunit_put_resource(res);
700 
701 	return 0;
702 }
703 EXPORT_SYMBOL_GPL(kunit_destroy_resource);
704 
705 struct kunit_kmalloc_array_params {
706 	size_t n;
707 	size_t size;
708 	gfp_t gfp;
709 };
710 
kunit_kmalloc_array_init(struct kunit_resource * res,void * context)711 static int kunit_kmalloc_array_init(struct kunit_resource *res, void *context)
712 {
713 	struct kunit_kmalloc_array_params *params = context;
714 
715 	res->data = kmalloc_array(params->n, params->size, params->gfp);
716 	if (!res->data)
717 		return -ENOMEM;
718 
719 	return 0;
720 }
721 
kunit_kmalloc_array_free(struct kunit_resource * res)722 static void kunit_kmalloc_array_free(struct kunit_resource *res)
723 {
724 	kfree(res->data);
725 }
726 
kunit_kmalloc_array(struct kunit * test,size_t n,size_t size,gfp_t gfp)727 void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)
728 {
729 	struct kunit_kmalloc_array_params params = {
730 		.size = size,
731 		.n = n,
732 		.gfp = gfp
733 	};
734 
735 	return kunit_alloc_resource(test,
736 				    kunit_kmalloc_array_init,
737 				    kunit_kmalloc_array_free,
738 				    gfp,
739 				    &params);
740 }
741 EXPORT_SYMBOL_GPL(kunit_kmalloc_array);
742 
kunit_kfree(struct kunit * test,const void * ptr)743 void kunit_kfree(struct kunit *test, const void *ptr)
744 {
745 	struct kunit_resource *res;
746 
747 	res = kunit_find_resource(test, kunit_resource_instance_match,
748 				  (void *)ptr);
749 
750 	/*
751 	 * Removing the resource from the list of resources drops the
752 	 * reference count to 1; the final put will trigger the free.
753 	 */
754 	kunit_remove_resource(test, res);
755 
756 	kunit_put_resource(res);
757 
758 }
759 EXPORT_SYMBOL_GPL(kunit_kfree);
760 
kunit_cleanup(struct kunit * test)761 void kunit_cleanup(struct kunit *test)
762 {
763 	struct kunit_resource *res;
764 	unsigned long flags;
765 
766 	/*
767 	 * test->resources is a stack - each allocation must be freed in the
768 	 * reverse order from which it was added since one resource may depend
769 	 * on another for its entire lifetime.
770 	 * Also, we cannot use the normal list_for_each constructs, even the
771 	 * safe ones because *arbitrary* nodes may be deleted when
772 	 * kunit_resource_free is called; the list_for_each_safe variants only
773 	 * protect against the current node being deleted, not the next.
774 	 */
775 	while (true) {
776 		spin_lock_irqsave(&test->lock, flags);
777 		if (list_empty(&test->resources)) {
778 			spin_unlock_irqrestore(&test->lock, flags);
779 			break;
780 		}
781 		res = list_last_entry(&test->resources,
782 				      struct kunit_resource,
783 				      node);
784 		/*
785 		 * Need to unlock here as a resource may remove another
786 		 * resource, and this can't happen if the test->lock
787 		 * is held.
788 		 */
789 		spin_unlock_irqrestore(&test->lock, flags);
790 		kunit_remove_resource(test, res);
791 	}
792 	current->kunit_test = NULL;
793 }
794 EXPORT_SYMBOL_GPL(kunit_cleanup);
795 
kunit_init(void)796 static int __init kunit_init(void)
797 {
798 	kunit_debugfs_init();
799 
800 	return 0;
801 }
802 late_initcall(kunit_init);
803 
kunit_exit(void)804 static void __exit kunit_exit(void)
805 {
806 	kunit_debugfs_cleanup();
807 }
808 module_exit(kunit_exit);
809 
810 MODULE_LICENSE("GPL v2");
811