Files
mosh/src/tests/prediction-unicode.test
T
2016-01-11 06:14:27 -05:00

153 lines
3.2 KiB
Bash
Executable File

#!/bin/sh
#
# This is a regression test for a bug seen where mosh-client's
# prediction code would sometimes show "gück" when "glück" was typed.
# mosh-client would output a predicted Unicode input character
# first as an 8-bit character containing the lowest 8 bits of the
# Unicode code point, then redraw it correctly with its UTF-8 sequence
# when the prediction is validated. For many accented Latin
# characters, the 8-bit character is an illegal UTF-8 code sequence.
# Most terminal emulators will output the Unicode replacement
# character, which is only visible until validation. urxvt, however,
# draws no character and does not change the cursor location on an
# illegal UTF-8 sequence, causing this bug to be visible as ongoing
# display corruption. A subset of wide characters (including CJK)
# will show display corruption with all terminal emulators, because a
# narrow replacement character will be drawn when a wide character
# should have been.
#
# tmux draws a replacement character for invalid UTF-8, and we
# depend on that in this test.
#
# Another similar failing case is typing "faĩl". In this case the "ĩ"
# would be predicted as ")" before being replaced by the
# correct character.
#
fail()
{
printf "$@" 2>&1
exit 99
}
PATH=$PATH:.:$srcdir
# Top-level wrapper.
if [ $# -eq 0 ]; then
e2e-test $0 tmux baseline mosh-args post
exit
fi
sleepf()
{
(sleep .1 || sleep 1) > /dev/null 2>&1
}
seq()
{
if [ $# -lt 1 -o $# -gt 3 ]; then
echo "bad args" >&2
fi
first=$1
incr=1
last=0
case $# in
3)
incr=$2
last=$3
;;
2)
last=$2
;;
1)
;;
esac
while :; do
printf '%d\n' $first
first=$(expr $first + $incr)
if [ $first -gt $last ]; then
break
fi
done
}
chr()
{
printf "\\$(printf %03o $1)"
}
utf8cp()
{
local c=$1
if [ $c -gt $((0x10ffff)) ]; then
fail "illegal Unicode code point %x\n" $c
elif [ $c -lt $((0x80)) ]; then
chr $c
elif [ $c -lt $((0x800)) ]; then
chr $(( (($c >> 6) & 0x1f) | 0xc0 ))
chr $(( ($c & 0x3f) | 0x80 ))
elif [ $c -lt $((0x10000)) ]; then
chr $(( (($c >> 12) & 0x0f) | 0xe0 ))
chr $(( (($c >> 6) & 0x3f) | 0x80 ))
chr $(( ($c & 0x3f) | 0x80 ))
elif [ $c -lt $((0x200000)) ]; then
chr $(( (($c >> 18) & 0x03) | 0xf0 ))
chr $(( (($c >> 12) & 0x3f) | 0x80 ))
chr $(( (($c >> 6) & 0x3f) | 0x80 ))
chr $(( ($c & 0x3f) | 0x80 ))
fi
}
tmux_commands()
{
for x in $(seq 1 5); do
for y in $(seq 1 5); do
for i in g l ü c k " " f a ĩ l " "; do
printf "send-keys '%s'\n" "$i"
sleepf
done
done
printf "send-keys 0x0d\n"
done
printf "send-keys 0x0d\n"
sleep 1
printf "send-keys 0x04\n"
sleep 10
}
tmux_stdin()
{
tmux_commands | "$@"
exit
}
baseline()
{
# Just receive and toss input in canonical mode.
cat > /dev/null
}
post()
{
# Look for bad output: ')' or \374
if [ -n "$(env -u LC_ALL -u LC_CTYPE -u LANGUAGE LANG=C egrep "%output %0 (\)|$(printf \\374))" $(basename $0).d/baseline.tmux.log)" ]; then
exit 1
fi
exit 0
}
case $1 in
tmux)
shift;
tmux_stdin "$@";;
baseline)
baseline;;
mosh-args)
printf "%s\n" "--predict=always";;
post)
post;;
*)
fail "unknown test argument %s\n" $1;;
esac