All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Namhyung Kim <namhyung@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	James Clark <james.clark@linaro.org>,
	Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Clark Williams <williams@redhat.com>,
	linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH v2 14/19] perf test attr: State, spelled out in a line, why a test is skipped
Date: Tue, 13 Oct 2026 17:14:09 -0300	[thread overview]
Message-ID: <20261013201415.36428-15-acme@kernel.org> (raw)
In-Reply-To: <20261013201415.36428-1-acme@kernel.org>

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Per skip the default output shows a self contained one liner:

  unsupp  'test-record-branch-filter-any' exit 255, expected 1, likely a missing capability
  skipped [kernel newer than 6.12] 'test-record-group-sampling'
  skipped [arch = !aarch64, machine = aarch64] 'test-record-graph-default'

The extra notes explaining the reason, with a copy pasteable command to
observe the failure, come in the very same stream when the verbosity is
bumped, at -vvv, nothing is written to a separate place for later
consultation, it is just the logging ladder:

  detail: '/root/bin/perf record --no-bpf-event -j any kill' exited with
  255, the expectations want the workload's 1 exit, so there are no attrs
  recorded to verify; this is normally a capability problem, run
  '/root/bin/perf record --no-bpf-event -j any kill' to see why

Note that 'perf test -v/-vv/-vvv attribute' appends a single -v to the
shell test entry (shell_test__run()), so to see the notes one runs the
python module directly, f.i.:

  python3 tests/shell/lib/attr.py -vvv -d tests/shell/attr -p ./perf

The skip functions now return the reason fragment when they want to skip
and None when the test can go on.

Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/shell/lib/attr.py | 96 ++++++++++++++++++++----------
 1 file changed, 63 insertions(+), 33 deletions(-)

diff --git a/tools/perf/tests/shell/lib/attr.py b/tools/perf/tests/shell/lib/attr.py
index 3bf07d4df95987d8..ee78c912d94693dd 100644
--- a/tools/perf/tests/shell/lib/attr.py
+++ b/tools/perf/tests/shell/lib/attr.py
@@ -209,10 +209,13 @@ class Notest(Exception):
         return '[%s] \'%s\'' % (self.arch, self.test.path)
 
 class Unsup(Exception):
-    def __init__(self, test):
+    def __init__(self, test, ret, expected):
         self.test = test
+        self.ret = ret
+        self.expected = expected
     def getMsg(self):
