Linux-kselftest Archive on lore.kernel.org
 help / color / Atom feed
From: Knut Omang <knut.omang@oracle.com>
To: linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: linux-doc@vger.kernel.org, linux-kbuild@vger.kernel.org,
	Shuah Khan <shuah@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	Masahiro Yamada <yamada.masahiro@socionext.com>,
	Michal Marek <michal.lkml@markovi.net>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Shreyans Devendra Doshi <0xinfosect0r@gmail.com>,
	Alan Maguire <alan.maguire@oracle.com>,
	Brendan Higgins <brendanhiggins@google.com>,
	Kevin Hilman <khilman@baylibre.com>,
	Hidenori Yamaji <hidenori.yamaji@sony.com>,
	Frank Rowand <frowand.list@gmail.com>,
	Timothy Bird <Tim.Bird@sony.com>,
	Luis Chamberlain <mcgrof@kernel.org>,
	"Theodore Ts'o" <tytso@mit.edu>, Daniel Vetter <daniel@ffwll.ch>,
	Stephen Boyd <sboyd@kernel.org>,
	Knut Omang <knut.omang@oracle.com>
Subject: [RFC 06/19] ktf: A simple debugfs interface to test results
Date: Tue, 13 Aug 2019 08:09:21 +0200
Message-ID: <ae6c38384e2338aa3cfb8a4e4dd1002833789253.1565676440.git-series.knut.omang@oracle.com> (raw)
In-Reply-To: <cover.92d76bb4f6dcedc971d0b72a49e8e459a98bca54.1565676440.git-series.knut.omang@oracle.com>

From: Alan Maguire <alan.maguire@oracle.com>

While test results is available via netlink from user space, sometimes
it may be useful to be able to access the results from the kernel as well,
for instance due to a crash. Make that possible via debugfs.

ktf_debugfs.h:   Support for creating a debugfs representation of test

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
---
 tools/testing/selftests/ktf/kernel/ktf_debugfs.c | 356 ++++++++++++++++-
 tools/testing/selftests/ktf/kernel/ktf_debugfs.h |  34 ++-
 2 files changed, 390 insertions(+)
 create mode 100644 tools/testing/selftests/ktf/kernel/ktf_debugfs.c
 create mode 100644 tools/testing/selftests/ktf/kernel/ktf_debugfs.h

