1e2219db2SAlan Maguire // SPDX-License-Identifier: GPL-2.0
2e2219db2SAlan Maguire /*
3e2219db2SAlan Maguire * Copyright (c) 2020, Oracle and/or its affiliates.
4e2219db2SAlan Maguire * Author: Alan Maguire <alan.maguire@oracle.com>
5e2219db2SAlan Maguire */
6e2219db2SAlan Maguire
7e2219db2SAlan Maguire #include <linux/debugfs.h>
8e2219db2SAlan Maguire #include <linux/module.h>
9e2219db2SAlan Maguire
10e2219db2SAlan Maguire #include <kunit/test.h>
11e2219db2SAlan Maguire
12e2219db2SAlan Maguire #include "string-stream.h"
1323108f6aSArnd Bergmann #include "debugfs.h"
14e2219db2SAlan Maguire
15e2219db2SAlan Maguire #define KUNIT_DEBUGFS_ROOT "kunit"
16e2219db2SAlan Maguire #define KUNIT_DEBUGFS_RESULTS "results"
17e2219db2SAlan Maguire
18e2219db2SAlan Maguire /*
19e2219db2SAlan Maguire * Create a debugfs representation of test suites:
20e2219db2SAlan Maguire *
21e2219db2SAlan Maguire * Path Semantics
22e2219db2SAlan Maguire * /sys/kernel/debug/kunit/<testsuite>/results Show results of last run for
23e2219db2SAlan Maguire * testsuite
24e2219db2SAlan Maguire *
25e2219db2SAlan Maguire */
26e2219db2SAlan Maguire
27e2219db2SAlan Maguire static struct dentry *debugfs_rootdir;
28e2219db2SAlan Maguire
kunit_debugfs_cleanup(void)29e2219db2SAlan Maguire void kunit_debugfs_cleanup(void)
30e2219db2SAlan Maguire {
31e2219db2SAlan Maguire debugfs_remove_recursive(debugfs_rootdir);
32e2219db2SAlan Maguire }
33e2219db2SAlan Maguire
kunit_debugfs_init(void)34e2219db2SAlan Maguire void kunit_debugfs_init(void)
35e2219db2SAlan Maguire {
36e2219db2SAlan Maguire if (!debugfs_rootdir)
37e2219db2SAlan Maguire debugfs_rootdir = debugfs_create_dir(KUNIT_DEBUGFS_ROOT, NULL);
38e2219db2SAlan Maguire }
39e2219db2SAlan Maguire
debugfs_print_result(struct seq_file * seq,struct kunit_suite * suite,struct kunit_case * test_case)40e2219db2SAlan Maguire static void debugfs_print_result(struct seq_file *seq,
41e2219db2SAlan Maguire struct kunit_suite *suite,
42e2219db2SAlan Maguire struct kunit_case *test_case)
43e2219db2SAlan Maguire {
44e2219db2SAlan Maguire if (!test_case || !test_case->log)
45e2219db2SAlan Maguire return;
46e2219db2SAlan Maguire
47e2219db2SAlan Maguire seq_printf(seq, "%s", test_case->log);
48e2219db2SAlan Maguire }
49e2219db2SAlan Maguire
50e2219db2SAlan Maguire /*
51e2219db2SAlan Maguire * /sys/kernel/debug/kunit/<testsuite>/results shows all results for testsuite.
52e2219db2SAlan Maguire */
debugfs_print_results(struct seq_file * seq,void * v)53e2219db2SAlan Maguire static int debugfs_print_results(struct seq_file *seq, void *v)
54e2219db2SAlan Maguire {
55e2219db2SAlan Maguire struct kunit_suite *suite = (struct kunit_suite *)seq->private;
56*5e990887SRichard Fitzgerald enum kunit_status success;
57e2219db2SAlan Maguire struct kunit_case *test_case;
58e2219db2SAlan Maguire
59f9a301c3SRae Moar if (!suite)
60e2219db2SAlan Maguire return 0;
61e2219db2SAlan Maguire
62*5e990887SRichard Fitzgerald success = kunit_suite_has_succeeded(suite);
63*5e990887SRichard Fitzgerald
64f9a301c3SRae Moar /* Print KTAP header so the debugfs log can be parsed as valid KTAP. */
65f9a301c3SRae Moar seq_puts(seq, "KTAP version 1\n");
66f9a301c3SRae Moar seq_puts(seq, "1..1\n");
67f9a301c3SRae Moar
68f9a301c3SRae Moar /* Print suite header because it is not stored in the test logs. */
69f9a301c3SRae Moar seq_puts(seq, KUNIT_SUBTEST_INDENT "KTAP version 1\n");
70f9a301c3SRae Moar seq_printf(seq, KUNIT_SUBTEST_INDENT "# Subtest: %s\n", suite->name);
71f9a301c3SRae Moar seq_printf(seq, KUNIT_SUBTEST_INDENT "1..%zd\n", kunit_suite_num_test_cases(suite));
72e2219db2SAlan Maguire
73e2219db2SAlan Maguire kunit_suite_for_each_test_case(suite, test_case)
74e2219db2SAlan Maguire debugfs_print_result(seq, suite, test_case);
75e2219db2SAlan Maguire
76f9a301c3SRae Moar if (suite->log)
77f9a301c3SRae Moar seq_printf(seq, "%s", suite->log);
78f9a301c3SRae Moar
796c738b52SRae Moar seq_printf(seq, "%s %d %s\n",
806d2426b2SDavid Gow kunit_status_to_ok_not_ok(success), 1, suite->name);
81e2219db2SAlan Maguire return 0;
82e2219db2SAlan Maguire }
83e2219db2SAlan Maguire
debugfs_release(struct inode * inode,struct file * file)84e2219db2SAlan Maguire static int debugfs_release(struct inode *inode, struct file *file)
85e2219db2SAlan Maguire {
86e2219db2SAlan Maguire return single_release(inode, file);
87e2219db2SAlan Maguire }
88e2219db2SAlan Maguire
debugfs_results_open(struct inode * inode,struct file * file)89e2219db2SAlan Maguire static int debugfs_results_open(struct inode *inode, struct file *file)
90e2219db2SAlan Maguire {
91e2219db2SAlan Maguire struct kunit_suite *suite;
92e2219db2SAlan Maguire
93e2219db2SAlan Maguire suite = (struct kunit_suite *)inode->i_private;
94e2219db2SAlan Maguire
95e2219db2SAlan Maguire return single_open(file, debugfs_print_results, suite);
96e2219db2SAlan Maguire }
97e2219db2SAlan Maguire
98e2219db2SAlan Maguire static const struct file_operations debugfs_results_fops = {
99e2219db2SAlan Maguire .open = debugfs_results_open,
100e2219db2SAlan Maguire .read = seq_read,
101e2219db2SAlan Maguire .llseek = seq_lseek,
102e2219db2SAlan Maguire .release = debugfs_release,
103e2219db2SAlan Maguire };
104e2219db2SAlan Maguire
kunit_debugfs_create_suite(struct kunit_suite * suite)105e2219db2SAlan Maguire void kunit_debugfs_create_suite(struct kunit_suite *suite)
106e2219db2SAlan Maguire {
107e2219db2SAlan Maguire struct kunit_case *test_case;
108e2219db2SAlan Maguire
109e2219db2SAlan Maguire /* Allocate logs before creating debugfs representation. */
110e2219db2SAlan Maguire suite->log = kzalloc(KUNIT_LOG_SIZE, GFP_KERNEL);
111e2219db2SAlan Maguire kunit_suite_for_each_test_case(suite, test_case)
112e2219db2SAlan Maguire test_case->log = kzalloc(KUNIT_LOG_SIZE, GFP_KERNEL);
113e2219db2SAlan Maguire
114e2219db2SAlan Maguire suite->debugfs = debugfs_create_dir(suite->name, debugfs_rootdir);
115e2219db2SAlan Maguire
116e2219db2SAlan Maguire debugfs_create_file(KUNIT_DEBUGFS_RESULTS, S_IFREG | 0444,
117e2219db2SAlan Maguire suite->debugfs,
118e2219db2SAlan Maguire suite, &debugfs_results_fops);
119e2219db2SAlan Maguire }
120e2219db2SAlan Maguire
kunit_debugfs_destroy_suite(struct kunit_suite * suite)121e2219db2SAlan Maguire void kunit_debugfs_destroy_suite(struct kunit_suite *suite)
122e2219db2SAlan Maguire {
123e2219db2SAlan Maguire struct kunit_case *test_case;
124e2219db2SAlan Maguire
125e2219db2SAlan Maguire debugfs_remove_recursive(suite->debugfs);
126e2219db2SAlan Maguire kfree(suite->log);
127e2219db2SAlan Maguire kunit_suite_for_each_test_case(suite, test_case)
128e2219db2SAlan Maguire kfree(test_case->log);
129e2219db2SAlan Maguire }
130