From: Jakub Brnak <jbrnak@redhat.com>
To: acme@kernel.org, acme@redhat.com, linux-perf-users@vger.kernel.org
Cc: namhyung@kernel.org, irogers@google.com, mpetlan@redhat.com,
vmolnaro@redhat.com
Subject: [PATCH v5 4/7] perf test: Introduce storing logs for shell tests
Date: Tue, 25 Nov 2025 16:56:45 +0100 [thread overview]
Message-ID: <20251125155648.197527-5-jbrnak@redhat.com> (raw)
In-Reply-To: <20251125155648.197527-1-jbrnak@redhat.com>
Create temporary directories for storing log files for shell tests
that could help while debugging. The log files are necessary for
perftool testsuite test cases also. If the variable PERFTEST_KEEP_LOGS
is set keep the logs, else delete them.
Signed-off-by: Michael Petlan <mpetlan@redhat.com>
Co-developed-by: Veronika Molnarova <vmolnaro@redhat.com>
Signed-off-by: Veronika Molnarova <vmolnaro@redhat.com>
Signed-off-by: Jakub Brnak <jbrnak@redhat.com>
---
tools/perf/tests/builtin-test.c | 91 ++++++++++++++++++++++++++++++++
tools/perf/tests/tests-scripts.c | 3 ++
tools/perf/tests/tests-scripts.h | 1 +
3 files changed, 95 insertions(+)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 04114e6dc2d6..e5a4e86db644 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -6,6 +6,7 @@
*/
#include <ctype.h>
#include <fcntl.h>
+#include <ftw.h>
#include <errno.h>
#ifdef HAVE_BACKTRACE_SUPPORT
#include <execinfo.h>
@@ -282,6 +283,85 @@ static bool test_exclusive(const struct test_suite *t, int test_case)
return t->test_cases[test_case].exclusive;
}
+static int delete_file(const char *fpath, const struct stat *sb __maybe_unused,
+ int typeflag, struct FTW *ftwbuf)
+{
+ int rv = -1;
+
+ /* Stop traversal if going too deep */
+ if (ftwbuf->level > 5) {
+ pr_err("Tree traversal reached level %d, stopping.", ftwbuf->level);
+ return rv;
+ }
+
+ /* Remove only expected directories */
+ if (typeflag == FTW_D || typeflag == FTW_DP) {
+ const char *dirname = fpath + ftwbuf->base;
+
+ if (strcmp(dirname, "logs") && strcmp(dirname, "examples") &&
+ strcmp(dirname, "header_tar") && strncmp(dirname, "perf_", 5)) {
+ pr_err("Unknown directory %s", dirname);
+ return rv;
+ }
+ }
+
+ /* Attempt to remove the file */
+ rv = remove(fpath);
+ if (rv)
+ pr_err("Failed to remove file: %s", fpath);
+
+ return rv;
+}
+
+static bool create_logs(struct test_suite *t, int pass)
+{
+ bool store_logs = t->priv && ((struct shell_test_info *)(t->priv))->store_logs;
+
+ if (pass == 1 && (!test_exclusive(t, 0) || sequential || dont_fork)) {
+ /* Sequential and non-exclusive tests run on the first pass. */
+ return store_logs;
+ } else if (pass != 1 && test_exclusive(t, 0) && !sequential && !dont_fork) {
+ /* Exclusive tests without sequential run on the second pass. */
+ return store_logs;
+ }
+ return false;
+}
+
+static char *setup_shell_logs(const char *name)
+{
+ char template[PATH_MAX];
+ char *temp_dir;
+
+ if (snprintf(template, PATH_MAX, "/tmp/perf_test_%s.XXXXXX", name) < 0) {
+ pr_err("Failed to create log dir template");
+ return NULL; /* Skip the testsuite */
+ }
+
+ temp_dir = mkdtemp(template);
+ if (temp_dir) {
+ setenv("PERFSUITE_RUN_DIR", temp_dir, 1);
+ return strdup(temp_dir);
+ }
+
+ pr_err("Failed to create the temporary directory");
+
+ return NULL; /* Skip the testsuite */
+}
+
+static void cleanup_shell_logs(char *dirname)
+{
+ char *keep_logs = getenv("PERFTEST_KEEP_LOGS");
+
+ /* Check if logs should be kept or do cleanup */
+ if (dirname) {
+ if (!keep_logs || strcmp(keep_logs, "y") != 0)
+ nftw(dirname, delete_file, 8, FTW_DEPTH | FTW_PHYS);
+ free(dirname);
+ }
+
+ unsetenv("PERFSUITE_RUN_DIR");
+}
+
static bool perf_test__matches(const char *desc, int suite_num, int argc, const char *argv[])
{
int i;
@@ -628,6 +708,7 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
for (struct test_suite **t = suites; *t; t++, curr_suite++) {
int curr_test_case;
bool suite_matched = false;
+ char *tmpdir = NULL;
if (!perf_test__matches(test_description(*t, -1), curr_suite, argc, argv)) {
/*
@@ -657,6 +738,15 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
}
for (unsigned int run = 0; run < runs_per_test; run++) {
+ /* Setup temporary log directories for shell test suites */
+ if (create_logs(*t, pass)) {
+ tmpdir = setup_shell_logs((*t)->desc);
+
+ /* Couldn't create log dir, skip test suite */
+ if (tmpdir == NULL)
+ ((struct shell_test_info *)((*t)->priv))->has_setup =
+ FAILED_SETUP;
+ }
test_suite__for_each_test_case(*t, curr_test_case) {
if (!suite_matched &&
!perf_test__matches(test_description(*t, curr_test_case),
@@ -669,6 +759,7 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
goto err_out;
}
}
+ cleanup_shell_logs(tmpdir);
}
if (!sequential) {
/* Parallel mode starts tests but doesn't finish them. Do that now. */
diff --git a/tools/perf/tests/tests-scripts.c b/tools/perf/tests/tests-scripts.c
index 3703ad7b3b75..bf974e4b9051 100644
--- a/tools/perf/tests/tests-scripts.c
+++ b/tools/perf/tests/tests-scripts.c
@@ -272,6 +272,7 @@ static struct test_suite *prepare_test_suite(int dir_fd)
test_info->base_path = strdup_check(dirpath); /* Absolute path to dir */
test_info->has_setup = NO_SETUP;
+ test_info->store_logs = false;
test_suite->priv = test_info;
test_suite->desc = NULL;
@@ -438,6 +439,8 @@ static void append_suites_in_dir(int dir_fd,
continue;
}
+ /* Store logs for testsuite is sub-directories */
+ ((struct shell_test_info *)(test_suite->priv))->store_logs = true;
if (is_test_script(fd, SHELL_SETUP)) { /* Check for setup existence */
char *desc = shell_test__description(fd, SHELL_SETUP);
diff --git a/tools/perf/tests/tests-scripts.h b/tools/perf/tests/tests-scripts.h
index 013031239883..05d403e9be31 100644
--- a/tools/perf/tests/tests-scripts.h
+++ b/tools/perf/tests/tests-scripts.h
@@ -16,6 +16,7 @@ enum shell_setup {
struct shell_test_info {
const char *base_path;
enum shell_setup has_setup;
+ bool store_logs;
};
struct test_suite **create_script_test_suites(void);
--
2.51.1
next prev parent reply other threads:[~2025-11-25 15:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-25 15:56 [PATCH v5 0/7] Introduce structure for shell tests Jakub Brnak
2025-11-25 15:56 ` [PATCH v5 1/7] perf tests: Create a " Jakub Brnak
2025-11-25 15:56 ` [PATCH v5 2/7] perf test: Provide setup for the shell test suite Jakub Brnak
2025-11-25 15:56 ` [PATCH v5 3/7] perftool-testsuite: Add empty setup for base_probe Jakub Brnak
2025-11-25 15:56 ` Jakub Brnak [this message]
2025-11-25 15:56 ` [PATCH v5 5/7] perf test: Format log directories for shell tests Jakub Brnak
2025-11-25 15:56 ` [PATCH v5 6/7] perf test: Remove perftool drivers Jakub Brnak
2025-11-25 15:56 ` [PATCH v5 7/7] perf test: Fix relative path for 'stderr-whitelist.txt' Jakub Brnak
Reply instructions:
You may reply publicly 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=20251125155648.197527-5-jbrnak@redhat.com \
--to=jbrnak@redhat.com \
--cc=acme@kernel.org \
--cc=acme@redhat.com \
--cc=irogers@google.com \
--cc=linux-perf-users@vger.kernel.org \
--cc=mpetlan@redhat.com \
--cc=namhyung@kernel.org \
--cc=vmolnaro@redhat.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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).