#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#
#
# Additional tests borrowed from ksh93 builtin tail test script
#
# test setup
function err_exit
{
print -u2 -n "\t"
}
alias err_exit='err_exit $LINENO'
set -o nounset
integer Errors=0
# common functions
function isvalidpid
{
return 1
}
function waitpidtimeout
{
integer pid=$1
float timeout=$2
float i
float -r STEP=0.5 # const
isvalidpid ${pid} || break
done
return 0
}
function myintseq
{
integer i
float arg1=$1
float arg2=$2
float arg3=$3
case $# in
1)
done
;;
2)
done
;;
3)
done
;;
*)
return 1
;;
esac
return 0
}
# quote input string but use single-backslash that "err_exit" prints
# the strings correctly
function singlebackslashquote
{
typeset s
print -r "$s"
return 0
}
# quote input string but use double-backslash that "err_exit" prints
# the strings correctly
function doublebackslashquote
{
typeset s
s="${s//\\/\\\\}"
print -r "$s"
return 0
}
# main
# builtin tail || err_exit "tail builtin not found"
typeset ocwd
typeset tmpdir
# create temporary test directory
tmpdir="$(mktemp -t -d "test_sun_solaris_builtin_tail.XXXXXXXX")" || err_exit "Cannot create temporary directory"
# run tests:
# test1: basic tests
compound -a testcases=(
(
name="reverse_n"
input=$'hello\nworld'
compound -A tail_args=(
)
expected_output=$'world\nhello'
)
(
name="revlist0n"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "0" ) )
)
expected_output=$''
)
(
name="revlist0nr"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "0" "-r" ) )
# [long_options]=( argv=( "--lines" "0" "--reverse" ) )
)
(
name="revlist1n"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "1" ) )
# [long_options]=( argv=( "--lines" "1" ) )
)
(
name="revlist1nr"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "1" "-r" ) )
# [long_options]=( argv=( "--lines" "1" "--reverse" ) )
)
expected_output=$'4'
)
(
name="revlist2n"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "2" ) )
)
expected_output=$'3\n4'
)
(
name="revlist2nr"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "2" "-r" ) )
)
expected_output=$'4\n3'
)
(
name="revlist3nr"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "3" "-r" ) )
)
expected_output=$'4\n3\n2'
)
(
name="revlist2p"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "+2" ) )
)
expected_output=$'2\n3\n4'
)
# Note: following test case trips up legacy Solaris 'tail' as well
# (
# name="revlist2pr"
# input=$'1\n2\n3\n4'
# compound -A tail_args=(
# [legacy]=( argv=( "+2r" ) )
# [std_like]=( argv=( "-n" "+2" "-r" ) )
# )
# expected_output=$'4\n3\n2'
# )
(
name="revlist3p"
input=$'1\n2\n3\n4'
compound -A tail_args=(
)
expected_output=$'3\n4'
)
# Note: following test case trips up legacy Solaris 'tail' as well
# (
# name="revlist3pr"
# input=$'1\n2\n3\n4'
# compound -A tail_args=(
# [legacy]=( argv=( "+3r" ) )
# [std_like]=( argv=( "-n" "+3" "-r" ) )
# )
# expected_output=$'4\n3'
# )
(
name="revlist4p"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "+4" ) )
)
expected_output=$'4'
)
# Note: following test case trips up legacy Solaris 'tail' as well
# (
# name="revlist4pr"
# input=$'1\n2\n3\n4'
# compound -A tail_args=(
# [legacy]=( argv=( "+4r" ) )
# [std_like]=( argv=( "-n" "+4" "-r" ) )
# )
# expected_output=$'4'
# )
(
name="revlist5p"
input=$'1\n2\n3\n4'
compound -A tail_args=(
# [std_like]=( argv=( "-n" "+5" ) )
)
expected_output=$''
)
# Note: following test case trips up legacy Solaris 'tail' as well
# (
# name="revlist5pr"
# input=$'1\n2\n3\n4'
# compound -A tail_args=(
# [legacy]=( argv=( "+5r" ) )
# [std_like]=( argv=( "-n" "+5" "-r" ) )
# )
# expected_output=$''
# )
)
output=$(
set -o pipefail
[[ "${output}" == "${tc.expected_output}" ]] || err_exit "test ${tc.name}/${argv_variants}: Expected $(doublebackslashquote "${tc.expected_output}"), got $(doublebackslashquote "${output}")"
done
done
[[ "$($TAIL -r </etc/profile | rev -l)" == "$( cat /etc/profile )" ]] || err_exit "'tail -r </etc/profile | rev -l' output does not match 'cat /etc/profile'"
# Test case not applicable to FreeBSD 'tail'
# test 3: ast-ksh.2009-05-05 "tail" builtin may crash if we pass unsupported long options
#$SHELL -o errexit -c 'builtin tail ; print "hello" | tail --attack_of_chicken_monsters' >/dev/null 2>&1
#(( $? == 2 )) || err_exit "expected exit code 2 for unsupported long option, got $?"
# test 4: FIFO tests
# FIFO test functions
# (we use functions here to do propper garbage collection)
function test_tail_fifo_1
{
typeset tail_cmd="$1"
integer i
integer tail_pid=-1
# cleanup trap
# create test FIFO
${tail_cmd} -f <tailtestfifo >tailout &
tail_pid=$!
myintseq 20 >tailtestfifo
waitpidtimeout ${tail_pid} 5
if isvalidpid ${tail_pid} ; then
err_exit "test_tail_fifo_1: # tail hung (not expected)"
fi
wait || err_exit "tail child returned non-zero exit code=$?"
[[ "$(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)")"
return 0
}
function test_tail_fifo_2
{
typeset tail_cmd="$1"
integer i
integer tail_pid=-1
# cleanup trap
# create test FIFO
${tail_cmd} -f tailtestfifo >tailout &
tail_pid=$!
myintseq 14 >tailtestfifo
waitpidtimeout ${tail_pid} 5
if isvalidpid ${tail_pid} ; then
[[ "$(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)")"
myintseq 15 >>tailtestfifo
waitpidtimeout ${tail_pid} 5
if isvalidpid ${tail_pid} ; then
else
err_exit "test_tail_fifo_2: # tail exit with return code $? (not expected)"
fi
fi
wait || err_exit "tail child returned non-zero exit code=$?"
[[ "$(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)")"
return 0
}
# test 5: "tail -f" tests
function followtest1
{
typeset -r FOLLOWFILE="followfile.txt"
typeset -r OUTFILE="outfile.txt"
typeset title="$1"
typeset testcmd="$2"
typeset usenewline=$3
typeset followstr=""
typeset newline=""
integer i
integer tailchild=-1
if ${usenewline} ; then
newline=$'\n'
fi
rm -f "${FOLLOWFILE}" "${OUTFILE}"
print -n "${newline}" > "${FOLLOWFILE}"
for (( i=0 ; i < 10 ; i++)) ; do
followstr+="${newline}${i}"
print -n "${i}${newline}" >>"${FOLLOWFILE}"
sleep 2
[[ "$( < "${OUTFILE}")" == "${followstr}" ]] || err_exit "${title}: Expected $(doublebackslashquote "${followstr}"), got "$(doublebackslashquote "$( < "${OUTFILE}")")""
done
waitpidtimeout ${tailchild} 5
if isvalidpid ${tailchild} ; then
err_exit "${title}: tail pid=${tailchild} hung."
fi
rm -f "${FOLLOWFILE}" "${OUTFILE}"
return 0
}
followtest1 "test5a" "$TAIL" true
# fixme: later we should test this, too:
#followtest1 "test5b" "tail" false
# test 6: "tail -f" tests
function followtest2
{
typeset -r FOLLOWFILE="followfile.txt"
typeset -r OUTFILE="outfile.txt"
typeset title="$1"
typeset testcmd="$2"
integer tailchild=-1
rm -f "${FOLLOWFILE}" "${OUTFILE}"
myintseq 50000 >"${FOLLOWFILE}"
sleep 10
waitpidtimeout ${tailchild} 5
if isvalidpid ${tailchild} ; then
err_exit "${title}: tail pid=${tailchild} hung."
fi
# this tail should be an external process
[[ "${outstr}" == 49991*50000 ]] || err_exit "${title}: Expected match for 49991*50000, got "$(singlebackslashquote "${outstr}")""
rm -f "${FOLLOWFILE}" "${OUTFILE}"
return 0
}
followtest2 "test6a" "$TAIL"
followtest2 "test6b" "$TAIL"
# fixme: later we should test this, too:
# cleanup
cd "${ocwd}"
# tests done