Merge pull request #1009 from ZyX-I/fix-1008

Improve Python 3 compatibility when using daemon and client
This commit is contained in:
Nikolai Aleksandrovich Pavlov 2014-08-23 16:30:59 +04:00
commit 1a71ed3eba
13 changed files with 275 additions and 117 deletions

View File

@ -60,20 +60,28 @@ int main(int argc, char *argv[]) {
int i; int i;
ptrdiff_t read_size; ptrdiff_t read_size;
struct sockaddr_un server; struct sockaddr_un server;
char address[ADDRESS_SIZE]; char address_buf[ADDRESS_SIZE];
const char eof[2] = "\0\0"; const char eof[2] = "\0\0";
char num_args[NUM_ARGS_SIZE]; char num_args[NUM_ARGS_SIZE];
char buf[BUF_SIZE]; char buf[BUF_SIZE];
char *newargv[NEW_ARGV_SIZE]; char *newargv[NEW_ARGV_SIZE];
char *wd = NULL; char *wd = NULL;
char **envp; char **envp;
const char *address;
if (argc < 2) { if (argc < 2) {
printf("Must provide at least one argument.\n"); printf("Must provide at least one argument.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
snprintf(address, ADDRESS_SIZE, ADDRESS_TEMPLATE, getuid()); if (argc > 3 && strcmp(argv[1], "--socket") == 0) {
address = argv[2];
argv += 2;
argc -= 2;
} else {
snprintf(address_buf, ADDRESS_SIZE, ADDRESS_TEMPLATE, getuid());
address = &(address_buf[0]);
}
sd = socket(AF_UNIX, SOCK_STREAM, 0); sd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sd == -1) if (sd == -1)

View File

@ -8,16 +8,22 @@ import socket
import os import os
import errno import errno
if len(sys.argv) < 2: if len(sys.argv) < 2:
print('Must provide at least one argument.', file=sys.stderr) print('Must provide at least one argument.', file=sys.stderr)
raise SystemExit(1) raise SystemExit(1)
platform = sys.platform.lower() platform = sys.platform.lower()
use_filesystem = 'darwin' in platform use_filesystem = 'darwin' in platform
# use_filesystem = True
del platform del platform
address = ('/tmp/powerline-ipc-%d' if use_filesystem else '\0powerline-ipc-%d') % os.getuid() if sys.argv[1] == '--socket':
address = sys.argv[2]
if not use_filesystem:
address = '\0' + address
del sys.argv[1:3]
else:
address = ('/tmp/powerline-ipc-%d' if use_filesystem else '\0powerline-ipc-%d') % os.getuid()
sock = socket.socket(family=socket.AF_UNIX) sock = socket.socket(family=socket.AF_UNIX)
@ -42,22 +48,23 @@ fenc = sys.getfilesystemencoding() or 'utf-8'
if fenc == 'ascii': if fenc == 'ascii':
fenc = 'utf-8' fenc = 'utf-8'
args = [bytes('%x' % (len(sys.argv) - 1))] tobytes = lambda s: s if isinstance(s, bytes) else s.encode(fenc)
args.extend((x.encode(fenc) if isinstance(x, type('')) else x for x in sys.argv[1:]))
args = [tobytes('%x' % (len(sys.argv) - 1))]
args.extend((tobytes(s) for s in sys.argv[1:]))
try: try:
cwd = os.getcwd() cwd = os.getcwd()
except EnvironmentError: except EnvironmentError:
pass pass
else: else:
if isinstance(cwd, type('')): if not isinstance(cwd, bytes):
cwd = cwd.encode(fenc) cwd = cwd.encode(fenc)
args.append(cwd) args.append(cwd)
env = (k + b'=' + v for k, v in os.environ.items()) args.extend((tobytes(k) + b'=' + tobytes(v) for k, v in os.environ.items()))
env = (x if isinstance(x, bytes) else x.encode(fenc, 'replace') for x in env)
args.extend(env)
EOF = b'\0\0' EOF = b'\0\0'
@ -75,4 +82,7 @@ while True:
sock.close() sock.close()
sys.stdout.write(b''.join(received)) if sys.version_info < (3,):
sys.stdout.write(b''.join(received))
else:
sys.stdout.buffer.write(b''.join(received))

View File

@ -1,6 +1,12 @@
#!/bin/sh #!/bin/sh
ADDRESS="powerline-ipc-${UID:-`id -u`}" if test "$1" = "--socket" ; then
shift
ADDRESS="$1"
shift
else
ADDRESS="powerline-ipc-${UID:-`id -u`}"
fi
# Warning: env -0 does not work in busybox. Consider switching to parsing # Warning: env -0 does not work in busybox. Consider switching to parsing
# `set` output in this case # `set` output in this case

View File

@ -122,11 +122,9 @@ powerline into different directory.
.. note:: .. note::
``$POWERLINE_COMMAND`` appears in shell scripts without quotes thus you can ``$POWERLINE_COMMAND`` appears in shell scripts without quotes thus you can
specify additional parameters in bash. In zsh you will have to make specify additional parameters in bash. In tmux it is passed to ``eval`` and
``$POWERLINE_COMMAND`` an array parameter to achieve the same result. In depends on the shell used. POSIX-compatible shells, zsh, bash and fish will
tmux it is passed to ``eval`` and depends on the shell used. split this variable in this case.
POSIX-compatible shells, zsh, bash and fish will split this variable in this
case.
If you want to disable prompt in shell, but still have tmux support or if you If you want to disable prompt in shell, but still have tmux support or if you
want to disable tmux support you can use variables want to disable tmux support you can use variables
@ -147,9 +145,3 @@ tcsh you should set ``$POWERLINE_NO_TCSH_ABOVE`` or
If you do not want to see additional space which is added to the right prompt in If you do not want to see additional space which is added to the right prompt in
fish in order to support multiline prompt you should set fish in order to support multiline prompt you should set
``$POWERLINE_NO_FISH_ABOVE`` or ``$POWERLINE_NO_SHELL_ABOVE`` variables. ``$POWERLINE_NO_FISH_ABOVE`` or ``$POWERLINE_NO_SHELL_ABOVE`` variables.
.. note::
Most supported shells configuration scripts check for ``$POWERLINE_CONFIG``
and ``$POWERLINE_COMMAND`` configuration variables being empty. But tcsh
configuration script checks for variables being *defined*, not empty.

View File

@ -11,6 +11,14 @@ if ! $?POWERLINE_CONFIG then
else else
set POWERLINE_CONFIG="$POWERLINE_SOURCED[2]:h:h:h:h/scripts/powerline-config" set POWERLINE_CONFIG="$POWERLINE_SOURCED[2]:h:h:h:h/scripts/powerline-config"
endif endif
else
if "$POWERLINE_CONFIG" == "" then
if ( { which powerline-config > /dev/null } ) then
set POWERLINE_CONFIG="powerline-config"
else
set POWERLINE_CONFIG="$POWERLINE_SOURCED[2]:h:h:h:h/scripts/powerline-config"
endif
endif
endif endif
if ( { $POWERLINE_CONFIG shell --shell=tcsh uses tmux } ) then if ( { $POWERLINE_CONFIG shell --shell=tcsh uses tmux } ) then
alias _powerline_tmux_set_pwd 'if ( $?TMUX && { tmux refresh -S >&/dev/null } ) tmux setenv -g TMUX_PWD_`tmux display -p "#D" | tr -d %` $PWD:q ; if ( $?TMUX ) tmux refresh -S >&/dev/null' alias _powerline_tmux_set_pwd 'if ( $?TMUX && { tmux refresh -S >&/dev/null } ) tmux setenv -g TMUX_PWD_`tmux display -p "#D" | tr -d %` $PWD:q ; if ( $?TMUX ) tmux refresh -S >&/dev/null'
@ -19,6 +27,10 @@ endif
if ( { $POWERLINE_CONFIG shell --shell=tcsh uses prompt } ) then if ( { $POWERLINE_CONFIG shell --shell=tcsh uses prompt } ) then
if ! $?POWERLINE_COMMAND then if ! $?POWERLINE_COMMAND then
set POWERLINE_COMMAND="`$POWERLINE_CONFIG:q shell command`" set POWERLINE_COMMAND="`$POWERLINE_CONFIG:q shell command`"
else
if "$POWERLINE_COMMAND" == "" then
set POWERLINE_COMMAND="`$POWERLINE_CONFIG:q shell command`"
endif
endif endif
if ( $?POWERLINE_NO_TCSH_ABOVE || $?POWERLINE_NO_SHELL_ABOVE ) then if ( $?POWERLINE_NO_TCSH_ABOVE || $?POWERLINE_NO_SHELL_ABOVE ) then

View File

@ -131,7 +131,7 @@ _powerline_setup_prompt() {
} }
else else
if test -z "${POWERLINE_COMMAND}" ; then if test -z "${POWERLINE_COMMAND}" ; then
POWERLINE_COMMAND=( "$($POWERLINE_CONFIG shell command)" ) POWERLINE_COMMAND="$($POWERLINE_CONFIG shell command)"
fi fi
local add_args='-r .zsh' local add_args='-r .zsh'
@ -145,11 +145,11 @@ _powerline_setup_prompt() {
local add_args_2=$add_args$new_args_2 local add_args_2=$add_args$new_args_2
add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - 1 ))' add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - 1 ))'
local add_args_r2=$add_args$new_args_2 local add_args_r2=$add_args$new_args_2
PS1='$($POWERLINE_COMMAND shell aboveleft '$add_args')' PS1='$($=POWERLINE_COMMAND shell aboveleft '$add_args')'
RPS1='$($POWERLINE_COMMAND shell right '$add_args')' RPS1='$($=POWERLINE_COMMAND shell right '$add_args')'
PS2='$($POWERLINE_COMMAND shell left '$add_args_2')' PS2='$($=POWERLINE_COMMAND shell left '$add_args_2')'
RPS2='$($POWERLINE_COMMAND shell right '$add_args_r2')' RPS2='$($=POWERLINE_COMMAND shell right '$add_args_r2')'
PS3='$($POWERLINE_COMMAND shell left '$add_args_3')' PS3='$($=POWERLINE_COMMAND shell left '$add_args_3')'
fi fi
} }

