1#!/bin/sh
2
3# ftracetest - Ftrace test shell scripts
4#
5# Copyright (C) Hitachi Ltd., 2014
6#  Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7#
8# Released under the terms of the GPL v2.
9
10usage() { # errno [message]
11[ "$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 "		-v|--verbose Show all stdout messages in testcases"
17echo "		-q|--quiet Do not show error log on stdout"
18echo "		-d|--debug Debug mode (trace all shell commands)"
19exit $1
20}
21
22errexit() { # message
23  echo "Error: $1" 1>&2
24  exit 1
25}
26
27# Ensuring user privilege
28if [ `id -u` -ne 0 ]; then
29  errexit "this must be run by root user"
30fi
31
32# Utilities
33absdir() { # file_path
34  (cd `dirname $1`; pwd)
35}
36
37abspath() {
38  echo `absdir $1`/`basename $1`
39}
40
41find_testcases() { #directory
42  echo `find $1 -name \*.tc | sort`
43}
44
45parse_opts() { # opts
46  local OPT_TEST_CASES=
47  local OPT_TEST_DIR=
48
49  while [ "$1" ]; do
50    case "$1" in
51    --help|-h)
52      usage 0
53    ;;
54    --keep|-k)
55      KEEP_LOG=1
56      shift 1
57    ;;
58    --verbose|-v)
59      VERBOSE=1
60      shift 1
61    ;;
62    --quiet|-q)
63      BE_QUIET=1
64      shift 1
65    ;;
66    --debug|-d)
67      DEBUG=1
68      shift 1
69    ;;
70    *.tc)
71      if [ -f "$1" ]; then
72        OPT_TEST_CASES="$OPT_TEST_CASES `abspath $1`"
73        shift 1
74      else
75        usage 1 "$1 is not a testcase"
76      fi
77      ;;
78    *)
79      if [ -d "$1" ]; then
80        OPT_TEST_DIR=`abspath $1`
81        OPT_TEST_CASES="$OPT_TEST_CASES `find_testcases $OPT_TEST_DIR`"
82        shift 1
83      else
84        usage 1 "Invalid option ($1)"
85      fi
86    ;;
87    esac
88  done
89  if [ "$OPT_TEST_CASES" ]; then
90    TEST_CASES=$OPT_TEST_CASES
91  fi
92}
93
94# Parameters
95DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
96if [ -z "$DEBUGFS_DIR" ]; then
97    TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
98else
99    TRACING_DIR=$DEBUGFS_DIR/tracing
100fi
101
102TOP_DIR=`absdir $0`
103TEST_DIR=$TOP_DIR/test.d
104TEST_CASES=`find_testcases $TEST_DIR`
105LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
106KEEP_LOG=0
107DEBUG=0
108VERBOSE=0
109BE_QUIET=0
110# Parse command-line options
111parse_opts $*
112
113[ $DEBUG -ne 0 ] && set -x
114
115# Verify parameters
116if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
117  errexit "No ftrace directory found"
118fi
119
120# Preparing logs
121LOG_FILE=$LOG_DIR/ftracetest.log
122mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
123date > $LOG_FILE
124prlog() { # messages
125  echo "$@" | tee -a $LOG_FILE
126}
127catlog() { #file
128  cat $1 | tee -a $LOG_FILE
129}
130prlog "=== Ftrace unit tests ==="
131
132
133# Testcase management
134# Test result codes - Dejagnu extended code
135PASS=0	# The test succeeded.
136FAIL=1	# The test failed, but was expected to succeed.
137UNRESOLVED=2  # The test produced indeterminate results. (e.g. interrupted)
138UNTESTED=3    # The test was not run, currently just a placeholder.
139UNSUPPORTED=4 # The test failed because of lack of feature.
140XFAIL=5	# The test failed, and was expected to fail.
141
142# Accumulations
143PASSED_CASES=
144FAILED_CASES=
145UNRESOLVED_CASES=
146UNTESTED_CASES=
147UNSUPPORTED_CASES=
148XFAILED_CASES=
149UNDEFINED_CASES=
150TOTAL_RESULT=0
151
152CASENO=0
153testcase() { # testfile
154  CASENO=$((CASENO+1))
155  desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
156  prlog -n "[$CASENO]$desc"
157}
158
159eval_result() { # sigval
160  case $1 in
161    $PASS)
162      prlog "	[PASS]"
163      PASSED_CASES="$PASSED_CASES $CASENO"
164      return 0
165    ;;
166    $FAIL)
167      prlog "	[FAIL]"
168      FAILED_CASES="$FAILED_CASES $CASENO"
169      return 1 # this is a bug.
170    ;;
171    $UNRESOLVED)
172      prlog "	[UNRESOLVED]"
173      UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO"
174      return 1 # this is a kind of bug.. something happened.
175    ;;
176    $UNTESTED)
177      prlog "	[UNTESTED]"
178      UNTESTED_CASES="$UNTESTED_CASES $CASENO"
179      return 0
180    ;;
181    $UNSUPPORTED)
182      prlog "	[UNSUPPORTED]"
183      UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
184      return 1 # this is not a bug, but the result should be reported.
185    ;;
186    $XFAIL)
187      prlog "	[XFAIL]"
188      XFAILED_CASES="$XFAILED_CASES $CASENO"
189      return 0
190    ;;
191    *)
192      prlog "	[UNDEFINED]"
193      UNDEFINED_CASES="$UNDEFINED_CASES $CASENO"
194      return 1 # this must be a test bug
195    ;;
196  esac
197}
198
199# Signal handling for result codes
200SIG_RESULT=
201SIG_BASE=36	# Use realtime signals
202SIG_PID=$$
203
204SIG_FAIL=$((SIG_BASE + FAIL))
205trap 'SIG_RESULT=$FAIL' $SIG_FAIL
206
207SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED))
208exit_unresolved () {
209  kill -s $SIG_UNRESOLVED $SIG_PID
210  exit 0
211}
212trap 'SIG_RESULT=$UNRESOLVED' $SIG_UNRESOLVED
213
214SIG_UNTESTED=$((SIG_BASE + UNTESTED))
215exit_untested () {
216  kill -s $SIG_UNTESTED $SIG_PID
217  exit 0
218}
219trap 'SIG_RESULT=$UNTESTED' $SIG_UNTESTED
220
221SIG_UNSUPPORTED=$((SIG_BASE + UNSUPPORTED))
222exit_unsupported () {
223  kill -s $SIG_UNSUPPORTED $SIG_PID
224  exit 0
225}
226trap 'SIG_RESULT=$UNSUPPORTED' $SIG_UNSUPPORTED
227
228SIG_XFAIL=$((SIG_BASE + XFAIL))
229exit_xfail () {
230  kill -s $SIG_XFAIL $SIG_PID
231  exit 0
232}
233trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL
234
235__run_test() { # testfile
236  # setup PID and PPID, $$ is not updated.
237  (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; initialize_ftrace; . $1)
238  [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID
239}
240
241# Run one test case
242run_test() { # testfile
243  local testname=`basename $1`
244  local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
245  export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
246  testcase $1
247  echo "execute: "$1 > $testlog
248  SIG_RESULT=0
249  if [ $VERBOSE -ne 0 ]; then
250    __run_test $1 2>> $testlog | tee -a $testlog
251  else
252    __run_test $1 >> $testlog 2>&1
253  fi
254  eval_result $SIG_RESULT
255  if [ $? -eq 0 ]; then
256    # Remove test log if the test was done as it was expected.
257    [ $KEEP_LOG -eq 0 ] && rm $testlog
258  else
259    [ $BE_QUIET -eq 0 ] && catlog $testlog
260    TOTAL_RESULT=1
261  fi
262  rm -rf $TMPDIR
263}
264
265# load in the helper functions
266. $TEST_DIR/functions
267
268# Main loop
269for t in $TEST_CASES; do
270  run_test $t
271done
272
273prlog ""
274prlog "# of passed: " `echo $PASSED_CASES | wc -w`
275prlog "# of failed: " `echo $FAILED_CASES | wc -w`
276prlog "# of unresolved: " `echo $UNRESOLVED_CASES | wc -w`
277prlog "# of untested: " `echo $UNTESTED_CASES | wc -w`
278prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w`
279prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w`
280prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
281
282# if no error, return 0
283exit $TOTAL_RESULT
284