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