View File

@ -66,6 +66,7 @@ def get_argparser(parser=None, *args, **kwargs):
p.add_argument('-t', '--theme_option', metavar='THEME.KEY.KEY=VALUE', action='append', help='Like above, but theme-specific. THEME should point to an existing and used theme to have any effect, but it is fine to use any theme here.') p.add_argument('-t', '--theme_option', metavar='THEME.KEY.KEY=VALUE', action='append', help='Like above, but theme-specific. THEME should point to an existing and used theme to have any effect, but it is fine to use any theme here.')
p.add_argument('-R', '--renderer_arg', metavar='KEY=VAL', action='append', help='Like above, but provides argument for renderer. Is supposed to be used only by shell bindings to provide various data like last_exit_code or last_pipe_status (they are not using --renderer_arg for historical resons: renderer_arg was added later).') p.add_argument('-R', '--renderer_arg', metavar='KEY=VAL', action='append', help='Like above, but provides argument for renderer. Is supposed to be used only by shell bindings to provide various data like last_exit_code or last_pipe_status (they are not using --renderer_arg for historical resons: renderer_arg was added later).')
p.add_argument('-p', '--config_path', action='append', metavar='PATH', help='Path to configuration directory. If it is present then configuration files will only be seeked in the provided path. May be provided multiple times to search in a list of directories.') p.add_argument('-p', '--config_path', action='append', metavar='PATH', help='Path to configuration directory. If it is present then configuration files will only be seeked in the provided path. May be provided multiple times to search in a list of directories.')
p.add_argument('--socket', metavar='ADDRESS', type=str, help='Socket address to use in daemon clients. Is always UNIX domain socket on linux and file socket on Mac OS X. Not used here, present only for compatibility with other powerline clients. This argument must always be the first one and be in a form `--socket ADDRESS\': no `=\' or short form allowed (in other powerline clients, not here).')
return p return p

