Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tests: Harden branch stack sampling test

On continuous testing the perf script output can be empty, or nearly
empty, causing tr/grep to exit and due to "set -e" the test traps and
fails.

Add some empty file handling that sets the test to skip and make grep
and other text rewriting failures non-fatal by adding "|| true".

Committer testing:

root@number:~# grep -m1 "model name" /proc/cpuinfo
model name : AMD Ryzen 9 9950X3D 16-Core Processor
root@number:~# perf test "Check branch stack sampling"
104: Check branch stack sampling : Ok
root@number:~#
root@number:~# perf test -vvvvvvv "Check branch stack sampling"
104: Check branch stack sampling:
--- start ---
test child forked, pid 396047
142d22-142da0 l brstack_bench
perf does have symbol 'brstack_bench'
Testing user branch stack sampling
Testing branch stack filtering permutation (any_call,CALL|IND_CALL|COND_CALL|SYSCALL|IRQ)
Testing branch stack filtering permutation (call,CALL|SYSCALL)
Testing branch stack filtering permutation (cond,COND)
Testing branch stack filtering permutation (any_ret,RET|COND_RET|SYSRET|ERET)
Testing branch stack filtering permutation (call,cond,CALL|SYSCALL|COND)
Testing branch stack filtering permutation (any_call,cond,CALL|IND_CALL|COND_CALL|IRQ|SYSCALL|COND)
Testing branch stack filtering permutation (cond,any_call,any_ret,COND|CALL|IND_CALL|COND_CALL|SYSCALL|IRQ|RET|COND_RET|SYSRET|ERET)
---- end(0) ----
104: Check branch stack sampling : Ok
root@number:~#

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250318161639.34446-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
f3061d52 255f5b6d

+52 -20
+52 -20
tools/perf/tests/shell/test_brstack.sh
··· 1 - #!/bin/sh 1 + #!/bin/bash 2 2 # Check branch stack sampling 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 ··· 17 17 18 18 skip_test_missing_symbol brstack_bench 19 19 20 + err=0 20 21 TMPDIR=$(mktemp -d /tmp/__perf_test.program.XXXXX) 21 22 TESTPROG="perf test -w brstack" 22 23 23 24 cleanup() { 24 25 rm -rf $TMPDIR 26 + trap - EXIT TERM INT 25 27 } 26 28 27 - trap cleanup EXIT TERM INT 29 + trap_cleanup() { 30 + set +e 31 + echo "Unexpected signal in ${FUNCNAME[1]}" 32 + cleanup 33 + exit 1 34 + } 35 + trap trap_cleanup EXIT TERM INT 28 36 29 37 test_user_branches() { 30 38 echo "Testing user branch stack sampling" 31 39 32 - perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u -- ${TESTPROG} > /dev/null 2>&1 33 - perf script -i $TMPDIR/perf.data --fields brstacksym | tr -s ' ' '\n' > $TMPDIR/perf.script 40 + perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 41 + perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script" 34 42 35 43 # example of branch entries: 36 44 # brstack_foo+0x14/brstack_bar+0x40/P/-/-/0/CALL 37 45 38 - set -x 39 - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/IND_CALL/.*$" $TMPDIR/perf.script 40 - grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" $TMPDIR/perf.script 41 - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/CALL/.*$" $TMPDIR/perf.script 42 - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" $TMPDIR/perf.script 43 - grep -E -m1 "^brstack_bar\+[^ ]*/brstack_foo\+[^ ]*/RET/.*$" $TMPDIR/perf.script 44 - grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bench\+[^ ]*/RET/.*$" $TMPDIR/perf.script 45 - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bench\+[^ ]*/COND/.*$" $TMPDIR/perf.script 46 - grep -E -m1 "^brstack\+[^ ]*/brstack\+[^ ]*/UNCOND/.*$" $TMPDIR/perf.script 47 - set +x 48 - 46 + expected=( 47 + "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/IND_CALL/.*$" 48 + "^brstack_foo\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" 49 + "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/CALL/.*$" 50 + "^brstack_bench\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" 51 + "^brstack_bar\+[^ ]*/brstack_foo\+[^ ]*/RET/.*$" 52 + "^brstack_foo\+[^ ]*/brstack_bench\+[^ ]*/RET/.*$" 53 + "^brstack_bench\+[^ ]*/brstack_bench\+[^ ]*/COND/.*$" 54 + "^brstack\+[^ ]*/brstack\+[^ ]*/UNCOND/.*$" 55 + ) 56 + for x in "${expected[@]}" 57 + do 58 + if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$x" 59 + then 60 + echo "Branches missing $x" 61 + err=1 62 + fi 63 + done 49 64 # some branch types are still not being tested: 50 65 # IND COND_CALL COND_RET SYSCALL SYSRET IRQ SERROR NO_TX 51 66 } ··· 72 57 test_filter_expect=$2 73 58 74 59 echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)" 75 - 76 - perf record -o $TMPDIR/perf.data --branch-filter $test_filter_filter,save_type,u -- ${TESTPROG} > /dev/null 2>&1 77 - perf script -i $TMPDIR/perf.data --fields brstack | tr -s ' ' '\n' | grep '.' > $TMPDIR/perf.script 60 + perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 61 + perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script" 78 62 79 63 # fail if we find any branch type that doesn't match any of the expected ones 80 64 # also consider UNKNOWN branch types (-) 81 - if grep -E -vm1 "^[^ ]*/($test_filter_expect|-|( *))/.*$" $TMPDIR/perf.script; then 82 - return 1 65 + if [ ! -s "$TMPDIR/perf.script" ] 66 + then 67 + echo "Empty script output" 68 + err=1 69 + return 70 + fi 71 + # Look for lines not matching test_filter_expect ignoring issues caused 72 + # by empty output 73 + tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep '.' | \ 74 + grep -E -vm1 "^[^ ]*/($test_filter_expect|-|( *))/.*$" \ 75 + > "$TMPDIR/perf.script-filtered" || true 76 + if [ -s "$TMPDIR/perf.script-filtered" ] 77 + then 78 + echo "Unexpected branch filter in script output" 79 + cat "$TMPDIR/perf.script" 80 + err=1 81 + return 83 82 fi 84 83 } 85 84 ··· 109 80 test_filter "call,cond" "CALL|SYSCALL|COND" 110 81 test_filter "any_call,cond" "CALL|IND_CALL|COND_CALL|IRQ|SYSCALL|COND" 111 82 test_filter "cond,any_call,any_ret" "COND|CALL|IND_CALL|COND_CALL|SYSCALL|IRQ|RET|COND_RET|SYSRET|ERET" 83 + 84 + cleanup 85 + exit $err