| .. | .. | 
|---|
| 1 | 1 | #!/bin/sh | 
|---|
|  | 2 | +# SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 2 | 3 |  | 
|---|
| 3 | 4 | # ftracetest - Ftrace test shell scripts | 
|---|
| 4 | 5 | # | 
|---|
| 5 | 6 | # Copyright (C) Hitachi Ltd., 2014 | 
|---|
| 6 | 7 | #  Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 
|---|
| 7 | 8 | # | 
|---|
| 8 |  | -# Released under the terms of the GPL v2. | 
|---|
| 9 | 9 |  | 
|---|
| 10 | 10 | usage() { # errno [message] | 
|---|
| 11 | 11 | [ ! -z "$2" ] && echo $2 | 
|---|
| .. | .. | 
|---|
| 17 | 17 | echo "		-vv        Alias of -v -v (Show all results in stdout)" | 
|---|
| 18 | 18 | echo "		-vvv       Alias of -v -v -v (Show all commands immediately)" | 
|---|
| 19 | 19 | echo "		--fail-unsupported Treat UNSUPPORTED as a failure" | 
|---|
|  | 20 | +echo "		--fail-unresolved Treat UNRESOLVED as a failure" | 
|---|
| 20 | 21 | echo "		-d|--debug Debug mode (trace all shell commands)" | 
|---|
| 21 | 22 | echo "		-l|--logdir <dir> Save logs on the <dir>" | 
|---|
| 22 | 23 | echo "		            If <dir> is -, all logs output in console only" | 
|---|
| 23 | 24 | exit $1 | 
|---|
| 24 | 25 | } | 
|---|
| 25 | 26 |  | 
|---|
|  | 27 | +# default error | 
|---|
|  | 28 | +err_ret=1 | 
|---|
|  | 29 | + | 
|---|
|  | 30 | +# kselftest skip code is 4 | 
|---|
|  | 31 | +err_skip=4 | 
|---|
|  | 32 | + | 
|---|
|  | 33 | +# umount required | 
|---|
|  | 34 | +UMOUNT_DIR="" | 
|---|
|  | 35 | + | 
|---|
|  | 36 | +# cgroup RT scheduling prevents chrt commands from succeeding, which | 
|---|
|  | 37 | +# induces failures in test wakeup tests.  Disable for the duration of | 
|---|
|  | 38 | +# the tests. | 
|---|
|  | 39 | + | 
|---|
|  | 40 | +readonly sched_rt_runtime=/proc/sys/kernel/sched_rt_runtime_us | 
|---|
|  | 41 | + | 
|---|
|  | 42 | +sched_rt_runtime_orig=$(cat $sched_rt_runtime) | 
|---|
|  | 43 | + | 
|---|
|  | 44 | +setup() { | 
|---|
|  | 45 | +  echo -1 > $sched_rt_runtime | 
|---|
|  | 46 | +} | 
|---|
|  | 47 | + | 
|---|
|  | 48 | +cleanup() { | 
|---|
|  | 49 | +  echo $sched_rt_runtime_orig > $sched_rt_runtime | 
|---|
|  | 50 | +  if [ -n "${UMOUNT_DIR}" ]; then | 
|---|
|  | 51 | +    umount ${UMOUNT_DIR} ||: | 
|---|
|  | 52 | +  fi | 
|---|
|  | 53 | +} | 
|---|
|  | 54 | + | 
|---|
| 26 | 55 | errexit() { # message | 
|---|
| 27 | 56 | echo "Error: $1" 1>&2 | 
|---|
| 28 |  | -  exit 1 | 
|---|
|  | 57 | +  cleanup | 
|---|
|  | 58 | +  exit $err_ret | 
|---|
| 29 | 59 | } | 
|---|
| 30 | 60 |  | 
|---|
| 31 | 61 | # Ensuring user privilege | 
|---|
| 32 | 62 | if [ `id -u` -ne 0 ]; then | 
|---|
| 33 | 63 | errexit "this must be run by root user" | 
|---|
| 34 | 64 | fi | 
|---|
|  | 65 | + | 
|---|
|  | 66 | +setup | 
|---|
| 35 | 67 |  | 
|---|
| 36 | 68 | # Utilities | 
|---|
| 37 | 69 | absdir() { # file_path | 
|---|
| .. | .. | 
|---|
| 60 | 92 | shift 1 | 
|---|
| 61 | 93 | ;; | 
|---|
| 62 | 94 | --verbose|-v|-vv|-vvv) | 
|---|
|  | 95 | +      if [ $VERBOSE -eq -1 ]; then | 
|---|
|  | 96 | +	usage "--console can not use with --verbose" | 
|---|
|  | 97 | +      fi | 
|---|
| 63 | 98 | VERBOSE=$((VERBOSE + 1)) | 
|---|
| 64 | 99 | [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1)) | 
|---|
| 65 | 100 | [ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2)) | 
|---|
|  | 101 | +      shift 1 | 
|---|
|  | 102 | +    ;; | 
|---|
|  | 103 | +    --console) | 
|---|
|  | 104 | +      if [ $VERBOSE -ne 0 ]; then | 
|---|
|  | 105 | +	usage "--console can not use with --verbose" | 
|---|
|  | 106 | +      fi | 
|---|
|  | 107 | +      VERBOSE=-1 | 
|---|
| 66 | 108 | shift 1 | 
|---|
| 67 | 109 | ;; | 
|---|
| 68 | 110 | --debug|-d) | 
|---|
| 69 | 111 | DEBUG=1 | 
|---|
| 70 | 112 | shift 1 | 
|---|
| 71 | 113 | ;; | 
|---|
|  | 114 | +    --stop-fail) | 
|---|
|  | 115 | +      STOP_FAILURE=1 | 
|---|
|  | 116 | +      shift 1 | 
|---|
|  | 117 | +    ;; | 
|---|
| 72 | 118 | --fail-unsupported) | 
|---|
| 73 | 119 | UNSUPPORTED_RESULT=1 | 
|---|
|  | 120 | +      shift 1 | 
|---|
|  | 121 | +    ;; | 
|---|
|  | 122 | +    --fail-unresolved) | 
|---|
|  | 123 | +      UNRESOLVED_RESULT=1 | 
|---|
| 74 | 124 | shift 1 | 
|---|
| 75 | 125 | ;; | 
|---|
| 76 | 126 | --logdir|-l) | 
|---|
| .. | .. | 
|---|
| 102 | 152 | } | 
|---|
| 103 | 153 |  | 
|---|
| 104 | 154 | # Parameters | 
|---|
| 105 |  | -DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1` | 
|---|
| 106 |  | -if [ -z "$DEBUGFS_DIR" ]; then | 
|---|
| 107 |  | -    TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1` | 
|---|
| 108 |  | -else | 
|---|
| 109 |  | -    TRACING_DIR=$DEBUGFS_DIR/tracing | 
|---|
|  | 155 | +TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1` | 
|---|
|  | 156 | +if [ -z "$TRACING_DIR" ]; then | 
|---|
|  | 157 | +    DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1` | 
|---|
|  | 158 | +    if [ -z "$DEBUGFS_DIR" ]; then | 
|---|
|  | 159 | +	# If tracefs exists, then so does /sys/kernel/tracing | 
|---|
|  | 160 | +	if [ -d "/sys/kernel/tracing" ]; then | 
|---|
|  | 161 | +	    mount -t tracefs nodev /sys/kernel/tracing || | 
|---|
|  | 162 | +	      errexit "Failed to mount /sys/kernel/tracing" | 
|---|
|  | 163 | +	    TRACING_DIR="/sys/kernel/tracing" | 
|---|
|  | 164 | +	    UMOUNT_DIR=${TRACING_DIR} | 
|---|
|  | 165 | +	# If debugfs exists, then so does /sys/kernel/debug | 
|---|
|  | 166 | +	elif [ -d "/sys/kernel/debug" ]; then | 
|---|
|  | 167 | +	    mount -t debugfs nodev /sys/kernel/debug || | 
|---|
|  | 168 | +	      errexit "Failed to mount /sys/kernel/debug" | 
|---|
|  | 169 | +	    TRACING_DIR="/sys/kernel/debug/tracing" | 
|---|
|  | 170 | +	    UMOUNT_DIR=${TRACING_DIR} | 
|---|
|  | 171 | +	else | 
|---|
|  | 172 | +	    err_ret=$err_skip | 
|---|
|  | 173 | +	    errexit "debugfs and tracefs are not configured in this kernel" | 
|---|
|  | 174 | +	fi | 
|---|
|  | 175 | +    else | 
|---|
|  | 176 | +	TRACING_DIR="$DEBUGFS_DIR/tracing" | 
|---|
|  | 177 | +    fi | 
|---|
|  | 178 | +fi | 
|---|
|  | 179 | +if [ ! -d "$TRACING_DIR" ]; then | 
|---|
|  | 180 | +    err_ret=$err_skip | 
|---|
|  | 181 | +    errexit "ftrace is not configured in this kernel" | 
|---|
| 110 | 182 | fi | 
|---|
| 111 | 183 |  | 
|---|
| 112 | 184 | TOP_DIR=`absdir $0` | 
|---|
| .. | .. | 
|---|
| 117 | 189 | DEBUG=0 | 
|---|
| 118 | 190 | VERBOSE=0 | 
|---|
| 119 | 191 | UNSUPPORTED_RESULT=0 | 
|---|
|  | 192 | +UNRESOLVED_RESULT=0 | 
|---|
|  | 193 | +STOP_FAILURE=0 | 
|---|
| 120 | 194 | # Parse command-line options | 
|---|
| 121 | 195 | parse_opts $* | 
|---|
| 122 | 196 |  | 
|---|
| .. | .. | 
|---|
| 137 | 211 | date > $LOG_FILE | 
|---|
| 138 | 212 | fi | 
|---|
| 139 | 213 |  | 
|---|
|  | 214 | +# Define text colors | 
|---|
|  | 215 | +# Check available colors on the terminal, if any | 
|---|
|  | 216 | +ncolors=`tput colors 2>/dev/null || echo 0` | 
|---|
|  | 217 | +color_reset= | 
|---|
|  | 218 | +color_red= | 
|---|
|  | 219 | +color_green= | 
|---|
|  | 220 | +color_blue= | 
|---|
|  | 221 | +# If stdout exists and number of colors is eight or more, use them | 
|---|
|  | 222 | +if [ -t 1 -a "$ncolors" -ge 8 ]; then | 
|---|
|  | 223 | +  color_reset="\033[0m" | 
|---|
|  | 224 | +  color_red="\033[31m" | 
|---|
|  | 225 | +  color_green="\033[32m" | 
|---|
|  | 226 | +  color_blue="\033[34m" | 
|---|
|  | 227 | +fi | 
|---|
|  | 228 | + | 
|---|
|  | 229 | +strip_esc() { | 
|---|
|  | 230 | +  # busybox sed implementation doesn't accept "\x1B", so use [:cntrl:] instead. | 
|---|
|  | 231 | +  sed -E "s/[[:cntrl:]]\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | 
|---|
|  | 232 | +} | 
|---|
|  | 233 | + | 
|---|
| 140 | 234 | prlog() { # messages | 
|---|
| 141 |  | -  [ -z "$LOG_FILE" ] && echo "$@" || echo "$@" | tee -a $LOG_FILE | 
|---|
|  | 235 | +  newline="\n" | 
|---|
|  | 236 | +  if [ "$1" = "-n" ] ; then | 
|---|
|  | 237 | +    newline= | 
|---|
|  | 238 | +    shift | 
|---|
|  | 239 | +  fi | 
|---|
|  | 240 | +  printf "$*$newline" | 
|---|
|  | 241 | +  [ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE | 
|---|
| 142 | 242 | } | 
|---|
| 143 | 243 | catlog() { #file | 
|---|
| 144 |  | -  [ -z "$LOG_FILE" ] && cat $1 || cat $1 | tee -a $LOG_FILE | 
|---|
|  | 244 | +  cat $1 | 
|---|
|  | 245 | +  [ "$LOG_FILE" ] && cat $1 | strip_esc >> $LOG_FILE | 
|---|
| 145 | 246 | } | 
|---|
| 146 | 247 | prlog "=== Ftrace unit tests ===" | 
|---|
| 147 | 248 |  | 
|---|
| .. | .. | 
|---|
| 167 | 268 |  | 
|---|
| 168 | 269 | INSTANCE= | 
|---|
| 169 | 270 | CASENO=0 | 
|---|
|  | 271 | + | 
|---|
| 170 | 272 | testcase() { # testfile | 
|---|
| 171 | 273 | CASENO=$((CASENO+1)) | 
|---|
| 172 |  | -  desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:` | 
|---|
|  | 274 | +  desc=`grep "^#[ \t]*description:" $1 | cut -f2- -d:` | 
|---|
| 173 | 275 | prlog -n "[$CASENO]$INSTANCE$desc" | 
|---|
|  | 276 | +} | 
|---|
|  | 277 | + | 
|---|
|  | 278 | +checkreq() { # testfile | 
|---|
|  | 279 | +  requires=`grep "^#[ \t]*requires:" $1 | cut -f2- -d:` | 
|---|
|  | 280 | +  # Use eval to pass quoted-patterns correctly. | 
|---|
|  | 281 | +  eval check_requires "$requires" | 
|---|
| 174 | 282 | } | 
|---|
| 175 | 283 |  | 
|---|
| 176 | 284 | test_on_instance() { # testfile | 
|---|
| .. | .. | 
|---|
| 180 | 288 | eval_result() { # sigval | 
|---|
| 181 | 289 | case $1 in | 
|---|
| 182 | 290 | $PASS) | 
|---|
| 183 |  | -      prlog "	[PASS]" | 
|---|
|  | 291 | +      prlog "	[${color_green}PASS${color_reset}]" | 
|---|
| 184 | 292 | PASSED_CASES="$PASSED_CASES $CASENO" | 
|---|
| 185 | 293 | return 0 | 
|---|
| 186 | 294 | ;; | 
|---|
| 187 | 295 | $FAIL) | 
|---|
| 188 |  | -      prlog "	[FAIL]" | 
|---|
|  | 296 | +      prlog "	[${color_red}FAIL${color_reset}]" | 
|---|
| 189 | 297 | FAILED_CASES="$FAILED_CASES $CASENO" | 
|---|
| 190 | 298 | return 1 # this is a bug. | 
|---|
| 191 | 299 | ;; | 
|---|
| 192 | 300 | $UNRESOLVED) | 
|---|
| 193 |  | -      prlog "	[UNRESOLVED]" | 
|---|
|  | 301 | +      prlog "	[${color_blue}UNRESOLVED${color_reset}]" | 
|---|
| 194 | 302 | UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO" | 
|---|
| 195 |  | -      return 1 # this is a kind of bug.. something happened. | 
|---|
|  | 303 | +      return $UNRESOLVED_RESULT # depends on use case | 
|---|
| 196 | 304 | ;; | 
|---|
| 197 | 305 | $UNTESTED) | 
|---|
| 198 |  | -      prlog "	[UNTESTED]" | 
|---|
|  | 306 | +      prlog "	[${color_blue}UNTESTED${color_reset}]" | 
|---|
| 199 | 307 | UNTESTED_CASES="$UNTESTED_CASES $CASENO" | 
|---|
| 200 | 308 | return 0 | 
|---|
| 201 | 309 | ;; | 
|---|
| 202 | 310 | $UNSUPPORTED) | 
|---|
| 203 |  | -      prlog "	[UNSUPPORTED]" | 
|---|
|  | 311 | +      prlog "	[${color_blue}UNSUPPORTED${color_reset}]" | 
|---|
| 204 | 312 | UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO" | 
|---|
| 205 | 313 | return $UNSUPPORTED_RESULT # depends on use case | 
|---|
| 206 | 314 | ;; | 
|---|
| 207 | 315 | $XFAIL) | 
|---|
| 208 |  | -      prlog "	[XFAIL]" | 
|---|
|  | 316 | +      prlog "	[${color_green}XFAIL${color_reset}]" | 
|---|
| 209 | 317 | XFAILED_CASES="$XFAILED_CASES $CASENO" | 
|---|
| 210 | 318 | return 0 | 
|---|
| 211 | 319 | ;; | 
|---|
| 212 | 320 | *) | 
|---|
| 213 |  | -      prlog "	[UNDEFINED]" | 
|---|
|  | 321 | +      prlog "	[${color_blue}UNDEFINED${color_reset}]" | 
|---|
| 214 | 322 | UNDEFINED_CASES="$UNDEFINED_CASES $CASENO" | 
|---|
| 215 | 323 | return 1 # this must be a test bug | 
|---|
| 216 | 324 | ;; | 
|---|
| .. | .. | 
|---|
| 262 | 370 |  | 
|---|
| 263 | 371 | __run_test() { # testfile | 
|---|
| 264 | 372 | # setup PID and PPID, $$ is not updated. | 
|---|
| 265 |  | -  (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; initialize_ftrace; . $1) | 
|---|
|  | 373 | +  (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; | 
|---|
|  | 374 | +   checkreq $1; initialize_ftrace; . $1) | 
|---|
| 266 | 375 | [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID | 
|---|
| 267 | 376 | } | 
|---|
| 268 | 377 |  | 
|---|
| 269 | 378 | # Run one test case | 
|---|
| 270 | 379 | run_test() { # testfile | 
|---|
| 271 | 380 | local testname=`basename $1` | 
|---|
|  | 381 | +  testcase $1 | 
|---|
| 272 | 382 | if [ ! -z "$LOG_FILE" ] ; then | 
|---|
| 273 |  | -    local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` | 
|---|
|  | 383 | +    local testlog=`mktemp $LOG_DIR/${CASENO}-${testname}-log.XXXXXX` | 
|---|
| 274 | 384 | else | 
|---|
| 275 | 385 | local testlog=/proc/self/fd/1 | 
|---|
| 276 | 386 | fi | 
|---|
| 277 | 387 | export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX` | 
|---|
| 278 |  | -  testcase $1 | 
|---|
|  | 388 | +  export FTRACETEST_ROOT=$TOP_DIR | 
|---|
| 279 | 389 | echo "execute$INSTANCE: "$1 > $testlog | 
|---|
| 280 | 390 | SIG_RESULT=0 | 
|---|
| 281 |  | -  if [ -z "$LOG_FILE" ]; then | 
|---|
|  | 391 | +  if [ $VERBOSE -eq -1 ]; then | 
|---|
|  | 392 | +    __run_test $1 | 
|---|
|  | 393 | +  elif [ -z "$LOG_FILE" ]; then | 
|---|
| 282 | 394 | __run_test $1 2>&1 | 
|---|
| 283 | 395 | elif [ $VERBOSE -ge 3 ]; then | 
|---|
| 284 | 396 | __run_test $1 | tee -a $testlog 2>&1 | 
|---|
| .. | .. | 
|---|
| 304 | 416 | # Main loop | 
|---|
| 305 | 417 | for t in $TEST_CASES; do | 
|---|
| 306 | 418 | run_test $t | 
|---|
|  | 419 | +  if [ $STOP_FAILURE -ne 0 -a $TOTAL_RESULT -ne 0 ]; then | 
|---|
|  | 420 | +    echo "A failure detected. Stop test." | 
|---|
|  | 421 | +    exit 1 | 
|---|
|  | 422 | +  fi | 
|---|
| 307 | 423 | done | 
|---|
| 308 | 424 |  | 
|---|
| 309 | 425 | # Test on instance loop | 
|---|
| .. | .. | 
|---|
| 315 | 431 | run_test $t | 
|---|
| 316 | 432 | rmdir $TRACING_DIR | 
|---|
| 317 | 433 | TRACING_DIR=$SAVED_TRACING_DIR | 
|---|
|  | 434 | +  if [ $STOP_FAILURE -ne 0 -a $TOTAL_RESULT -ne 0 ]; then | 
|---|
|  | 435 | +    echo "A failure detected. Stop test." | 
|---|
|  | 436 | +    exit 1 | 
|---|
|  | 437 | +  fi | 
|---|
| 318 | 438 | done | 
|---|
|  | 439 | +(cd $TRACING_DIR; initialize_ftrace) # for cleanup | 
|---|
| 319 | 440 |  | 
|---|
| 320 | 441 | prlog "" | 
|---|
| 321 | 442 | prlog "# of passed: " `echo $PASSED_CASES | wc -w` | 
|---|
| .. | .. | 
|---|
| 326 | 447 | prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w` | 
|---|
| 327 | 448 | prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w` | 
|---|
| 328 | 449 |  | 
|---|
|  | 450 | +cleanup | 
|---|
|  | 451 | + | 
|---|
| 329 | 452 | # if no error, return 0 | 
|---|
| 330 | 453 | exit $TOTAL_RESULT | 
|---|