xref: /titanic_51/usr/src/cmd/tail/tests/sun_solaris_tail.sh (revision 209e49b2ff611e7d61ff58e13756ae67f51be550)
1*209e49b2SChris Love#
2*209e49b2SChris Love# CDDL HEADER START
3*209e49b2SChris Love#
4*209e49b2SChris Love# The contents of this file are subject to the terms of the
5*209e49b2SChris Love# Common Development and Distribution License (the "License").
6*209e49b2SChris Love# You may not use this file except in compliance with the License.
7*209e49b2SChris Love#
8*209e49b2SChris Love# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*209e49b2SChris Love# or http://www.opensolaris.org/os/licensing.
10*209e49b2SChris Love# See the License for the specific language governing permissions
11*209e49b2SChris Love# and limitations under the License.
12*209e49b2SChris Love#
13*209e49b2SChris Love# When distributing Covered Code, include this CDDL HEADER in each
14*209e49b2SChris Love# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*209e49b2SChris Love# If applicable, add the following below this CDDL HEADER, with the
16*209e49b2SChris Love# fields enclosed by brackets "[]" replaced with your own identifying
17*209e49b2SChris Love# information: Portions Copyright [yyyy] [name of copyright owner]
18*209e49b2SChris Love#
19*209e49b2SChris Love# CDDL HEADER END
20*209e49b2SChris Love#
21*209e49b2SChris Love
22*209e49b2SChris Love#
23*209e49b2SChris Love# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*209e49b2SChris Love#
25*209e49b2SChris Love
26*209e49b2SChris Love#
27*209e49b2SChris Love# Additional tests borrowed from ksh93 builtin tail test script
28*209e49b2SChris Love# (usr/src/lib/libshell/common/tests/sun_solaris_builtin_tail).  Modified
29*209e49b2SChris Love# to use /usr/bin/tail rather than the ksh93 builtin.
30*209e49b2SChris Love#
31*209e49b2SChris LoveTAIL=/usr/bin/tail
32*209e49b2SChris Love
33*209e49b2SChris Love# test setup
34*209e49b2SChris Lovefunction err_exit
35*209e49b2SChris Love{
36*209e49b2SChris Love	print -u2 -n "\t"
37*209e49b2SChris Love	print -u2 -r ${Command}[$1]: "${@:2}"
38*209e49b2SChris Love	(( Errors < 127 && Errors++ ))
39*209e49b2SChris Love}
40*209e49b2SChris Lovealias err_exit='err_exit $LINENO'
41*209e49b2SChris Love
42*209e49b2SChris Loveset -o nounset
43*209e49b2SChris LoveCommand=${0##*/}
44*209e49b2SChris Loveinteger Errors=0
45*209e49b2SChris Love
46*209e49b2SChris Love# common functions
47*209e49b2SChris Lovefunction isvalidpid
48*209e49b2SChris Love{
49*209e49b2SChris Love        kill -0 ${1} 2>/dev/null && return 0
50*209e49b2SChris Love        return 1
51*209e49b2SChris Love}
52*209e49b2SChris Love
53*209e49b2SChris Lovefunction waitpidtimeout
54*209e49b2SChris Love{
55*209e49b2SChris Love	integer pid=$1
56*209e49b2SChris Love	float timeout=$2
57*209e49b2SChris Love	float i
58*209e49b2SChris Love	float -r STEP=0.5 # const
59*209e49b2SChris Love
60*209e49b2SChris Love	(( timeout=timeout/STEP ))
61*209e49b2SChris Love
62*209e49b2SChris Love	for (( i=0 ; i < timeout ; i+=STEP )) ; do
63*209e49b2SChris Love		isvalidpid ${pid} || break
64*209e49b2SChris Love		sleep ${STEP}
65*209e49b2SChris Love	done
66*209e49b2SChris Love
67*209e49b2SChris Love	return 0
68*209e49b2SChris Love}
69*209e49b2SChris Love
70*209e49b2SChris Lovefunction myintseq
71*209e49b2SChris Love{
72*209e49b2SChris Love        integer i
73*209e49b2SChris Love	float arg1=$1
74*209e49b2SChris Love	float arg2=$2
75*209e49b2SChris Love	float arg3=$3
76*209e49b2SChris Love
77*209e49b2SChris Love        case $# in
78*209e49b2SChris Love                1)
79*209e49b2SChris Love                        for (( i=1 ; i <= arg1 ; i++ )) ; do
80*209e49b2SChris Love                                printf "%d\n" i
81*209e49b2SChris Love                        done
82*209e49b2SChris Love                        ;;
83*209e49b2SChris Love                2)
84*209e49b2SChris Love                        for (( i=arg1 ; i <= arg2 ; i++ )) ; do
85*209e49b2SChris Love                                printf "%d\n" i
86*209e49b2SChris Love                        done
87*209e49b2SChris Love                        ;;
88*209e49b2SChris Love                3)
89*209e49b2SChris Love                        for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do
90*209e49b2SChris Love                                printf "%d\n" i
91*209e49b2SChris Love                        done
92*209e49b2SChris Love                        ;;
93*209e49b2SChris Love                *)
94*209e49b2SChris Love                        print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $#
95*209e49b2SChris Love			return 1
96*209e49b2SChris Love                        ;;
97*209e49b2SChris Love        esac
98*209e49b2SChris Love
99*209e49b2SChris Love        return 0
100*209e49b2SChris Love}
101*209e49b2SChris Love
102*209e49b2SChris Love# quote input string but use single-backslash that "err_exit" prints
103*209e49b2SChris Love# the strings correctly
104*209e49b2SChris Lovefunction singlebackslashquote
105*209e49b2SChris Love{
106*209e49b2SChris Love	typeset s
107*209e49b2SChris Love	s="$(printf "%q\n" "$1")"
108*209e49b2SChris Love	print -r "$s"
109*209e49b2SChris Love	return 0
110*209e49b2SChris Love}
111*209e49b2SChris Love
112*209e49b2SChris Love# quote input string but use double-backslash that "err_exit" prints
113*209e49b2SChris Love# the strings correctly
114*209e49b2SChris Lovefunction doublebackslashquote
115*209e49b2SChris Love{
116*209e49b2SChris Love	typeset s
117*209e49b2SChris Love	s="$(printf "%q\n" "$1")"
118*209e49b2SChris Love	s="${s//\\/\\\\}"
119*209e49b2SChris Love	print -r "$s"
120*209e49b2SChris Love	return 0
121*209e49b2SChris Love}
122*209e49b2SChris Love
123*209e49b2SChris Love
124*209e49b2SChris Love# main
125*209e49b2SChris Lovebuiltin mktemp || err_exit "mktemp builtin not found"
126*209e49b2SChris Lovebuiltin rm || err_exit "rm builtin not found"
127*209e49b2SChris Love# builtin tail || err_exit "tail builtin not found"
128*209e49b2SChris Love
129*209e49b2SChris Lovetypeset ocwd
130*209e49b2SChris Lovetypeset tmpdir
131*209e49b2SChris Love
132*209e49b2SChris Love# create temporary test directory
133*209e49b2SChris Loveocwd="$PWD"
134*209e49b2SChris Lovetmpdir="$(mktemp -t -d "test_sun_solaris_builtin_tail.XXXXXXXX")" || err_exit "Cannot create temporary directory"
135*209e49b2SChris Love
136*209e49b2SChris Lovecd "${tmpdir}" || { err_exit "cd ${tmpdir} failed." ; exit $((Errors)) ; }
137*209e49b2SChris Love
138*209e49b2SChris Love
139*209e49b2SChris Love# run tests:
140*209e49b2SChris Love
141*209e49b2SChris Love# test1: basic tests
142*209e49b2SChris Lovecompound -a testcases=(
143*209e49b2SChris Love	(
144*209e49b2SChris Love		name="reverse_n"
145*209e49b2SChris Love		input=$'hello\nworld'
146*209e49b2SChris Love		compound -A tail_args=(
147*209e49b2SChris Love			[legacy]=(   argv=( "-r"  ) )
148*209e49b2SChris Love		)
149*209e49b2SChris Love		expected_output=$'world\nhello'
150*209e49b2SChris Love	)
151*209e49b2SChris Love	(
152*209e49b2SChris Love		name="revlist0n"
153*209e49b2SChris Love		input=$'1\n2\n3\n4'
154*209e49b2SChris Love		compound -A tail_args=(
155*209e49b2SChris Love			[legacy]=(   argv=( "-0"	 ) )
156*209e49b2SChris Love#			[std_like]=( argv=( "-n" "0" ) )
157*209e49b2SChris Love		)
158*209e49b2SChris Love		expected_output=$''
159*209e49b2SChris Love	)
160*209e49b2SChris Love	(
161*209e49b2SChris Love		name="revlist0nr"
162*209e49b2SChris Love		input=$'1\n2\n3\n4'
163*209e49b2SChris Love		compound -A tail_args=(
164*209e49b2SChris Love			[legacy]=(       argv=( "-0r"	      ) )
165*209e49b2SChris Love#			[std_like]=(     argv=( "-n" "0" "-r" ) )
166*209e49b2SChris Love#			[long_options]=( argv=( "--lines" "0" "--reverse" ) )
167*209e49b2SChris Love		)
168*209e49b2SChris Love		expected_output=$'' )
169*209e49b2SChris Love	(
170*209e49b2SChris Love		name="revlist1n"
171*209e49b2SChris Love		input=$'1\n2\n3\n4'
172*209e49b2SChris Love		compound -A tail_args=(
173*209e49b2SChris Love			[legacy]=(       argv=( "-1"     ) )
174*209e49b2SChris Love#			[std_like]=(     argv=( "-n" "1" ) )
175*209e49b2SChris Love#			[long_options]=( argv=( "--lines" "1" ) )
176*209e49b2SChris Love		)
177*209e49b2SChris Love		expected_output=$'4' )
178*209e49b2SChris Love	(
179*209e49b2SChris Love		name="revlist1nr"
180*209e49b2SChris Love		input=$'1\n2\n3\n4'
181*209e49b2SChris Love		compound -A tail_args=(
182*209e49b2SChris Love			[legacy]=(       argv=( "-1r" ) )
183*209e49b2SChris Love#			[std_like]=(     argv=( "-n" "1" "-r" ) )
184*209e49b2SChris Love#			[long_options]=( argv=( "--lines" "1" "--reverse" ) )
185*209e49b2SChris Love		)
186*209e49b2SChris Love		expected_output=$'4'
187*209e49b2SChris Love	)
188*209e49b2SChris Love	(
189*209e49b2SChris Love		name="revlist2n"
190*209e49b2SChris Love		input=$'1\n2\n3\n4'
191*209e49b2SChris Love		compound -A tail_args=(
192*209e49b2SChris Love			[legacy]=(   argv=( "-2"  ) )
193*209e49b2SChris Love#			[std_like]=( argv=( "-n" "2" ) )
194*209e49b2SChris Love		)
195*209e49b2SChris Love		expected_output=$'3\n4'
196*209e49b2SChris Love	)
197*209e49b2SChris Love	(
198*209e49b2SChris Love		name="revlist2nr"
199*209e49b2SChris Love		input=$'1\n2\n3\n4'
200*209e49b2SChris Love		compound -A tail_args=(
201*209e49b2SChris Love			[legacy]=(   argv=( "-2r" ) )
202*209e49b2SChris Love#			[std_like]=( argv=( "-n" "2" "-r" ) )
203*209e49b2SChris Love			)
204*209e49b2SChris Love		expected_output=$'4\n3'
205*209e49b2SChris Love	)
206*209e49b2SChris Love	(
207*209e49b2SChris Love		name="revlist3nr"
208*209e49b2SChris Love		input=$'1\n2\n3\n4'
209*209e49b2SChris Love		compound -A tail_args=(
210*209e49b2SChris Love			[legacy]=(   argv=( "-3r" ) )
211*209e49b2SChris Love#			[std_like]=( argv=( "-n" "3" "-r" ) )
212*209e49b2SChris Love		)
213*209e49b2SChris Love		expected_output=$'4\n3\n2'
214*209e49b2SChris Love	)
215*209e49b2SChris Love	(
216*209e49b2SChris Love		name="revlist2p"
217*209e49b2SChris Love		input=$'1\n2\n3\n4'
218*209e49b2SChris Love		compound -A tail_args=(
219*209e49b2SChris Love			[legacy]=(   argv=( "+2"  ) )
220*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+2" ) )
221*209e49b2SChris Love			)
222*209e49b2SChris Love		expected_output=$'2\n3\n4'
223*209e49b2SChris Love	)
224*209e49b2SChris Love#	Note:  following test case trips up legacy Solaris 'tail' as well
225*209e49b2SChris Love#	(
226*209e49b2SChris Love#		name="revlist2pr"
227*209e49b2SChris Love#		input=$'1\n2\n3\n4'
228*209e49b2SChris Love#		compound -A tail_args=(
229*209e49b2SChris Love#			[legacy]=(   argv=( "+2r" ) )
230*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+2" "-r" ) )
231*209e49b2SChris Love#		)
232*209e49b2SChris Love#		expected_output=$'4\n3\n2'
233*209e49b2SChris Love#	)
234*209e49b2SChris Love	(
235*209e49b2SChris Love		name="revlist3p"
236*209e49b2SChris Love		input=$'1\n2\n3\n4'
237*209e49b2SChris Love		compound -A tail_args=(
238*209e49b2SChris Love			[legacy]=(   argv=( "+3"  ) )
239*209e49b2SChris Love			[std_like]=( argv=( "-n" "+3"  ) )
240*209e49b2SChris Love		)
241*209e49b2SChris Love		expected_output=$'3\n4'
242*209e49b2SChris Love	)
243*209e49b2SChris Love#	Note: following test case trips up legacy Solaris 'tail' as well
244*209e49b2SChris Love#	(
245*209e49b2SChris Love#		name="revlist3pr"
246*209e49b2SChris Love#		input=$'1\n2\n3\n4'
247*209e49b2SChris Love#		compound -A tail_args=(
248*209e49b2SChris Love#			[legacy]=(   argv=( "+3r" ) )
249*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+3" "-r" ) )
250*209e49b2SChris Love#		)
251*209e49b2SChris Love#		expected_output=$'4\n3'
252*209e49b2SChris Love#	)
253*209e49b2SChris Love	(
254*209e49b2SChris Love		name="revlist4p"
255*209e49b2SChris Love		input=$'1\n2\n3\n4'
256*209e49b2SChris Love		compound -A tail_args=(
257*209e49b2SChris Love			[legacy]=(   argv=( "+4"  ) )
258*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+4"  ) )
259*209e49b2SChris Love		)
260*209e49b2SChris Love		expected_output=$'4'
261*209e49b2SChris Love	)
262*209e49b2SChris Love#	Note: following test case trips up legacy Solaris 'tail' as well
263*209e49b2SChris Love#	(
264*209e49b2SChris Love#		name="revlist4pr"
265*209e49b2SChris Love#		input=$'1\n2\n3\n4'
266*209e49b2SChris Love#		compound -A tail_args=(
267*209e49b2SChris Love#			[legacy]=(   argv=( "+4r" ) )
268*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+4" "-r" ) )
269*209e49b2SChris Love#		)
270*209e49b2SChris Love#		expected_output=$'4'
271*209e49b2SChris Love#	)
272*209e49b2SChris Love	(
273*209e49b2SChris Love		name="revlist5p"
274*209e49b2SChris Love		input=$'1\n2\n3\n4'
275*209e49b2SChris Love		compound -A tail_args=(
276*209e49b2SChris Love			[legacy]=(   argv=( "+5"  ) )
277*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+5"  ) )
278*209e49b2SChris Love		)
279*209e49b2SChris Love		expected_output=$''
280*209e49b2SChris Love	)
281*209e49b2SChris Love#	Note: following test case trips up legacy Solaris 'tail' as well
282*209e49b2SChris Love#	(
283*209e49b2SChris Love#		name="revlist5pr"
284*209e49b2SChris Love#		input=$'1\n2\n3\n4'
285*209e49b2SChris Love#		compound -A tail_args=(
286*209e49b2SChris Love#			[legacy]=(   argv=( "+5r" ) )
287*209e49b2SChris Love#			[std_like]=( argv=( "-n" "+5" "-r" ) )
288*209e49b2SChris Love#		)
289*209e49b2SChris Love#		expected_output=$''
290*209e49b2SChris Love#	)
291*209e49b2SChris Love)
292*209e49b2SChris Love
293*209e49b2SChris Lovefor testid in "${!testcases[@]}" ; do
294*209e49b2SChris Love	nameref tc=testcases[${testid}]
295*209e49b2SChris Love
296*209e49b2SChris Love	for argv_variants in "${!tc.tail_args[@]}" ; do
297*209e49b2SChris Love		nameref argv=tc.tail_args[${argv_variants}].argv
298*209e49b2SChris Love		output=$(
299*209e49b2SChris Love				set -o pipefail
300*209e49b2SChris Love	          		(trap "" PIPE ; print -r -- "${tc.input}") | $TAIL "${argv[@]}"
301*209e49b2SChris Love			) || err_exit "test ${tc.name}/${argv_variants}: command failed with exit code $?"
302*209e49b2SChris Love
303*209e49b2SChris Love		[[ "${output}" == "${tc.expected_output}" ]] || err_exit "test ${tc.name}/${argv_variants}: Expected $(doublebackslashquote "${tc.expected_output}"), got $(doublebackslashquote "${output}")"
304*209e49b2SChris Love	done
305*209e49b2SChris Lovedone
306*209e49b2SChris Love
307*209e49b2SChris Love
308*209e49b2SChris Love# test2: test "tail -r </etc/profile | rev -l" vs. "cat </etc/profile"
309*209e49b2SChris Love[[ "$($TAIL -r </etc/profile | rev -l)" == "$( cat /etc/profile )" ]] || err_exit "'tail -r </etc/profile | rev -l' output does not match 'cat /etc/profile'"
310*209e49b2SChris Love
311*209e49b2SChris Love# Test case not applicable to FreeBSD 'tail'
312*209e49b2SChris Love# test 3: ast-ksh.2009-05-05 "tail" builtin may crash if we pass unsupported long options
313*209e49b2SChris Love#$SHELL -o errexit -c 'builtin tail ; print "hello" | tail --attack_of_chicken_monsters' >/dev/null 2>&1
314*209e49b2SChris Love#(( $? == 2 )) || err_exit "expected exit code 2 for unsupported long option, got $?"
315*209e49b2SChris Love
316*209e49b2SChris Love
317*209e49b2SChris Love# test 4: FIFO tests
318*209e49b2SChris Love
319*209e49b2SChris Love# FIFO test functions
320*209e49b2SChris Love# (we use functions here to do propper garbage collection)
321*209e49b2SChris Lovefunction test_tail_fifo_1
322*209e49b2SChris Love{
323*209e49b2SChris Love	typeset tail_cmd="$1"
324*209e49b2SChris Love	integer i
325*209e49b2SChris Love	integer tail_pid=-1
326*209e49b2SChris Love
327*209e49b2SChris Love	# cleanup trap
328*209e49b2SChris Love	trap "rm -f tailtestfifo tailout" EXIT
329*209e49b2SChris Love
330*209e49b2SChris Love	# create test FIFO
331*209e49b2SChris Love	mkfifo tailtestfifo
332*209e49b2SChris Love
333*209e49b2SChris Love	${tail_cmd} -f <tailtestfifo >tailout &
334*209e49b2SChris Love	tail_pid=$!
335*209e49b2SChris Love
336*209e49b2SChris Love	myintseq 20 >tailtestfifo
337*209e49b2SChris Love
338*209e49b2SChris Love	waitpidtimeout ${tail_pid} 5
339*209e49b2SChris Love
340*209e49b2SChris Love	if isvalidpid ${tail_pid} ; then
341*209e49b2SChris Love		err_exit "test_tail_fifo_1: # tail hung (not expected)"
342*209e49b2SChris Love		kill -KILL ${tail_pid}
343*209e49b2SChris Love	fi
344*209e49b2SChris Love
345*209e49b2SChris Love	wait || err_exit "tail child returned non-zero exit code=$?"
346*209e49b2SChris Love
347*209e49b2SChris Love	[[ "$(cat tailout)" == $'11\n12\n13\n14\n15\n16\n17\n18\n19\n20' ]] || err_exit "test_tail_fifo_1: Expected $(doublebackslashquote '11\n12\n13\n14\n15\n16\n17\n18\n19\n20'), got $(doublebackslashquote "$(cat tailout)")"
348*209e49b2SChris Love
349*209e49b2SChris Love	return 0
350*209e49b2SChris Love}
351*209e49b2SChris Love
352*209e49b2SChris Lovefunction test_tail_fifo_2
353*209e49b2SChris Love{
354*209e49b2SChris Love	typeset tail_cmd="$1"
355*209e49b2SChris Love	integer i
356*209e49b2SChris Love	integer tail_pid=-1
357*209e49b2SChris Love
358*209e49b2SChris Love	# cleanup trap
359*209e49b2SChris Love	trap "rm -f tailtestfifo tailout" EXIT
360*209e49b2SChris Love
361*209e49b2SChris Love	# create test FIFO
362*209e49b2SChris Love	mkfifo tailtestfifo
363*209e49b2SChris Love
364*209e49b2SChris Love	${tail_cmd} -f tailtestfifo >tailout &
365*209e49b2SChris Love	tail_pid=$!
366*209e49b2SChris Love
367*209e49b2SChris Love	myintseq 14 >tailtestfifo
368*209e49b2SChris Love
369*209e49b2SChris Love	waitpidtimeout ${tail_pid} 5
370*209e49b2SChris Love
371*209e49b2SChris Love	if isvalidpid ${tail_pid} ; then
372*209e49b2SChris Love		[[ "$(cat tailout)" == $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14' ]] || err_exit "test_tail_fifo_2: Expected $(doublebackslashquote $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14'), got $(doublebackslashquote "$(cat tailout)")"
373*209e49b2SChris Love
374*209e49b2SChris Love		myintseq 15 >>tailtestfifo
375*209e49b2SChris Love
376*209e49b2SChris Love		waitpidtimeout ${tail_pid} 5
377*209e49b2SChris Love
378*209e49b2SChris Love		if isvalidpid ${tail_pid} ; then
379*209e49b2SChris Love			kill -KILL ${tail_pid}
380*209e49b2SChris Love		else
381*209e49b2SChris Love			err_exit "test_tail_fifo_2: # tail exit with return code $? (not expected)"
382*209e49b2SChris Love		fi
383*209e49b2SChris Love	fi
384*209e49b2SChris Love
385*209e49b2SChris Love	wait || err_exit "tail child returned non-zero exit code=$?"
386*209e49b2SChris Love
387*209e49b2SChris Love	[[ "$(cat tailout)" == $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15' ]] || err_exit "test_tail_fifo_2: Expected $(doublebackslashquote $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15'), got $(doublebackslashquote "$(cat tailout)")"
388*209e49b2SChris Love
389*209e49b2SChris Love	return 0
390*209e49b2SChris Love}
391*209e49b2SChris Love
392*209e49b2SChris Love# fixme: This should test /usr/bin/tail and /usr/xpg4/bin/tail in Solaris
393*209e49b2SChris Lovetest_tail_fifo_1 "$TAIL"
394*209e49b2SChris Lovetest_tail_fifo_2 "$TAIL"
395*209e49b2SChris Love
396*209e49b2SChris Love
397*209e49b2SChris Love# test 5: "tail -f" tests
398*209e49b2SChris Lovefunction followtest1
399*209e49b2SChris Love{
400*209e49b2SChris Love	typeset -r FOLLOWFILE="followfile.txt"
401*209e49b2SChris Love	typeset -r OUTFILE="outfile.txt"
402*209e49b2SChris Love
403*209e49b2SChris Love	typeset title="$1"
404*209e49b2SChris Love	typeset testcmd="$2"
405*209e49b2SChris Love	typeset usenewline=$3
406*209e49b2SChris Love	typeset followstr=""
407*209e49b2SChris Love	typeset newline=""
408*209e49b2SChris Love	integer i
409*209e49b2SChris Love	integer tailchild=-1
410*209e49b2SChris Love
411*209e49b2SChris Love	if ${usenewline} ; then
412*209e49b2SChris Love		newline=$'\n'
413*209e49b2SChris Love	fi
414*209e49b2SChris Love
415*209e49b2SChris Love	rm -f "${FOLLOWFILE}" "${OUTFILE}"
416*209e49b2SChris Love	print -n "${newline}" > "${FOLLOWFILE}"
417*209e49b2SChris Love
418*209e49b2SChris Love	${testcmd} -f "${FOLLOWFILE}" >"${OUTFILE}" &
419*209e49b2SChris Love	(( tailchild=$! ))
420*209e49b2SChris Love
421*209e49b2SChris Love	for (( i=0 ; i < 10 ; i++)) ; do
422*209e49b2SChris Love		followstr+="${newline}${i}"
423*209e49b2SChris Love		print -n "${i}${newline}" >>"${FOLLOWFILE}"
424*209e49b2SChris Love		sleep 2
425*209e49b2SChris Love
426*209e49b2SChris Love		[[ "$( < "${OUTFILE}")" == "${followstr}" ]] || err_exit "${title}: Expected $(doublebackslashquote "${followstr}"), got "$(doublebackslashquote "$( < "${OUTFILE}")")""
427*209e49b2SChris Love	done
428*209e49b2SChris Love
429*209e49b2SChris Love	kill -KILL ${tailchild} 2>/dev/null
430*209e49b2SChris Love	#kill -TERM ${tailchild} 2>/dev/null
431*209e49b2SChris Love	waitpidtimeout ${tailchild} 5
432*209e49b2SChris Love
433*209e49b2SChris Love	if isvalidpid ${tailchild} ; then
434*209e49b2SChris Love		err_exit "${title}: tail pid=${tailchild} hung."
435*209e49b2SChris Love		kill -KILL ${tailchild} 2>/dev/null
436*209e49b2SChris Love	fi
437*209e49b2SChris Love
438*209e49b2SChris Love	wait ${tailchild} 2>/dev/null
439*209e49b2SChris Love
440*209e49b2SChris Love	rm -f "${FOLLOWFILE}" "${OUTFILE}"
441*209e49b2SChris Love
442*209e49b2SChris Love	return 0
443*209e49b2SChris Love}
444*209e49b2SChris Love
445*209e49b2SChris Lovefollowtest1 "test5a" "$TAIL" true
446*209e49b2SChris Love# fixme: later we should test this, too:
447*209e49b2SChris Love#followtest1 "test5b" "tail" false
448*209e49b2SChris Love#followtest1 "test5c" "/usr/xpg4/bin/tail" true
449*209e49b2SChris Love#followtest1 "test5d" "/usr/xpg4/bin/tail" false
450*209e49b2SChris Love#followtest1 "test5e" "/usr/bin/tail" true
451*209e49b2SChris Love#followtest1 "test5f" "/usr/bin/tail" false
452*209e49b2SChris Love
453*209e49b2SChris Love
454*209e49b2SChris Love# test 6: "tail -f" tests
455*209e49b2SChris Lovefunction followtest2
456*209e49b2SChris Love{
457*209e49b2SChris Love	typeset -r FOLLOWFILE="followfile.txt"
458*209e49b2SChris Love	typeset -r OUTFILE="outfile.txt"
459*209e49b2SChris Love
460*209e49b2SChris Love	typeset title="$1"
461*209e49b2SChris Love	typeset testcmd="$2"
462*209e49b2SChris Love	integer tailchild=-1
463*209e49b2SChris Love
464*209e49b2SChris Love	rm -f "${FOLLOWFILE}" "${OUTFILE}"
465*209e49b2SChris Love
466*209e49b2SChris Love	myintseq 50000 >"${FOLLOWFILE}"
467*209e49b2SChris Love
468*209e49b2SChris Love	${testcmd} -n 60000 -f "${FOLLOWFILE}" >"${OUTFILE}" &
469*209e49b2SChris Love	(( tailchild=$! ))
470*209e49b2SChris Love
471*209e49b2SChris Love	sleep 10
472*209e49b2SChris Love
473*209e49b2SChris Love	kill -KILL ${tailchild} 2>/dev/null
474*209e49b2SChris Love	#kill -TERM ${tailchild} 2>/dev/null
475*209e49b2SChris Love	waitpidtimeout ${tailchild} 5
476*209e49b2SChris Love
477*209e49b2SChris Love	if isvalidpid ${tailchild} ; then
478*209e49b2SChris Love		err_exit "${title}: tail pid=${tailchild} hung."
479*209e49b2SChris Love		kill -KILL ${tailchild} 2>/dev/null
480*209e49b2SChris Love	fi
481*209e49b2SChris Love
482*209e49b2SChris Love	wait ${tailchild} 2>/dev/null
483*209e49b2SChris Love
484*209e49b2SChris Love	# this tail should be an external process
485*209e49b2SChris Love	outstr=$(/usr/bin/tail "${OUTFILE}") || err_exit "tail returned non-zero exit code $?"
486*209e49b2SChris Love        [[ "${outstr}" == 49991*50000 ]] || err_exit "${title}: Expected match for 49991*50000, got "$(singlebackslashquote "${outstr}")""
487*209e49b2SChris Love
488*209e49b2SChris Love	rm -f "${FOLLOWFILE}" "${OUTFILE}"
489*209e49b2SChris Love
490*209e49b2SChris Love	return 0
491*209e49b2SChris Love}
492*209e49b2SChris Love
493*209e49b2SChris Lovefollowtest2 "test6a" "$TAIL"
494*209e49b2SChris Lovefollowtest2 "test6b" "$TAIL"
495*209e49b2SChris Love# fixme: later we should test this, too:
496*209e49b2SChris Love#followtest2 "test6c" "/usr/bin/tail"
497*209e49b2SChris Love
498*209e49b2SChris Love
499*209e49b2SChris Love# cleanup
500*209e49b2SChris Lovecd "${ocwd}"
501*209e49b2SChris Lovermdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
502*209e49b2SChris Love
503*209e49b2SChris Love
504*209e49b2SChris Love# tests done
505*209e49b2SChris Loveexit $((Errors))
506