• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2#
3# Copyright (c) Linux Test Project, 2014-2017
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18#
19# Written by Cyril Hrubis <chrubis@suse.cz>
20#
21# This is a LTP test library for shell.
22#
23
24export LTP_RET_VAL=0
25export TST_COUNT=1
26export TST_LIB_LOADED=1
27export TST_TMPDIR_RHOST=0
28
29. tst_ansi_color.sh
30
31# Exit values map
32tst_flag2mask()
33{
34	case "$1" in
35	TPASS) return 0;;
36	TFAIL) return 1;;
37	TBROK) return 2;;
38	TWARN) return 4;;
39	TINFO) return 16;;
40	TCONF) return 32;;
41	*) tst_brkm TBROK "Invalid resm type '$1'";;
42	esac
43}
44
45tst_resm()
46{
47	local ttype="$1"
48
49	tst_flag2mask "$ttype"
50	local mask=$?
51	LTP_RET_VAL=$((LTP_RET_VAL|mask))
52
53	local ret=$1
54	shift
55
56	printf "$TCID $TST_COUNT "
57	tst_print_colored $ret "$ret:"
58	echo " $@"
59
60	case "$ret" in
61	TPASS|TFAIL)
62	TST_COUNT=$((TST_COUNT+1));;
63	esac
64}
65
66tst_brkm()
67{
68	case "$1" in
69	TFAIL) ;;
70	TBROK) ;;
71	TCONF) ;;
72	*) tst_brkm TBROK "Invalid tst_brkm type '$1'";;
73	esac
74
75	local ret=$1
76	shift
77	tst_resm "$ret" "$@"
78	tst_exit
79}
80
81tst_record_childstatus()
82{
83	if [ $# -ne 1 ]; then
84		tst_brkm TBROK "Requires child pid as parameter"
85	fi
86
87	local child_pid=$1
88	local ret=0
89
90	wait $child_pid
91	ret=$?
92	if [ $ret -eq 127 ]; then
93		tst_brkm TBROK "Child process pid='$child_pid' does not exist"
94	fi
95	LTP_RET_VAL=$((LTP_RET_VAL|ret))
96}
97
98tst_require_root()
99{
100	if [ "$(id -ru)" != 0 ]; then
101		tst_brkm TCONF "Must be super/root for this test!"
102	fi
103}
104
105tst_exit()
106{
107	if [ -n "${TST_CLEANUP:-}" -a -z "${TST_NO_CLEANUP:-}" ]; then
108		$TST_CLEANUP
109	fi
110
111	if [ -n "${LTP_IPC_PATH:-}" -a -f "${LTP_IPC_PATH:-}" ]; then
112		rm -f "$LTP_IPC_PATH"
113	fi
114
115	# Mask out TINFO
116	exit $((LTP_RET_VAL & ~16))
117}
118
119tst_tmpdir()
120{
121	if [ -z "$TMPDIR" ]; then
122		export TMPDIR="/tmp"
123	fi
124
125	TST_TMPDIR=$(mktemp -d "$TMPDIR/$TCID.XXXXXXXXXX")
126
127	chmod 777 "$TST_TMPDIR"
128
129	TST_STARTWD=$(pwd)
130
131	cd "$TST_TMPDIR"
132}
133
134tst_rmdir()
135{
136	if [ -n "$TST_TMPDIR" ]; then
137		cd "$LTPROOT"
138		rm -r "$TST_TMPDIR"
139		[ "$TST_TMPDIR_RHOST" = 1 ] && tst_cleanup_rhost
140	fi
141}
142
143#
144# Checks if commands passed as arguments exists
145#
146tst_check_cmds()
147{
148	local cmd
149	for cmd in $*; do
150		if ! command -v $cmd > /dev/null 2>&1; then
151			tst_brkm TCONF "'$cmd' not found"
152		fi
153	done
154}
155
156# tst_retry "command" [times]
157# try run command for specified times, default is 3.
158# Function returns 0 if succeed in RETRIES times or the last retcode the cmd
159# returned
160tst_retry()
161{
162	local cmd="$1"
163	local RETRIES=${2:-"3"}
164	local i=$RETRIES
165
166	while [ $i -gt 0 ]; do
167		eval "$cmd"
168		ret=$?
169		if [ $ret -eq 0 ]; then
170			break
171		fi
172		i=$((i-1))
173		sleep 1
174	done
175
176	if [ $ret -ne 0 ]; then
177		tst_resm TINFO "Failed to execute '$cmd' after $RETRIES retries"
178	fi
179
180	return $ret
181}
182
183# tst_timeout "command arg1 arg2 ..." timeout
184# Runs command for specified timeout (in seconds).
185# Function returns retcode of command or 1 if arguments are invalid.
186tst_timeout()
187{
188	local command=$1
189	local timeout=$(echo $2 | grep -o "^[0-9]\+$")
190
191	# command must be non-empty string with command to run
192	if [ -z "$command" ]; then
193		echo "first argument must be non-empty string"
194		return 1
195	fi
196
197	# accept only numbers as timeout
198	if [ -z "$timeout" ]; then
199		echo "only numbers as second argument"
200		return 1
201	fi
202
203	setsid sh -c "eval $command" 2>&1 &
204	local pid=$!
205	while [ $timeout -gt 0 ]; do
206		kill -s 0 $pid 2>/dev/null
207		if [ $? -ne 0 ]; then
208			break
209		fi
210		timeout=$((timeout - 1))
211		sleep 1
212	done
213
214	local ret=0
215	if [ $timeout -le 0 ]; then
216		ret=128
217		kill -TERM -- -$pid
218	fi
219
220	wait $pid
221	ret=$((ret | $?))
222
223	return $ret
224}
225
226ROD_SILENT()
227{
228	$@ > /dev/null 2>&1
229	if [ $? -ne 0 ]; then
230		tst_brkm TBROK "$@ failed"
231	fi
232}
233
234ROD_BASE()
235{
236	local cmd
237	local arg
238	local file
239	local flag
240
241	for arg; do
242		file="${arg#\>}"
243		if [ "$file" != "$arg" ]; then
244			flag=1
245			if [ -n "$file" ]; then
246				break
247			fi
248			continue
249		fi
250
251		if [ -n "$flag" ]; then
252			file="$arg"
253			break
254		fi
255
256		cmd="$cmd $arg"
257	done
258
259	if [ -n "$flag" ]; then
260		$cmd > $file
261	else
262		$@
263	fi
264}
265
266ROD()
267{
268	ROD_BASE "$@"
269	if [ $? -ne 0 ]; then
270		tst_brkm TBROK "$@ failed"
271	fi
272}
273
274EXPECT_PASS()
275{
276	ROD_BASE "$@"
277	if [ $? -eq 0 ]; then
278		tst_resm TPASS "$@ passed as expected"
279	else
280		tst_resm TFAIL "$@ failed unexpectedly"
281	fi
282}
283
284EXPECT_FAIL()
285{
286	# redirect stderr since we expect the command to fail
287	ROD_BASE "$@" 2> /dev/null
288	if [ $? -ne 0 ]; then
289		tst_resm TPASS "$@ failed as expected"
290	else
291		tst_resm TFAIL "$@ passed unexpectedly"
292	fi
293}
294
295tst_mkfs()
296{
297	local fs_type=$1
298	local device=$2
299	shift 2
300	local fs_opts="$@"
301
302	if [ -z "$fs_type" ]; then
303		tst_brkm TBROK "No fs_type specified"
304	fi
305
306	if [ -z "$device" ]; then
307		tst_brkm TBROK "No device specified"
308	fi
309
310	tst_resm TINFO "Formatting $device with $fs_type extra opts='$fs_opts'"
311
312	ROD_SILENT mkfs.$fs_type $fs_opts $device
313}
314
315tst_umount()
316{
317	local device="$1"
318	local i=0
319
320	if ! grep -q "$device" /proc/mounts; then
321		tst_resm TINFO "The $device is not mounted, skipping umount"
322		return
323	fi
324
325	while [ "$i" -lt 50 ]; do
326		if umount "$device" > /dev/null; then
327			return
328		fi
329
330		i=$((i+1))
331
332		tst_resm TINFO "umount($device) failed, try $i ..."
333		tst_resm TINFO "Likely gvfsd-trash is probing newly mounted "\
334			       "fs, kill it to speed up tests."
335
336		tst_sleep 100ms
337	done
338
339	tst_resm TWARN "Failed to umount($device) after 50 retries"
340}
341
342# Check a module file existence
343# Should be called after tst_tmpdir()
344tst_module_exists()
345{
346	local mod_name="$1"
347
348	if [ -f "$mod_name" ]; then
349		TST_MODPATH="$mod_name"
350		return
351	fi
352
353	local mod_path="$LTPROOT/testcases/bin/$mod_name"
354	if [ -f "$mod_path" ]; then
355		TST_MODPATH="$mod_path"
356		return
357	fi
358
359	if [ -n "$TST_TMPDIR" ]; then
360		mod_path="$TST_STARTWD/$mod_name"
361		if [ -f "$mod_path" ]; then
362			TST_MODPATH="$mod_path"
363			return
364		fi
365	fi
366
367	tst_brkm TCONF "Failed to find module '$mod_name'"
368}
369
370# Appends LTP path when doing su
371tst_su()
372{
373	local usr="$1"
374	shift
375
376	su "$usr" -c "PATH=\$PATH:$LTPROOT/testcases/bin/ $@"
377}
378
379TST_CHECKPOINT_WAIT()
380{
381	ROD tst_checkpoint wait 10000 "$1"
382}
383
384TST_CHECKPOINT_WAKE()
385{
386	ROD tst_checkpoint wake 10000 "$1" 1
387}
388
389TST_CHECKPOINT_WAKE2()
390{
391	ROD tst_checkpoint wake 10000 "$1" "$2"
392}
393
394TST_CHECKPOINT_WAKE_AND_WAIT()
395{
396	TST_CHECKPOINT_WAKE "$1"
397	TST_CHECKPOINT_WAIT "$1"
398}
399
400# Check that test name is set
401if [ -z "$TCID" ]; then
402	tst_brkm TBROK "TCID is not defined"
403fi
404
405if [ -z "$TST_TOTAL" ]; then
406	tst_brkm TBROK "TST_TOTAL is not defined"
407fi
408
409export TCID="$TCID"
410export TST_TOTAL="$TST_TOTAL"
411
412# Setup LTPROOT, default to current directory if not set
413if [ -z "$LTPROOT" ]; then
414	export LTPROOT="$PWD"
415	export LTP_DATAROOT="$LTPROOT/datafiles"
416else
417	export LTP_DATAROOT="$LTPROOT/testcases/data/$TCID"
418fi
419
420if [ "$TST_NEEDS_CHECKPOINTS" = "1" ]; then
421	LTP_IPC_PATH="/dev/shm/ltp_${TCID}_$$"
422
423	LTP_IPC_SIZE=$(getconf PAGESIZE)
424	if [ $? -ne 0 ]; then
425		tst_brkm TBROK "getconf PAGESIZE failed"
426	fi
427
428	ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$LTP_IPC_SIZE" count=1
429	ROD_SILENT chmod 600 "$LTP_IPC_PATH"
430	export LTP_IPC_PATH
431fi
432