Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0-only
3
4# ftracetest - Ftrace test shell scripts
5#
6# Copyright (C) Hitachi Ltd., 2014
7# Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
8#
9
10usage() { # errno [message]
11[ ! -z "$2" ] && echo $2
12echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
13echo " Options:"
14echo " -h|--help Show help message"
15echo " -k|--keep Keep passed test logs"
16echo " -K|--ktap Output in KTAP format"
17echo " -v|--verbose Increase verbosity of test messages"
18echo " -vv Alias of -v -v (Show all results in stdout)"
19echo " -vvv Alias of -v -v -v (Show all commands immediately)"
20echo " --fail-unsupported Treat UNSUPPORTED as a failure"
21echo " --fail-unresolved Treat UNRESOLVED as a failure"
22echo " -d|--debug Debug mode (trace all shell commands)"
23echo " -l|--logdir <dir> Save logs on the <dir>"
24echo " If <dir> is -, all logs output in console only"
25echo " --rv Run RV selftests instead of ftrace ones"
26exit $1
27}
28
29# default error
30err_ret=1
31
32# kselftest skip code is 4
33err_skip=4
34
35# umount required
36UMOUNT_DIR=""
37
38# cgroup RT scheduling prevents chrt commands from succeeding, which
39# induces failures in test wakeup tests. Disable for the duration of
40# the tests.
41
42readonly sched_rt_runtime=/proc/sys/kernel/sched_rt_runtime_us
43
44sched_rt_runtime_orig=$(cat $sched_rt_runtime)
45
46setup() {
47 echo -1 > $sched_rt_runtime
48}
49
50cleanup() {
51 echo $sched_rt_runtime_orig > $sched_rt_runtime
52 if [ -n "${UMOUNT_DIR}" ]; then
53 umount ${UMOUNT_DIR} ||:
54 fi
55}
56
57errexit() { # message
58 echo "Error: $1" 1>&2
59 cleanup
60 exit $err_ret
61}
62
63# Ensuring user privilege
64if [ `id -u` -ne 0 ]; then
65 errexit "this must be run by root user"
66fi
67
68setup
69
70# Utilities
71absdir() { # file_path
72 (cd `dirname $1`; pwd)
73}
74
75abspath() {
76 echo `absdir $1`/`basename $1`
77}
78
79find_testcases() { #directory
80 echo `find $1 -name \*.tc | sort`
81}
82
83parse_opts() { # opts
84 local OPT_TEST_CASES=
85 local OPT_TEST_DIR=
86
87 while [ ! -z "$1" ]; do
88 case "$1" in
89 --help|-h)
90 usage 0
91 ;;
92 --keep|-k)
93 KEEP_LOG=1
94 shift 1
95 ;;
96 --ktap|-K)
97 KTAP=1
98 shift 1
99 ;;
100 --verbose|-v|-vv|-vvv)
101 if [ $VERBOSE -eq -1 ]; then
102 usage "--console can not use with --verbose"
103 fi
104 VERBOSE=$((VERBOSE + 1))
105 [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
106 [ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2))
107 shift 1
108 ;;
109 --console)
110 if [ $VERBOSE -ne 0 ]; then
111 usage "--console can not use with --verbose"
112 fi
113 VERBOSE=-1
114 shift 1
115 ;;
116 --debug|-d)
117 DEBUG=1
118 shift 1
119 ;;
120 --stop-fail)
121 STOP_FAILURE=1
122 shift 1
123 ;;
124 --fail-unsupported)
125 UNSUPPORTED_RESULT=1
126 shift 1
127 ;;
128 --fail-unresolved)
129 UNRESOLVED_RESULT=1
130 shift 1
131 ;;
132 --logdir|-l)
133 USER_LOG_DIR=$2
134 shift 2
135 ;;
136 --rv)
137 RV_TEST=1
138 shift 1
139 ;;
140 *.tc)
141 if [ -f "$1" ]; then
142 OPT_TEST_CASES="$OPT_TEST_CASES `abspath $1`"
143 shift 1
144 else
145 usage 1 "$1 is not a testcase"
146 fi
147 ;;
148 *)
149 if [ -d "$1" ]; then
150 OPT_TEST_DIR=`abspath $1`
151 OPT_TEST_CASES="$OPT_TEST_CASES `find_testcases $OPT_TEST_DIR`"
152 shift 1
153 else
154 usage 1 "Invalid option ($1)"
155 fi
156 ;;
157 esac
158 done
159 if [ -n "$OPT_TEST_CASES" ]; then
160 TEST_CASES=$OPT_TEST_CASES
161 fi
162 if [ -n "$OPT_TEST_DIR" -a -f "$OPT_TEST_DIR"/test.d/functions ]; then
163 TOP_DIR=$OPT_TEST_DIR
164 TEST_DIR=$TOP_DIR/test.d
165 fi
166}
167
168# Parameters
169TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
170if [ -z "$TRACING_DIR" ]; then
171 DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
172 if [ -z "$DEBUGFS_DIR" ]; then
173 # If tracefs exists, then so does /sys/kernel/tracing
174 if [ -d "/sys/kernel/tracing" ]; then
175 mount -t tracefs nodev /sys/kernel/tracing ||
176 errexit "Failed to mount /sys/kernel/tracing"
177 TRACING_DIR="/sys/kernel/tracing"
178 UMOUNT_DIR=${TRACING_DIR}
179 # If debugfs exists, then so does /sys/kernel/debug
180 elif [ -d "/sys/kernel/debug" ]; then
181 mount -t debugfs nodev /sys/kernel/debug ||
182 errexit "Failed to mount /sys/kernel/debug"
183 TRACING_DIR="/sys/kernel/debug/tracing"
184 UMOUNT_DIR=${TRACING_DIR}
185 else
186 err_ret=$err_skip
187 errexit "debugfs and tracefs are not configured in this kernel"
188 fi
189 else
190 TRACING_DIR="$DEBUGFS_DIR/tracing"
191 fi
192fi
193if [ ! -d "$TRACING_DIR" ]; then
194 err_ret=$err_skip
195 errexit "ftrace is not configured in this kernel"
196fi
197
198TOP_DIR=`absdir $0`
199TEST_DIR=$TOP_DIR/test.d
200TEST_CASES=`find_testcases $TEST_DIR`
201USER_LOG_DIR=
202KEEP_LOG=0
203KTAP=0
204DEBUG=0
205VERBOSE=0
206UNSUPPORTED_RESULT=0
207UNRESOLVED_RESULT=0
208STOP_FAILURE=0
209RV_TEST=0
210# Parse command-line options
211parse_opts $*
212
213[ $DEBUG -ne 0 ] && set -x
214
215# TOP_DIR can be changed for rv. Setting log directory.
216LOG_TOP_DIR=$TOP_DIR/logs
217LOG_DATE=`date +%Y%m%d-%H%M%S`
218if [ -n "$USER_LOG_DIR" ]; then
219 LOG_DIR=$USER_LOG_DIR
220 LINK_PTR=
221else
222 LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/
223 LINK_PTR=$LOG_TOP_DIR/latest
224fi
225
226if [ $RV_TEST -ne 0 ]; then
227 TRACING_DIR=$TRACING_DIR/rv
228 if [ ! -d "$TRACING_DIR" ]; then
229 err_ret=$err_skip
230 errexit "rv is not configured in this kernel"
231 fi
232fi
233
234# Preparing logs
235if [ "x$LOG_DIR" = "x-" ]; then
236 LOG_FILE=
237 date
238else
239 LOG_FILE=$LOG_DIR/ftracetest.log
240 mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
241 date > $LOG_FILE
242 if [ "x-$LINK_PTR" != "x-" ]; then
243 unlink $LINK_PTR
244 ln -fs $LOG_DATE $LINK_PTR
245 fi
246fi
247
248# Define text colors
249# Check available colors on the terminal, if any
250ncolors=`tput colors 2>/dev/null || echo 0`
251color_reset=
252color_red=
253color_green=
254color_blue=
255# If stdout exists and number of colors is eight or more, use them
256if [ -t 1 -a "$ncolors" -ge 8 ]; then
257 color_reset="\033[0m"
258 color_red="\033[31m"
259 color_green="\033[32m"
260 color_blue="\033[34m"
261fi
262
263strip_esc() {
264 # busybox sed implementation doesn't accept "\x1B", so use [:cntrl:] instead.
265 sed -E "s/[[:cntrl:]]\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
266}
267
268prlog() { # messages
269 newline="\n"
270 if [ "$1" = "-n" ] ; then
271 newline=
272 shift
273 fi
274 [ "$KTAP" != "1" ] && printf "$*$newline"
275 [ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE
276}
277catlog() { #file
278 if [ "${KTAP}" = "1" ]; then
279 cat $1 | while read line ; do
280 echo "# $line"
281 done
282 else
283 cat $1
284 fi
285 [ "$LOG_FILE" ] && cat $1 | strip_esc >> $LOG_FILE
286}
287prlog "=== Ftrace unit tests ==="
288
289
290# Testcase management
291# Test result codes - Dejagnu extended code
292PASS=0 # The test succeeded.
293FAIL=1 # The test failed, but was expected to succeed.
294UNRESOLVED=2 # The test produced indeterminate results. (e.g. interrupted)
295UNTESTED=3 # The test was not run, currently just a placeholder.
296UNSUPPORTED=4 # The test failed because of lack of feature.
297XFAIL=5 # The test failed, and was expected to fail.
298
299# Accumulations
300PASSED_CASES=
301FAILED_CASES=
302UNRESOLVED_CASES=
303UNTESTED_CASES=
304UNSUPPORTED_CASES=
305XFAILED_CASES=
306UNDEFINED_CASES=
307TOTAL_RESULT=0
308
309INSTANCE=
310CASENO=0
311CASENAME=
312
313testcase() { # testfile
314 CASENO=$((CASENO+1))
315 CASENAME=`grep "^#[ \t]*description:" $1 | cut -f2- -d:`
316}
317
318checkreq() { # testfile
319 requires=`grep "^#[ \t]*requires:" $1 | cut -f2- -d:`
320 # Use eval to pass quoted-patterns correctly.
321 eval check_requires "$requires"
322}
323
324test_on_instance() { # testfile
325 grep -q "^#[ \t]*flags:.*instance" $1
326}
327
328ktaptest() { # result comment
329 if [ "$KTAP" != "1" ]; then
330 return
331 fi
332
333 local result=
334 if [ "$1" = "1" ]; then
335 result="ok"
336 else
337 result="not ok"
338 fi
339 shift
340
341 local comment=$*
342 if [ "$comment" != "" ]; then
343 comment="# $comment"
344 fi
345
346 echo $result $CASENO $INSTANCE$CASENAME $comment
347}
348
349eval_result() { # sigval
350 case $1 in
351 $PASS)
352 prlog " [${color_green}PASS${color_reset}]"
353 ktaptest 1
354 PASSED_CASES="$PASSED_CASES $CASENO"
355 return 0
356 ;;
357 $FAIL)
358 prlog " [${color_red}FAIL${color_reset}]"
359 ktaptest 0
360 FAILED_CASES="$FAILED_CASES $CASENO"
361 return 1 # this is a bug.
362 ;;
363 $UNRESOLVED)
364 prlog " [${color_blue}UNRESOLVED${color_reset}]"
365 ktaptest 0 UNRESOLVED
366 UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO"
367 return $UNRESOLVED_RESULT # depends on use case
368 ;;
369 $UNTESTED)
370 prlog " [${color_blue}UNTESTED${color_reset}]"
371 ktaptest 1 SKIP
372 UNTESTED_CASES="$UNTESTED_CASES $CASENO"
373 return 0
374 ;;
375 $UNSUPPORTED)
376 prlog " [${color_blue}UNSUPPORTED${color_reset}]"
377 ktaptest 1 SKIP
378 UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
379 return $UNSUPPORTED_RESULT # depends on use case
380 ;;
381 $XFAIL)
382 prlog " [${color_green}XFAIL${color_reset}]"
383 ktaptest 1 XFAIL
384 XFAILED_CASES="$XFAILED_CASES $CASENO"
385 return 0
386 ;;
387 *)
388 prlog " [${color_blue}UNDEFINED${color_reset}]"
389 ktaptest 0 error
390 UNDEFINED_CASES="$UNDEFINED_CASES $CASENO"
391 return 1 # this must be a test bug
392 ;;
393 esac
394}
395
396# Signal handling for result codes
397SIG_RESULT=
398SIG_BASE=36 # Use realtime signals
399SIG_PID=$$
400
401exit_pass () {
402 exit 0
403}
404
405SIG_FAIL=$((SIG_BASE + FAIL))
406exit_fail () {
407 exit 1
408}
409trap 'SIG_RESULT=$FAIL' $SIG_FAIL
410
411SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED))
412exit_unresolved () {
413 kill -s $SIG_UNRESOLVED $SIG_PID
414 exit 0
415}
416trap 'SIG_RESULT=$UNRESOLVED' $SIG_UNRESOLVED
417
418SIG_UNTESTED=$((SIG_BASE + UNTESTED))
419exit_untested () {
420 kill -s $SIG_UNTESTED $SIG_PID
421 exit 0
422}
423trap 'SIG_RESULT=$UNTESTED' $SIG_UNTESTED
424
425SIG_UNSUPPORTED=$((SIG_BASE + UNSUPPORTED))
426exit_unsupported () {
427 kill -s $SIG_UNSUPPORTED $SIG_PID
428 exit 0
429}
430trap 'SIG_RESULT=$UNSUPPORTED' $SIG_UNSUPPORTED
431
432SIG_XFAIL=$((SIG_BASE + XFAIL))
433exit_xfail () {
434 kill -s $SIG_XFAIL $SIG_PID
435 exit 0
436}
437trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL
438
439__run_test() { # testfile
440 # setup PID and PPID, $$ is not updated.
441 (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x;
442 checkreq $1; initialize_system; . $1)
443 [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID
444}
445
446# Run one test case
447run_test() { # testfile
448 local testname=`basename $1`
449 testcase $1
450 prlog -n "[$CASENO]$INSTANCE$CASENAME"
451 if [ ! -z "$LOG_FILE" ] ; then
452 local testlog=`mktemp $LOG_DIR/${CASENO}-${testname}-log.XXXXXX`
453 else
454 local testlog=/proc/self/fd/1
455 fi
456 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
457 export FTRACETEST_ROOT=$TOP_DIR
458 echo "execute$INSTANCE: "$1 > $testlog
459 SIG_RESULT=0
460 if [ $VERBOSE -eq -1 ]; then
461 __run_test $1
462 elif [ -z "$LOG_FILE" ]; then
463 __run_test $1 2>&1
464 elif [ $VERBOSE -ge 3 ]; then
465 __run_test $1 | tee -a $testlog 2>&1
466 elif [ $VERBOSE -eq 2 ]; then
467 __run_test $1 2>> $testlog | tee -a $testlog
468 else
469 __run_test $1 >> $testlog 2>&1
470 fi
471 eval_result $SIG_RESULT
472 if [ $? -eq 0 ]; then
473 # Remove test log if the test was done as it was expected.
474 [ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog
475 else
476 [ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog
477 TOTAL_RESULT=1
478 fi
479 rm -rf $TMPDIR
480}
481
482# load in the helper functions
483. $TEST_DIR/functions
484
485if [ "$KTAP" = "1" ]; then
486 echo "TAP version 13"
487
488 casecount=`echo $TEST_CASES | wc -w`
489 for t in $TEST_CASES; do
490 test_on_instance $t || continue
491 casecount=$((casecount+1))
492 done
493 echo "1..${casecount}"
494fi
495
496# Main loop
497for t in $TEST_CASES; do
498 run_test $t
499 if [ $STOP_FAILURE -ne 0 -a $TOTAL_RESULT -ne 0 ]; then
500 echo "A failure detected. Stop test."
501 exit 1
502 fi
503done
504
505# Test on instance loop
506INSTANCE=" (instance) "
507for t in $TEST_CASES; do
508 test_on_instance $t || continue
509 SAVED_TRACING_DIR=$TRACING_DIR
510 export TRACING_DIR=`mktemp -d $TRACING_DIR/instances/ftracetest.XXXXXX`
511 run_test $t
512 rmdir $TRACING_DIR
513 TRACING_DIR=$SAVED_TRACING_DIR
514 if [ $STOP_FAILURE -ne 0 -a $TOTAL_RESULT -ne 0 ]; then
515 echo "A failure detected. Stop test."
516 exit 1
517 fi
518done
519(cd $TRACING_DIR; finish_system) # for cleanup
520
521prlog ""
522prlog "# of passed: " `echo $PASSED_CASES | wc -w`
523prlog "# of failed: " `echo $FAILED_CASES | wc -w`
524prlog "# of unresolved: " `echo $UNRESOLVED_CASES | wc -w`
525prlog "# of untested: " `echo $UNTESTED_CASES | wc -w`
526prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w`
527prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w`
528prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
529
530if [ "$KTAP" = "1" ]; then
531 echo -n "# Totals:"
532 echo -n " pass:"`echo $PASSED_CASES | wc -w`
533 echo -n " fail:"`echo $FAILED_CASES | wc -w`
534 echo -n " xfail:"`echo $XFAILED_CASES | wc -w`
535 echo -n " xpass:0"
536 echo -n " skip:"`echo $UNTESTED_CASES $UNSUPPORTED_CASES | wc -w`
537 echo -n " error:"`echo $UNRESOLVED_CASES $UNDEFINED_CASES | wc -w`
538 echo
539fi
540
541cleanup
542
543# if no error, return 0
544exit $TOTAL_RESULT