Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240#!/bin/bash# SPDX-License-Identifier: GPL-2.0## Run the objtool klp tests. Each test-*.sh prints one TAP result line.## Tests live in generic/ and in a directory per architecture. A run executes# generic/ plus the one matching this architecture, so a test which cannot# apply here is not run rather than reporting a skip; what was left out is# reported once, as a comment, so differing coverage is still visible.## A run covers one compiler and one architecture; CI runs the combinations.# The harness checks the environment once up front and fails the run if the# suite cannot execute, rather than letting every test skip and exit 0.
set -u
# Determinism: the order test-*.sh expands in, and how grep's character ranges# and sort's collation behave inside the tests, are all locale-dependent. A# suite whose results depend on the invoking shell's locale is a suite whose# failures cannot be reproduced.export LC_ALL=C
usage(){ cat <<EOFusage: $(basename "$0") [-k|--keep] [test...]
Run the objtool klp tests for this architecture: everything in generic/, pluseverything in the directory named for it. With no arguments, runs all of them.A test may be named with or without its "test-" prefix and ".sh" suffix, and islooked for in both directories.
Options: -k, --keep same as KEEP=all (see below)
Environment: OBJTOOL objtool binary to test (default ../objtool) CC compiler used to build fixtures (default gcc) ARCH architecture the tests are for (default: uname -m) KEEP failed keep only failing tests (default) all keep every test's working directory none remove all working directories
A test which needs something of its own says so in its skip message.EOF exit "${1:-0}"}
cd "$(dirname "$0")" || exit 1
keep_from_args=while [ $# -gt 0 ]; do case "$1" in -h|--help) usage ;; -k|--keep) keep_from_args=all; shift ;; --) shift; break ;; -*) echo "unknown option: $1" >&2; usage 1 ;; *) break ;; esacdone
KLP_TEST_KEEP="${KEEP:-failed}"[ -n "$keep_from_args" ] && KLP_TEST_KEEP="$keep_from_args"case "$KLP_TEST_KEEP" inall|none|failed) ;;*) echo "invalid KEEP=$KLP_TEST_KEEP (want failed, all, or none)" >&2 exit 1 ;;esacexport KLP_TEST_KEEP
echo "TAP version 13"
# Sourcing the harness runs its preflight, which decides which architecture# this run is for -- so the test list cannot be built before it has, and the# tests inherit the answers rather than working them out again.. ./lib.sh
dirs=( generic )[ -d "$KLP_TEST_ARCH" ] && dirs+=( "$KLP_TEST_ARCH" )
if [ $# -gt 0 ]; then tests=() for arg in "$@"; do name="test-${arg#test-}"; name="${name%.sh}.sh" found= for d in "${dirs[@]}"; do [ -f "$d/$name" ] || continue [ -x "$d/$name" ] || { echo "not executable: $d/$name" >&2; exit 1; } tests+=( "$d/$name" ); found=y done [ -n "$found" ] || { echo "no such test for $KLP_TEST_ARCH: $arg" >&2; exit 1; } doneelse tests=() for d in "${dirs[@]}"; do for t in "$d"/test-*.sh; do [ -f "$t" ] && tests+=( "$t" ) done done [ "${#tests[@]}" -gt 0 ] || { echo "1..0 # SKIP no tests found"; exit 0; }
# Tests for another architecture are absent from this run entirely. Say # how many, so a run which covers less than the tree holds does not look # like one that covers all of it. for d in */; do d="${d%/}" case "$d" in generic|"$KLP_TEST_ARCH") continue ;; esac n=$(ls "$d"/test-*.sh 2>/dev/null | wc -l) [ "$n" -gt 0 ] || continue echo "# not run: $n test$( [ "$n" = 1 ] || echo s ) in $d/" \ "(this run is $KLP_TEST_ARCH)" donefi
# One directory for the whole run, one per test inside it, mirroring the# source layout. A run then leaves a single thing behind instead of 39# scattered among everything else using mktemp.rundir="$(mktemp -d "${TMPDIR:-/tmp}/klp-tests.XXXXXXXX")" || { echo "Bail out! cannot create a working directory" >&2; exit 1; }
# The run's own two levels: each test's directory, and the one per source# directory holding them. Take them away if the tests left them empty, and# say so if they did not. Either rmdir may fail -- the glob stays unexpanded# when nothing was created -- so ask the directory itself rather than trusting# the status. Never rm -rf: what to keep is the tests' decision, made in# cleanup() as each one exits, and this must not overrule it.reap_rundir(){ rmdir "$rundir"/*/ 2>/dev/null rmdir "$rundir" 2>/dev/null [ -d "$rundir" ]}
# An interrupted run has the same directory to answer for, and the tests it# never reached will not clean up on their way out. The one it was running# has, and under the default it kept what it had built, so say where.interrupted(){ reap_rundir && echo "# interrupted; what was built is in $rundir" exit 130}trap interrupted INT TERM HUP
echo "1..${#tests[@]}"
pass=0 fail=0 static_skip=0 probe_skip=0 xfail=0 xpass=0failed_dirs=()
for t in "${tests[@]}"; do out="$(KLP_TEST_WORKDIR="$rundir/${t%.sh}" ./"$t" 2>&1)" rc=$?
# A test prints one result line, but it is not necessarily the only # thing it prints: objtool warns on stderr, and the runner captures # that. Classify the result line itself rather than the whole of the # output, or a stray line ahead of it makes every pattern below miss and # the exit status decide -- which would count an expected failure, which # exits 0, as a pass. result="$(printf '%s\n' "$out" | grep -E '^(ok|not ok)' | tail -1)" rest="$(printf '%s\n' "$out" | grep -Ev '^(ok|not ok)')"
# Classify from the result line, not the exit status: a skip and a pass # both exit 0, and telling them apart is the point of counting. # # The two skip kinds differ in what they promise. A static skip was # declared before the test ran ("clang does not do this"), so it is # expected indefinitely. A probe skip means the construct did not turn # up this time, which is weaker and worth watching: one that becomes # permanent is a fixture that quietly stopped testing anything. case "$result" in *"# SKIP (declared)"*) static_skip=$((static_skip + 1)) ;; *"# SKIP (probe)"*) probe_skip=$((probe_skip + 1)) ;; *"# SKIP"*) # An undeclared skip: the test gave up for a reason it never # said it might. That is a hole, not an expected outcome. # # Replace the line rather than adding one. Every test owes the # plan exactly one result, and a consumer counting them is # entitled to say so when the totals disagree. rest="$rest${rest:+$'\n'}was: $result" result="not ok - $(basename "$t" .sh): undeclared skip" result="$result (use gcc_only/clang_only or require_input_*)" fail=$((fail + 1)); failed_dirs+=( "$rundir/${t%.sh}" ) ;; "not ok"*"# TODO"*) xfail=$((xfail + 1)) ;; "ok"*"# TODO"*) xpass=$((xpass + 1)); failed_dirs+=( "$rundir/${t%.sh}" ) ;; "not ok"*) fail=$((fail + 1)); failed_dirs+=( "$rundir/${t%.sh}" ) ;; "ok"*) pass=$((pass + 1)) ;; *) # No result line at all: the test died before reporting. rest="$rest${rest:+$'\n'}exited $rc without a result line" result="not ok - $(basename "$t" .sh): no TAP result" fail=$((fail + 1)); failed_dirs+=( "$rundir/${t%.sh}" ) ;; esac
echo "$result" [ -n "$rest" ] && printf '%s\n' "$rest" | sed 's/^[^#]/# &/'
done
echo "# pass:$pass fail:$fail static-skip:$static_skip" \ "probe-skip:$probe_skip xfail:$xfail xpass:$xpass"
case "$KLP_TEST_KEEP" inall) echo "# keep=all: workdirs kept in $rundir" echo "# inspect: diff.log, readelf -S out.o under each test-* subdirectory" echo "# cleanup: rm -rf $rundir" ;;failed) if [ "${#failed_dirs[@]}" -gt 0 ]; then echo "# keep=failed: ${#failed_dirs[@]} failing test(s) kept under $rundir:" for d in "${failed_dirs[@]}"; do echo "# ${d#"$rundir"/}/" done echo "# inspect: diff.log readelf -S out.o" echo "# one test: $PWD/run-tests.sh <name>" echo "# cleanup: rm -rf $rundir" elif reap_rundir; then echo "# $rundir was not empty;" \ "a test did not clean up after itself" fi ;;none) if reap_rundir; then echo "# $rundir was not empty;" \ "a test did not clean up after itself" elif [ "$fail" != 0 ] || [ "$xpass" != 0 ]; then echo "# keep=none: artifacts were removed" \ "(re-run with KEEP=failed or KEEP=all)" fi ;;esac
[ "$fail" = 0 ] && [ "$xpass" = 0 ]