summaryrefslogtreecommitdiff
path: root/tools/perf/tests
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-21 10:51:08 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-21 10:51:08 -0800
commitc7decec2f2d2ab0366567f9e30c0e1418cece43f (patch)
tree50312739ad43d0655ea71c942d848db2ff123e8e /tools/perf/tests
parent3544d5ce36f403db6e5c994f526101c870ffe9fe (diff)
parentdbf0108347bdb5d4ccef8910555b16c1f1a505f8 (diff)
Merge tag 'perf-tools-for-v7.0-1-2026-02-21' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools
Pull perf tools updates from Arnaldo Carvalho de Melo: - Introduce 'perf sched stats' tool with record/report/diff workflows using schedstat counters - Add a faster libdw based addr2line implementation and allow selecting it or its alternatives via 'perf config addr2line.style=' - Data-type profiling fixes and improvements including the ability to select fields using 'perf report''s -F/-fields, e.g.: 'perf report --fields overhead,type' - Add 'perf test' regression tests for Data-type profiling with C and Rust workloads - Fix srcline printing with inlines in callchains, make sure this has coverage in 'perf test' - Fix printing of leaf IP in LBR callchains - Fix display of metrics without sufficient permission in 'perf stat' - Print all machines in 'perf kvm report -vvv', not just the host - Switch from SHA-1 to BLAKE2s for build ID generation, remove SHA-1 code - Fix 'perf report's histogram entry collapsing with '-F' option - Use system's cacheline size instead of a hardcoded value in 'perf report' - Allow filtering conversion by time range in 'perf data' - Cover conversion to CTF using 'perf data' in 'perf test' - Address newer glibc const-correctness (-Werror=discarded-qualifiers) issues - Fixes and improvements for ARM's CoreSight support, simplify ARM SPE event config in 'perf mem', update docs for 'perf c2c' including the ARM events it can be used with - Build support for generating metrics from arch specific python script, add extra AMD, Intel, ARM64 metrics using it - Add AMD Zen 6 events and metrics - Add JSON file with OpenHW Risc-V CVA6 hardware counters - Add 'perf kvm' stats live testing - Add more 'perf stat' tests to 'perf test' - Fix segfault in `perf lock contention -b/--use-bpf` - Fix various 'perf test' cases for s390 - Build system cleanups, bump minimum shellcheck version to 0.7.2 - Support building the capstone based annotation routines as a plugin - Allow passing extra Clang flags via EXTRA_BPF_FLAGS * tag 'perf-tools-for-v7.0-1-2026-02-21' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (255 commits) perf test script: Add python script testing support perf test script: Add perl script testing support perf script: Allow the generated script to be a path perf test: perf data --to-ctf testing perf test: Test pipe mode with data conversion --to-json perf json: Pipe mode --to-ctf support perf json: Pipe mode --to-json support perf check: Add libbabeltrace to the listed features perf build: Allow passing extra Clang flags via EXTRA_BPF_FLAGS perf test data_type_profiling.sh: Skip just the Rust tests if code_with_type workload is missing tools build: Fix feature test for rust compiler perf libunwind: Fix calls to thread__e_machine() perf stat: Add no-affinity flag perf evlist: Reduce affinity use and move into iterator, fix no affinity perf evlist: Missing TPEBS close in evlist__close() perf evlist: Special map propagation for tool events that read on 1 CPU perf stat-shadow: In prepare_metric fix guard on reading NULL perf_stat_evsel Revert "perf tool_pmu: More accurately set the cpus for tool events" tools build: Emit dependencies file for test-rust.bin tools build: Make test-rust.bin be removed by the 'clean' target ...
Diffstat (limited to 'tools/perf/tests')
-rw-r--r--tools/perf/tests/builtin-test.c5
-rw-r--r--tools/perf/tests/dlfilter-test.c1
-rw-r--r--tools/perf/tests/kallsyms-split.c1
-rw-r--r--tools/perf/tests/make14
-rw-r--r--tools/perf/tests/parse-events.c10
-rw-r--r--tools/perf/tests/parse-metric.c2
-rw-r--r--tools/perf/tests/pmu.c91
-rwxr-xr-xtools/perf/tests/shell/addr2line_inlines.sh96
-rwxr-xr-xtools/perf/tests/shell/data_type_profiling.sh89
-rwxr-xr-xtools/perf/tests/shell/evlist.sh9
-rwxr-xr-xtools/perf/tests/shell/inject-callchain.sh45
-rwxr-xr-xtools/perf/tests/shell/kvm.sh30
-rwxr-xr-xtools/perf/tests/shell/perf_sched_stats.sh64
-rwxr-xr-xtools/perf/tests/shell/record.sh16
-rwxr-xr-xtools/perf/tests/shell/sched.sh2
-rwxr-xr-xtools/perf/tests/shell/script_dlfilter.sh10
-rwxr-xr-xtools/perf/tests/shell/script_perl.sh102
-rwxr-xr-xtools/perf/tests/shell/script_python.sh113
-rwxr-xr-xtools/perf/tests/shell/stat.sh244
-rwxr-xr-xtools/perf/tests/shell/stat_all_metricgroups.sh26
-rwxr-xr-xtools/perf/tests/shell/stat_all_metrics.sh29
-rwxr-xr-xtools/perf/tests/shell/test_arm_coresight.sh54
-rwxr-xr-xtools/perf/tests/shell/test_java_symbol.sh4
-rwxr-xr-xtools/perf/tests/shell/test_perf_data_converter_ctf.sh104
-rwxr-xr-xtools/perf/tests/shell/test_perf_data_converter_json.sh33
-rw-r--r--tools/perf/tests/subcmd-help.c26
-rw-r--r--tools/perf/tests/sw-clock.c3
-rw-r--r--tools/perf/tests/tests.h5
-rw-r--r--tools/perf/tests/util.c85
-rw-r--r--tools/perf/tests/workloads/Build7
-rw-r--r--tools/perf/tests/workloads/code_with_type.c46
-rw-r--r--tools/perf/tests/workloads/code_with_type.rs27
-rw-r--r--tools/perf/tests/workloads/inlineloop.c52
33 files changed, 1367 insertions, 78 deletions
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index bd6ffa8e4578..06507066213b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -153,6 +153,11 @@ static struct test_workload *workloads[] = {
&workload__datasym,
&workload__landlock,
&workload__traploop,
+ &workload__inlineloop,
+
+#ifdef HAVE_RUST_SUPPORT
+ &workload__code_with_type,
+#endif
};
#define workloads__for_each(workload) \
diff --git a/tools/perf/tests/dlfilter-test.c b/tools/perf/tests/dlfilter-test.c
index 80a1c941138d..e63790c61d53 100644
--- a/tools/perf/tests/dlfilter-test.c
+++ b/tools/perf/tests/dlfilter-test.c
@@ -30,7 +30,6 @@
#include "symbol.h"
#include "synthetic-events.h"
#include "util.h"
-#include "archinsn.h"
#include "dlfilter.h"
#include "tests.h"
#include "util/sample.h"
diff --git a/tools/perf/tests/kallsyms-split.c b/tools/perf/tests/kallsyms-split.c
index bbbc66957e5d..117ed3b70f63 100644
--- a/tools/perf/tests/kallsyms-split.c
+++ b/tools/perf/tests/kallsyms-split.c
@@ -148,6 +148,7 @@ static int test__kallsyms_split(struct test_suite *test __maybe_unused,
ret = TEST_OK;
out:
+ map__put(map);
remove_proc_dir(0);
machine__exit(&m);
return ret;
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 6641701e4828..6587dc326d1b 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -70,6 +70,7 @@ make_python_perf_so := $(python_perf_so)
make_debug := DEBUG=1
make_nondistro := BUILD_NONDISTRO=1
make_extra_tests := EXTRA_TESTS=1
+make_no_jevents := NO_JEVENTS=1
make_jevents_all := JEVENTS_ARCH=all
make_no_bpf_skel := BUILD_BPF_SKEL=0
make_gen_vmlinux_h := GEN_VMLINUX_H=1
@@ -83,9 +84,9 @@ make_no_demangle := NO_DEMANGLE=1
make_no_libelf := NO_LIBELF=1
make_no_libdw := NO_LIBDW=1
make_libunwind := LIBUNWIND=1
-make_no_libdw_dwarf_unwind := NO_LIBDW_DWARF_UNWIND=1
make_no_backtrace := NO_BACKTRACE=1
make_no_libcapstone := NO_CAPSTONE=1
+make_libcapstone_dlopen := LIBCAPSTONE_DLOPEN=1
make_no_libnuma := NO_LIBNUMA=1
make_no_libbionic := NO_LIBBIONIC=1
make_no_libbpf := NO_LIBBPF=1
@@ -120,9 +121,12 @@ make_static := LDFLAGS=-static NO_PERF_READ_VDSO32=1 NO_PERF_READ_VDSOX3
make_minimal := NO_LIBPYTHON=1 NO_GTK2=1
make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBBIONIC=1 NO_LIBDW=1
-make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_LIBBPF=1
+make_minimal += NO_LIBBPF=1
make_minimal += NO_SDT=1 NO_JVMTI=1 NO_LIBZSTD=1
-make_minimal += NO_LIBCAP=1 NO_CAPSTONE=1
+make_minimal += NO_CAPSTONE=1
+
+# binutils 2_42 and newer have bfd_thread_init()
+new_libbfd := $(shell echo '#include <bfd.h>' | $(CC) -E -x c - | grep bfd_thread_init)
# $(run) contains all available tests
run := make_pure
@@ -137,8 +141,11 @@ MAKE_F := $(MAKE) -f $(MK)
endif
run += make_python_perf_so
run += make_debug
+ifneq ($(new_libbfd),)
run += make_nondistro
+endif
run += make_extra_tests
+run += make_no_jevents
run += make_jevents_all
run += make_no_bpf_skel
run += make_gen_vmlinux_h
@@ -155,6 +162,7 @@ run += make_libunwind
run += make_no_libdw_dwarf_unwind
run += make_no_backtrace
run += make_no_libcapstone
+run += make_libcapstone_dlopen
run += make_no_libnuma
run += make_no_libbionic
run += make_no_libbpf
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 128d21dc389f..1d3cc224fbc2 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -2609,8 +2609,8 @@ static int test_events(const struct evlist_test *events, int cnt)
for (int i = 0; i < cnt; i++) {
struct evlist_test e = events[i];
int test_ret;
- const char *pos = e.name;
- char buf[1024], *buf_pos = buf, *end;
+ const char *pos = e.name, *end;
+ char buf[1024], *buf_pos = buf;
while ((end = strstr(pos, "default_core"))) {
size_t len = end - pos;
@@ -2627,7 +2627,7 @@ static int test_events(const struct evlist_test *events, int cnt)
pr_debug("running test %d '%s'\n", i, e.name);
test_ret = test_event(&e);
if (test_ret != TEST_OK) {
- pr_debug("Event test failure: test %d '%s'", i, e.name);
+ pr_debug("Event test failure: test %d '%s'\n", i, e.name);
ret = combine_test_results(ret, test_ret);
}
}
@@ -2764,7 +2764,7 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest
test_ret = test_event(&e);
if (test_ret != TEST_OK) {
- pr_debug("Test PMU event failed for '%s'", name);
+ pr_debug("Test PMU event failed for '%s'\n", name);
ret = combine_test_results(ret, test_ret);
}
@@ -2790,7 +2790,7 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest
e.check = test__checkevent_pmu_events_mix;
test_ret = test_event(&e);
if (test_ret != TEST_OK) {
- pr_debug("Test PMU event failed for '%s'", name);
+ pr_debug("Test PMU event failed for '%s'\n", name);
ret = combine_test_results(ret, test_ret);
}
}
diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c
index 6bbc209a5c6a..7c7f489a5eb0 100644
--- a/tools/perf/tests/parse-metric.c
+++ b/tools/perf/tests/parse-metric.c
@@ -41,6 +41,8 @@ static void load_runtime_stat(struct evlist *evlist, struct value *vals)
count = find_value(evsel->name, vals);
evsel->supported = true;
evsel->stats->aggr->counts.val = count;
+ evsel->stats->aggr->counts.ena = 1;
+ evsel->stats->aggr->counts.run = 1;
}
}
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index cbded2c6faa4..0ebf2d7b2cb4 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -192,12 +192,102 @@ static int test__pmu_format(struct test_suite *test __maybe_unused, int subtest
}
if (attr.config2 != 0x0400000020041d07) {
pr_err("Unexpected config2 value %llx\n", attr.config2);
+ }
+
+ ret = TEST_OK;
+err_out:
+ parse_events_terms__exit(&terms);
+ test_pmu_put(dir, pmu);
+ return ret;
+}
+
+static int test__pmu_usr_chgs(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
+{
+ const char *event = "perf-pmu-test/config=15,config1=4,krava02=170,"
+ "krava03=1,krava11=27,krava12=1/";
+ struct parse_events_terms terms;
+ struct parse_events_error err;
+ LIST_HEAD(config_terms);
+ struct evlist *evlist;
+ struct perf_pmu *pmu;
+ struct evsel *evsel;
+ int ret = TEST_FAIL;
+ char dir[PATH_MAX];
+ u64 val;
+
+ pmu = test_pmu_get(dir, sizeof(dir));
+ if (!pmu)
+ return TEST_FAIL;
+
+ evlist = evlist__new();
+ if (evlist == NULL) {
+ pr_err("Failed allocation");
+ goto err_out;
+ }
+
+ parse_events_terms__init(&terms);
+ ret = parse_events(evlist, event, &err);
+ if (ret) {
+ pr_debug("failed to parse event '%s', err %d\n", event, ret);
+ parse_events_error__print(&err, event);
+ if (parse_events_error__contains(&err, "can't access trace events"))
+ ret = TEST_SKIP;
goto err_out;
}
+ evsel = evlist__first(evlist);
+
+ /*
+ * Set via config=15, krava01 bits 0-1
+ * Set via config1=4, krava11 bit 1
+ * Set values: krava02=170, krava03=1, krava11=27, krava12=1
+ *
+ * Test that already set values aren't overwritten.
+ */
+ evsel__set_config_if_unset(evsel, "krava01", 16);
+ evsel__get_config_val(evsel, "krava01", &val);
+ TEST_ASSERT_EQUAL("krava01 overwritten", (int) val, (15 & 0b11));
+
+ evsel__set_config_if_unset(evsel, "krava11", 45);
+ evsel__get_config_val(evsel, "krava11", &val);
+ TEST_ASSERT_EQUAL("krava11 overwritten", (int) val, (27 | (4 << 1)));
+
+ evsel__set_config_if_unset(evsel, "krava02", 32);
+ evsel__get_config_val(evsel, "krava02", &val);
+ TEST_ASSERT_EQUAL("krava02 overwritten", (int) val, 170);
+
+ evsel__set_config_if_unset(evsel, "krava03", 0);
+ evsel__get_config_val(evsel, "krava03", &val);
+ TEST_ASSERT_EQUAL("krava03 overwritten", (int) val, 1);
+
+ /*
+ * krava13 doesn't have any bits set by either krava13= or config1=
+ * but setting _any_ raw value for config1 implies that krava13
+ * shouldn't be overwritten. So it's value should remain as 0.
+ */
+ evsel__set_config_if_unset(evsel, "krava13", 5);
+ evsel__get_config_val(evsel, "krava13", &val);
+ TEST_ASSERT_EQUAL("krava13 overwritten", (int) val, 0);
+
+ /*
+ * Unset values: krava21, krava22, krava23
+ *
+ * Test that unset values are overwritten.
+ */
+ evsel__set_config_if_unset(evsel, "krava21", 13905);
+ evsel__get_config_val(evsel, "krava21", &val);
+ TEST_ASSERT_EQUAL("krava21 not overwritten", (int) val, 13905);
+
+ evsel__set_config_if_unset(evsel, "krava22", 11);
+ evsel__get_config_val(evsel, "krava22", &val);
+ TEST_ASSERT_EQUAL("krava22 not overwritten", (int) val, 11);
+ evsel__set_config_if_unset(evsel, "krava23", 0);
+ evsel__get_config_val(evsel, "krava23", &val);
+ TEST_ASSERT_EQUAL("krava23 not overwritten", (int) val, 0);
ret = TEST_OK;
err_out:
parse_events_terms__exit(&terms);
+ evlist__delete(evlist);
test_pmu_put(dir, pmu);
return ret;
}
@@ -539,6 +629,7 @@ static struct test_case tests__pmu[] = {
TEST_CASE("PMU name combining", name_len),
TEST_CASE("PMU name comparison", name_cmp),
TEST_CASE("PMU cmdline match", pmu_match),
+ TEST_CASE("PMU user config changes", pmu_usr_chgs),
{ .name = NULL, }
};
diff --git a/tools/perf/tests/shell/addr2line_inlines.sh b/tools/perf/tests/shell/addr2line_inlines.sh
new file mode 100755
index 000000000000..e8754ef2d7f2
--- /dev/null
+++ b/tools/perf/tests/shell/addr2line_inlines.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# test addr2line inline unwinding
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+err=0
+test_dir=$(mktemp -d /tmp/perf-test-inline-addr2line.XXXXXXXXXX)
+perf_data="${test_dir}/perf.data"
+perf_script_txt="${test_dir}/perf_script.txt"
+
+cleanup() {
+ rm -rf "${test_dir}"
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cleanup
+ exit 1
+}
+trap trap_cleanup EXIT TERM INT
+
+test_fp() {
+ echo "Inline unwinding fp verification test"
+ # Record data. Currently only dwarf callchains support inlined functions.
+ perf record --call-graph fp -e task-clock:u -o "${perf_data}" -- perf test -w inlineloop 1
+
+ # Check output with inline (default) and srcline
+ perf script -i "${perf_data}" --fields +srcline > "${perf_script_txt}"
+
+ # Expect the leaf and middle functions to occur on lines in the 20s, with
+ # the non-inlined parent function on a line in the 30s.
+ if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
+ grep -q "inlineloop.c:3.$" "${perf_script_txt}"
+ then
+ echo "Inline unwinding fp verification test [Success]"
+ else
+ echo "Inline unwinding fp verification test [Failed missing inlined functions]"
+ err=1
+ fi
+}
+
+test_dwarf() {
+ echo "Inline unwinding dwarf verification test"
+ # Record data. Currently only dwarf callchains support inlined functions.
+ perf record --call-graph dwarf -e task-clock:u -o "${perf_data}" -- perf test -w inlineloop 1
+
+ # Check output with inline (default) and srcline
+ perf script -i "${perf_data}" --fields +srcline > "${perf_script_txt}"
+
+ # Expect the leaf and middle functions to occur on lines in the 20s, with
+ # the non-inlined parent function on a line in the 30s.
+ if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
+ grep -q "inlineloop.c:3.$" "${perf_script_txt}"
+ then
+ echo "Inline unwinding dwarf verification test [Success]"
+ else
+ echo "Inline unwinding dwarf verification test [Failed missing inlined functions]"
+ err=1
+ fi
+}
+
+test_lbr() {
+ echo "Inline unwinding LBR verification test"
+ if [ ! -f /sys/bus/event_source/devices/cpu/caps/branches ] &&
+ [ ! -f /sys/bus/event_source/devices/cpu_core/caps/branches ]
+ then
+ echo "Skip: only x86 CPUs support LBR"
+ return
+ fi
+
+ # Record data. Currently only dwarf callchains support inlined functions.
+ perf record --call-graph lbr -e cycles:u -o "${perf_data}" -- perf test -w inlineloop 1
+
+ # Check output with inline (default) and srcline
+ perf script -i "${perf_data}" --fields +srcline > "${perf_script_txt}"
+
+ # Expect the leaf and middle functions to occur on lines in the 20s, with
+ # the non-inlined parent function on a line in the 30s.
+ if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
+ grep -q "inlineloop.c:3.$" "${perf_script_txt}"
+ then
+ echo "Inline unwinding lbr verification test [Success]"
+ else
+ echo "Inline unwinding lbr verification test [Failed missing inlined functions]"
+ err=1
+ fi
+}
+
+test_fp
+test_dwarf
+test_lbr
+
+cleanup
+exit $err
diff --git a/tools/perf/tests/shell/data_type_profiling.sh b/tools/perf/tests/shell/data_type_profiling.sh
new file mode 100755
index 000000000000..2a7f8f7c42d0
--- /dev/null
+++ b/tools/perf/tests/shell/data_type_profiling.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+# perf data type profiling tests
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+# The logic below follows the same line as the annotate test, but looks for a
+# data type profiling manifestation
+
+# Values in testtypes and testprogs should match
+testtypes=("# data-type: struct Buf" "# data-type: struct _buf")
+testprogs=("perf test -w code_with_type" "perf test -w datasym")
+
+err=0
+perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
+perfout=$(mktemp /tmp/__perf_test.perf.out.XXXXX)
+
+cleanup() {
+ rm -rf "${perfdata}" "${perfout}"
+ rm -rf "${perfdata}".old
+
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cleanup
+ exit 1
+}
+trap trap_cleanup EXIT TERM INT
+
+test_basic_annotate() {
+ mode=$1
+ runtime=$2
+
+ echo "${mode} ${runtime} perf annotate test"
+
+ case "x${runtime}" in
+ "xRust")
+ if ! perf check feature -q rust
+ then
+ echo "Skip: code_with_type workload not built in 'perf test'"
+ return
+ fi
+ index=0 ;;
+
+ "xC")
+ index=1 ;;
+ esac
+
+ if [ "x${mode}" == "xBasic" ]
+ then
+ perf mem record -o "${perfdata}" ${testprogs[$index]} 2> /dev/null
+ else
+ perf mem record -o - ${testprogs[$index]} 2> /dev/null > "${perfdata}"
+ fi
+ if [ "x$?" != "x0" ]
+ then
+ echo "${mode} annotate [Failed: perf record]"
+ err=1
+ return
+ fi
+
+ # Generate the annotated output file
+ if [ "x${mode}" == "xBasic" ]
+ then
+ perf annotate --code-with-type -i "${perfdata}" --stdio --percent-limit 1 2> /dev/null > "${perfout}"
+ else
+ perf annotate --code-with-type -i - --stdio 2> /dev/null --percent-limit 1 < "${perfdata}" > "${perfout}"
+ fi
+
+ # check if it has the target data type
+ if ! grep -q "${testtypes[$index]}" "${perfout}"
+ then
+ echo "${mode} annotate [Failed: missing target data type]"
+ cat "${perfout}"
+ err=1
+ return
+ fi
+ echo "${mode} annotate test [Success]"
+}
+
+test_basic_annotate Basic Rust
+test_basic_annotate Pipe Rust
+test_basic_annotate Basic C
+test_basic_annotate Pipe C
+
+cleanup
+exit $err
diff --git a/tools/perf/tests/shell/evlist.sh b/tools/perf/tests/shell/evlist.sh
index 140f099e75c1..8a22f4171c07 100755
--- a/tools/perf/tests/shell/evlist.sh
+++ b/tools/perf/tests/shell/evlist.sh
@@ -21,13 +21,13 @@ trap trap_cleanup EXIT TERM INT
test_evlist_simple() {
echo "Simple evlist test"
- if ! perf record -e cycles -o "${perfdata}" true 2> /dev/null
+ if ! perf record -e cpu-clock -o "${perfdata}" true 2> /dev/null
then
echo "Simple evlist [Failed record]"
err=1
return
fi
- if ! perf evlist -i "${perfdata}" | grep -q "cycles"
+ if ! perf evlist -i "${perfdata}" | grep -q "cpu-clock"
then
echo "Simple evlist [Failed to list event]"
err=1
@@ -38,13 +38,14 @@ test_evlist_simple() {
test_evlist_group() {
echo "Group evlist test"
- if ! perf record -e "{cycles,instructions}" -o "${perfdata}" true 2> /dev/null
+ if ! perf record -e "{cpu-clock,task-clock}" -o "${perfdata}" \
+ -- perf test -w noploop 2> /dev/null
then
echo "Group evlist [Skipped event group recording failed]"
return
fi
- if ! perf evlist -i "${perfdata}" -g | grep -q "{.*cycles.*,.*instructions.*}"
+ if ! perf evlist -i "${perfdata}" -g | grep -q "{.*cpu-clock.*,.*task-clock.*}"
then
echo "Group evlist [Failed to list event group]"
err=1
diff --git a/tools/perf/tests/shell/inject-callchain.sh b/tools/perf/tests/shell/inject-callchain.sh
new file mode 100755
index 000000000000..a1cba8010f95
--- /dev/null
+++ b/tools/perf/tests/shell/inject-callchain.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# perf inject to convert DWARF callchains to regular ones
+# SPDX-License-Identifier: GPL-2.0
+
+if ! perf check feature -q dwarf; then
+ echo "SKIP: DWARF support is not available"
+ exit 2
+fi
+
+TESTDATA=$(mktemp /tmp/perf-test.XXXXXX)
+
+err=0
+
+cleanup()
+{
+ trap - EXIT TERM INT
+ rm -f ${TESTDATA}*
+}
+
+trap_cleanup()
+{
+ cleanup
+ exit 1
+}
+
+trap trap_cleanup EXIT TERM INT
+
+echo "recording data with DWARF callchain"
+perf record -F 999 --call-graph dwarf -o "${TESTDATA}" -- perf test -w noploop
+
+echo "convert DWARF callchain using perf inject"
+perf inject -i "${TESTDATA}" --convert-callchain -o "${TESTDATA}.new"
+
+perf report -i "${TESTDATA}" --no-children -q --percent-limit=1 > ${TESTDATA}.out
+perf report -i "${TESTDATA}.new" --no-children -q --percent-limit=1 > ${TESTDATA}.new.out
+
+echo "compare the both result excluding inlined functions"
+if diff -u "${TESTDATA}.out" "${TESTDATA}.new.out" | grep "^- " | grep -qv "(inlined)"; then
+ echo "Found some differences"
+ diff -u "${TESTDATA}.out" "${TESTDATA}.new.out"
+ err=1
+fi
+
+cleanup
+exit $err
diff --git a/tools/perf/tests/shell/kvm.sh b/tools/perf/tests/shell/kvm.sh
index 2a399b83fe80..f88e859025c4 100755
--- a/tools/perf/tests/shell/kvm.sh
+++ b/tools/perf/tests/shell/kvm.sh
@@ -7,9 +7,10 @@ set -e
err=0
perfdata=$(mktemp /tmp/__perf_kvm_test.perf.data.XXXXX)
qemu_pid_file=$(mktemp /tmp/__perf_kvm_test.qemu.pid.XXXXX)
+log_file=$(mktemp /tmp/__perf_kvm_test.live_log.XXXXX)
cleanup() {
- rm -f "${perfdata}"
+ rm -f "${perfdata}" "${log_file}"
if [ -f "${qemu_pid_file}" ]; then
if [ -s "${qemu_pid_file}" ]; then
qemu_pid=$(cat "${qemu_pid_file}")
@@ -96,6 +97,32 @@ test_kvm_buildid_list() {
echo "perf kvm buildid-list test [Success]"
}
+test_kvm_stat_live() {
+ echo "Testing perf kvm stat live"
+
+ # Run perf kvm live for 5 seconds, monitoring that PID
+ # Use sleep to keep stdin open but silent, preventing EOF loop or interactive spam
+ if ! sleep 10 | timeout 5s perf kvm stat live -p "${qemu_pid}" > "${log_file}" 2>&1; then
+ retval=$?
+ if [ $retval -ne 124 ] && [ $retval -ne 0 ]; then
+ echo "perf kvm stat live [Failed: perf kvm stat live failed to start or run (ret=$retval)]"
+ head -n 50 "${log_file}"
+ err=1
+ return
+ fi
+ fi
+
+ # Check for some sample data (percentage)
+ if ! grep -E -q "[0-9]+\.[0-9]+%" "${log_file}"; then
+ echo "perf kvm stat live [Failed: no sample percentage found]"
+ head -n 50 "${log_file}"
+ err=1
+ return
+ fi
+
+ echo "perf kvm stat live test [Success]"
+}
+
setup_qemu() {
# Find qemu
if [ "$(uname -m)" = "x86_64" ]; then
@@ -148,6 +175,7 @@ if [ $err -eq 0 ]; then
test_kvm_stat
test_kvm_record_report
test_kvm_buildid_list
+ test_kvm_stat_live
fi
cleanup
diff --git a/tools/perf/tests/shell/perf_sched_stats.sh b/tools/perf/tests/shell/perf_sched_stats.sh
new file mode 100755
index 000000000000..2b1410b050d0
--- /dev/null
+++ b/tools/perf/tests/shell/perf_sched_stats.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# perf sched stats tests
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+err=0
+test_perf_sched_stats_record() {
+ echo "Basic perf sched stats record test"
+ if ! perf sched stats record true 2>&1 | \
+ grep -E -q "[ perf sched stats: Wrote samples to perf.data ]"
+ then
+ echo "Basic perf sched stats record test [Failed]"
+ err=1
+ return
+ fi
+ echo "Basic perf sched stats record test [Success]"
+}
+
+test_perf_sched_stats_report() {
+ echo "Basic perf sched stats report test"
+ perf sched stats record true > /dev/null
+ if ! perf sched stats report 2>&1 | grep -E -q "Description"
+ then
+ echo "Basic perf sched stats report test [Failed]"
+ err=1
+ rm perf.data
+ return
+ fi
+ rm perf.data
+ echo "Basic perf sched stats report test [Success]"
+}
+
+test_perf_sched_stats_live() {
+ echo "Basic perf sched stats live mode test"
+ if ! perf sched stats true 2>&1 | grep -E -q "Description"
+ then
+ echo "Basic perf sched stats live mode test [Failed]"
+ err=1
+ return
+ fi
+ echo "Basic perf sched stats live mode test [Success]"
+}
+
+test_perf_sched_stats_diff() {
+ echo "Basic perf sched stats diff test"
+ perf sched stats record true > /dev/null
+ perf sched stats record true > /dev/null
+ if ! perf sched stats diff > /dev/null
+ then
+ echo "Basic perf sched stats diff test [Failed]"
+ err=1
+ rm perf.data.old perf.data
+ return
+ fi
+ rm perf.data.old perf.data
+ echo "Basic perf sched stats diff test [Success]"
+}
+
+test_perf_sched_stats_record
+test_perf_sched_stats_report
+test_perf_sched_stats_live
+test_perf_sched_stats_diff
+exit $err
diff --git a/tools/perf/tests/shell/record.sh b/tools/perf/tests/shell/record.sh
index 0f5841c479e7..7cb81cf3444a 100755
--- a/tools/perf/tests/shell/record.sh
+++ b/tools/perf/tests/shell/record.sh
@@ -260,7 +260,21 @@ test_uid() {
test_leader_sampling() {
echo "Basic leader sampling test"
- if ! perf record -o "${perfdata}" -e "{cycles,cycles}:Su" -- \
+ events="{cycles,cycles}:Su"
+ [ "$(uname -m)" = "s390x" ] && {
+ [ ! -d /sys/devices/cpum_sf ] && {
+ echo "No CPUMF [Skipped record]"
+ return
+ }
+ events="{cpum_sf/SF_CYCLES_BASIC/,cycles}:Su"
+ perf record -o "${perfdata}" -e "$events" -- perf test -w brstack 2> /dev/null
+ # Perf grouping might be unsupported, depends on version.
+ [ "$?" -ne 0 ] && {
+ echo "Grouping not support [Skipped record]"
+ return
+ }
+ }
+ if ! perf record -o "${perfdata}" -e "$events" -- \
perf test -w brstack 2> /dev/null
then
echo "Leader sampling [Failed record]"
diff --git a/tools/perf/tests/shell/sched.sh b/tools/perf/tests/shell/sched.sh
index b9b81eaf856e..b9637069adb1 100755
--- a/tools/perf/tests/shell/sched.sh
+++ b/tools/perf/tests/shell/sched.sh
@@ -53,7 +53,7 @@ start_noploops() {
}
cleanup_noploops() {
- kill "$PID1" "$PID2"
+ kill "$PID1" "$PID2" || true
}
test_sched_record() {
diff --git a/tools/perf/tests/shell/script_dlfilter.sh b/tools/perf/tests/shell/script_dlfilter.sh
index 45c97d4a7d5f..aaed92bb7828 100755
--- a/tools/perf/tests/shell/script_dlfilter.sh
+++ b/tools/perf/tests/shell/script_dlfilter.sh
@@ -68,17 +68,17 @@ test_dlfilter() {
fi
# Build the dlfilter
- if ! cc -c -I tools/perf/include -fpic -x c "${dlfilter_c}" -o "${dlfilter_so}.o"
+ if ! cc -c -I ${shelldir}/../../include -fpic -x c "${dlfilter_c}" -o "${dlfilter_so}.o"
then
- echo "Basic --dlfilter test [Failed to build dlfilter object]"
- err=1
+ echo "Basic --dlfilter test [Skip - failed to build dlfilter object]"
+ err=2
return
fi
if ! cc -shared -o "${dlfilter_so}" "${dlfilter_so}.o"
then
- echo "Basic --dlfilter test [Failed to link dlfilter shared object]"
- err=1
+ echo "Basic --dlfilter test [Skip - failed to link dlfilter shared object]"
+ err=2
return
fi
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
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
diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh
index 0b2f0f88ca16..4edb04039036 100755
--- a/tools/perf/tests/shell/stat.sh
+++ b/tools/perf/tests/shell/stat.sh
@@ -5,6 +5,21 @@
set -e
err=0
+stat_output=$(mktemp /tmp/perf-stat-test-output.XXXXX)
+
+cleanup() {
+ rm -f "${stat_output}"
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cleanup
+ exit 1
+}
+
+trap trap_cleanup EXIT TERM INT
+
test_default_stat() {
echo "Basic stat command test"
if ! perf stat true 2>&1 | grep -E -q "Performance counter stats for 'true':"
@@ -233,7 +248,7 @@ test_hybrid() {
fi
# Run default Perf stat
- cycles_events=$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/[uH]*| cpu-cycles[:uH]* " -c)
+ cycles_events=$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/[uH]*| cpu-cycles[:uH]* " | wc -l)
# The expectation is that default output will have a cycles events on each
# hybrid PMU. In situations with no cycles PMU events, like virtualized, this
@@ -248,6 +263,226 @@ test_hybrid() {
echo "hybrid test [Success]"
}
+test_stat_cpu() {
+ echo "stat -C <cpu> test"
+ # Test the full online CPU list (ranges and lists)
+ online_cpus=$(cat /sys/devices/system/cpu/online)
+ if ! perf stat -C "$online_cpus" -a true > "${stat_output}" 2>&1
+ then
+ echo "stat -C <cpu> test [Failed - command failed for cpus $online_cpus]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! grep -E -q "Performance counter stats for" "${stat_output}"
+ then
+ echo "stat -C <cpu> test [Failed - missing output for cpus $online_cpus]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ # Test each individual online CPU
+ for cpu_dir in /sys/devices/system/cpu/cpu[0-9]*; do
+ cpu=${cpu_dir##*/cpu}
+ # Check if online
+ if [ -f "$cpu_dir/online" ] && [ "$(cat "$cpu_dir/online")" -eq 0 ]
+ then
+ continue
+ fi
+
+ if ! perf stat -C "$cpu" -a true > "${stat_output}" 2>&1
+ then
+ echo "stat -C <cpu> test [Failed - command failed for cpu $cpu]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ if ! grep -E -q "Performance counter stats for" "${stat_output}"
+ then
+ echo "stat -C <cpu> test [Failed - missing output for cpu $cpu]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ done
+
+ # Test synthetic list and range if cpu0 and cpu1 are online
+ c0_online=0
+ c1_online=0
+ if [ -d "/sys/devices/system/cpu/cpu0" ]
+ then
+ if [ ! -f "/sys/devices/system/cpu/cpu0/online" ] || [ "$(cat /sys/devices/system/cpu/cpu0/online)" -eq 1 ]
+ then
+ c0_online=1
+ fi
+ fi
+ if [ -d "/sys/devices/system/cpu/cpu1" ]
+ then
+ if [ ! -f "/sys/devices/system/cpu/cpu1/online" ] || [ "$(cat /sys/devices/system/cpu/cpu1/online)" -eq 1 ]
+ then
+ c1_online=1
+ fi
+ fi
+
+ if [ $c0_online -eq 1 ] && [ $c1_online -eq 1 ]
+ then
+ # Test list "0,1"
+ if ! perf stat -C "0,1" -a true > "${stat_output}" 2>&1
+ then
+ echo "stat -C <cpu> test [Failed - command failed for cpus 0,1]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ if ! grep -E -q "Performance counter stats for" "${stat_output}"
+ then
+ echo "stat -C <cpu> test [Failed - missing output for cpus 0,1]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ # Test range "0-1"
+ if ! perf stat -C "0-1" -a true > "${stat_output}" 2>&1
+ then
+ echo "stat -C <cpu> test [Failed - command failed for cpus 0-1]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ if ! grep -E -q "Performance counter stats for" "${stat_output}"
+ then
+ echo "stat -C <cpu> test [Failed - missing output for cpus 0-1]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ fi
+
+ echo "stat -C <cpu> test [Success]"
+}
+
+test_stat_no_aggr() {
+ echo "stat -A test"
+ if ! perf stat -A -a true > "${stat_output}" 2>&1
+ then
+ echo "stat -A test [Failed - command failed]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! grep -E -q "CPU" "${stat_output}"
+ then
+ echo "stat -A test [Failed - missing CPU column]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ echo "stat -A test [Success]"
+}
+
+test_stat_detailed() {
+ echo "stat -d test"
+ if ! perf stat -d true > "${stat_output}" 2>&1
+ then
+ echo "stat -d test [Failed - command failed]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! grep -E -q "Performance counter stats" "${stat_output}"
+ then
+ echo "stat -d test [Failed - missing output]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! perf stat -dd true > "${stat_output}" 2>&1
+ then
+ echo "stat -dd test [Failed - command failed]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! grep -E -q "Performance counter stats" "${stat_output}"
+ then
+ echo "stat -dd test [Failed - missing output]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! perf stat -ddd true > "${stat_output}" 2>&1
+ then
+ echo "stat -ddd test [Failed - command failed]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! grep -E -q "Performance counter stats" "${stat_output}"
+ then
+ echo "stat -ddd test [Failed - missing output]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ echo "stat -d test [Success]"
+}
+
+test_stat_repeat() {
+ echo "stat -r test"
+ if ! perf stat -r 2 true > "${stat_output}" 2>&1
+ then
+ echo "stat -r test [Failed - command failed]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+
+ if ! grep -E -q "\([[:space:]]*\+-.*%[[:space:]]*\)" "${stat_output}"
+ then
+ echo "stat -r test [Failed - missing variance]"
+ cat "${stat_output}"
+ err=1
+ return
+ fi
+ echo "stat -r test [Success]"
+}
+
+test_stat_pid() {
+ echo "stat -p test"
+ sleep 1 &
+ pid=$!
+ if ! perf stat -p $pid > "${stat_output}" 2>&1
+ then
+ echo "stat -p test [Failed - command failed]"
+ cat "${stat_output}"
+ err=1
+ kill $pid 2>/dev/null || true
+ wait $pid 2>/dev/null || true
+ return
+ fi
+
+ if ! grep -E -q "Performance counter stats" "${stat_output}"
+ then
+ echo "stat -p test [Failed - missing output]"
+ cat "${stat_output}"
+ err=1
+ else
+ echo "stat -p test [Success]"
+ fi
+ kill $pid 2>/dev/null || true
+ wait $pid 2>/dev/null || true
+}
+
test_default_stat
test_null_stat
test_offline_cpu_stat
@@ -258,4 +493,11 @@ test_topdown_groups
test_topdown_weak_groups
test_cputype
test_hybrid
+test_stat_cpu
+test_stat_no_aggr
+test_stat_detailed
+test_stat_repeat
+test_stat_pid
+
+cleanup
exit $err
diff --git a/tools/perf/tests/shell/stat_all_metricgroups.sh b/tools/perf/tests/shell/stat_all_metricgroups.sh
index 1400880ec01f..81bc7070b5ab 100755
--- a/tools/perf/tests/shell/stat_all_metricgroups.sh
+++ b/tools/perf/tests/shell/stat_all_metricgroups.sh
@@ -12,31 +12,32 @@ if ParanoidAndNotRoot 0
then
system_wide_flag=""
fi
-err=0
+
+err=3
+skip=0
for m in $(perf list --raw-dump metricgroups)
do
echo "Testing $m"
result=$(perf stat -M "$m" $system_wide_flag sleep 0.01 2>&1)
result_err=$?
- if [[ $result_err -gt 0 ]]
+ if [[ $result_err -eq 0 ]]
then
+ if [[ "$err" -ne 1 ]]
+ then
+ err=0
+ fi
+ else
if [[ "$result" =~ \
"Access to performance monitoring and observability operations is limited" ]]
then
echo "Permission failure"
echo $result
- if [[ $err -eq 0 ]]
- then
- err=2 # Skip
- fi
+ skip=1
elif [[ "$result" =~ "in per-thread mode, enable system wide" ]]
then
echo "Permissions - need system wide mode"
echo $result
- if [[ $err -eq 0 ]]
- then
- err=2 # Skip
- fi
+ skip=1
elif [[ "$m" == @(Default2|Default3|Default4) ]]
then
echo "Ignoring failures in $m that may contain unsupported legacy events"
@@ -48,4 +49,9 @@ do
fi
done
+if [[ "$err" -eq 3 && "$skip" -eq 1 ]]
+then
+ err=2
+fi
+
exit $err
diff --git a/tools/perf/tests/shell/stat_all_metrics.sh b/tools/perf/tests/shell/stat_all_metrics.sh
index 3dabb39c7cc8..b582d23f28c9 100755
--- a/tools/perf/tests/shell/stat_all_metrics.sh
+++ b/tools/perf/tests/shell/stat_all_metrics.sh
@@ -15,7 +15,8 @@ then
test_prog="perf test -w noploop"
fi
-err=0
+skip=0
+err=3
for m in $(perf list --raw-dump metrics); do
echo "Testing $m"
result=$(perf stat -M "$m" $system_wide_flag -- $test_prog 2>&1)
@@ -23,6 +24,10 @@ for m in $(perf list --raw-dump metrics); do
if [[ $result_err -eq 0 && "$result" =~ ${m:0:50} ]]
then
# No error result and metric shown.
+ if [[ "$err" -ne 1 ]]
+ then
+ err=0
+ fi
continue
fi
if [[ "$result" =~ "Cannot resolve IDs for" || "$result" =~ "No supported events found" ]]
@@ -44,7 +49,7 @@ for m in $(perf list --raw-dump metrics); do
echo $result
if [[ $err -eq 0 ]]
then
- err=2 # Skip
+ skip=1
fi
continue
elif [[ "$result" =~ "in per-thread mode, enable system wide" ]]
@@ -53,7 +58,7 @@ for m in $(perf list --raw-dump metrics); do
echo $result
if [[ $err -eq 0 ]]
then
- err=2 # Skip
+ skip=1
fi
continue
elif [[ "$result" =~ "<not supported>" ]]
@@ -68,7 +73,7 @@ for m in $(perf list --raw-dump metrics); do
echo $result
if [[ $err -eq 0 ]]
then
- err=2 # Skip
+ skip=1
fi
continue
elif [[ "$result" =~ "<not counted>" ]]
@@ -77,7 +82,7 @@ for m in $(perf list --raw-dump metrics); do
echo $result
if [[ $err -eq 0 ]]
then
- err=2 # Skip
+ skip=1
fi
continue
elif [[ "$result" =~ "FP_ARITH" || "$result" =~ "AMX" ]]
@@ -86,7 +91,7 @@ for m in $(perf list --raw-dump metrics); do
echo $result
if [[ $err -eq 0 ]]
then
- err=2 # Skip
+ skip=1
fi
continue
elif [[ "$result" =~ "PMM" ]]
@@ -95,7 +100,7 @@ for m in $(perf list --raw-dump metrics); do
echo $result
if [[ $err -eq 0 ]]
then
- err=2 # Skip
+ skip=1
fi
continue
fi
@@ -106,6 +111,10 @@ for m in $(perf list --raw-dump metrics); do
if [[ $result_err -eq 0 && "$result" =~ ${m:0:50} ]]
then
# No error result and metric shown.
+ if [[ "$err" -ne 1 ]]
+ then
+ err=0
+ fi
continue
fi
echo "[Failed $m] has non-zero error '$result_err' or not printed in:"
@@ -113,4 +122,10 @@ for m in $(perf list --raw-dump metrics); do
err=1
done
+# return SKIP only if no success returned
+if [[ "$err" -eq 3 && "$skip" -eq 1 ]]
+then
+ err=2
+fi
+
exit "$err"
diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh
index 1c750b67d141..bbf89e944e7b 100755
--- a/tools/perf/tests/shell/test_arm_coresight.sh
+++ b/tools/perf/tests/shell/test_arm_coresight.sh
@@ -198,6 +198,58 @@ arm_cs_etm_basic_test() {
arm_cs_report "CoreSight basic testing with '$*'" $err
}
+arm_cs_etm_test_cpu_list() {
+ echo "Testing sparse CPU list: $1"
+ perf record -o ${perfdata} -e cs_etm//u -C $1 \
+ -- taskset --cpu-list $1 true > /dev/null 2>&1
+ perf_script_branch_samples true
+ err=$?
+ arm_cs_report "CoreSight sparse CPUs with '$*'" $err
+}
+
+arm_cs_etm_sparse_cpus_test() {
+ # Iterate for every ETM device
+ cpus=()
+ for dev in /sys/bus/event_source/devices/cs_etm/cpu*; do
+ # Canonicalize the path
+ dev=`readlink -f $dev`
+
+ # Find the ETM device belonging to which CPU
+ cpus+=("$(cat $dev/cpu)")
+ done
+
+ mapfile -t cpus < <(printf '%s\n' "${cpus[@]}" | sort -n)
+ total=${#cpus[@]}
+
+ # Need more than 1 to test
+ if [ $total -le 1 ]; then
+ return 0
+ fi
+
+ half=$((total / 2))
+
+ # First half
+ first_half=$(IFS=,; echo "${cpus[*]:0:$half}")
+ arm_cs_etm_test_cpu_list $first_half
+
+ # Second half
+ second_half=$(IFS=,; echo "${cpus[*]:$half}")
+ arm_cs_etm_test_cpu_list $second_half
+
+ # Odd list is the same as halves unless >= 4 CPUs
+ if [ $total -lt 4 ]; then
+ return 0
+ fi
+
+ # Odd indices
+ odd_cpus=()
+ for ((i=1; i<total; i+=2)); do
+ odd_cpus+=("${cpus[$i]}")
+ done
+ odd_list=$(IFS=,; echo "${odd_cpus[*]}")
+ arm_cs_etm_test_cpu_list $odd_list
+}
+
arm_cs_etm_traverse_path_test
arm_cs_etm_system_wide_test
arm_cs_etm_snapshot_test
@@ -211,4 +263,6 @@ arm_cs_etm_basic_test -e cs_etm/timestamp=1/ -a
arm_cs_etm_basic_test -e cs_etm/timestamp=0/
arm_cs_etm_basic_test -e cs_etm/timestamp=1/
+arm_cs_etm_sparse_cpus_test
+
exit $glb_err
diff --git a/tools/perf/tests/shell/test_java_symbol.sh b/tools/perf/tests/shell/test_java_symbol.sh
index 499539d1c479..63a2cc9bf13f 100755
--- a/tools/perf/tests/shell/test_java_symbol.sh
+++ b/tools/perf/tests/shell/test_java_symbol.sh
@@ -22,10 +22,13 @@ cleanup_files()
trap cleanup_files exit term int
+PERF_DIR=$(dirname "$(which perf)")
if [ -e "$PWD/tools/perf/libperf-jvmti.so" ]; then
LIBJVMTI=$PWD/tools/perf/libperf-jvmti.so
elif [ -e "$PWD/libperf-jvmti.so" ]; then
LIBJVMTI=$PWD/libperf-jvmti.so
+elif [ -e "$PERF_DIR/libperf-jvmti.so" ]; then
+ LIBJVMTI=$PERF_DIR/libperf-jvmti.so
elif [ -e "$PREFIX/lib64/libperf-jvmti.so" ]; then
LIBJVMTI=$PREFIX/lib64/libperf-jvmti.so
elif [ -e "$PREFIX/lib/libperf-jvmti.so" ]; then
@@ -34,6 +37,7 @@ elif [ -e "/usr/lib/linux-tools-$(uname -a | awk '{ print $3 }' | sed -r 's/-gen
LIBJVMTI=/usr/lib/linux-tools-$(uname -a | awk '{ print $3 }' | sed -r 's/-generic//')/libperf-jvmti.so
else
echo "Fail to find libperf-jvmti.so"
+
# JVMTI is a build option, skip the test if fail to find lib
exit 2
fi
diff --git a/tools/perf/tests/shell/test_perf_data_converter_ctf.sh b/tools/perf/tests/shell/test_perf_data_converter_ctf.sh
new file mode 100755
index 000000000000..334eebc9945e
--- /dev/null
+++ b/tools/perf/tests/shell/test_perf_data_converter_ctf.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+# 'perf data convert --to-ctf' command test
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+err=0
+
+perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
+ctf_dir=$(mktemp -d /tmp/__perf_test.ctf.XXXXX)
+
+cleanup()
+{
+ rm -f "${perfdata}"
+ rm -rf "${ctf_dir}"
+ trap - exit term int
+}
+
+trap_cleanup()
+{
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cleanup
+ exit ${err}
+}
+trap trap_cleanup exit term int
+
+check_babeltrace_support()
+{
+ if ! perf check feature libbabeltrace
+ then
+ echo "perf not linked with libbabeltrace, skipping test"
+ exit 2
+ fi
+}
+
+test_ctf_converter_file()
+{
+ echo "Testing Perf Data Conversion Command to CTF (File input)"
+ # Record some data
+ if ! perf record -o "$perfdata" -F 99 -g -- perf test -w noploop
+ then
+ echo "Failed to record perf data"
+ err=1
+ return
+ fi
+
+ # Cleanup previous ctf dir
+ rm -rf "${ctf_dir}"
+
+ # Convert
+ if ! perf data convert --to-ctf "$ctf_dir" --force -i "$perfdata"
+ then
+ echo "Perf Data Converter Command to CTF (File input) [FAILED]"
+ err=1
+ return
+ fi
+
+ if [ -d "${ctf_dir}" ] && [ "$(ls -A "${ctf_dir}")" ]
+ then
+ echo "Perf Data Converter Command to CTF (File input) [SUCCESS]"
+ else
+ echo "Perf Data Converter Command to CTF (File input) [FAILED]"
+ echo " Output directory empty or missing"
+ err=1
+ fi
+}
+
+test_ctf_converter_pipe()
+{
+ echo "Testing Perf Data Conversion Command to CTF (Pipe mode)"
+
+ # Cleanup previous ctf dir
+ rm -rf "${ctf_dir}"
+
+ # Record to stdout and pipe to $perfdata file
+ if ! perf record -o - -F 99 -g -- perf test -w noploop > "$perfdata"
+ then
+ echo "Failed to record perf data"
+ err=1
+ return
+ fi
+
+ if ! perf data convert --to-ctf "$ctf_dir" --force -i "$perfdata"
+ then
+ echo "Perf Data Converter Command to CTF (Pipe mode) [FAILED]"
+ err=1
+ return
+ fi
+
+ if [ -d "${ctf_dir}" ] && [ "$(ls -A "${ctf_dir}")" ]
+ then
+ echo "Perf Data Converter Command to CTF (Pipe mode) [SUCCESS]"
+ else
+ echo "Perf Data Converter Command to CTF (Pipe mode) [FAILED]"
+ echo " Output directory empty or missing"
+ err=1
+ fi
+}
+
+check_babeltrace_support
+test_ctf_converter_file
+test_ctf_converter_pipe
+
+exit ${err}
diff --git a/tools/perf/tests/shell/test_perf_data_converter_json.sh b/tools/perf/tests/shell/test_perf_data_converter_json.sh
index c4f1b59d116f..35d81e39a26c 100755
--- a/tools/perf/tests/shell/test_perf_data_converter_json.sh
+++ b/tools/perf/tests/shell/test_perf_data_converter_json.sh
@@ -15,29 +15,42 @@ result=$(mktemp /tmp/__perf_test.output.json.XXXXX)
cleanup()
{
- rm -f "${perfdata}"
+ rm -f "${perfdata}*"
rm -f "${result}"
trap - exit term int
}
trap_cleanup()
{
+ echo "Unexpected signal in ${FUNCNAME[1]}"
cleanup
- exit ${err}
+ exit 1
}
trap trap_cleanup exit term int
test_json_converter_command()
{
- echo "Testing Perf Data Convertion Command to JSON"
- perf record -o "$perfdata" -F 99 -g -- perf test -w noploop > /dev/null 2>&1
- perf data convert --to-json "$result" --force -i "$perfdata" >/dev/null 2>&1
+ echo "Testing Perf Data Conversion Command to JSON"
+ perf record -o "$perfdata" -F 99 -g -- perf test -w noploop
+ perf data convert --to-json "$result" --force -i "$perfdata"
if [ "$(cat ${result} | wc -l)" -gt "0" ] ; then
echo "Perf Data Converter Command to JSON [SUCCESS]"
else
echo "Perf Data Converter Command to JSON [FAILED]"
err=1
- exit
+ fi
+}
+
+test_json_converter_pipe()
+{
+ echo "Testing Perf Data Conversion Command to JSON (Pipe mode)"
+ perf record -o - -F 99 -g -- perf test -w noploop > "$perfdata"
+ cat "$perfdata" | perf data convert --to-json "$result" --force -i -
+ if [ "$(cat ${result} | wc -l)" -gt "0" ] ; then
+ echo "Perf Data Converter Command to JSON (Pipe mode) [SUCCESS]"
+ else
+ echo "Perf Data Converter Command to JSON (Pipe mode) [FAILED]"
+ err=1
fi
}
@@ -50,16 +63,18 @@ validate_json_format()
else
echo "The file does not contain valid JSON format [FAILED]"
err=1
- exit
fi
else
echo "File not found [FAILED]"
- err=2
- exit
+ err=1
fi
}
test_json_converter_command
validate_json_format
+test_json_converter_pipe
+validate_json_format
+
+cleanup
exit ${err}
diff --git a/tools/perf/tests/subcmd-help.c b/tools/perf/tests/subcmd-help.c
index 2280b4c0e5e7..9da96a16fd20 100644
--- a/tools/perf/tests/subcmd-help.c
+++ b/tools/perf/tests/subcmd-help.c
@@ -95,10 +95,36 @@ static int test__exclude_cmdnames(struct test_suite *test __maybe_unused,
return TEST_OK;
}
+static int test__exclude_cmdnames_no_overlap(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ struct cmdnames cmds1 = {};
+ struct cmdnames cmds2 = {};
+
+ add_cmdname(&cmds1, "read-vdso32", 11);
+ add_cmdname(&cmds2, "archive", 7);
+
+ TEST_ASSERT_VAL("invalid original size", cmds1.cnt == 1);
+ TEST_ASSERT_VAL("invalid original size", cmds2.cnt == 1);
+
+ exclude_cmds(&cmds1, &cmds2);
+
+ TEST_ASSERT_VAL("invalid excluded size", cmds1.cnt == 1);
+ TEST_ASSERT_VAL("invalid excluded size", cmds2.cnt == 1);
+
+ TEST_ASSERT_VAL("cannot find cmd", is_in_cmdlist(&cmds1, "read-vdso32") == 1);
+ TEST_ASSERT_VAL("wrong cmd", is_in_cmdlist(&cmds1, "archive") == 0);
+
+ clean_cmdnames(&cmds1);
+ clean_cmdnames(&cmds2);
+ return TEST_OK;
+}
+
static struct test_case tests__subcmd_help[] = {
TEST_CASE("Load subcmd names", load_cmdnames),
TEST_CASE("Uniquify subcmd names", uniq_cmdnames),
TEST_CASE("Exclude duplicate subcmd names", exclude_cmdnames),
+ TEST_CASE("Exclude disjoint subcmd names", exclude_cmdnames_no_overlap),
{ .name = NULL, }
};
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 4a2ad7176fa0..b6e46975379c 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
+#include <linux/compiler.h>
#include <linux/string.h>
#include "tests.h"
@@ -28,7 +29,7 @@
static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
{
int i, err = -1;
- volatile int tmp = 0;
+ volatile int tmp __maybe_unused = 0;
u64 total_periods = 0;
int nr_samples = 0;
char sbuf[STRERR_BUFSIZE];
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index cb67ddbd0375..f5f1238d1f7f 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -240,6 +240,11 @@ DECLARE_WORKLOAD(brstack);
DECLARE_WORKLOAD(datasym);
DECLARE_WORKLOAD(landlock);
DECLARE_WORKLOAD(traploop);
+DECLARE_WORKLOAD(inlineloop);
+
+#ifdef HAVE_RUST_SUPPORT
+DECLARE_WORKLOAD(code_with_type);
+#endif
extern const char *dso_to_test;
extern const char *test_objdump_path;
diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c
index b273d287e164..bf2c5b133884 100644
--- a/tools/perf/tests/util.c
+++ b/tools/perf/tests/util.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "tests.h"
+#include "util/blake2s.h"
#include "util/debug.h"
-#include "util/sha1.h"
#include <linux/compiler.h>
#include <stdlib.h>
@@ -17,45 +17,72 @@ static int test_strreplace(char needle, const char *haystack,
return ret == 0;
}
-#define MAX_LEN 512
+/* Maximum data length tested by test_blake2s() */
+#define MAX_DATA_LEN 512
-/* Test sha1() for all lengths from 0 to MAX_LEN inclusively. */
-static int test_sha1(void)
+/*
+ * Hash length tested by test_blake2s(). BLAKE2s supports variable-length
+ * hashes. However, the only user of BLAKE2s in 'perf' uses 20-byte hashes,
+ * matching the length of the ELF build ID field. So that's the length we test.
+ */
+#define HASH_LEN 20
+
+/* Test the implementation of the BLAKE2s hash algorithm. */
+static int test_blake2s(void)
{
- u8 data[MAX_LEN];
- size_t digests_size = (MAX_LEN + 1) * SHA1_DIGEST_SIZE;
- u8 *digests;
- u8 digest_of_digests[SHA1_DIGEST_SIZE];
+ u8 data[MAX_DATA_LEN];
+ u8 hash[HASH_LEN];
+ u8 hash2[HASH_LEN];
+ struct blake2s_ctx main_ctx;
/*
- * The correctness of this value was verified by running this test with
- * sha1() replaced by OpenSSL's SHA1().
+ * This value was generated by the following Python code:
+ *
+ * import hashlib
+ *
+ * data = bytes(i % 256 for i in range(513))
+ * h = hashlib.blake2s(digest_size=20)
+ * for i in range(513):
+ * h.update(hashlib.blake2s(data=data[:i], digest_size=20).digest())
+ * print(h.hexdigest())
*/
- static const u8 expected_digest_of_digests[SHA1_DIGEST_SIZE] = {
- 0x74, 0xcd, 0x4c, 0xb9, 0xd8, 0xa6, 0xd5, 0x95, 0x22, 0x8b,
- 0x7e, 0xd6, 0x8b, 0x7e, 0x46, 0x95, 0x31, 0x9b, 0xa2, 0x43,
+ static const u8 expected_hash_of_hashes[20] = {
+ 0xef, 0x9b, 0x13, 0x98, 0x78, 0x8e, 0x74, 0x59, 0x9c, 0xd5,
+ 0x0c, 0xf0, 0x33, 0x97, 0x79, 0x3d, 0x3e, 0xd0, 0x95, 0xa6
};
size_t i;
- digests = malloc(digests_size);
- TEST_ASSERT_VAL("failed to allocate digests", digests != NULL);
-
- /* Generate MAX_LEN bytes of data. */
- for (i = 0; i < MAX_LEN; i++)
+ /* Generate MAX_DATA_LEN bytes of data. */
+ for (i = 0; i < MAX_DATA_LEN; i++)
data[i] = i;
- /* Calculate a SHA-1 for each length 0 through MAX_LEN inclusively. */
- for (i = 0; i <= MAX_LEN; i++)
- sha1(data, i, &digests[i * SHA1_DIGEST_SIZE]);
+ blake2s_init(&main_ctx, sizeof(hash));
+ for (i = 0; i <= MAX_DATA_LEN; i++) {
+ struct blake2s_ctx ctx;
+
+ /* Compute the BLAKE2s hash of 'i' data bytes. */
+ blake2s_init(&ctx, HASH_LEN);
+ blake2s_update(&ctx, data, i);
+ blake2s_final(&ctx, hash);
- /* Calculate digest of all digests calculated above. */
- sha1(digests, digests_size, digest_of_digests);
+ /* Verify that multiple updates produce the same result. */
+ blake2s_init(&ctx, HASH_LEN);
+ blake2s_update(&ctx, data, i / 2);
+ blake2s_update(&ctx, &data[i / 2], i - (i / 2));
+ blake2s_final(&ctx, hash2);
+ TEST_ASSERT_VAL("inconsistent BLAKE2s hashes",
+ memcmp(hash, hash2, HASH_LEN) == 0);
- free(digests);
+ /*
+ * Pass the hash to another BLAKE2s context, so that we
+ * incrementally compute the hash of all the hashes.
+ */
+ blake2s_update(&main_ctx, hash, HASH_LEN);
+ }
- /* Check for the expected result. */
- TEST_ASSERT_VAL("wrong output from sha1()",
- memcmp(digest_of_digests, expected_digest_of_digests,
- SHA1_DIGEST_SIZE) == 0);
+ /* Verify the hash of all the hashes. */
+ blake2s_final(&main_ctx, hash);
+ TEST_ASSERT_VAL("wrong BLAKE2s hashes",
+ memcmp(hash, expected_hash_of_hashes, HASH_LEN) == 0);
return 0;
}
@@ -68,7 +95,7 @@ static int test__util(struct test_suite *t __maybe_unused, int subtest __maybe_u
TEST_ASSERT_VAL("replace long", test_strreplace('a', "abcabc", "longlong",
"longlongbclonglongbc"));
- return test_sha1();
+ return test_blake2s();
}
DEFINE_SUITE("util", util);
diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build
index fb1012cc4fc3..2ef97f7affce 100644
--- a/tools/perf/tests/workloads/Build
+++ b/tools/perf/tests/workloads/Build
@@ -8,9 +8,16 @@ perf-test-y += brstack.o
perf-test-y += datasym.o
perf-test-y += landlock.o
perf-test-y += traploop.o
+perf-test-y += inlineloop.o
+
+ifeq ($(CONFIG_RUST_SUPPORT),y)
+ perf-test-y += code_with_type.o
+ perf-test-y += code_with_type.a
+endif
CFLAGS_sqrtloop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_leafloop.o = -g -O0 -fno-inline -fno-omit-frame-pointer -U_FORTIFY_SOURCE
CFLAGS_brstack.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_datasym.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_traploop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
+CFLAGS_inlineloop.o = -g -O2
diff --git a/tools/perf/tests/workloads/code_with_type.c b/tools/perf/tests/workloads/code_with_type.c
new file mode 100644
index 000000000000..65d7be7dac24
--- /dev/null
+++ b/tools/perf/tests/workloads/code_with_type.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <linux/compiler.h>
+#include "../tests.h"
+
+extern void test_rs(uint count);
+
+static volatile sig_atomic_t done;
+
+static void sighandler(int sig __maybe_unused)
+{
+ done = 1;
+}
+
+static int code_with_type(int argc, const char **argv)
+{
+ int sec = 1, num_loops = 100;
+
+ pthread_setname_np(pthread_self(), "perf-code-with-type");
+ if (argc > 0)
+ sec = atoi(argv[0]);
+
+ if (argc > 1)
+ num_loops = atoi(argv[1]);
+
+ signal(SIGINT, sighandler);
+ signal(SIGALRM, sighandler);
+ alarm(sec);
+
+ /*
+ * Rust doesn't have signal management in the standard library. To
+ * not deal with any external crates, offload signal handling to the
+ * outside code.
+ */
+ while (!done) {
+ test_rs(num_loops);
+ continue;
+ }
+
+ return 0;
+}
+
+DEFINE_WORKLOAD(code_with_type);
diff --git a/tools/perf/tests/workloads/code_with_type.rs b/tools/perf/tests/workloads/code_with_type.rs
new file mode 100644
index 000000000000..3dab39b22dd7
--- /dev/null
+++ b/tools/perf/tests/workloads/code_with_type.rs
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// We're going to look for this structure in the data type profiling report
+#[allow(dead_code)]
+struct Buf {
+ data1: u64,
+ data2: String,
+ data3: u64,
+}
+
+#[no_mangle]
+pub extern "C" fn test_rs(count: u32) {
+ let mut b = Buf {
+ data1: 0,
+ data2: String::from("data"),
+ data3: 0,
+ };
+
+ for _ in 1..count {
+ b.data1 += 1;
+ if b.data1 == 123 {
+ b.data1 += 1;
+ }
+
+ b.data3 += b.data1;
+ }
+}
diff --git a/tools/perf/tests/workloads/inlineloop.c b/tools/perf/tests/workloads/inlineloop.c
new file mode 100644
index 000000000000..bc82dfc7c410
--- /dev/null
+++ b/tools/perf/tests/workloads/inlineloop.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <linux/compiler.h>
+#include "../tests.h"
+
+static volatile int a;
+static volatile sig_atomic_t done;
+
+static void sighandler(int sig __maybe_unused)
+{
+ done = 1;
+}
+
+static inline void __attribute__((always_inline)) leaf(int b)
+{
+again:
+ a += b;
+ if (!done)
+ goto again;
+}
+
+static inline void __attribute__((always_inline)) middle(int b)
+{
+ leaf(b);
+}
+
+static noinline void parent(int b)
+{
+ middle(b);
+}
+
+static int inlineloop(int argc, const char **argv)
+{
+ int sec = 1;
+
+ pthread_setname_np(pthread_self(), "perf-inlineloop");
+ if (argc > 0)
+ sec = atoi(argv[0]);
+
+ signal(SIGINT, sighandler);
+ signal(SIGALRM, sighandler);
+ alarm(sec);
+
+ parent(sec);
+
+ return 0;
+}
+
+DEFINE_WORKLOAD(inlineloop);