View File

@ -17,20 +17,13 @@ from io import StringIO
from powerline.shell import get_argparser, finish_args, ShellPowerline, write_output from powerline.shell import get_argparser, finish_args, ShellPowerline, write_output
from powerline.lib.monotonic import monotonic from powerline.lib.monotonic import monotonic
is_daemon = False is_daemon = False
platform = sys.platform.lower() platform = sys.platform.lower()
use_filesystem = 'darwin' in platform use_filesystem = 'darwin' in platform
# use_filesystem = True
del platform
if use_filesystem: address = None
address = '/tmp/powerline-ipc-%d' pidfile = None
pidfile = address + '.pid'
else:
# Use the abstract namespace for sockets rather than the filesystem
# (Available only in linux)
address = '\0powerline-ipc-%d'
address = address % os.getuid()
class NonInteractiveArgParser(ArgumentParser): class NonInteractiveArgParser(ArgumentParser):
@ -274,9 +267,9 @@ def daemonize(stdin=os.devnull, stdout=os.devnull, stderr=os.devnull):
sys.exit(1) sys.exit(1)
# Redirect standard file descriptors. # Redirect standard file descriptors.
si = file(stdin, 'r') si = open(stdin, 'rb')
so = file(stdout, 'a+') so = open(stdout, 'a+b')
se = file(stderr, 'a+', 0) se = open(stderr, 'a+b', 0)
os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno()) os.dup2(se.fileno(), sys.stderr.fileno())
@ -334,8 +327,11 @@ def lockpidfile():
import fcntl import fcntl
import atexit import atexit
import stat import stat
fd = os.open(pidfile, os.O_WRONLY | os.O_CREAT, fd = os.open(
stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) pidfile,
os.O_WRONLY | os.O_CREAT,
stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
)
try: try:
fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except EnvironmentError: except EnvironmentError:
@ -352,15 +348,34 @@ def lockpidfile():
def main(): def main():
p = ArgumentParser(description= global address
'Daemon to improve the performance of powerline') global pidfile
p = ArgumentParser(description='Daemon to improve the performance of powerline')
p.add_argument('--quiet', '-q', action='store_true', help='Without other options: do not complain about already running powerline-daemon instance. Will still exit with 1. With `--kill\' and `--replace\': do not show any messages. With `--foreground\': ignored. Does not silence exceptions in any case.') p.add_argument('--quiet', '-q', action='store_true', help='Without other options: do not complain about already running powerline-daemon instance. Will still exit with 1. With `--kill\' and `--replace\': do not show any messages. With `--foreground\': ignored. Does not silence exceptions in any case.')
p.add_argument('--socket', '-s', help='Specify socket which will be used for connecting to daemon.')
a = p.add_mutually_exclusive_group().add_argument a = p.add_mutually_exclusive_group().add_argument
a('--kill', '-k', action='store_true', help='Kill an already running instance') a('--kill', '-k', action='store_true', help='Kill an already running instance')
a('--foreground', '-f', action='store_true', help='Run in the foreground (dont daemonize)') a('--foreground', '-f', action='store_true', help='Run in the foreground (dont daemonize)')
a('--replace', '-r', action='store_true', help='Replace an already running instance') a('--replace', '-r', action='store_true', help='Replace an already running instance')
args = p.parse_args() args = p.parse_args()
if args.socket:
address = args.socket
if not use_filesystem:
address = '\0' + address
else:
if use_filesystem:
address = '/tmp/powerline-ipc-%d'
else:
# Use the abstract namespace for sockets rather than the filesystem
# (Available only in linux)
address = '\0powerline-ipc-%d'
address = address % os.getuid()
if use_filesystem:
pidfile = address + '.pid'
if args.kill: if args.kill:
if kill_daemon(): if kill_daemon():
if not args.quiet: if not args.quiet:

