134f9b3eeSRoland Mainz#
234f9b3eeSRoland Mainz# CDDL HEADER START
334f9b3eeSRoland Mainz#
434f9b3eeSRoland Mainz# The contents of this file are subject to the terms of the
534f9b3eeSRoland Mainz# Common Development and Distribution License (the "License").
634f9b3eeSRoland Mainz# You may not use this file except in compliance with the License.
734f9b3eeSRoland Mainz#
834f9b3eeSRoland Mainz# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
934f9b3eeSRoland Mainz# or http://www.opensolaris.org/os/licensing.
1034f9b3eeSRoland Mainz# See the License for the specific language governing permissions
1134f9b3eeSRoland Mainz# and limitations under the License.
1234f9b3eeSRoland Mainz#
1334f9b3eeSRoland Mainz# When distributing Covered Code, include this CDDL HEADER in each
1434f9b3eeSRoland Mainz# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1534f9b3eeSRoland Mainz# If applicable, add the following below this CDDL HEADER, with the
1634f9b3eeSRoland Mainz# fields enclosed by brackets "[]" replaced with your own identifying
1734f9b3eeSRoland Mainz# information: Portions Copyright [yyyy] [name of copyright owner]
1834f9b3eeSRoland Mainz#
1934f9b3eeSRoland Mainz# CDDL HEADER END
2034f9b3eeSRoland Mainz#
2134f9b3eeSRoland Mainz
2234f9b3eeSRoland Mainz#
233e14f97fSRoger A. Faulkner# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2434f9b3eeSRoland Mainz#
2534f9b3eeSRoland Mainz
2634f9b3eeSRoland Mainz#
2734f9b3eeSRoland Mainz# Test whether the ksh93/libcmd tail builtin is compatible to
2834f9b3eeSRoland Mainz# Solaris/SystemV { /usr/bin/tail, /usr/xpg4/bin/tail } and
2934f9b3eeSRoland Mainz# POSIX "tail"
3034f9b3eeSRoland Mainz#
3134f9b3eeSRoland Mainz
3234f9b3eeSRoland Mainz# test setup
3334f9b3eeSRoland Mainzfunction err_exit
3434f9b3eeSRoland Mainz{
3534f9b3eeSRoland Mainz	print -u2 -n "\t"
3634f9b3eeSRoland Mainz	print -u2 -r ${Command}[$1]: "${@:2}"
373e14f97fSRoger A. Faulkner	(( Errors < 127 && Errors++ ))
3834f9b3eeSRoland Mainz}
3934f9b3eeSRoland Mainzalias err_exit='err_exit $LINENO'
4034f9b3eeSRoland Mainz
4134f9b3eeSRoland Mainzset -o nounset
4234f9b3eeSRoland MainzCommand=${0##*/}
4334f9b3eeSRoland Mainzinteger Errors=0
4434f9b3eeSRoland Mainz
4534f9b3eeSRoland Mainz# common functions
4634f9b3eeSRoland Mainzfunction isvalidpid
4734f9b3eeSRoland Mainz{
4834f9b3eeSRoland Mainz        kill -0 ${1} 2>/dev/null && return 0
4934f9b3eeSRoland Mainz        return 1
5034f9b3eeSRoland Mainz}
5134f9b3eeSRoland Mainz
5234f9b3eeSRoland Mainzfunction waitpidtimeout
5334f9b3eeSRoland Mainz{
5434f9b3eeSRoland Mainz	integer pid=$1
5534f9b3eeSRoland Mainz	float timeout=$2
5634f9b3eeSRoland Mainz	float i
5734f9b3eeSRoland Mainz	float -r STEP=0.5 # const
5834f9b3eeSRoland Mainz
5934f9b3eeSRoland Mainz	(( timeout=timeout/STEP ))
60*b30d1939SAndy Fiddaman
6134f9b3eeSRoland Mainz	for (( i=0 ; i < timeout ; i+=STEP )) ; do
6234f9b3eeSRoland Mainz		isvalidpid ${pid} || break
6334f9b3eeSRoland Mainz		sleep ${STEP}
6434f9b3eeSRoland Mainz	done
65*b30d1939SAndy Fiddaman
6634f9b3eeSRoland Mainz	return 0
6734f9b3eeSRoland Mainz}
6834f9b3eeSRoland Mainz
6934f9b3eeSRoland Mainzfunction myintseq
7034f9b3eeSRoland Mainz{
7134f9b3eeSRoland Mainz        integer i
7234f9b3eeSRoland Mainz
7334f9b3eeSRoland Mainz        case $# in
7434f9b3eeSRoland Mainz                1)
75*b30d1939SAndy Fiddaman                        for (( i=1 ; i <= $1 ; i++ )) ; do
7634f9b3eeSRoland Mainz                                printf "%d\n" i
7734f9b3eeSRoland Mainz                        done
7834f9b3eeSRoland Mainz                        ;;
7934f9b3eeSRoland Mainz                2)
80*b30d1939SAndy Fiddaman                        for (( i=$1 ; i <= $2 ; i++ )) ; do
8134f9b3eeSRoland Mainz                                printf "%d\n" i
8234f9b3eeSRoland Mainz                        done
8334f9b3eeSRoland Mainz                        ;;
8434f9b3eeSRoland Mainz                3)
85*b30d1939SAndy Fiddaman                        for (( i=$1 ; i <= $3 ; i+=$2 )) ; do
8634f9b3eeSRoland Mainz                                printf "%d\n" i
8734f9b3eeSRoland Mainz                        done
8834f9b3eeSRoland Mainz                        ;;
8934f9b3eeSRoland Mainz                *)
9034f9b3eeSRoland Mainz                        print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $#
9134f9b3eeSRoland Mainz			return 1
9234f9b3eeSRoland Mainz                        ;;
9334f9b3eeSRoland Mainz        esac
94*b30d1939SAndy Fiddaman
9534f9b3eeSRoland Mainz        return 0
9634f9b3eeSRoland Mainz}
9734f9b3eeSRoland Mainz
983e14f97fSRoger A. Faulkner# quote input string but use single-backslash that "err_exit" prints
993e14f97fSRoger A. Faulkner# the strings correctly
1003e14f97fSRoger A. Faulknerfunction singlebackslashquote
1013e14f97fSRoger A. Faulkner{
1023e14f97fSRoger A. Faulkner	typeset s
1033e14f97fSRoger A. Faulkner	s="$(printf "%q\n" "$1")"
1043e14f97fSRoger A. Faulkner	print -r "$s"
1053e14f97fSRoger A. Faulkner	return 0
1063e14f97fSRoger A. Faulkner}
1073e14f97fSRoger A. Faulkner
10834f9b3eeSRoland Mainz# quote input string but use double-backslash that "err_exit" prints
10934f9b3eeSRoland Mainz# the strings correctly
11034f9b3eeSRoland Mainzfunction doublebackslashquote
11134f9b3eeSRoland Mainz{
11234f9b3eeSRoland Mainz	typeset s
11334f9b3eeSRoland Mainz	s="$(printf "%q\n" "$1")"
11434f9b3eeSRoland Mainz	s="${s//\\/\\\\}"
11534f9b3eeSRoland Mainz	print -r "$s"
11634f9b3eeSRoland Mainz	return 0
11734f9b3eeSRoland Mainz}
11834f9b3eeSRoland Mainz
11934f9b3eeSRoland Mainz
12034f9b3eeSRoland Mainz# main
12134f9b3eeSRoland Mainzbuiltin mktemp || err_exit "mktemp builtin not found"
12234f9b3eeSRoland Mainzbuiltin rm || err_exit "rm builtin not found"
12334f9b3eeSRoland Mainzbuiltin tail || err_exit "tail builtin not found"
12434f9b3eeSRoland Mainz
12534f9b3eeSRoland Mainztypeset ocwd
12634f9b3eeSRoland Mainztypeset tmpdir
12734f9b3eeSRoland Mainz
12834f9b3eeSRoland Mainz# create temporary test directory
12934f9b3eeSRoland Mainzocwd="$PWD"
1303e14f97fSRoger A. Faulknertmpdir="$(mktemp -t -d "test_sun_solaris_builtin_tail.XXXXXXXX")" || err_exit "Cannot create temporary directory"
13134f9b3eeSRoland Mainz
1323e14f97fSRoger A. Faulknercd "${tmpdir}" || { err_exit "cd ${tmpdir} failed." ; exit $((Errors)) ; }
13334f9b3eeSRoland Mainz
13434f9b3eeSRoland Mainz
13534f9b3eeSRoland Mainz# run tests:
13634f9b3eeSRoland Mainz
13734f9b3eeSRoland Mainz# test1: basic tests
13834f9b3eeSRoland Mainzcompound -a testcases=(
13934f9b3eeSRoland Mainz	(
14034f9b3eeSRoland Mainz		name="reverse_n"
14134f9b3eeSRoland Mainz		input=$'hello\nworld'
14234f9b3eeSRoland Mainz		compound -A tail_args=(
14334f9b3eeSRoland Mainz			[legacy]=(   argv=( "-r"  ) )
14434f9b3eeSRoland Mainz		)
14534f9b3eeSRoland Mainz		expected_output=$'world\nhello'
14634f9b3eeSRoland Mainz	)
14734f9b3eeSRoland Mainz	(
14834f9b3eeSRoland Mainz		name="revlist0n"
14934f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
15034f9b3eeSRoland Mainz		compound -A tail_args=(
15134f9b3eeSRoland Mainz			[legacy]=(   argv=( "-0"	 ) )
152*b30d1939SAndy Fiddaman			[std_like]=( argv=( "-n" "0" ) )
15334f9b3eeSRoland Mainz		)
15434f9b3eeSRoland Mainz		expected_output=$''
15534f9b3eeSRoland Mainz	)
15634f9b3eeSRoland Mainz	(
15734f9b3eeSRoland Mainz		name="revlist0nr"
15834f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
15934f9b3eeSRoland Mainz		compound -A tail_args=(
16034f9b3eeSRoland Mainz			[legacy]=(       argv=( "-0r"	      ) )
16134f9b3eeSRoland Mainz			[std_like]=(     argv=( "-n" "0" "-r" ) )
16234f9b3eeSRoland Mainz			[long_options]=( argv=( "--lines" "0" "--reverse" ) )
16334f9b3eeSRoland Mainz		)
16434f9b3eeSRoland Mainz		expected_output=$'' )
16534f9b3eeSRoland Mainz	(
16634f9b3eeSRoland Mainz		name="revlist1n"
16734f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
16834f9b3eeSRoland Mainz		compound -A tail_args=(
16934f9b3eeSRoland Mainz			[legacy]=(       argv=( "-1"     ) )
17034f9b3eeSRoland Mainz			[std_like]=(     argv=( "-n" "1" ) )
17134f9b3eeSRoland Mainz			[long_options]=( argv=( "--lines" "1" ) )
17234f9b3eeSRoland Mainz		)
17334f9b3eeSRoland Mainz		expected_output=$'4' )
17434f9b3eeSRoland Mainz	(
17534f9b3eeSRoland Mainz		name="revlist1nr"
17634f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
17734f9b3eeSRoland Mainz		compound -A tail_args=(
17834f9b3eeSRoland Mainz			[legacy]=(       argv=( "-1r" ) )
17934f9b3eeSRoland Mainz			[std_like]=(     argv=( "-n" "1" "-r" ) )
18034f9b3eeSRoland Mainz			[long_options]=( argv=( "--lines" "1" "--reverse" ) )
18134f9b3eeSRoland Mainz		)
18234f9b3eeSRoland Mainz		expected_output=$'4'
18334f9b3eeSRoland Mainz	)
18434f9b3eeSRoland Mainz	(
18534f9b3eeSRoland Mainz		name="revlist2n"
18634f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
18734f9b3eeSRoland Mainz		compound -A tail_args=(
18834f9b3eeSRoland Mainz			[legacy]=(   argv=( "-2"  ) )
18934f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "2" ) )
19034f9b3eeSRoland Mainz		)
19134f9b3eeSRoland Mainz		expected_output=$'3\n4'
19234f9b3eeSRoland Mainz	)
19334f9b3eeSRoland Mainz	(
19434f9b3eeSRoland Mainz		name="revlist2nr"
19534f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
19634f9b3eeSRoland Mainz		compound -A tail_args=(
19734f9b3eeSRoland Mainz			[legacy]=(   argv=( "-2r" ) )
19834f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "2" "-r" ) )
19934f9b3eeSRoland Mainz			)
20034f9b3eeSRoland Mainz		expected_output=$'4\n3'
20134f9b3eeSRoland Mainz	)
20234f9b3eeSRoland Mainz	(
20334f9b3eeSRoland Mainz		name="revlist3nr"
20434f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
20534f9b3eeSRoland Mainz		compound -A tail_args=(
20634f9b3eeSRoland Mainz			[legacy]=(   argv=( "-3r" ) )
20734f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "3" "-r" ) )
20834f9b3eeSRoland Mainz		)
20934f9b3eeSRoland Mainz		expected_output=$'4\n3\n2'
21034f9b3eeSRoland Mainz	)
21134f9b3eeSRoland Mainz	(
21234f9b3eeSRoland Mainz		name="revlist2p"
21334f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
21434f9b3eeSRoland Mainz		compound -A tail_args=(
21534f9b3eeSRoland Mainz			[legacy]=(   argv=( "+2"  ) )
21634f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+2" ) )
21734f9b3eeSRoland Mainz			)
21834f9b3eeSRoland Mainz		expected_output=$'2\n3\n4'
21934f9b3eeSRoland Mainz	)
22034f9b3eeSRoland Mainz	(
22134f9b3eeSRoland Mainz		name="revlist2pr"
22234f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
22334f9b3eeSRoland Mainz		compound -A tail_args=(
22434f9b3eeSRoland Mainz			[legacy]=(   argv=( "+2r" ) )
22534f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+2" "-r" ) )
22634f9b3eeSRoland Mainz		)
22734f9b3eeSRoland Mainz		expected_output=$'4\n3\n2'
22834f9b3eeSRoland Mainz	)
22934f9b3eeSRoland Mainz	(
23034f9b3eeSRoland Mainz		name="revlist3p"
23134f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
23234f9b3eeSRoland Mainz		compound -A tail_args=(
23334f9b3eeSRoland Mainz			[legacy]=(   argv=( "+3"  ) )
23434f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+3"  ) )
23534f9b3eeSRoland Mainz		)
23634f9b3eeSRoland Mainz		expected_output=$'3\n4'
23734f9b3eeSRoland Mainz	)
23834f9b3eeSRoland Mainz	(
23934f9b3eeSRoland Mainz		name="revlist3pr"
24034f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
24134f9b3eeSRoland Mainz		compound -A tail_args=(
24234f9b3eeSRoland Mainz			[legacy]=(   argv=( "+3r" ) )
24334f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+3" "-r" ) )
24434f9b3eeSRoland Mainz		)
24534f9b3eeSRoland Mainz		expected_output=$'4\n3'
24634f9b3eeSRoland Mainz	)
24734f9b3eeSRoland Mainz	(
24834f9b3eeSRoland Mainz		name="revlist4p"
24934f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
25034f9b3eeSRoland Mainz		compound -A tail_args=(
25134f9b3eeSRoland Mainz			[legacy]=(   argv=( "+4"  ) )
25234f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+4"  ) )
25334f9b3eeSRoland Mainz		)
25434f9b3eeSRoland Mainz		expected_output=$'4'
25534f9b3eeSRoland Mainz	)
25634f9b3eeSRoland Mainz	(
25734f9b3eeSRoland Mainz		name="revlist4pr"
25834f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
25934f9b3eeSRoland Mainz		compound -A tail_args=(
26034f9b3eeSRoland Mainz			[legacy]=(   argv=( "+4r" ) )
26134f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+4" "-r" ) )
26234f9b3eeSRoland Mainz		)
26334f9b3eeSRoland Mainz		expected_output=$'4'
26434f9b3eeSRoland Mainz	)
26534f9b3eeSRoland Mainz	(
26634f9b3eeSRoland Mainz		name="revlist5p"
26734f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
26834f9b3eeSRoland Mainz		compound -A tail_args=(
26934f9b3eeSRoland Mainz			[legacy]=(   argv=( "+5"  ) )
27034f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+5"  ) )
27134f9b3eeSRoland Mainz		)
27234f9b3eeSRoland Mainz		expected_output=$''
27334f9b3eeSRoland Mainz	)
27434f9b3eeSRoland Mainz	(
27534f9b3eeSRoland Mainz		name="revlist5pr"
27634f9b3eeSRoland Mainz		input=$'1\n2\n3\n4'
27734f9b3eeSRoland Mainz		compound -A tail_args=(
27834f9b3eeSRoland Mainz			[legacy]=(   argv=( "+5r" ) )
27934f9b3eeSRoland Mainz			[std_like]=( argv=( "-n" "+5" "-r" ) )
28034f9b3eeSRoland Mainz		)
28134f9b3eeSRoland Mainz		expected_output=$''
28234f9b3eeSRoland Mainz	)
28334f9b3eeSRoland Mainz)
28434f9b3eeSRoland Mainz
28534f9b3eeSRoland Mainzfor testid in "${!testcases[@]}" ; do
28634f9b3eeSRoland Mainz	nameref tc=testcases[${testid}]
28734f9b3eeSRoland Mainz
28834f9b3eeSRoland Mainz	for argv_variants in "${!tc.tail_args[@]}" ; do
28934f9b3eeSRoland Mainz		nameref argv=tc.tail_args[${argv_variants}].argv
29034f9b3eeSRoland Mainz		output=$(
2913e14f97fSRoger A. Faulkner				set -o pipefail
2923e14f97fSRoger A. Faulkner	          		(trap "" PIPE ; print -r -- "${tc.input}") | tail "${argv[@]}"
29334f9b3eeSRoland Mainz			) || err_exit "test ${tc.name}/${argv_variants}: command failed with exit code $?"
294*b30d1939SAndy Fiddaman
29534f9b3eeSRoland Mainz		[[ "${output}" == "${tc.expected_output}" ]] || err_exit "test ${tc.name}/${argv_variants}: Expected $(doublebackslashquote "${tc.expected_output}"), got $(doublebackslashquote "${output}")"
29634f9b3eeSRoland Mainz	done
29734f9b3eeSRoland Mainzdone
29834f9b3eeSRoland Mainz
29934f9b3eeSRoland Mainz
30034f9b3eeSRoland Mainz# test2: test "tail -r </etc/profile | rev -l" vs. "cat </etc/profile"
301*b30d1939SAndy Fiddaman[[ "$(tail -r </etc/profile | rev -l)" == "$( cat /etc/profile )" ]] || err_exit "'tail -r </etc/profile | rev -l' output does not match 'cat /etc/profile'"
30234f9b3eeSRoland Mainz
30334f9b3eeSRoland Mainz
30434f9b3eeSRoland Mainz# test 3: ast-ksh.2009-05-05 "tail" builtin may crash if we pass unsupported long options
30534f9b3eeSRoland Mainz$SHELL -o errexit -c 'builtin tail ; print "hello" | tail --attack_of_chicken_monsters' >/dev/null 2>&1
306*b30d1939SAndy Fiddaman(( $? == 2 )) || err_exit "expected exit code 2 for unsupported long option, got $?"
30734f9b3eeSRoland Mainz
30834f9b3eeSRoland Mainz
30934f9b3eeSRoland Mainz# test 4: FIFO tests
31034f9b3eeSRoland Mainz
31134f9b3eeSRoland Mainz# FIFO test functions
31234f9b3eeSRoland Mainz# (we use functions here to do propper garbage collection)
31334f9b3eeSRoland Mainzfunction test_tail_fifo_1
31434f9b3eeSRoland Mainz{
31534f9b3eeSRoland Mainz	typeset tail_cmd="$1"
31634f9b3eeSRoland Mainz	integer i
31734f9b3eeSRoland Mainz	integer tail_pid=-1
318*b30d1939SAndy Fiddaman
31934f9b3eeSRoland Mainz	# cleanup trap
32034f9b3eeSRoland Mainz	trap "rm -f tailtestfifo tailout" EXIT
32134f9b3eeSRoland Mainz
32234f9b3eeSRoland Mainz	# create test FIFO
32334f9b3eeSRoland Mainz	mkfifo tailtestfifo
32434f9b3eeSRoland Mainz
32534f9b3eeSRoland Mainz	${tail_cmd} -f <tailtestfifo >tailout &
32634f9b3eeSRoland Mainz	tail_pid=$!
32734f9b3eeSRoland Mainz
32834f9b3eeSRoland Mainz	myintseq 20 >tailtestfifo
32934f9b3eeSRoland Mainz
33034f9b3eeSRoland Mainz	waitpidtimeout ${tail_pid} 5
33134f9b3eeSRoland Mainz
33234f9b3eeSRoland Mainz	if isvalidpid ${tail_pid} ; then
33334f9b3eeSRoland Mainz		err_exit "test_tail_fifo_1: # tail hung (not expected)"
33434f9b3eeSRoland Mainz		kill -KILL ${tail_pid}
33534f9b3eeSRoland Mainz	fi
33634f9b3eeSRoland Mainz
33734f9b3eeSRoland Mainz	wait || err_exit "tail child returned non-zero exit code=$?"
338*b30d1939SAndy Fiddaman
33934f9b3eeSRoland Mainz	[[ "$(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)")"
34034f9b3eeSRoland Mainz
34134f9b3eeSRoland Mainz	return 0
34234f9b3eeSRoland Mainz}
34334f9b3eeSRoland Mainz
34434f9b3eeSRoland Mainzfunction test_tail_fifo_2
34534f9b3eeSRoland Mainz{
34634f9b3eeSRoland Mainz	typeset tail_cmd="$1"
34734f9b3eeSRoland Mainz	integer i
34834f9b3eeSRoland Mainz	integer tail_pid=-1
349*b30d1939SAndy Fiddaman
35034f9b3eeSRoland Mainz	# cleanup trap
35134f9b3eeSRoland Mainz	trap "rm -f tailtestfifo tailout" EXIT
35234f9b3eeSRoland Mainz
35334f9b3eeSRoland Mainz	# create test FIFO
35434f9b3eeSRoland Mainz	mkfifo tailtestfifo
35534f9b3eeSRoland Mainz
35634f9b3eeSRoland Mainz	${tail_cmd} -f tailtestfifo >tailout &
35734f9b3eeSRoland Mainz	tail_pid=$!
35834f9b3eeSRoland Mainz
35934f9b3eeSRoland Mainz	myintseq 14 >tailtestfifo
36034f9b3eeSRoland Mainz
36134f9b3eeSRoland Mainz	waitpidtimeout ${tail_pid} 5
36234f9b3eeSRoland Mainz
36334f9b3eeSRoland Mainz	if isvalidpid ${tail_pid} ; then
36434f9b3eeSRoland Mainz		[[ "$(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)")"
36534f9b3eeSRoland Mainz
36634f9b3eeSRoland Mainz		myintseq 15 >>tailtestfifo
36734f9b3eeSRoland Mainz
36834f9b3eeSRoland Mainz		waitpidtimeout ${tail_pid} 5
36934f9b3eeSRoland Mainz
37034f9b3eeSRoland Mainz		if isvalidpid ${tail_pid} ; then
37134f9b3eeSRoland Mainz			kill -KILL ${tail_pid}
37234f9b3eeSRoland Mainz		else
37334f9b3eeSRoland Mainz			err_exit "test_tail_fifo_2: # tail exit with return code $? (not expected)"
37434f9b3eeSRoland Mainz		fi
37534f9b3eeSRoland Mainz	fi
37634f9b3eeSRoland Mainz
37734f9b3eeSRoland Mainz	wait || err_exit "tail child returned non-zero exit code=$?"
378*b30d1939SAndy Fiddaman
37934f9b3eeSRoland Mainz	[[ "$(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)")"
38034f9b3eeSRoland Mainz
38134f9b3eeSRoland Mainz	return 0
38234f9b3eeSRoland Mainz}
38334f9b3eeSRoland Mainz
38434f9b3eeSRoland Mainz# fixme: This should test /usr/bin/tail and /usr/xpg4/bin/tail in Solaris
38534f9b3eeSRoland Mainztest_tail_fifo_1 "tail"
38634f9b3eeSRoland Mainztest_tail_fifo_2 "tail"
38734f9b3eeSRoland Mainz
38834f9b3eeSRoland Mainz
38934f9b3eeSRoland Mainz# test 5: "tail -f" tests
39034f9b3eeSRoland Mainzfunction followtest1
39134f9b3eeSRoland Mainz{
39234f9b3eeSRoland Mainz	typeset -r FOLLOWFILE="followfile.txt"
39334f9b3eeSRoland Mainz	typeset -r OUTFILE="outfile.txt"
39434f9b3eeSRoland Mainz
39534f9b3eeSRoland Mainz	typeset title="$1"
39634f9b3eeSRoland Mainz	typeset testcmd="$2"
39734f9b3eeSRoland Mainz	typeset usenewline=$3
39834f9b3eeSRoland Mainz	typeset followstr=""
39934f9b3eeSRoland Mainz	typeset newline=""
40034f9b3eeSRoland Mainz	integer i
40134f9b3eeSRoland Mainz	integer tailchild=-1
40234f9b3eeSRoland Mainz
40334f9b3eeSRoland Mainz	if ${usenewline} ; then
40434f9b3eeSRoland Mainz		newline=$'\n'
40534f9b3eeSRoland Mainz	fi
406*b30d1939SAndy Fiddaman
40734f9b3eeSRoland Mainz	rm -f "${FOLLOWFILE}" "${OUTFILE}"
40834f9b3eeSRoland Mainz	print -n "${newline}" > "${FOLLOWFILE}"
40934f9b3eeSRoland Mainz
41034f9b3eeSRoland Mainz	${testcmd} -f "${FOLLOWFILE}" >"${OUTFILE}" &
41134f9b3eeSRoland Mainz	(( tailchild=$! ))
41234f9b3eeSRoland Mainz
41334f9b3eeSRoland Mainz	for (( i=0 ; i < 10 ; i++)) ; do
41434f9b3eeSRoland Mainz		followstr+="${newline}${i}"
41534f9b3eeSRoland Mainz		print -n "${i}${newline}" >>"${FOLLOWFILE}"
41634f9b3eeSRoland Mainz		sleep 2
41734f9b3eeSRoland Mainz
41834f9b3eeSRoland Mainz		[[ "$( < "${OUTFILE}")" == "${followstr}" ]] || err_exit "${title}: Expected $(doublebackslashquote "${followstr}"), got "$(doublebackslashquote "$( < "${OUTFILE}")")""
41934f9b3eeSRoland Mainz	done
42034f9b3eeSRoland Mainz
42134f9b3eeSRoland Mainz	kill -KILL ${tailchild} 2>/dev/null
4223e14f97fSRoger A. Faulkner	#kill -TERM ${tailchild} 2>/dev/null
42334f9b3eeSRoland Mainz	waitpidtimeout ${tailchild} 5
424*b30d1939SAndy Fiddaman
42534f9b3eeSRoland Mainz	if isvalidpid ${tailchild} ; then
42634f9b3eeSRoland Mainz		err_exit "${title}: tail pid=${tailchild} hung."
42734f9b3eeSRoland Mainz		kill -KILL ${tailchild} 2>/dev/null
42834f9b3eeSRoland Mainz	fi
429*b30d1939SAndy Fiddaman
43034f9b3eeSRoland Mainz	wait ${tailchild} 2>/dev/null
431*b30d1939SAndy Fiddaman
43234f9b3eeSRoland Mainz	rm -f "${FOLLOWFILE}" "${OUTFILE}"
43334f9b3eeSRoland Mainz
43434f9b3eeSRoland Mainz	return 0
43534f9b3eeSRoland Mainz}
43634f9b3eeSRoland Mainz
43734f9b3eeSRoland Mainzfollowtest1 "test5a" "tail" true
43834f9b3eeSRoland Mainz# fixme: later we should test this, too:
43934f9b3eeSRoland Mainz#followtest1 "test5b" "tail" false
44034f9b3eeSRoland Mainz#followtest1 "test5c" "/usr/xpg4/bin/tail" true
44134f9b3eeSRoland Mainz#followtest1 "test5d" "/usr/xpg4/bin/tail" false
44234f9b3eeSRoland Mainz#followtest1 "test5e" "/usr/bin/tail" true
44334f9b3eeSRoland Mainz#followtest1 "test5f" "/usr/bin/tail" false
44434f9b3eeSRoland Mainz
44534f9b3eeSRoland Mainz
4463e14f97fSRoger A. Faulkner# test 6: "tail -f" tests
4473e14f97fSRoger A. Faulknerfunction followtest2
4483e14f97fSRoger A. Faulkner{
4493e14f97fSRoger A. Faulkner	typeset -r FOLLOWFILE="followfile.txt"
4503e14f97fSRoger A. Faulkner	typeset -r OUTFILE="outfile.txt"
4513e14f97fSRoger A. Faulkner
4523e14f97fSRoger A. Faulkner	typeset title="$1"
4533e14f97fSRoger A. Faulkner	typeset testcmd="$2"
4543e14f97fSRoger A. Faulkner	integer tailchild=-1
4553e14f97fSRoger A. Faulkner
4563e14f97fSRoger A. Faulkner	rm -f "${FOLLOWFILE}" "${OUTFILE}"
4573e14f97fSRoger A. Faulkner
4583e14f97fSRoger A. Faulkner	myintseq 50000 >"${FOLLOWFILE}"
4593e14f97fSRoger A. Faulkner
4603e14f97fSRoger A. Faulkner	${testcmd} -n 60000 -f "${FOLLOWFILE}" >"${OUTFILE}" &
4613e14f97fSRoger A. Faulkner	(( tailchild=$! ))
462*b30d1939SAndy Fiddaman
4633e14f97fSRoger A. Faulkner	sleep 10
4643e14f97fSRoger A. Faulkner
4653e14f97fSRoger A. Faulkner	kill -KILL ${tailchild} 2>/dev/null
4663e14f97fSRoger A. Faulkner	#kill -TERM ${tailchild} 2>/dev/null
4673e14f97fSRoger A. Faulkner	waitpidtimeout ${tailchild} 5
468*b30d1939SAndy Fiddaman
4693e14f97fSRoger A. Faulkner	if isvalidpid ${tailchild} ; then
4703e14f97fSRoger A. Faulkner		err_exit "${title}: tail pid=${tailchild} hung."
4713e14f97fSRoger A. Faulkner		kill -KILL ${tailchild} 2>/dev/null
4723e14f97fSRoger A. Faulkner	fi
473*b30d1939SAndy Fiddaman
4743e14f97fSRoger A. Faulkner	wait ${tailchild} 2>/dev/null
475*b30d1939SAndy Fiddaman
4763e14f97fSRoger A. Faulkner	# this tail should be an external process
4773e14f97fSRoger A. Faulkner	outstr=$(/usr/bin/tail "${OUTFILE}") || err_exit "tail returned non-zero exit code $?"
478*b30d1939SAndy Fiddaman        [[ "${outstr}" == 49991*50000 ]] || err_exit "${title}: Expected match for 49991*50000, got "$(singlebackslashquote "${outstr}")""
479*b30d1939SAndy Fiddaman
4803e14f97fSRoger A. Faulkner	rm -f "${FOLLOWFILE}" "${OUTFILE}"
4813e14f97fSRoger A. Faulkner
4823e14f97fSRoger A. Faulkner	return 0
4833e14f97fSRoger A. Faulkner}
4843e14f97fSRoger A. Faulkner
4853e14f97fSRoger A. Faulknerfollowtest2 "test6a" "tail"
4863e14f97fSRoger A. Faulknerfollowtest2 "test6b" "/usr/xpg4/bin/tail"
4873e14f97fSRoger A. Faulkner# fixme: later we should test this, too:
4883e14f97fSRoger A. Faulkner#followtest2 "test6c" "/usr/bin/tail"
4893e14f97fSRoger A. Faulkner
4903e14f97fSRoger A. Faulkner
49134f9b3eeSRoland Mainz# cleanup
49234f9b3eeSRoland Mainzcd "${ocwd}"
49334f9b3eeSRoland Mainzrmdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
49434f9b3eeSRoland Mainz
49534f9b3eeSRoland Mainz
49634f9b3eeSRoland Mainz# tests done
49734f9b3eeSRoland Mainzexit $((Errors))
498