diff --git a/tools/testing/selftests/ktf/kernel/ktf_debugfs.c b/tools/testing/selftests/ktf/kernel/ktf_debugfs.c
new file mode 100644
index 0000000..a20fbd2
--- /dev/null
+++ b/tools/testing/selftests/ktf/kernel/ktf_debugfs.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Alan Maguire <alan.maguire@oracle.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+#include <asm/unistd.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include "ktf_debugfs.h"
+#include "ktf.h"
+#include "ktf_test.h"
+#include "ktf_cov.h"
+
+/* Create a debugfs representation of test sets/tests.  Hierarchy looks like
+ * this:
+ *
+ * Path					Semantics
+ * /sys/kernel/debug/ktf/run/<testset>		Run all tests in testset
+ * /sys/kernel/debug/ktf/run/<testset>/<test>	Run specific test in testset
+ * /sys/kernel/debug/ktf/results/<testset>	Show results of last run for
+ *						testset
+ *
+ * /sys/kernel/debug/ktf/results/<testset>/<test>
+ *						Show results of last run for
+ *						test
+ *
+ */
+
+static struct dentry *ktf_debugfs_rootdir;
+static struct dentry *ktf_debugfs_rundir;
+static struct dentry *ktf_debugfs_resultsdir;
+static struct dentry *ktf_debugfs_cov_file;
+
+static void ktf_debugfs_print_result(struct seq_file *seq, struct ktf_test *t)
+{
+	struct timespec now;
+
+	if (t && strlen(t->log) > 0) {
+		getnstimeofday(&now);
+		seq_printf(seq, "[%s/%s, %ld seconds ago] %s\n",
+			   t->tclass, t->name,
+			   now.tv_sec - t->lastrun.tv_sec, t->log);
+	}
+}
+
+/* /sys/kernel/debug/ktf/results/<testset>-tests/<test> shows specific result */
+static int ktf_debugfs_result(struct seq_file *seq, void *v)
+{
+	struct ktf_test *t = (struct ktf_test *)seq->private;
+
+	ktf_debugfs_print_result(seq, t);
+
+	return 0;
+}
+
+/* /sys/kernel/debug/ktf/results/<testset> shows all results for testset. */
+static int ktf_debugfs_results_all(struct seq_file *seq, void *v)
+{
+	struct ktf_case *testset = (struct ktf_case *)seq->private;
+	struct ktf_test *t;
+
+	if (!testset)
+		return 0;
+
+	seq_printf(seq, "%s results:\n", ktf_case_name(testset));
+	ktf_testcase_for_each_test(t, testset)
+		ktf_debugfs_print_result(seq, t);
+
+	return 0;
+}
+
+/* /sys/kernel/debug/ktf/run/<testset>-tests/<test> runs specific test. */
+static int ktf_debugfs_run(struct seq_file *seq, void *v)
+{
+	struct ktf_test *t = (struct ktf_test *)seq->private;
+
+	if (!t)
+		return 0;
+
+	ktf_run_hook(NULL, NULL, t, 0, NULL, 0);
+	ktf_debugfs_print_result(seq, t);
+
+	return 0;
+}
+
+/* /sys/kernel/debug/ktf/run/<testset> runs all tests in testset. */
+static int ktf_debugfs_run_all(struct seq_file *seq, void *v)
+{
+	struct ktf_case *testset = (struct ktf_case *)seq->private;
+	struct ktf_test *t;
+
+	if (!testset)
+		return 0;
+
+	seq_printf(seq, "Running %s\n", ktf_case_name(testset));
+	ktf_testcase_for_each_test(t, testset) {
+		ktf_run_hook(NULL, NULL, t, 0, NULL, 0);
+		ktf_debugfs_print_result(seq, t);
+	}
+
+	return 0;
+}
+
+static int ktf_run_test_open(struct inode *inode, struct file *file)
+{
+	struct ktf_test *t;
+
+	if (!try_module_get(THIS_MODULE))
+		return -EIO;
+
+	t = (struct ktf_test *)inode->i_private;
+
+	return single_open(file, ktf_debugfs_run, t);
+}
+
+static int ktf_debugfs_release(struct inode *inode, struct file *file)
+{
+	module_put(THIS_MODULE);
+	return single_release(inode, file);
+}
+
+static const struct file_operations ktf_run_test_fops = {
+	.open = ktf_run_test_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = ktf_debugfs_release,
+};
+
+static int ktf_results_test_open(struct inode *inode, struct file *file)
+{
+	struct ktf_test *t;
+
+	if (!try_module_get(THIS_MODULE))
+		return -EIO;
+
+	t = (struct ktf_test *)inode->i_private;
+
+	return single_open(file, ktf_debugfs_result, t);
+}
+
+static const struct file_operations ktf_results_test_fops = {
+	.open = ktf_results_test_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = ktf_debugfs_release,
+};
+
+static void _ktf_debugfs_destroy_test(struct ktf_test *t)
+{
+	if (!t)
+		return;
+
+	tlog(T_DEBUG, "Destroying debugfs test %s", t->name);
+	debugfs_remove(t->debugfs.debugfs_results_test);
+	debugfs_remove(t->debugfs.debugfs_run_test);
+	memset(&t->debugfs, 0, sizeof(t->debugfs));
+}
+
+void ktf_debugfs_create_test(struct ktf_test *t)
+{
+	struct ktf_case *testset = ktf_case_find(t->tclass);
+
+	if (!testset)
+		return;
+
+	memset(&t->debugfs, 0, sizeof(t->debugfs));
+
+	t->debugfs.debugfs_results_test =
+		debugfs_create_file(t->name, S_IFREG | 0444,
+				    testset->debugfs.debugfs_results_test,
+				 t, &ktf_results_test_fops);
+
+	if (t->debugfs.debugfs_results_test) {
+		t->debugfs.debugfs_run_test =
+			debugfs_create_file(t->name, S_IFREG | 0444,
+					    testset->debugfs.debugfs_run_test,
+				 t, &ktf_run_test_fops);
+		if (!t->debugfs.debugfs_run_test) {
+			_ktf_debugfs_destroy_test(t);
+		} else {
+			/* Take reference for test for debugfs */
+			ktf_test_get(t);
+		}
+	}
+	/* Drop reference to testset from ktf_case_find(). */
+	ktf_case_put(testset);
+}
+
+void ktf_debugfs_destroy_test(struct ktf_test *t)
+{
+	_ktf_debugfs_destroy_test(t);
+	/* Release reference now debugfs files are gone. */
+	ktf_test_put(t);
+}
+
+static int ktf_results_testset_open(struct inode *inode, struct file *file)
+{
+	struct ktf_case *testset;
+
+	if (!try_module_get(THIS_MODULE))
+		return -EIO;
+
+	testset = (struct ktf_case *)inode->i_private;
+
+	return single_open(file, ktf_debugfs_results_all, testset);
+}
+
+static const struct file_operations ktf_results_testset_fops = {
+	.open = ktf_results_testset_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = ktf_debugfs_release,
+};
+
+static int ktf_run_testset_open(struct inode *inode, struct file *file)
+{
+	struct ktf_case *testset;
+
+	if (!try_module_get(THIS_MODULE))
+		return -EIO;
+
+	testset = (struct ktf_case *)inode->i_private;
+
+	return single_open(file, ktf_debugfs_run_all, testset);
+}
+
+static const struct file_operations ktf_run_testset_fops = {
+	.open = ktf_run_testset_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = ktf_debugfs_release,
+};
+
+static void _ktf_debugfs_destroy_testset(struct ktf_case *testset)
+{
+	debugfs_remove(testset->debugfs.debugfs_run_testset);
+	debugfs_remove(testset->debugfs.debugfs_run_test);
+	debugfs_remove(testset->debugfs.debugfs_results_testset);
+	debugfs_remove(testset->debugfs.debugfs_results_test);
+}
+
+void ktf_debugfs_create_testset(struct ktf_case *testset)
+{
+	char tests_subdir[KTF_DEBUGFS_NAMESZ];
+	const char *name = ktf_case_name(testset);
+
+	memset(&testset->debugfs, 0, sizeof(testset->debugfs));
+
+	/* First add /sys/kernel/debug/ktf/[results|run]/<testset> */
+	testset->debugfs.debugfs_results_testset =
+		debugfs_create_file(name, S_IFREG | 0444,
+				    ktf_debugfs_resultsdir,
+				 testset, &ktf_results_testset_fops);
+	if (!testset->debugfs.debugfs_results_testset)
+		goto err;
+
+	testset->debugfs.debugfs_run_testset =
+		debugfs_create_file(name, S_IFREG | 0444,
+				    ktf_debugfs_rundir,
+				    testset, &ktf_run_testset_fops);
+	if (!testset->debugfs.debugfs_run_testset)
+		goto err;
+
+	/* Now add parent directories for individual test result/run tests
+	 * which live in
+	 * /sys/kernel/debug/ktf/[results|run]/<testset>-tests/<testname>
+	 */
+	(void)snprintf(tests_subdir, sizeof(tests_subdir), "%s%s",
+			name, KTF_DEBUGFS_TESTS_SUFFIX);
+
+	testset->debugfs.debugfs_results_test =
+		debugfs_create_dir(tests_subdir, ktf_debugfs_resultsdir);
+	if (!testset->debugfs.debugfs_results_test)
+		goto err;
+
+	testset->debugfs.debugfs_run_test =
+		debugfs_create_dir(tests_subdir, ktf_debugfs_rundir);
+	if (!testset->debugfs.debugfs_run_test)
+		goto err;
+
+	/* Take reference count for testset.  One will do as we will always
+	 * free testset debugfs resources together.
+	 */
+	ktf_case_get(testset);
+	return;
+err:
+	_ktf_debugfs_destroy_testset(testset);
+}
+
+void ktf_debugfs_destroy_testset(struct ktf_case *testset)
+{
+	tlog(T_DEBUG, "Destroying debugfs testset %s", ktf_case_name(testset));
+	_ktf_debugfs_destroy_testset(testset);
+	/* Remove our debugfs reference cout to testset */
+	ktf_case_put(testset);
+}
+
+/* /sys/kernel/debug/ktf/coverage shows coverage statistics. */
+static int ktf_debugfs_cov(struct seq_file *seq, void *v)
+{
+	ktf_cov_seq_print(seq);
+
+	return 0;
+}
+
+static int ktf_cov_open(struct inode *inode, struct file *file)
+{
+	if (!try_module_get(THIS_MODULE))
+		return -EIO;
+
+	return single_open(file, ktf_debugfs_cov, NULL);
+}
+
+static const struct file_operations ktf_cov_fops = {
+	.open = ktf_cov_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = ktf_debugfs_release,
+};
+
+void ktf_debugfs_cleanup(void)
+{
+	tlog(T_DEBUG, "Removing ktf debugfs dirs...");
+	debugfs_remove(ktf_debugfs_cov_file);
+	debugfs_remove(ktf_debugfs_rundir);
+	debugfs_remove(ktf_debugfs_resultsdir);
+	debugfs_remove(ktf_debugfs_rootdir);
+}
+
+void ktf_debugfs_init(void)
+{
+	ktf_debugfs_rootdir = debugfs_create_dir(KTF_DEBUGFS_ROOT, NULL);
+	if (!ktf_debugfs_rootdir)
+		goto err;
+	ktf_debugfs_rundir = debugfs_create_dir(KTF_DEBUGFS_RUN,
+						ktf_debugfs_rootdir);
+	if (!ktf_debugfs_rundir)
+		goto err;
+	ktf_debugfs_resultsdir = debugfs_create_dir(KTF_DEBUGFS_RESULTS,
+						    ktf_debugfs_rootdir);
+	if (!ktf_debugfs_resultsdir)
+		goto err;
+
+	ktf_debugfs_cov_file = debugfs_create_file(KTF_DEBUGFS_COV,
+						   S_IFREG | 0444,
+						   ktf_debugfs_rootdir,
+						   NULL,
+						   &ktf_cov_fops);
+	if (ktf_debugfs_cov_file)
+		return;
+err:
+	terr("Could not init %s\n", KTF_DEBUGFS_ROOT);
+	ktf_debugfs_cleanup();
+}
diff --git a/tools/testing/selftests/ktf/kernel/ktf_debugfs.h b/tools/testing/selftests/ktf/kernel/ktf_debugfs.h
new file mode 100644
index 0000000..4dab1ea
--- /dev/null
+++ b/tools/testing/selftests/ktf/kernel/ktf_debugfs.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Alan Maguire <alan.maguire@oracle.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * ktf_debugfs.h: Support for creating a debugfs representation of test
+ * sets/tests.
+ */
+
+#ifndef KTF_DEBUGFS_H
+#define KTF_DEBUGFS_H
+#include <linux/debugfs.h>
+
+#define KTF_DEBUGFS_ROOT                        "ktf"
+#define KTF_DEBUGFS_RUN                         "run"
+#define KTF_DEBUGFS_RESULTS                     "results"
+#define KTF_DEBUGFS_COV				"coverage"
+#define KTF_DEBUGFS_TESTS_SUFFIX                "-tests"
+
+#define KTF_DEBUGFS_NAMESZ                      256
+
+struct ktf_test;
+struct ktf_case;
+
+void ktf_debugfs_create_test(struct ktf_test *);
+void ktf_debugfs_destroy_test(struct ktf_test *);
+void ktf_debugfs_create_testset(struct ktf_case *);
+void ktf_debugfs_destroy_testset(struct ktf_case *);
+void ktf_debugfs_init(void);
+void ktf_debugfs_cleanup(void);
+
+
+#endif
-- 
git-series 0.9.1

  parent reply index

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-13  6:09 [RFC 00/19] Integration of Kernel Test Framework (KTF) into the kernel tree Knut Omang
2019-08-13  6:09 ` [RFC 01/19] kbuild: Fixes to rules for host-cshlib and host-cxxshlib Knut Omang
2019-08-13 14:01   ` Masahiro Yamada
2019-08-13 16:19     ` Knut Omang
2019-08-14  2:02       ` Masahiro Yamada
2019-08-14  5:50         ` Knut Omang
2019-08-14  5:52         ` Knut Omang
2019-08-14 12:52           ` Knut Omang
2019-08-21  1:47             ` Masahiro Yamada
2019-08-21  4:03               ` Knut Omang
2019-08-13  6:09 ` [RFC 02/19] ktf: Introduce the main part of the kernel side of ktf Knut Omang
2019-09-09  1:23   ` Brendan Higgins
2019-09-10  6:15     ` Knut Omang
2019-08-13  6:09 ` [RFC 03/19] ktf: Introduce a generic netlink protocol for test result communication Knut Omang
2019-09-09  1:28   ` Brendan Higgins
2019-09-10  6:30     ` Knut Omang
2019-08-13  6:09 ` [RFC 04/19] ktf: An implementation of a generic associative array container Knut Omang
2019-08-13  6:09 ` [RFC 05/19] ktf: Implementation of ktf support for overriding function entry and return Knut Omang
2019-08-13  6:09 ` Knut Omang [this message]
2019-08-13  8:21   ` [RFC 06/19] ktf: A simple debugfs interface to test results Greg Kroah-Hartman
2019-08-14 17:17     ` Knut Omang
2019-08-15  8:49       ` Greg Kroah-Hartman
2019-08-15 10:35         ` Knut Omang
2019-08-15 10:52           ` Greg Kroah-Hartman
2019-08-13  6:09 ` [RFC 07/19] ktf: Simple coverage support Knut Omang
2019-08-13  6:09 ` [RFC 08/19] ktf: Configurable context support for network info setup Knut Omang
2019-08-13  6:09 ` [RFC 09/19] ktf: resolve: A helper utility to aid in exposing private kernel symbols to KTF tests Knut Omang
2019-08-13  6:09 ` [RFC 10/19] ktf: Add documentation for Kernel Test Framework (KTF) Knut Omang
2019-08-13  6:09 ` [RFC 11/19] ktf: Add a small test suite with a few tests to test KTF itself Knut Omang
2019-08-13  6:09 ` [RFC 12/19] ktf: Main part of user land library for executing tests Knut Omang
2019-08-13  6:09 ` [RFC 13/19] ktf: Integration logic for running ktf tests from googletest Knut Omang
2019-08-13  6:09 ` [RFC 14/19] ktf: Internal debugging facilities Knut Omang
2019-08-13  6:09 ` [RFC 15/19] ktf: Some simple examples Knut Omang
2019-08-13  6:09 ` [RFC 16/19] ktf: Some user applications to run tests Knut Omang
2019-08-13  6:09 ` [RFC 17/19] ktf: Toplevel ktf Makefile/makefile includes and scripts to run from kselftest Knut Omang
2019-08-13  6:09 ` [RFC 18/19] kselftests: Enable building ktf Knut Omang
2019-08-13  6:09 ` [RFC 19/19] Documentation/dev-tools: Add index entry for KTF documentation Knut Omang
2019-08-13  8:10 ` [RFC 00/19] Integration of Kernel Test Framework (KTF) into the kernel tree Brendan Higgins
2019-08-13  8:17 ` Brendan Higgins
2019-08-13 11:29   ` Knut Omang
2019-08-13 17:50     ` Brendan Higgins
2019-08-13  8:23 ` Greg Kroah-Hartman
2019-08-13  9:51   ` Knut Omang
2019-08-13 17:02     ` Brendan Higgins

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ae6c38384e2338aa3cfb8a4e4dd1002833789253.1565676440.git-series.knut.omang@oracle.com \
    --to=knut.omang@oracle.com \
    --cc=0xinfosect0r@gmail.com \
    --cc=Tim.Bird@sony.com \
    --cc=alan.maguire@oracle.com \
    --cc=brendanhiggins@google.com \
    --cc=corbet@lwn.net \
    --cc=daniel@ffwll.ch \
    --cc=frowand.list@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hidenori.yamaji@sony.com \
    --cc=khilman@baylibre.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=michal.lkml@markovi.net \
    --cc=sboyd@kernel.org \
    --cc=shuah@kernel.org \
    --cc=tytso@mit.edu \
    --cc=yamada.masahiro@socionext.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-kselftest Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-kselftest/0 linux-kselftest/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-kselftest linux-kselftest/ https://lore.kernel.org/linux-kselftest \
		linux-kselftest@vger.kernel.org linux-kselftest@archiver.kernel.org
	public-inbox-index linux-kselftest


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kselftest


AGPL code for this site: git clone https://public-inbox.org/ public-inbox