View File

@ -22,7 +22,7 @@ else
pip install ipython pip install ipython
fi fi
fi fi
sudo apt-get install -qq screen zsh tcsh mksh busybox sudo apt-get install -qq screen zsh tcsh mksh busybox socat
# Travis has too outdated fish. It cannot be used for tests. # Travis has too outdated fish. It cannot be used for tests.
# sudo apt-get install fish # sudo apt-get install fish
true true

View File

@ -20,7 +20,7 @@ for script in tests/*.vim ; do
FAILED=1 FAILED=1
fi fi
done done
if ! bash tests/test_shells/test.sh ; then if ! bash tests/test_shells/test.sh --fast ; then
echo "Failed shells" echo "Failed shells"
if ${PYTHON} -c 'import platform, sys; sys.exit(1 * (platform.python_implementation() == "PyPy"))' ; then if ${PYTHON} -c 'import platform, sys; sys.exit(1 * (platform.python_implementation() == "PyPy"))' ; then
FAILED=1 FAILED=1

View File

@ -9,9 +9,10 @@ import codecs
test_type = sys.argv[1] test_type = sys.argv[1]
shell = sys.argv[2] test_client = sys.argv[2]
fname = os.path.join('tests', 'shell', shell + '.' + test_type + '.full.log') shell = sys.argv[3]
new_fname = os.path.join('tests', 'shell', shell + '.' + test_type + '.log') fname = os.path.join('tests', 'shell', '.'.join((shell, test_type, test_client, 'full.log')))
new_fname = os.path.join('tests', 'shell', '.'.join((shell, test_type, test_client, 'log')))
pid_fname = os.path.join('tests', 'shell', '3rd', 'pid') pid_fname = os.path.join('tests', 'shell', '3rd', 'pid')

View File

@ -1,3 +1,3 @@
width 1024 width 1024
height 1 height 1
logfile "tests/shell/${SH}.${TEST_TYPE}.full.log" logfile "tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log"

View File

@ -1,23 +1,55 @@
#!/bin/bash #!/bin/sh
: ${PYTHON:=python}
FAILED=0 FAILED=0
if test "x$1" = "x--fast" ; then
FAST=1
shift
fi
ONLY_SHELL="$1" ONLY_SHELL="$1"
ONLY_TEST_TYPE="$2"
COMMAND_PATTERN="$3"
if ! test -z "$ONLY_SHELL$ONLY_TEST_TYPE$COMMAND_PATTERN" ; then
FAST=
fi
export PYTHON
if test "x$ONLY_SHELL" = "x--help" ; then
cat << EOF
Usage:
$0 [[[ONLY_SHELL | ""] (ONLY_TEST_TYPE | "")] (COMMAND_PATTERN | "")]
ONLY_SHELL: execute only tests for given shell
ONLY_TEST_TYPE: execute only "daemon" or "nodaemon" tests
COMMAND_PATTERN: use only commands that match given pattern for testing
EOF
exit 0
fi
check_screen_log() { check_screen_log() {
TEST_TYPE="$1" TEST_TYPE="$1"
SH="$2" TEST_CLIENT="$2"
SH="$3"
if test -e tests/test_shells/${SH}.${TEST_TYPE}.ok ; then if test -e tests/test_shells/${SH}.${TEST_TYPE}.ok ; then
diff -a -u tests/test_shells/${SH}.${TEST_TYPE}.ok tests/shell/${SH}.${TEST_TYPE}.log diff -a -u tests/test_shells/${SH}.${TEST_TYPE}.ok tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.log
return $? return $?
elif test -e tests/test_shells/${SH}.ok ; then elif test -e tests/test_shells/${SH}.ok ; then
diff -a -u tests/test_shells/${SH}.ok tests/shell/${SH}.${TEST_TYPE}.log diff -a -u tests/test_shells/${SH}.ok tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.log
return $? return $?
else else
cat tests/shell/${SH}.${TEST_TYPE}.log cat tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.log
return 1 return 1
fi fi
} }
run() { run() {
TEST_TYPE="$1"
shift
TEST_CLIENT="$1"
shift
SH="$1"
shift
local local_path="$PWD/tests/shell/path:$PWD/scripts" local local_path="$PWD/tests/shell/path:$PWD/scripts"
if test "x$SH" = "xfish" ; then if test "x$SH" = "xfish" ; then
local_path="${local_path}:/usr/bin:/bin" local_path="${local_path}:/usr/bin:/bin"
@ -33,6 +65,7 @@ run() {
COLUMNS="${COLUMNS}" \ COLUMNS="${COLUMNS}" \
LINES="${LINES}" \ LINES="${LINES}" \
TEST_TYPE="${TEST_TYPE}" \ TEST_TYPE="${TEST_TYPE}" \
TEST_CLIENT="${TEST_CLIENT}" \
SH="${SH}" \ SH="${SH}" \
DIR1="${DIR1}" \ DIR1="${DIR1}" \
DIR2="${DIR2}" \ DIR2="${DIR2}" \
@ -40,27 +73,21 @@ run() {
IPYTHONDIR="$PWD/tests/shell/ipython_home" \ IPYTHONDIR="$PWD/tests/shell/ipython_home" \
POWERLINE_SHELL_CONTINUATION=$additional_prompts \ POWERLINE_SHELL_CONTINUATION=$additional_prompts \
POWERLINE_SHELL_SELECT=$additional_prompts \ POWERLINE_SHELL_SELECT=$additional_prompts \
POWERLINE_COMMAND="${POWERLINE_COMMAND}" \
"$@" "$@"
} }
run_test() { run_test() {
TEST_TYPE="$1" TEST_TYPE="$1"
shift shift
TEST_CLIENT="$1"
shift
SH="$1" SH="$1"
SESNAME="powerline-shell-test-${SH}-$$" SESNAME="powerline-shell-test-${SH}-$$"
ARGS=( "$@" )
test "x$ONLY_SHELL" = "x" || test "x$ONLY_SHELL" = "x$SH" || return 0 run "${TEST_TYPE}" "${TEST_CLIENT}" "${SH}" \
screen -L -c tests/test_shells/screenrc -d -m -S "$SESNAME" \
if ! which "${SH}" ; then env LANG=en_US.UTF-8 BINDFILE="$BINDFILE" "$@"
return 0
fi
export TEST_TYPE
export SH
run screen -L -c tests/test_shells/screenrc -d -m -S "$SESNAME" \
env LANG=en_US.UTF-8 BINDFILE="$BINDFILE" "${ARGS[@]}"
while ! screen -S "$SESNAME" -X readreg a tests/test_shells/input.$SH ; do while ! screen -S "$SESNAME" -X readreg a tests/test_shells/input.$SH ; do
sleep 0.1s sleep 0.1s
done done
@ -77,7 +104,7 @@ run_test() {
# … # …
# prompt1> prompt2> … # prompt1> prompt2> …
while read -r line ; do while read -r line ; do
screen -S "$SESNAME" -p 0 -X stuff "$line"$'\n' screen -S "$SESNAME" -p 0 -X stuff "$line"$(printf '\r')
sleep 1 sleep 1
done < tests/test_shells/input.$SH done < tests/test_shells/input.$SH
else else
@ -88,23 +115,27 @@ run_test() {
while screen -S "$SESNAME" -X blankerprg "" > /dev/null ; do while screen -S "$SESNAME" -X blankerprg "" > /dev/null ; do
sleep 0.1s sleep 0.1s
done done
./tests/test_shells/postproc.py ${TEST_TYPE} ${SH} ./tests/test_shells/postproc.py ${TEST_TYPE} ${TEST_CLIENT} ${SH}
rm -f tests/shell/3rd/pid rm -f tests/shell/3rd/pid
if ! check_screen_log ${TEST_TYPE} ${SH} ; then if ! check_screen_log ${TEST_TYPE} ${TEST_CLIENT} ${SH} ; then
echo '____________________________________________________________' echo '____________________________________________________________'
if test "x$POWERLINE_TEST_NO_CAT_V" != "x1" ; then
# Repeat the diff to make it better viewable in travis output # Repeat the diff to make it better viewable in travis output
echo "Diff (cat -v):" echo "Diff (cat -v):"
echo '============================================================' echo '============================================================'
check_screen_log ${TEST_TYPE} ${SH} | cat -v check_screen_log ${TEST_TYPE} ${TEST_CLIENT} ${SH} | cat -v
echo '____________________________________________________________' echo '____________________________________________________________'
fi
echo "Failed ${SH}. Full output:" echo "Failed ${SH}. Full output:"
echo '============================================================' echo '============================================================'
cat tests/shell/${SH}.${TEST_TYPE}.full.log cat tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log
echo '____________________________________________________________' echo '____________________________________________________________'
if test "x$POWERLINE_TEST_NO_CAT_V" != "x1" ; then
echo "Full output (cat -v):" echo "Full output (cat -v):"
echo '============================================================' echo '============================================================'
cat -v tests/shell/${SH}.${TEST_TYPE}.full.log cat -v tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log
echo '____________________________________________________________' echo '____________________________________________________________'
fi
case ${SH} in case ${SH} in
*ksh) *ksh)
${SH} -c 'echo ${KSH_VERSION}' ${SH} -c 'echo ${KSH_VERSION}'
@ -146,7 +177,7 @@ mkdir tests/shell/fish_home
cp -r tests/test_shells/ipython_home tests/shell cp -r tests/test_shells/ipython_home tests/shell
mkdir tests/shell/path mkdir tests/shell/path
ln -s "$(which "${PYTHON:-python}")" tests/shell/path/python ln -s "$(which "${PYTHON}")" tests/shell/path/python
ln -s "$(which screen)" tests/shell/path ln -s "$(which screen)" tests/shell/path
ln -s "$(which env)" tests/shell/path ln -s "$(which env)" tests/shell/path
ln -s "$(which sleep)" tests/shell/path ln -s "$(which sleep)" tests/shell/path
@ -168,6 +199,9 @@ ln -s "$(which sed)" tests/shell/path
ln -s "$(which rm)" tests/shell/path ln -s "$(which rm)" tests/shell/path
ln -s ../../test_shells/bgscript.sh tests/shell/path ln -s ../../test_shells/bgscript.sh tests/shell/path
ln -s ../../test_shells/waitpid.sh tests/shell/path ln -s ../../test_shells/waitpid.sh tests/shell/path
if which socat ; then
ln -s "$(which socat)" tests/shell/path
fi
for pexe in powerline powerline-config ; do for pexe in powerline powerline-config ; do
if test -e scripts/$pexe ; then if test -e scripts/$pexe ; then
ln -s "$PWD/scripts/$pexe" tests/shell/path ln -s "$PWD/scripts/$pexe" tests/shell/path
@ -187,47 +221,104 @@ done
unset ENV unset ENV
if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || test "x${ONLY_SHELL}" = xbusybox ; then export ADDRESS="powerline-ipc-test-$$"
powerline-daemon -k || true export PYTHON
sleep 1s echo "Powerline address: $ADDRESS"
if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || test "x${ONLY_SHELL}" = xbusybox ; then
scripts/powerline-config shell command scripts/powerline-config shell command
for TEST_TYPE in "daemon" "nodaemon" ; do for TEST_TYPE in "daemon" "nodaemon" ; do
if test $TEST_TYPE == daemon ; then if test x$FAST = x1 ; then
sh -c 'echo $$ > tests/shell/daemon_pid; ./scripts/powerline-daemon -f &>tests/shell/daemon_log' & if test $TEST_TYPE = daemon ; then
VARIANTS=3
else
VARIANTS=4
fi fi
if ! run_test $TEST_TYPE bash --norc --noprofile -i ; then EXETEST="$(( ${RANDOM:-`date +%N | sed s/^0*//`} % $VARIANTS ))"
FAILED=1 echo "Execute tests: $EXETEST"
fi fi
if ! run_test $TEST_TYPE zsh -f -i ; then if test $TEST_TYPE = daemon ; then
FAILED=1 sh -c '
echo $$ > tests/shell/daemon_pid
$PYTHON ./scripts/powerline-daemon -s$ADDRESS -f &>tests/shell/daemon_log
' &
fi fi
if test "x$ONLY_TEST_TYPE" != "x" && test "x$ONLY_TEST_TYPE" != "x$TEST_TYPE" ; then
if ! run_test $TEST_TYPE fish -i ; then continue
FAILED=1
fi fi
echo "> Testing $TEST_TYPE"
if ! run_test $TEST_TYPE tcsh -f -i ; then I=-1
FAILED=1 for POWERLINE_COMMAND in \
$PWD/scripts/powerline \
$PWD/scripts/powerline-render \
"$PYTHON $PWD/client/powerline.py" \
$PWD/client/powerline.sh
do
case "$POWERLINE_COMMAND" in
*powerline) TEST_CLIENT=C ;;
*powerline-render) TEST_CLIENT=render ;;
*powerline.py) TEST_CLIENT=python ;;
*powerline.sh) TEST_CLIENT=shell ;;
esac
if test "$TEST_CLIENT" = render && test "$TEST_TYPE" = daemon ; then
continue
fi fi
I="$(( I + 1 ))"
if ! run_test $TEST_TYPE busybox ash -i ; then if test "$TEST_CLIENT" = "C" && ! test -x scripts/powerline ; then
FAILED=1 if which powerline >/dev/null ; then
POWERLINE_COMMAND=powerline
else
continue
fi fi
if ! run_test $TEST_TYPE mksh -i ; then
FAILED=1
fi fi
if test "$TEST_CLIENT" = "shell" && ! which socat >/dev/null ; then
if ! run_test $TEST_TYPE dash -i ; then continue
fi
if test "x$COMMAND_PATTERN" != "x" && ! (
echo "$POWERLINE_COMMAND" | grep -e"$COMMAND_PATTERN" &>/dev/null)
then
continue
fi
POWERLINE_COMMAND="$POWERLINE_COMMAND --socket $ADDRESS"
export POWERLINE_COMMAND
echo ">> powerline command is ${POWERLINE_COMMAND:-empty}"
J=-1
for TEST_COMMAND in \
"bash --norc --noprofile -i" \
"zsh -f -i" \
"fish -i" \
"tcsh -f -i" \
"busybox ash -i" \
"mksh -i" \
"dash -i"
do
J="$(( J + 1 ))"
if test x$FAST = x1 ; then
if test $(( (I + J) % $VARIANTS )) -ne $EXETEST ; then
continue
fi
fi
SH="${TEST_COMMAND%% *}"
# dash tests are not stable, see #931 # dash tests are not stable, see #931
# FAILED=1 if test x$FAST$SH = x1dash ; then
true continue
fi fi
if test $TEST_TYPE == daemon ; then if test "x$ONLY_SHELL" != "x" && test "x$ONLY_SHELL" != "x$SH" ; then
./scripts/powerline-daemon -k continue
fi
if ! which $SH >/dev/null ; then
continue
fi
echo ">>> $(which $SH)"
if ! run_test $TEST_TYPE $TEST_CLIENT $TEST_COMMAND ; then
FAILED=1
fi
done
done
if test $TEST_TYPE = daemon ; then
$PYTHON ./scripts/powerline-daemon -s$ADDRESS -k
wait $(cat tests/shell/daemon_pid) wait $(cat tests/shell/daemon_pid)
if ! test -z "$(cat tests/shell/daemon_log)" ; then if ! test -z "$(cat tests/shell/daemon_log)" ; then
echo '____________________________________________________________' echo '____________________________________________________________'
@ -240,8 +331,30 @@ if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || te
done done
fi fi
if ! run_test ipython ipython ; then if ! $PYTHON scripts/powerline-daemon -s$ADDRESS &> tests/shell/daemon_log_2 ; then
echo "Daemon exited with status $?"
FAILED=1 FAILED=1
else
sleep 1
$PYTHON scripts/powerline-daemon -s$ADDRESS -k
fi
if ! test -z "$(cat tests/shell/daemon_log_2)" ; then
FAILED=1
echo '____________________________________________________________'
echo "Daemon log (2nd):"
echo '============================================================'
cat tests/shell/daemon_log_2
FAILED=1
fi
if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xipython" ; then
if which ipython >/dev/null ; then
echo "> $(which ipython)"
if ! run_test ipython ipython ipython ; then
FAILED=1
fi
fi
fi fi
test $FAILED -eq 0 && rm -r tests/shell test $FAILED -eq 0 && rm -r tests/shell