-        return '\'%s\'' % self.test.path
+        return '\'%s\' exit %d, expected %s, likely a missing capability' % (
+            self.test.path, self.ret, self.expected)
 
 class Event(dict):
     terms = [
@@ -425,13 +428,17 @@ class Test(object):
 
     def skip_test_kernel_since(self):
         if not self.kernel_since:
-            return False
-        return not self.kernel_since <= parse_version(platform.release())
+            return None
+        if self.kernel_since <= parse_version(platform.release()):
+            return None
+        return "kernel older than %d.%d" % tuple(self.kernel_since)
 
     def skip_test_kernel_until(self):
         if not self.kernel_until:
-            return False
-        return not parse_version(platform.release()) < self.kernel_until
+            return None
+        if parse_version(platform.release()) < self.kernel_until:
+            return None
+        return "kernel newer than %d.%d" % tuple(self.kernel_until)
 
     def skip_test_auxv(self):
         def new_auxv(a, pattern):
@@ -447,18 +454,20 @@ class Test(object):
             return (items[0], value)
 
         if not self.auxv:
-            return False
+            return None
         auxv = subprocess.check_output("LD_SHOW_AUXV=1 sleep 0", shell=True) \
                .decode(sys.stdout.encoding)
         pattern = re.compile(r"[: ]+")
         auxv = dict([new_auxv(a, pattern) for a in auxv.splitlines()])
-        return not eval(self.auxv)
+        if eval(self.auxv):
+            return None
+
+        return "the auxv condition doesn't hold here"
 
     def skip_test_arch(self, myarch):
         # If architecture not set always run test
         if self.arch == '':
-            # log.warning("test for arch %s is ok" % myarch)
-            return False
+            return None
 
         # Allow multiple values in assignment separated by ','
         arch_list = self.arch.split(',')
@@ -468,24 +477,23 @@ class Test(object):
             arch_list[0] = arch_list[0][1:]
             log.warning("excluded architecture list %s", arch_list)
             for arch_item in arch_list:
-                # log.warning("test for %s arch is %s" % (arch_item, myarch))
                 if arch_item == myarch:
-                    return True
-            return False
+                    return "arch = %s, machine = %s" % (self.arch, myarch)
+            return None
 
         for arch_item in arch_list:
-            # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch))
             if arch_item == myarch:
-                return False
-        return True
+                return None
+
+        return "arch = %s, machine = %s" % (self.arch, myarch)
 
     def skip_test_requires(self):
         for requirement in filter(None, map(str.strip, self.requires.split(','))):
             if requirement == 'core-pmu' and not core_pmu_available():
                 log.warning("test limitation 'requires %s'", requirement)
-                return True
+                return "needs a core PMU, none here"
 
-        return False
+        return None
 
     def restore_sample_rate(self, value=10000):
         try:
@@ -529,20 +537,36 @@ class Test(object):
     def run_cmd(self, tempdir):
         _junk1, _junk2, _junk3, _junk4, myarch = (os.uname())
 
-        if self.skip_test_arch(myarch):
-            raise Notest(self, myarch)
-
-        if self.skip_test_auxv():
-            raise Notest(self, "auxv skip")
-
-        if self.skip_test_kernel_since():
-            raise Notest(self, "old kernel skip")
-
-        if self.skip_test_kernel_until():
-            raise Notest(self, "new kernel skip")
-
-        if self.skip_test_requires():
-            raise Notest(self, "requirements skip")
+        arch = self.skip_test_arch(myarch)
+        if arch:
+            log.debug("  detail: the test file has arch = %s, the machine reports %s",
+                     self.arch, myarch)
+            raise Notest(self, arch)
+
+        auxv = self.skip_test_auxv()
+        if auxv:
+            log.debug("  detail: the auxv condition %s doesn't hold, the bits come "
+                     "from the LD_SHOW_AUXV=1 output", self.auxv)
+            raise Notest(self, auxv)
+
+        kernel = self.skip_test_kernel_since()
+        if kernel:
+            log.debug("  detail: the test file's kernel_since = %d.%d, this kernel is %s",
+                     self.kernel_since[0], self.kernel_since[1], platform.release())
+            raise Notest(self, kernel)
+
+        kernel = self.skip_test_kernel_until()
+        if kernel:
+            log.debug("  detail: the test file's kernel_until = %d.%d, this kernel is %s",
+                     self.kernel_until[0], self.kernel_until[1], platform.release())
+            raise Notest(self, kernel)
+
+        requirement = self.skip_test_requires()
+        if requirement:
+            log.debug("  detail: requires core-pmu, nothing countable here, check "
+                     "kernel.perf_event_paranoid and the PMU nodes under "
+                     "/sys/bus/event_source/")
+            raise Notest(self, requirement)
 
         self.restore_sample_rate()
         cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
@@ -552,10 +576,16 @@ class Test(object):
         log.info("  '%s' ret '%s', expected '%s'", cmd, str(ret), str(self.ret))
 
         if not data_equal(str(ret), str(self.ret)):
+            plain_cmd = "%s %s %s" % (self.perf, self.command,
+                                      self.args.split('>/dev/null')[0].rstrip())
             if self.test_ret:
                 raise Fail(self, "Perf exit code failure")
             else:
-                raise Unsup(self)
+                log.debug("  detail: '%s' exited with %d, the expectations want the "
+                         "workload's %s exit, so there are no attrs recorded to "
+                         "verify; this is normally a capability problem, run '%s' "
+                         "to see why", plain_cmd, ret, self.ret, plain_cmd)
+                raise Unsup(self, ret, str(self.ret))
 
     def drop_dummy_tracking_events(self):
         """
-- 
2.55.0


  parent reply	other threads:[~2026-10-13 20:15 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 20:13 [PATCH v2 0/19] perf test attr: Report the failures again and cope with more than one core PMU Arnaldo Carvalho de Melo
2026-10-13 20:13 ` [PATCH v2 01/19] perf test attr: Fix record dwarf sample_type expectation Arnaldo Carvalho de Melo
2026-10-13 20:21   ` sashiko-bot
2026-10-13 20:13 ` [PATCH v2 02/19] perf test attr: Allow tests to require a core PMU Arnaldo Carvalho de Melo
2026-10-13 20:28   ` sashiko-bot
2026-10-13 20:13 ` [PATCH v2 03/19] perf test attr: Fix legacy event encodings in group tests Arnaldo Carvalho de Melo
2026-10-13 20:22   ` sashiko-bot
2026-10-13 20:13 ` [PATCH v2 04/19] perf test attr: Fix default stat metrics expectations Arnaldo Carvalho de Melo
2026-10-13 20:37   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 05/19] perf test attr: Relax group checking for ungrouped expectations Arnaldo Carvalho de Melo
2026-10-13 20:18   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 06/19] perf evsel: Mark the event as supported when retrying an open Arnaldo Carvalho de Melo
2026-10-13 20:23   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 07/19] perf test attr: Ignore the core PMU type perf puts in 'config' Arnaldo Carvalho de Melo
2026-10-13 20:25   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 08/19] perf evsel: Don't dump probe events to PERF_TEST_ATTR Arnaldo Carvalho de Melo
2026-10-13 20:26   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 09/19] perf test attr: Introduce mask_bits(), generalizing hide_core_pmu_type() Arnaldo Carvalho de Melo
2026-10-13 20:19   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 10/19] perf test attr: Accept either sample id bit perf asks for Arnaldo Carvalho de Melo
2026-10-13 20:24   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 11/19] perf test attr: Ignore the dummy tracking event and the terms it carries Arnaldo Carvalho de Melo
2026-10-13 20:21   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 12/19] perf test attr: Leave out the events of the other core PMUs Arnaldo Carvalho de Melo
2026-10-13 20:21   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 13/19] perf test attr: Ignore the group read_format bit the PMU count can remove Arnaldo Carvalho de Melo
2026-10-13 20:20   ` sashiko-bot
2026-10-13 20:14 ` Arnaldo Carvalho de Melo [this message]
2026-10-13 20:22   ` [PATCH v2 14/19] perf test attr: State, spelled out in a line, why a test is skipped sashiko-bot
2026-10-13 20:14 ` [PATCH v2 15/19] perf tests: Introduce a 'needs_mlock' suite flag Arnaldo Carvalho de Melo
2026-10-13 20:23   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 16/19] perf mutex: Add a robust, process-shared mutex initializer Arnaldo Carvalho de Melo
2026-10-13 20:27   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 17/19] perf test: Take turns using the perf mlock budget in the mmaping tests Arnaldo Carvalho de Melo
2026-10-13 20:26   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 18/19] perf tests: Mark the C tests mapping perf ring buffers Arnaldo Carvalho de Melo
2026-10-13 20:25   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 19/19] perf tests: Mark the shell tests not " Arnaldo Carvalho de Melo
2026-10-13 20:27   ` sashiko-bot

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=20261013201415.36428-15-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=adrian.hunter@intel.com \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=williams@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.