Files
mosh/src/tests/e2e-test
T
John Hood 7c68667bc0 Explicitly set tmux window size in tests.
Recent versions of tmux master gave us an 80x23 window.  tmux has been
fixed to default to 80x24, and also to allow setting window sizes in
control mode.  These flags fortunately do not conflict with older
versions tmux.  So we use them to avoid problems going forward.
2017-05-28 21:19:03 -04:00

327 lines
7.8 KiB
Bash
Executable File

#!/bin/sh
. "$(dirname "$0")/e2e-test-subrs"
#
# Validate that mosh produces expected output, using screen captures
# in tmux.
#
log()
{
printf "$@"
}
error()
{
printf "$@" >&2
}
dump_logs()
{
dir=$1
shift
testname=$(basename "$dir" .d)
for logfile in $dir/*.tmux.log; do
printf "travis_fold:start:%s-%s\n" "$testname" "$(basename "$logfile")"
cat "$logfile"
printf "travis_fold:end:%s-%s\n" "$testname" "$(basename "$logfile")"
done
}
test_success()
{
exit 0
}
test_failure()
{
error "$@"
exit 1
}
test_skipped()
{
error "$@"
exit 77
}
test_error()
{
error "$@"
exit 99
}
test_exitstatus()
{
status=$1
shift
error "$@"
exit "$status"
}
# Tmux check.
tmux_check()
{
# OpenBSD tmux does not have '-V'.
if [ "$(uname -s)" = "OpenBSD" ]; then
openbsd_major="$(uname -r)"
openbsd_major="${openbsd_major%%.*}"
if [ "${openbsd_major}" -ge 6 ]; then
return 0
fi
fi
version=$(tmux -V)
if [ $? != 0 ]; then
error "tmux unavailable\n"
return 1
fi
if [ "$version" = "tmux master" ]; then
return 0
fi
version=${version##tmux }
version_major=${version%%.*}
version_minor=${version##*.}
# need version 1.8 for capture-pane
if [ "$version_major" -lt 1 ] ||
{ [ "$version_major" -eq 1 ] && [ "$version_minor" -lt 8 ]; }; then
error "tmux version %s too old\n" "$version"
return 1
fi
# Finally, check that tmux actually works to some degree.
tmux -C new-session true
}
ssh_localhost_check()
{
ssh localhost :
if [ $? -ne 0 ]; then
error "ssh to localhost failed\n"
return 1
fi
return 0
}
# These two functions are wrappers for mosh-client/mosh-server to turn
# on verbosity and log stderr.
mosh_client()
{
if [ -z "$MOSH_CLIENT" ] || [ -z "$MOSH_E2E_TEST" ]; then
test_error "mosh_client: variables missing\n"
fi
exec 2> "${MOSH_E2E_TEST}.client.stderr"
exec "$MOSH_CLIENT" $MOSH_CLIENT_ARGS "$@"
}
mosh_server()
{
if [ -z "$MOSH_SERVER" ] || [ -z "$MOSH_E2E_TEST" ]; then
test_error "mosh_server: variables missing\n"
fi
exec 2> "${MOSH_E2E_TEST}.server.stderr"
exec "$MOSH_SERVER" new -vv $MOSH_SERVER_ARGS -@ "$@"
}
# main
# Set up environment
if [ -z "$srcdir" ]; then
export srcdir=$PWD
else
srcdir="$(cd "$srcdir" && pwd)"
if [ $? -ne 0 ]; then
error "can't cd to srcdir: %s\n" "$srcdir"
exit 99
fi
fi
# Wrappers.
case "$(basename "$0")" in
mosh-client)
mosh_client "$@"
exit
;;
mosh-server)
mosh_server "$@"
exit
;;
*)
;;
esac
if [ $# -lt 2 ]; then
test_error "not enough args\n"
fi
# Get arguments (only one so far)
test_name=$1
shift
test_args=$@
# XXX could use AM testsubdir macro instead
test_dir=$(basename "${test_name}").d
test_script="${test_name}"
tests_dir=$(dirname "${test_name}")
if ! set_locale "${tests_dir}"; then
test_error "e2e-test: no usable locale\n"
fi
if ! tmux_check; then
test_skipped "tmux unavailable\n"
fi
rm -rf "${test_dir}"
mkdir "${test_dir}"
on_exit() {
rv=$?
if test $rv -ne 0; then
dump_logs "$test_dir" $test_args
fi
exit $rv
}
trap on_exit EXIT
# Set up tests to run.
server_tests=
compare_tests=
for i in $test_args; do
case $i in
baseline|direct|variant)
server_tests="$server_tests $i";;
verify|same|different)
compare_tests="$compare_tests $i";;
tmux)
tmux=1;;
client)
client=1;;
server)
server=1;;
post)
post=1;;
mosh-args)
mosh_args=$("${test_script}" mosh-args);;
client-args)
MOSH_CLIENT_ARGS=$("${test_script}" client-args)
export MOSH_CLIENT_ARGS;;
server-args)
MOSH_SERVER_ARGS=$("${test_script}" server-args)
export MOSH_SERVER_ARGS;;
*)
error 'unknown test type argument %s\n' "$i"
exit 99
;;
esac
done
# Run test(s).
client_wrapper=
if [ -n "$client" ]; then
client_wrapper="${test_script} client"
fi
server_wrapper="\"${srcdir}/e2e-test-server\""
if [ -n "$server" ]; then
server_wrapper="\"${srcdir}/${test_script}\" server"
fi
tmux_stdin="${srcdir}/hold-stdin"
if [ -n "$tmux" ]; then
tmux_stdin="${test_script} tmux"
fi
for run in $server_tests; do
log "Running server test %s.\n" "$run"
# These three variables are for the benefit of the mosh-client and mosh-server wrappers.
export MOSH_CLIENT="$PWD/../frontend/mosh-client"
export MOSH_SERVER="$PWD/../frontend/mosh-server"
export MOSH_E2E_TEST="$PWD/${test_dir}/${run}"
# XXX need to quote special chars in server pathname here somehow
sut="../../scripts/mosh --client=${srcdir}/mosh-client --server=${srcdir}/mosh-server --local --bind-server=127.0.0.1 ${mosh_args} 127.0.0.1"
if [ "$run" = "direct" ]; then
sut=""
fi
# Actually execute code under test
# XXX tmux 1.8 requires shell command as a single arg; once we move to 2.0, undo these quotes
# XXX this ignores $TMPDIR, because it results in an overlong pathname on OS X
tmux_socket="/tmp/.tmux-mosh-test-$$"
ln -fs "${tmux_socket}" "${test_dir}/tmux-socket"
# tmux <= 2.5 ignore -x/-y, but the client sets the session to 80x24.
# tmux from 2017-05-27 and later should default to an 80x24 session,
# but do use -x/-y on control-master clients.
${tmux_stdin} tmux -f /dev/null -S "${tmux_socket}" -C new-session -x 80 -y 24 "${srcdir}/print-exitstatus ${client_wrapper} ${sut} ${server_wrapper} \"${PWD}/${test_dir}/${run}\" \"${PWD}/${test_script} ${run}\"" > "${test_dir}/${run}.tmux.log"
rv=$?
rm -f "${tmux_socket}" "${test_dir}/tmux-socket"
if [ $rv -ne 0 ]; then
test_error "tmux failure on test %s\n" "$run"
fi
# Check for mosh failures
if ! grep -q "@@@ exitstatus: 0 @@@" "${test_dir}/${run}.tmux.log"; then
test_error "mosh-client had non-zero exitstatus\n"
fi
# Check for server harness failures
if [ -z "$server" ]; then
if [ ! -s "${test_dir}/${run}.capture" ] \
|| [ ! -s "${test_dir}/${run}.exitstatus" ]; then
test_error "server harness failure on test %s\n" "$run"
fi
read -r server_rv < "${test_dir}/${run}.exitstatus"
if [ "$server_rv" -ne 0 ]; then
test_error "server harness exited with status %s\n" "$server_rv"
fi
fi
if [ "${run}" != "direct" ]; then
# Check for "round-trip" failures
if grep -q "round-trip Instruction verification failed" "${test_dir}/${run}.server.stderr"; then
test_error "Round-trip Instruction verification failed on server during %s\n" "$run"
fi
# Check for 0-timeout select() issue
if egrep -q "(polls, rate limiting|consecutive polls)" "${test_dir}/${run}.server.stderr"; then
test_error "select() with zero timeout called too often on server during %s\n" "$run"
fi
# Check for assert()
if egrep -q "assertion.*failed" "${test_dir}/${run}.server.stderr"; then
test_error "assertion during %s\n" "$run"
fi
fi
# XXX We'd also like to check for "target state Instruction
# verification failed", a new check, but tmux's lack of BCE
# support forces mosh to clear lines with spaces and change a
# framebuffer in a way that causes this to fire spuriously.
done
for compare in $compare_tests; do
log "Running server comparison %s.\n" "$compare"
# Compare captures
if [ "$compare" = verify ]; then
test1="direct"
test2="baseline"
else
test1="baseline"
test2="variant"
fi
if diff -q "${test_dir}/${test1}.capture" "${test_dir}/${test2}.capture"; then
differ=n
else
differ=y
fi
if [ "$compare" = different ]; then
desired=y
badresult=same
else
desired=n
badresult=different
fi
if [ $differ != $desired ]; then
test_failure "Output is %s between tests %s and %s\n" "$badresult" "$test1" "$test2"
fi
done
# Run a post script (usually a custom validation of results)
if [ -n "$post" ]; then
"${test_script}" post
status=$?
if [ $status -ne 0 ]; then
test_exitstatus $status "Post test failed with exitstatus %d\n" $status
fi
fi