• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15 
16 
17 
18 /* Kernel UTF suite, test and fixture management including user to kernel
19  * interaction */
20 
21 #include <linux/list.h>
22 #include <linux/slab.h>
23 #include <linux/debugfs.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/uaccess.h>
27 #include <linux/fs.h>
28 #include <linux/version.h>
29 
30 #include <generated/autoconf.h>
31 
32 #include <kutf/kutf_suite.h>
33 #include <kutf/kutf_resultset.h>
34 #include <kutf/kutf_utils.h>
35 
36 #if defined(CONFIG_DEBUG_FS)
37 
38 /**
39  * struct kutf_application - Structure which represents kutf application
40  * @name:	The name of this test application.
41  * @dir:	The debugfs directory for this test
42  * @suite_list:	List head to store all the suites which are part of this
43  *              application
44  */
45 struct kutf_application {
46 	const char         *name;
47 	struct dentry      *dir;
48 	struct list_head   suite_list;
49 };
50 
51 /**
52  * struct kutf_test_function - Structure which represents kutf test function
53  * @suite:		Back reference to the suite this test function
54  *                      belongs to
55  * @filters:		Filters that apply to this test function
56  * @test_id:		Test ID
57  * @execute:		Function to run for this test
58  * @test_data:		Static data for this test
59  * @node:		List node for test_list
60  * @variant_list:	List head to store all the variants which can run on
61  *                      this function
62  * @dir:		debugfs directory for this test function
63  */
64 struct kutf_test_function {
65 	struct kutf_suite  *suite;
66 	unsigned int       filters;
67 	unsigned int       test_id;
68 	void (*execute)(struct kutf_context *context);
69 	union kutf_callback_data test_data;
70 	struct list_head   node;
71 	struct list_head   variant_list;
72 	struct dentry      *dir;
73 };
74 
75 /**
76  * struct kutf_test_fixture - Structure which holds information on the kutf
77  *                            test fixture
78  * @test_func:		Test function this fixture belongs to
79  * @fixture_index:	Index of this fixture
80  * @node:		List node for variant_list
81  * @dir:		debugfs directory for this test fixture
82  */
83 struct kutf_test_fixture {
84 	struct kutf_test_function *test_func;
85 	unsigned int              fixture_index;
86 	struct list_head          node;
87 	struct dentry             *dir;
88 };
89 
90 struct dentry *base_dir;
91 
92 /**
93  * struct kutf_convert_table - Structure which keeps test results
94  * @result_name:	Status of the test result
95  * @result:		Status value for a single test
96  */
97 struct kutf_convert_table {
98 	char                    result_name[50];
99 	enum kutf_result_status result;
100 };
101 
102 struct kutf_convert_table kutf_convert[] = {
103 #define ADD_UTF_RESULT(_name) \
104 { \
105 	#_name, \
106 	_name, \
107 },
108 ADD_UTF_RESULT(KUTF_RESULT_BENCHMARK)
109 ADD_UTF_RESULT(KUTF_RESULT_SKIP)
110 ADD_UTF_RESULT(KUTF_RESULT_UNKNOWN)
111 ADD_UTF_RESULT(KUTF_RESULT_PASS)
112 ADD_UTF_RESULT(KUTF_RESULT_DEBUG)
113 ADD_UTF_RESULT(KUTF_RESULT_INFO)
114 ADD_UTF_RESULT(KUTF_RESULT_WARN)
115 ADD_UTF_RESULT(KUTF_RESULT_FAIL)
116 ADD_UTF_RESULT(KUTF_RESULT_FATAL)
117 ADD_UTF_RESULT(KUTF_RESULT_ABORT)
118 };
119 
120 #define UTF_CONVERT_SIZE (ARRAY_SIZE(kutf_convert))
121 
122 /**
123  * kutf_create_context() - Create a test context in which a specific fixture
124  *                         of an application will be run and its results
125  *                         reported back to the user
126  * @test_fix:	Test fixture to be run.
127  *
128  * Return: Returns the created test context on success or NULL on failure
129  */
130 static struct kutf_context *kutf_create_context(
131 		struct kutf_test_fixture *test_fix);
132 
133 /**
134  * kutf_destroy_context() - Destroy a previously created test context
135  * @context:	Test context to destroy
136  */
137 static void kutf_destroy_context(struct kutf_context *context);
138 
139 /**
140  * kutf_set_result() - Set the test result against the specified test context
141  * @context:	Test context
142  * @status:	Result status
143  */
144 static void kutf_set_result(struct kutf_context *context,
145 		enum kutf_result_status status);
146 
147 /**
148  * kutf_set_expected_result() - Set the expected test result for the specified
149  *                              test context
150  * @context:		Test context
151  * @expected_status:	Expected result status
152  */
153 static void kutf_set_expected_result(struct kutf_context *context,
154 		enum kutf_result_status expected_status);
155 
156 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
157 /* Pre 3.4.0 kernels don't have the simple_open helper */
158 
159 /**
160  * simple_open() - Helper for file opening which stores the inode private data
161  *                 into the file private data
162  * @inode:	File entry representation
163  * @file:	A specific opening of the file
164  *
165  * Return: always 0; if inode private data do not exist, the file will not
166  *         be assigned private data
167  */
simple_open(struct inode * inode,struct file * file)168 static int simple_open(struct inode *inode, struct file *file)
169 {
170 	if (inode->i_private)
171 		file->private_data = inode->i_private;
172 	return 0;
173 }
174 #endif
175 
176 /**
177  * kutf_result_to_string() - Converts a KUTF result into a string
178  * @result_str:      Output result string
179  * @result:          Result status to convert
180  *
181  * Return: 1 if test result was successfully converted to string, 0 otherwise
182  */
kutf_result_to_string(char ** result_str,enum kutf_result_status result)183 static int kutf_result_to_string(char **result_str,
184 		enum kutf_result_status result)
185 {
186 	int i;
187 	int ret = 0;
188 
189 	for (i = 0; i < UTF_CONVERT_SIZE; i++) {
190 		if (result == kutf_convert[i].result) {
191 			*result_str = kutf_convert[i].result_name;
192 			ret = 1;
193 		}
194 	}
195 	return ret;
196 }
197 
198 /**
199  * kutf_debugfs_const_string_read() - Simple debugfs read callback which
200  *                                    returns a constant string
201  * @file:	Opened file to read from
202  * @buf:	User buffer to write the data into
203  * @len:	Amount of data to read
204  * @ppos:	Offset into file to read from
205  *
206  * Return: On success, the number of bytes read and offset @ppos advanced by
207  *         this number; on error, negative value
208  */
kutf_debugfs_const_string_read(struct file * file,char __user * buf,size_t len,loff_t * ppos)209 static ssize_t kutf_debugfs_const_string_read(struct file *file,
210 		char __user *buf, size_t len, loff_t *ppos)
211 {
212 	char *str = file->private_data;
213 
214 	return simple_read_from_buffer(buf, len, ppos, str, strlen(str));
215 }
216 
217 static const struct file_operations kutf_debugfs_const_string_ops = {
218 	.owner = THIS_MODULE,
219 	.open = simple_open,
220 	.read = kutf_debugfs_const_string_read,
221 	.llseek  = default_llseek,
222 };
223 
224 /**
225  * kutf_add_explicit_result() - Check if an explicit result needs to be added
226  * @context:	KUTF test context
227  */
kutf_add_explicit_result(struct kutf_context * context)228 static void kutf_add_explicit_result(struct kutf_context *context)
229 {
230 	switch (context->expected_status) {
231 	case KUTF_RESULT_UNKNOWN:
232 		if (context->status == KUTF_RESULT_UNKNOWN)
233 			kutf_test_pass(context, "(implicit pass)");
234 		break;
235 
236 	case KUTF_RESULT_WARN:
237 		if (context->status == KUTF_RESULT_WARN)
238 			kutf_test_pass(context,
239 					"Pass (expected warn occurred)");
240 		else if (context->status != KUTF_RESULT_SKIP)
241 			kutf_test_fail(context,
242 					"Fail (expected warn missing)");
243 		break;
244 
245 	case KUTF_RESULT_FAIL:
246 		if (context->status == KUTF_RESULT_FAIL)
247 			kutf_test_pass(context,
248 					"Pass (expected fail occurred)");
249 		else if (context->status != KUTF_RESULT_SKIP) {
250 			/* Force the expected status so the fail gets logged */
251 			context->expected_status = KUTF_RESULT_PASS;
252 			kutf_test_fail(context,
253 					"Fail (expected fail missing)");
254 		}
255 		break;
256 
257 	case KUTF_RESULT_FATAL:
258 		if (context->status == KUTF_RESULT_FATAL)
259 			kutf_test_pass(context,
260 					"Pass (expected fatal occurred)");
261 		else if (context->status != KUTF_RESULT_SKIP)
262 			kutf_test_fail(context,
263 					"Fail (expected fatal missing)");
264 		break;
265 
266 	case KUTF_RESULT_ABORT:
267 		if (context->status == KUTF_RESULT_ABORT)
268 			kutf_test_pass(context,
269 					"Pass (expected abort occurred)");
270 		else if (context->status != KUTF_RESULT_SKIP)
271 			kutf_test_fail(context,
272 					"Fail (expected abort missing)");
273 		break;
274 	default:
275 		break;
276 	}
277 }
278 
279 /**
280  * kutf_debugfs_run_open() Debugfs open callback for the "run" entry.
281  * @inode:	inode of the opened file
282  * @file:	Opened file to read from
283  *
284  * This function retrieves the test fixture data that is associated with the
285  * opened file and works back to get the test, suite and application so
286  * it can then run the test that is associated with the file entry.
287  *
288  * Return: 0 on success
289  */
kutf_debugfs_run_open(struct inode * inode,struct file * file)290 static int kutf_debugfs_run_open(struct inode *inode, struct file *file)
291 {
292 	struct kutf_test_fixture *test_fix = inode->i_private;
293 	struct kutf_test_function *test_func = test_fix->test_func;
294 	struct kutf_suite *suite = test_func->suite;
295 	struct kutf_context *test_context;
296 
297 	test_context = kutf_create_context(test_fix);
298 	if (!test_context)
299 		return -ENODEV;
300 
301 	file->private_data = test_context;
302 
303 	/*
304 	 *  Call the create fixture function if required before the
305 	 * fixture is run
306 	 */
307 	if (suite->create_fixture)
308 		test_context->fixture = suite->create_fixture(test_context);
309 
310 	/* Only run the test if the fixture was created (if required) */
311 	if ((suite->create_fixture && test_context->fixture) ||
312 			(!suite->create_fixture)) {
313 		/* Run this fixture */
314 		test_func->execute(test_context);
315 
316 		if (suite->remove_fixture)
317 			suite->remove_fixture(test_context);
318 
319 		kutf_add_explicit_result(test_context);
320 	}
321 	return 0;
322 }
323 
324 /**
325  * kutf_debugfs_run_read() - Debugfs read callback for the "run" entry.
326  * @file:	Opened file to read from
327  * @buf:	User buffer to write the data into
328  * @len:	Amount of data to read
329  * @ppos:	Offset into file to read from
330  *
331  * This function emits the results which where logged during the opening of
332  * the file kutf_debugfs_run_open.
333  * Results will be emitted one at a time, once all the results have been read
334  * 0 will be returned to indicate there is no more data.
335  *
336  * Return: Number of bytes read.
337  */
kutf_debugfs_run_read(struct file * file,char __user * buf,size_t len,loff_t * ppos)338 static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf,
339 		size_t len, loff_t *ppos)
340 {
341 	struct kutf_context *test_context = file->private_data;
342 	struct kutf_result *res;
343 	unsigned long bytes_not_copied;
344 	ssize_t bytes_copied = 0;
345 
346 	/* Note: This code assumes a result is read completely */
347 	res = kutf_remove_result(test_context->result_set);
348 	if (res) {
349 		char *kutf_str_ptr = NULL;
350 		unsigned int kutf_str_len = 0;
351 		unsigned int message_len = 0;
352 		char separator = ':';
353 		char terminator = '\n';
354 
355 		kutf_result_to_string(&kutf_str_ptr, res->status);
356 		if (kutf_str_ptr)
357 			kutf_str_len = strlen(kutf_str_ptr);
358 
359 		if (res->message)
360 			message_len = strlen(res->message);
361 
362 		if ((kutf_str_len + 1 + message_len + 1) > len) {
363 			pr_err("Not enough space in user buffer for a single result");
364 			return 0;
365 		}
366 
367 		/* First copy the result string */
368 		if (kutf_str_ptr) {
369 			bytes_not_copied = copy_to_user(&buf[0], kutf_str_ptr,
370 							kutf_str_len);
371 			bytes_copied += kutf_str_len - bytes_not_copied;
372 			if (bytes_not_copied)
373 				goto exit;
374 		}
375 
376 		/* Then the separator */
377 		bytes_not_copied = copy_to_user(&buf[bytes_copied],
378 						&separator, 1);
379 		bytes_copied += 1 - bytes_not_copied;
380 		if (bytes_not_copied)
381 			goto exit;
382 
383 		/* Finally Next copy the result string */
384 		if (res->message) {
385 			bytes_not_copied = copy_to_user(&buf[bytes_copied],
386 							res->message, message_len);
387 			bytes_copied += message_len - bytes_not_copied;
388 			if (bytes_not_copied)
389 				goto exit;
390 		}
391 
392 		/* Finally the terminator */
393 		bytes_not_copied = copy_to_user(&buf[bytes_copied],
394 						&terminator, 1);
395 		bytes_copied += 1 - bytes_not_copied;
396 	}
397 exit:
398 	return bytes_copied;
399 }
400 
401 /**
402  * kutf_debugfs_run_release() - Debugfs release callback for the "run" entry.
403  * @inode:	File entry representation
404  * @file:	A specific opening of the file
405  *
406  * Release any resources that where created during the opening of the file
407  *
408  * Return: 0 on success
409  */
kutf_debugfs_run_release(struct inode * inode,struct file * file)410 static int kutf_debugfs_run_release(struct inode *inode, struct file *file)
411 {
412 	struct kutf_context *test_context = file->private_data;
413 
414 	kutf_destroy_context(test_context);
415 	return 0;
416 }
417 
418 static const struct file_operations kutf_debugfs_run_ops = {
419 	.owner = THIS_MODULE,
420 	.open = kutf_debugfs_run_open,
421 	.read = kutf_debugfs_run_read,
422 	.release = kutf_debugfs_run_release,
423 	.llseek  = default_llseek,
424 };
425 
426 /**
427  * create_fixture_variant() - Creates a fixture variant for the specified
428  *                            test function and index and the debugfs entries
429  *                            that represent it.
430  * @test_func:		Test function
431  * @fixture_index:	Fixture index
432  *
433  * Return: 0 on success, negative value corresponding to error code in failure
434  */
create_fixture_variant(struct kutf_test_function * test_func,unsigned int fixture_index)435 static int create_fixture_variant(struct kutf_test_function *test_func,
436 		unsigned int fixture_index)
437 {
438 	struct kutf_test_fixture *test_fix;
439 	char name[11];	/* Enough to print the MAX_UINT32 + the null terminator */
440 	struct dentry *tmp;
441 	int err;
442 
443 	test_fix = kmalloc(sizeof(*test_fix), GFP_KERNEL);
444 	if (!test_fix) {
445 		pr_err("Failed to create debugfs directory when adding fixture\n");
446 		err = -ENOMEM;
447 		goto fail_alloc;
448 	}
449 
450 	test_fix->test_func = test_func;
451 	test_fix->fixture_index = fixture_index;
452 
453 	snprintf(name, sizeof(name), "%d", fixture_index);
454 	test_fix->dir = debugfs_create_dir(name, test_func->dir);
455 	if (!test_func->dir) {
456 		pr_err("Failed to create debugfs directory when adding fixture\n");
457 		/* Might not be the right error, we don't get it passed back to us */
458 		err = -EEXIST;
459 		goto fail_dir;
460 	}
461 
462 	tmp = debugfs_create_file("type", S_IROTH, test_fix->dir, "fixture\n",
463 				  &kutf_debugfs_const_string_ops);
464 	if (!tmp) {
465 		pr_err("Failed to create debugfs file \"type\" when adding fixture\n");
466 		/* Might not be the right error, we don't get it passed back to us */
467 		err = -EEXIST;
468 		goto fail_file;
469 	}
470 
471 	tmp = debugfs_create_file("run", S_IROTH, test_fix->dir, test_fix,
472 				  &kutf_debugfs_run_ops);
473 	if (!tmp) {
474 		pr_err("Failed to create debugfs file \"run\" when adding fixture\n");
475 		/* Might not be the right error, we don't get it passed back to us */
476 		err = -EEXIST;
477 		goto fail_file;
478 	}
479 
480 	list_add(&test_fix->node, &test_func->variant_list);
481 	return 0;
482 
483 fail_file:
484 	debugfs_remove_recursive(test_fix->dir);
485 fail_dir:
486 	kfree(test_fix);
487 fail_alloc:
488 	return err;
489 }
490 
491 /**
492  * kutf_remove_test_variant() - Destroy a previously created fixture variant.
493  * @test_fix:	Test fixture
494  */
kutf_remove_test_variant(struct kutf_test_fixture * test_fix)495 static void kutf_remove_test_variant(struct kutf_test_fixture *test_fix)
496 {
497 	debugfs_remove_recursive(test_fix->dir);
498 	kfree(test_fix);
499 }
500 
kutf_add_test_with_filters_and_data(struct kutf_suite * suite,unsigned int id,const char * name,void (* execute)(struct kutf_context * context),unsigned int filters,union kutf_callback_data test_data)501 void kutf_add_test_with_filters_and_data(
502 		struct kutf_suite *suite,
503 		unsigned int id,
504 		const char *name,
505 		void (*execute)(struct kutf_context *context),
506 		unsigned int filters,
507 		union kutf_callback_data test_data)
508 {
509 	struct kutf_test_function *test_func;
510 	struct dentry *tmp;
511 	unsigned int i;
512 
513 	test_func = kmalloc(sizeof(*test_func), GFP_KERNEL);
514 	if (!test_func) {
515 		pr_err("Failed to allocate memory when adding test %s\n", name);
516 		goto fail_alloc;
517 	}
518 
519 	INIT_LIST_HEAD(&test_func->variant_list);
520 
521 	test_func->dir = debugfs_create_dir(name, suite->dir);
522 	if (!test_func->dir) {
523 		pr_err("Failed to create debugfs directory when adding test %s\n", name);
524 		goto fail_dir;
525 	}
526 
527 	tmp = debugfs_create_file("type", S_IROTH, test_func->dir, "test\n",
528 				  &kutf_debugfs_const_string_ops);
529 	if (!tmp) {
530 		pr_err("Failed to create debugfs file \"type\" when adding test %s\n", name);
531 		goto fail_file;
532 	}
533 
534 	test_func->filters = filters;
535 	tmp = debugfs_create_x32("filters", S_IROTH, test_func->dir,
536 				 &test_func->filters);
537 	if (!tmp) {
538 		pr_err("Failed to create debugfs file \"filters\" when adding test %s\n", name);
539 		goto fail_file;
540 	}
541 
542 	test_func->test_id = id;
543 	tmp = debugfs_create_u32("test_id", S_IROTH, test_func->dir,
544 				 &test_func->test_id);
545 	if (!tmp) {
546 		pr_err("Failed to create debugfs file \"test_id\" when adding test %s\n", name);
547 		goto fail_file;
548 	}
549 
550 	for (i = 0; i < suite->fixture_variants; i++) {
551 		if (create_fixture_variant(test_func, i)) {
552 			pr_err("Failed to create fixture %d when adding test %s\n", i, name);
553 			goto fail_file;
554 		}
555 	}
556 
557 	test_func->suite = suite;
558 	test_func->execute = execute;
559 	test_func->test_data = test_data;
560 
561 	list_add(&test_func->node, &suite->test_list);
562 	return;
563 
564 fail_file:
565 	debugfs_remove_recursive(test_func->dir);
566 fail_dir:
567 	kfree(test_func);
568 fail_alloc:
569 	return;
570 }
571 EXPORT_SYMBOL(kutf_add_test_with_filters_and_data);
572 
kutf_add_test_with_filters(struct kutf_suite * suite,unsigned int id,const char * name,void (* execute)(struct kutf_context * context),unsigned int filters)573 void kutf_add_test_with_filters(
574 		struct kutf_suite *suite,
575 		unsigned int id,
576 		const char *name,
577 		void (*execute)(struct kutf_context *context),
578 		unsigned int filters)
579 {
580 	union kutf_callback_data data;
581 
582 	data.ptr_value = NULL;
583 
584 	kutf_add_test_with_filters_and_data(suite,
585 					    id,
586 					    name,
587 					    execute,
588 					    suite->suite_default_flags,
589 					    data);
590 }
591 EXPORT_SYMBOL(kutf_add_test_with_filters);
592 
kutf_add_test(struct kutf_suite * suite,unsigned int id,const char * name,void (* execute)(struct kutf_context * context))593 void kutf_add_test(struct kutf_suite *suite,
594 		unsigned int id,
595 		const char *name,
596 		void (*execute)(struct kutf_context *context))
597 {
598 	union kutf_callback_data data;
599 
600 	data.ptr_value = NULL;
601 
602 	kutf_add_test_with_filters_and_data(suite,
603 					    id,
604 					    name,
605 					    execute,
606 					    suite->suite_default_flags,
607 					    data);
608 }
609 EXPORT_SYMBOL(kutf_add_test);
610 
611 /**
612  * kutf_remove_test(): Remove a previously added test function.
613  * @test_func: Test function
614  */
kutf_remove_test(struct kutf_test_function * test_func)615 static void kutf_remove_test(struct kutf_test_function *test_func)
616 {
617 	struct list_head *pos;
618 	struct list_head *tmp;
619 
620 	list_for_each_safe(pos, tmp, &test_func->variant_list) {
621 		struct kutf_test_fixture *test_fix;
622 
623 		test_fix = list_entry(pos, struct kutf_test_fixture, node);
624 		kutf_remove_test_variant(test_fix);
625 	}
626 
627 	list_del(&test_func->node);
628 	debugfs_remove_recursive(test_func->dir);
629 	kfree(test_func);
630 }
631 
kutf_create_suite_with_filters_and_data(struct kutf_application * app,const char * name,unsigned int fixture_count,void * (* create_fixture)(struct kutf_context * context),void (* remove_fixture)(struct kutf_context * context),unsigned int filters,union kutf_callback_data suite_data)632 struct kutf_suite *kutf_create_suite_with_filters_and_data(
633 		struct kutf_application *app,
634 		const char *name,
635 		unsigned int fixture_count,
636 		void *(*create_fixture)(struct kutf_context *context),
637 		void (*remove_fixture)(struct kutf_context *context),
638 		unsigned int filters,
639 		union kutf_callback_data suite_data)
640 {
641 	struct kutf_suite *suite;
642 	struct dentry *tmp;
643 
644 	suite = kmalloc(sizeof(*suite), GFP_KERNEL);
645 	if (!suite) {
646 		pr_err("Failed to allocate memory when creating suite %s\n", name);
647 		goto fail_kmalloc;
648 	}
649 
650 	suite->dir = debugfs_create_dir(name, app->dir);
651 	if (!suite->dir) {
652 		pr_err("Failed to create debugfs directory when adding test %s\n", name);
653 		goto fail_debugfs;
654 	}
655 
656 	tmp = debugfs_create_file("type", S_IROTH, suite->dir, "suite\n",
657 				  &kutf_debugfs_const_string_ops);
658 	if (!tmp) {
659 		pr_err("Failed to create debugfs file \"type\" when adding test %s\n", name);
660 		goto fail_file;
661 	}
662 
663 	INIT_LIST_HEAD(&suite->test_list);
664 	suite->app = app;
665 	suite->name = name;
666 	suite->fixture_variants = fixture_count;
667 	suite->create_fixture = create_fixture;
668 	suite->remove_fixture = remove_fixture;
669 	suite->suite_default_flags = filters;
670 	suite->suite_data = suite_data;
671 
672 	list_add(&suite->node, &app->suite_list);
673 
674 	return suite;
675 
676 fail_file:
677 	debugfs_remove_recursive(suite->dir);
678 fail_debugfs:
679 	kfree(suite);
680 fail_kmalloc:
681 	return NULL;
682 }
683 EXPORT_SYMBOL(kutf_create_suite_with_filters_and_data);
684 
kutf_create_suite_with_filters(struct kutf_application * app,const char * name,unsigned int fixture_count,void * (* create_fixture)(struct kutf_context * context),void (* remove_fixture)(struct kutf_context * context),unsigned int filters)685 struct kutf_suite *kutf_create_suite_with_filters(
686 		struct kutf_application *app,
687 		const char *name,
688 		unsigned int fixture_count,
689 		void *(*create_fixture)(struct kutf_context *context),
690 		void (*remove_fixture)(struct kutf_context *context),
691 		unsigned int filters)
692 {
693 	union kutf_callback_data data;
694 
695 	data.ptr_value = NULL;
696 	return kutf_create_suite_with_filters_and_data(app,
697 						       name,
698 						       fixture_count,
699 						       create_fixture,
700 						       remove_fixture,
701 						       filters,
702 						       data);
703 }
704 EXPORT_SYMBOL(kutf_create_suite_with_filters);
705 
kutf_create_suite(struct kutf_application * app,const char * name,unsigned int fixture_count,void * (* create_fixture)(struct kutf_context * context),void (* remove_fixture)(struct kutf_context * context))706 struct kutf_suite *kutf_create_suite(
707 		struct kutf_application *app,
708 		const char *name,
709 		unsigned int fixture_count,
710 		void *(*create_fixture)(struct kutf_context *context),
711 		void (*remove_fixture)(struct kutf_context *context))
712 {
713 	union kutf_callback_data data;
714 
715 	data.ptr_value = NULL;
716 	return kutf_create_suite_with_filters_and_data(app,
717 						       name,
718 						       fixture_count,
719 						       create_fixture,
720 						       remove_fixture,
721 						       KUTF_F_TEST_GENERIC,
722 						       data);
723 }
724 EXPORT_SYMBOL(kutf_create_suite);
725 
726 /**
727  * kutf_destroy_suite() - Destroy a previously added test suite.
728  * @suite:	Test suite
729  */
kutf_destroy_suite(struct kutf_suite * suite)730 static void kutf_destroy_suite(struct kutf_suite *suite)
731 {
732 	struct list_head *pos;
733 	struct list_head *tmp;
734 
735 	list_for_each_safe(pos, tmp, &suite->test_list) {
736 		struct kutf_test_function *test_func;
737 
738 		test_func = list_entry(pos, struct kutf_test_function, node);
739 		kutf_remove_test(test_func);
740 	}
741 
742 	list_del(&suite->node);
743 	debugfs_remove_recursive(suite->dir);
744 	kfree(suite);
745 }
746 
kutf_create_application(const char * name)747 struct kutf_application *kutf_create_application(const char *name)
748 {
749 	struct kutf_application *app;
750 	struct dentry *tmp;
751 
752 	app = kmalloc(sizeof(*app), GFP_KERNEL);
753 	if (!app) {
754 		pr_err("Failed to create allocate memory when creating application %s\n", name);
755 		goto fail_kmalloc;
756 	}
757 
758 	app->dir = debugfs_create_dir(name, base_dir);
759 	if (!app->dir) {
760 		pr_err("Failed to create debugfs direcotry when creating application %s\n", name);
761 		goto fail_debugfs;
762 	}
763 
764 	tmp = debugfs_create_file("type", S_IROTH, app->dir, "application\n",
765 				  &kutf_debugfs_const_string_ops);
766 	if (!tmp) {
767 		pr_err("Failed to create debugfs file \"type\" when creating application %s\n", name);
768 		goto fail_file;
769 	}
770 
771 	INIT_LIST_HEAD(&app->suite_list);
772 	app->name = name;
773 
774 	return app;
775 
776 fail_file:
777 	debugfs_remove_recursive(app->dir);
778 fail_debugfs:
779 	kfree(app);
780 fail_kmalloc:
781 	return NULL;
782 }
783 EXPORT_SYMBOL(kutf_create_application);
784 
kutf_destroy_application(struct kutf_application * app)785 void kutf_destroy_application(struct kutf_application *app)
786 {
787 	struct list_head *pos;
788 	struct list_head *tmp;
789 
790 	list_for_each_safe(pos, tmp, &app->suite_list) {
791 		struct kutf_suite *suite;
792 
793 		suite = list_entry(pos, struct kutf_suite, node);
794 		kutf_destroy_suite(suite);
795 	}
796 
797 	debugfs_remove_recursive(app->dir);
798 	kfree(app);
799 }
800 EXPORT_SYMBOL(kutf_destroy_application);
801 
kutf_create_context(struct kutf_test_fixture * test_fix)802 static struct kutf_context *kutf_create_context(
803 		struct kutf_test_fixture *test_fix)
804 {
805 	struct kutf_context *new_context;
806 
807 	new_context = kmalloc(sizeof(*new_context), GFP_KERNEL);
808 	if (!new_context) {
809 		pr_err("Failed to allocate test context");
810 		goto fail_alloc;
811 	}
812 
813 	new_context->result_set = kutf_create_result_set();
814 	if (!new_context->result_set) {
815 		pr_err("Failed to create resultset");
816 		goto fail_result_set;
817 	}
818 
819 	new_context->test_fix = test_fix;
820 	/* Save the pointer to the suite as the callbacks will require it */
821 	new_context->suite = test_fix->test_func->suite;
822 	new_context->status = KUTF_RESULT_UNKNOWN;
823 	new_context->expected_status = KUTF_RESULT_UNKNOWN;
824 
825 	kutf_mempool_init(&new_context->fixture_pool);
826 	new_context->fixture = NULL;
827 	new_context->fixture_index = test_fix->fixture_index;
828 	new_context->fixture_name = NULL;
829 	new_context->test_data = test_fix->test_func->test_data;
830 
831 	return new_context;
832 
833 fail_result_set:
834 	kfree(new_context);
835 fail_alloc:
836 	return NULL;
837 }
838 
kutf_destroy_context(struct kutf_context * context)839 static void kutf_destroy_context(struct kutf_context *context)
840 {
841 	kutf_destroy_result_set(context->result_set);
842 	kutf_mempool_destroy(&context->fixture_pool);
843 	kfree(context);
844 }
845 
kutf_set_result(struct kutf_context * context,enum kutf_result_status status)846 static void kutf_set_result(struct kutf_context *context,
847 		enum kutf_result_status status)
848 {
849 	context->status = status;
850 }
851 
kutf_set_expected_result(struct kutf_context * context,enum kutf_result_status expected_status)852 static void kutf_set_expected_result(struct kutf_context *context,
853 		enum kutf_result_status expected_status)
854 {
855 	context->expected_status = expected_status;
856 }
857 
858 /**
859  * kutf_test_log_result() - Log a result for the specified test context
860  * @context:	Test context
861  * @message:	Result string
862  * @new_status:	Result status
863  */
kutf_test_log_result(struct kutf_context * context,const char * message,enum kutf_result_status new_status)864 static void kutf_test_log_result(
865 	struct kutf_context *context,
866 	const char *message,
867 	enum kutf_result_status new_status)
868 {
869 	if (context->status < new_status)
870 		context->status = new_status;
871 
872 	if (context->expected_status != new_status)
873 		kutf_add_result(&context->fixture_pool, context->result_set,
874 				new_status, message);
875 }
876 
kutf_test_log_result_external(struct kutf_context * context,const char * message,enum kutf_result_status new_status)877 void kutf_test_log_result_external(
878 	struct kutf_context *context,
879 	const char *message,
880 	enum kutf_result_status new_status)
881 {
882 	kutf_test_log_result(context, message, new_status);
883 }
884 EXPORT_SYMBOL(kutf_test_log_result_external);
885 
kutf_test_expect_abort(struct kutf_context * context)886 void kutf_test_expect_abort(struct kutf_context *context)
887 {
888 	kutf_set_expected_result(context, KUTF_RESULT_ABORT);
889 }
890 EXPORT_SYMBOL(kutf_test_expect_abort);
891 
kutf_test_expect_fatal(struct kutf_context * context)892 void kutf_test_expect_fatal(struct kutf_context *context)
893 {
894 	kutf_set_expected_result(context, KUTF_RESULT_FATAL);
895 }
896 EXPORT_SYMBOL(kutf_test_expect_fatal);
897 
kutf_test_expect_fail(struct kutf_context * context)898 void kutf_test_expect_fail(struct kutf_context *context)
899 {
900 	kutf_set_expected_result(context, KUTF_RESULT_FAIL);
901 }
902 EXPORT_SYMBOL(kutf_test_expect_fail);
903 
kutf_test_expect_warn(struct kutf_context * context)904 void kutf_test_expect_warn(struct kutf_context *context)
905 {
906 	kutf_set_expected_result(context, KUTF_RESULT_WARN);
907 }
908 EXPORT_SYMBOL(kutf_test_expect_warn);
909 
kutf_test_expect_pass(struct kutf_context * context)910 void kutf_test_expect_pass(struct kutf_context *context)
911 {
912 	kutf_set_expected_result(context, KUTF_RESULT_PASS);
913 }
914 EXPORT_SYMBOL(kutf_test_expect_pass);
915 
kutf_test_skip(struct kutf_context * context)916 void kutf_test_skip(struct kutf_context *context)
917 {
918 	kutf_set_result(context, KUTF_RESULT_SKIP);
919 	kutf_set_expected_result(context, KUTF_RESULT_UNKNOWN);
920 
921 	kutf_test_log_result(context, "Test skipped", KUTF_RESULT_SKIP);
922 }
923 EXPORT_SYMBOL(kutf_test_skip);
924 
kutf_test_skip_msg(struct kutf_context * context,const char * message)925 void kutf_test_skip_msg(struct kutf_context *context, const char *message)
926 {
927 	kutf_set_result(context, KUTF_RESULT_SKIP);
928 	kutf_set_expected_result(context, KUTF_RESULT_UNKNOWN);
929 
930 	kutf_test_log_result(context, kutf_dsprintf(&context->fixture_pool,
931 			     "Test skipped: %s", message), KUTF_RESULT_SKIP);
932 	kutf_test_log_result(context, "!!!Test skipped!!!", KUTF_RESULT_SKIP);
933 }
934 EXPORT_SYMBOL(kutf_test_skip_msg);
935 
kutf_test_debug(struct kutf_context * context,char const * message)936 void kutf_test_debug(struct kutf_context *context, char const *message)
937 {
938 	kutf_test_log_result(context, message, KUTF_RESULT_DEBUG);
939 }
940 EXPORT_SYMBOL(kutf_test_debug);
941 
kutf_test_pass(struct kutf_context * context,char const * message)942 void kutf_test_pass(struct kutf_context *context, char const *message)
943 {
944 	static const char explicit_message[] = "(explicit pass)";
945 
946 	if (!message)
947 		message = explicit_message;
948 
949 	kutf_test_log_result(context, message, KUTF_RESULT_PASS);
950 }
951 EXPORT_SYMBOL(kutf_test_pass);
952 
kutf_test_info(struct kutf_context * context,char const * message)953 void kutf_test_info(struct kutf_context *context, char const *message)
954 {
955 	kutf_test_log_result(context, message, KUTF_RESULT_INFO);
956 }
957 EXPORT_SYMBOL(kutf_test_info);
958 
kutf_test_warn(struct kutf_context * context,char const * message)959 void kutf_test_warn(struct kutf_context *context, char const *message)
960 {
961 	kutf_test_log_result(context, message, KUTF_RESULT_WARN);
962 }
963 EXPORT_SYMBOL(kutf_test_warn);
964 
kutf_test_fail(struct kutf_context * context,char const * message)965 void kutf_test_fail(struct kutf_context *context, char const *message)
966 {
967 	kutf_test_log_result(context, message, KUTF_RESULT_FAIL);
968 }
969 EXPORT_SYMBOL(kutf_test_fail);
970 
kutf_test_fatal(struct kutf_context * context,char const * message)971 void kutf_test_fatal(struct kutf_context *context, char const *message)
972 {
973 	kutf_test_log_result(context, message, KUTF_RESULT_FATAL);
974 }
975 EXPORT_SYMBOL(kutf_test_fatal);
976 
kutf_test_abort(struct kutf_context * context)977 void kutf_test_abort(struct kutf_context *context)
978 {
979 	kutf_test_log_result(context, "", KUTF_RESULT_ABORT);
980 }
981 EXPORT_SYMBOL(kutf_test_abort);
982 
983 /**
984  * init_kutf_core() - Module entry point.
985  *
986  * Create the base entry point in debugfs.
987  */
init_kutf_core(void)988 static int __init init_kutf_core(void)
989 {
990 	int ret;
991 
992 	base_dir = debugfs_create_dir("kutf_tests", NULL);
993 	if (!base_dir) {
994 		ret = -ENODEV;
995 		goto exit_dir;
996 	}
997 
998 	return 0;
999 
1000 exit_dir:
1001 	return ret;
1002 }
1003 
1004 /**
1005  * exit_kutf_core() - Module exit point.
1006  *
1007  * Remove the base entry point in debugfs.
1008  */
exit_kutf_core(void)1009 static void __exit exit_kutf_core(void)
1010 {
1011 	debugfs_remove_recursive(base_dir);
1012 }
1013 
1014 #else	/* defined(CONFIG_DEBUG_FS) */
1015 
1016 /**
1017  * init_kutf_core() - Module entry point.
1018  *
1019  * Stub for when build against a kernel without debugfs support
1020  */
init_kutf_core(void)1021 static int __init init_kutf_core(void)
1022 {
1023 	pr_debug("KUTF requires a kernel with debug fs support");
1024 
1025 	return -ENODEV;
1026 }
1027 
1028 /**
1029  * exit_kutf_core() - Module exit point.
1030  *
1031  * Stub for when build against a kernel without debugfs support
1032  */
exit_kutf_core(void)1033 static void __exit exit_kutf_core(void)
1034 {
1035 }
1036 #endif	/* defined(CONFIG_DEBUG_FS) */
1037 
1038 MODULE_LICENSE("GPL");
1039 
1040 module_init(init_kutf_core);
1041 module_exit(exit_kutf_core);
1042