* [PATCH v1 1/3] perf script: Allow the generated script to be a path
2026-02-09 20:22 [PATCH v1 0/3] perf script engine testing Ian Rogers
@ 2026-02-09 20:22 ` Ian Rogers
2026-02-09 20:22 ` [PATCH v1 2/3] perf test script: Add perl script testing support Ian Rogers
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-02-09 20:22 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Sandipan Das, Leo Yan, Yujie Liu,
linux-kernel, linux-perf-users
Allow the script generated by "perf script -g <language>" to be a file
path and the language determined by the file extension. This is useful
in testing so that the generated script file can be written to a test
directory.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/Documentation/perf-script.txt | 6 ++++--
tools/perf/builtin-script.c | 24 ++++++++++++++++++++----
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 03d112960632..ddf92f9c7821 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -98,8 +98,10 @@ OPTIONS
-g::
--gen-script=::
- Generate perf-script.[ext] starter script for given language,
- using current perf.data.
+ Generate a starter script. If a language is given then the
+ script is named perf-script.[ext] according to the
+ language. If a file path is given then python is used for
+ files ending '.py' and perl used for files ending '.pl'.
--dlfilter=<file>::
Filter sample events using the given shared object file.
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 14c6f6c3c4f2..7c743a303507 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -4489,6 +4489,7 @@ int cmd_script(int argc, const char **argv)
if (generate_script_lang) {
struct stat perf_stat;
int input;
+ char *filename = strdup("perf-script");
if (output_set_by_user()) {
fprintf(stderr,
@@ -4516,17 +4517,32 @@ int cmd_script(int argc, const char **argv)
}
scripting_ops = script_spec__lookup(generate_script_lang);
+ if (!scripting_ops && ends_with(generate_script_lang, ".py")) {
+ scripting_ops = script_spec__lookup("python");
+ free(filename);
+ filename = strdup(generate_script_lang);
+ filename[strlen(filename) - 3] = '\0';
+ } else if (!scripting_ops && ends_with(generate_script_lang, ".pl")) {
+ scripting_ops = script_spec__lookup("perl");
+ free(filename);
+ filename = strdup(generate_script_lang);
+ filename[strlen(filename) - 3] = '\0';
+ }
if (!scripting_ops) {
- fprintf(stderr, "invalid language specifier");
+ fprintf(stderr, "invalid language specifier '%s'\n", generate_script_lang);
err = -ENOENT;
goto out_delete;
}
+ if (!filename) {
+ err = -ENOMEM;
+ goto out_delete;
+ }
#ifdef HAVE_LIBTRACEEVENT
- err = scripting_ops->generate_script(session->tevent.pevent,
- "perf-script");
+ err = scripting_ops->generate_script(session->tevent.pevent, filename);
#else
- err = scripting_ops->generate_script(NULL, "perf-script");
+ err = scripting_ops->generate_script(NULL, filename);
#endif
+ free(filename);
goto out_delete;
}
--
2.53.0.rc2.204.g2597b5adb4-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v1 2/3] perf test script: Add perl script testing support
2026-02-09 20:22 [PATCH v1 0/3] perf script engine testing Ian Rogers
2026-02-09 20:22 ` [PATCH v1 1/3] perf script: Allow the generated script to be a path Ian Rogers
@ 2026-02-09 20:22 ` Ian Rogers
2026-02-09 20:22 ` [PATCH v1 3/3] perf test script: Add python " Ian Rogers
2026-02-11 16:44 ` [PATCH v1 0/3] perf script engine testing Arnaldo Carvalho de Melo
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-02-09 20:22 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Sandipan Das, Leo Yan, Yujie Liu,
linux-kernel, linux-perf-users
Basic coverage of perl script support from `perf script`. This is
disabled by default and so the test will most normally skip.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/shell/script_perl.sh | 102 ++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
create mode 100755 tools/perf/tests/shell/script_perl.sh
diff --git a/tools/perf/tests/shell/script_perl.sh b/tools/perf/tests/shell/script_perl.sh
new file mode 100755
index 000000000000..b6d65b6fbda1
--- /dev/null
+++ b/tools/perf/tests/shell/script_perl.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+# perf script perl tests
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+# set PERF_EXEC_PATH to find scripts in the source directory
+perfdir=$(dirname "$0")/../..
+if [ -e "$perfdir/scripts/perl/Perf-Trace-Util" ]; then
+ export PERF_EXEC_PATH=$perfdir
+fi
+
+
+perfdata=$(mktemp /tmp/__perf_test_script_perl.perf.data.XXXXX)
+generated_script=$(mktemp /tmp/__perf_test_script.XXXXX.pl)
+
+cleanup() {
+ rm -f "${perfdata}"
+ rm -f "${generated_script}"
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cleanup
+ exit 1
+}
+trap trap_cleanup TERM INT
+trap cleanup EXIT
+
+check_perl_support() {
+ if perf check feature -q libperl; then
+ return 0
+ fi
+ echo "perf script perl test [Skipped: no libperl support]"
+ return 2
+}
+
+test_script() {
+ local event_name=$1
+ local expected_output=$2
+ local record_opts=$3
+
+ echo "Testing event: $event_name"
+
+ # Try to record. If this fails, it might be permissions or lack of support.
+ # We return 2 to indicate "skip this event" rather than "fail test".
+ if ! perf record -o "${perfdata}" -e "$event_name" $record_opts -- perf test -w thloop > /dev/null 2>&1; then
+ echo "perf script perl test [Skipped: failed to record $event_name]"
+ return 2
+ fi
+
+ echo "Generating perl script..."
+ if ! perf script -i "${perfdata}" -g "${generated_script}"; then
+ echo "perf script perl test [Failed: script generation for $event_name]"
+ return 1
+ fi
+
+ if [ ! -f "${generated_script}" ]; then
+ echo "perf script perl test [Failed: script not generated for $event_name]"
+ return 1
+ fi
+
+ echo "Executing perl script..."
+ output=$(perf script -i "${perfdata}" -s "${generated_script}" 2>&1)
+
+ if echo "$output" | grep -q "$expected_output"; then
+ echo "perf script perl test [Success: $event_name triggered $expected_output]"
+ return 0
+ else
+ echo "perf script perl test [Failed: $event_name did not trigger $expected_output]"
+ echo "Output was:"
+ echo "$output" | head -n 20
+ return 1
+ fi
+}
+
+check_perl_support || exit 2
+
+# Try tracepoint first
+test_script "sched:sched_switch" "sched::sched_switch" "-c 1" && res=0 || res=$?
+
+if [ $res -eq 0 ]; then
+ exit 0
+elif [ $res -eq 1 ]; then
+ exit 1
+fi
+
+# If tracepoint skipped (res=2), try task-clock
+# For generic events like task-clock, the generated script uses process_event()
+# which dumps data using Data::Dumper. We check for "$VAR1" which is standard Dumper output.
+test_script "task-clock" "\$VAR1" "-c 100" && res=0 || res=$?
+
+if [ $res -eq 0 ]; then
+ exit 0
+elif [ $res -eq 1 ]; then
+ exit 1
+fi
+
+# If both skipped
+echo "perf script perl test [Skipped: Could not record tracepoint or task-clock]"
+exit 2
--
2.53.0.rc2.204.g2597b5adb4-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v1 3/3] perf test script: Add python script testing support
2026-02-09 20:22 [PATCH v1 0/3] perf script engine testing Ian Rogers
2026-02-09 20:22 ` [PATCH v1 1/3] perf script: Allow the generated script to be a path Ian Rogers
2026-02-09 20:22 ` [PATCH v1 2/3] perf test script: Add perl script testing support Ian Rogers
@ 2026-02-09 20:22 ` Ian Rogers
2026-02-11 16:44 ` [PATCH v1 0/3] perf script engine testing Arnaldo Carvalho de Melo
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-02-09 20:22 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Sandipan Das, Leo Yan, Yujie Liu,
linux-kernel, linux-perf-users
Basic coverage of python script support from `perf script`.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/shell/script_python.sh | 113 ++++++++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100755 tools/perf/tests/shell/script_python.sh
diff --git a/tools/perf/tests/shell/script_python.sh b/tools/perf/tests/shell/script_python.sh
new file mode 100755
index 000000000000..6bc66074a31f
--- /dev/null
+++ b/tools/perf/tests/shell/script_python.sh
@@ -0,0 +1,113 @@
+#!/bin/bash
+# perf script python tests
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+# set PERF_EXEC_PATH to find scripts in the source directory
+perfdir=$(dirname "$0")/../..
+if [ -e "$perfdir/scripts/python/Perf-Trace-Util" ]; then
+ export PERF_EXEC_PATH=$perfdir
+fi
+
+
+perfdata=$(mktemp /tmp/__perf_test_script_python.perf.data.XXXXX)
+generated_script=$(mktemp /tmp/__perf_test_script.XXXXX.py)
+
+cleanup() {
+ rm -f "${perfdata}"
+ rm -f "${generated_script}"
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cleanup
+ exit 1
+}
+trap trap_cleanup TERM INT
+trap cleanup EXIT
+
+check_python_support() {
+ if perf check feature -q libpython; then
+ return 0
+ fi
+ echo "perf script python test [Skipped: no libpython support]"
+ return 2
+}
+
+test_script() {
+ local event_name=$1
+ local expected_output=$2
+ local record_opts=$3
+
+ echo "Testing event: $event_name"
+
+ # Try to record. If this fails, it might be permissions or lack of
+ # support. Return 2 to indicate "skip this event" rather than "fail
+ # test".
+ if ! perf record -o "${perfdata}" -e "$event_name" $record_opts -- perf test -w thloop > /dev/null 2>&1; then
+ echo "perf script python test [Skipped: failed to record $event_name]"
+ return 2
+ fi
+
+ echo "Generating python script..."
+ if ! perf script -i "${perfdata}" -g "${generated_script}"; then
+ echo "perf script python test [Failed: script generation for $event_name]"
+ return 1
+ fi
+
+ if [ ! -f "${generated_script}" ]; then
+ echo "perf script python test [Failed: script not generated for $event_name]"
+ return 1
+ fi
+
+ # Perf script -g python doesn't generate process_event for generic
+ # events so append it manually to test that the callback works.
+ if ! grep -q "def process_event" "${generated_script}"; then
+ cat <<EOF >> "${generated_script}"
+
+def process_event(param_dict):
+ print("param_dict: %s" % param_dict)
+EOF
+ fi
+
+ echo "Executing python script..."
+ output=$(perf script -i "${perfdata}" -s "${generated_script}" 2>&1)
+
+ if echo "$output" | grep -q "$expected_output"; then
+ echo "perf script python test [Success: $event_name triggered $expected_output]"
+ return 0
+ else
+ echo "perf script python test [Failed: $event_name did not trigger $expected_output]"
+ echo "Output was:"
+ echo "$output" | head -n 20
+ return 1
+ fi
+}
+
+check_python_support || exit 2
+
+# Try tracepoint first
+test_script "sched:sched_switch" "sched__sched_switch" "-c 1" && res=0 || res=$?
+
+if [ $res -eq 0 ]; then
+ exit 0
+elif [ $res -eq 1 ]; then
+ exit 1
+fi
+
+# If tracepoint skipped (res=2), try task-clock
+# For generic events like task-clock, the generated script uses process_event()
+# which prints the param_dict.
+test_script "task-clock" "param_dict" "-c 100" && res=0 || res=$?
+
+if [ $res -eq 0 ]; then
+ exit 0
+elif [ $res -eq 1 ]; then
+ exit 1
+fi
+
+# If both skipped
+echo "perf script python test [Skipped: Could not record tracepoint or task-clock]"
+exit 2
--
2.53.0.rc2.204.g2597b5adb4-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH v1 0/3] perf script engine testing
2026-02-09 20:22 [PATCH v1 0/3] perf script engine testing Ian Rogers
` (2 preceding siblings ...)
2026-02-09 20:22 ` [PATCH v1 3/3] perf test script: Add python " Ian Rogers
@ 2026-02-11 16:44 ` Arnaldo Carvalho de Melo
3 siblings, 0 replies; 5+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-02-11 16:44 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
Jiri Olsa, Adrian Hunter, James Clark, Sandipan Das, Leo Yan,
Yujie Liu, linux-kernel, linux-perf-users
On Mon, Feb 09, 2026 at 12:22:05PM -0800, Ian Rogers wrote:
> Add tests for generating a script and that the basic APIs work. I'd
> grown concerned that refactoring patches may inadvertently break perf
> script engine support, particularly for perl, and this does something
> to prevent this.
Thanks, tested and applied to perf-tools-next,
- Arnaldo
> Ian Rogers (3):
> perf script: Allow the generated script to be a path
> perf test script: Add perl script testing support
> perf test script: Add python script testing support
>
> tools/perf/Documentation/perf-script.txt | 6 +-
> tools/perf/builtin-script.c | 24 ++++-
> tools/perf/tests/shell/script_perl.sh | 102 ++++++++++++++++++++
> tools/perf/tests/shell/script_python.sh | 113 +++++++++++++++++++++++
> 4 files changed, 239 insertions(+), 6 deletions(-)
> create mode 100755 tools/perf/tests/shell/script_perl.sh
> create mode 100755 tools/perf/tests/shell/script_python.sh
>
> --
> 2.53.0.rc2.204.g2597b5adb4-goog
>
^ permalink raw reply [flat|nested] 5+ messages in thread