Merge pull request from ZyX-I/integration-tests

Improve integration tests
This commit is contained in:
Nikolai Aleksandrovich Pavlov 2015-01-06 03:36:54 +03:00
commit 8a09aba211
35 changed files with 664 additions and 166 deletions

@ -1,13 +1,22 @@
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
- "pypy"
- "pypy3"
install: tests/install.sh
script: tests/test.sh
matrix:
include:
- python: "2.6"
- python: "2.7"
- python: "3.2"
- python: "3.3"
- python: "3.4"
- python: "pypy"
- python: "pypy3"
- python: "2.6"
env: >-
USE_UCS2_PYTHON=1
UCS2_PYTHON_VARIANT="2.6"
- python: "2.7"
env: >-
USE_UCS2_PYTHON=1
UCS2_PYTHON_VARIANT="2.7"
# vim: et

@ -31,6 +31,12 @@ Vim configuration can be overridden using the following options:
If this variable is set to a true value it will prevent Powerline from reporting
an error when loaded in a copy of vim without the necessary Python support.
``g:powerline_use_var_handler``
This variable may be set to either 0 or 1. If it is set to 1 then Vim will
save log in ``g:powerline_log_messages`` variable in addition to whatever
was configured in :ref:`log_* options <config-common-log>`. Level is always
:ref:`log_level <config-common-log_level>`, same for format.
Powerline script overrides
==========================

@ -98,6 +98,8 @@ Common configuration is a subdictionary that is a value of ``common`` key in
Defines path which will hold powerline logs. If not present, logging will be
done to stderr.
.. _config-common-log_level:
``log_level``
String, determines logging level. Defaults to ``WARNING``.

@ -11,7 +11,7 @@ from powerline.colorscheme import Colorscheme
from powerline.lib.config import ConfigLoader
from powerline.lib.unicode import safe_unicode, FailedUnicode
from powerline.config import DEFAULT_SYSTEM_CONFIG_DIR
from powerline.lib import mergedicts
from powerline.lib.dict import mergedicts
from powerline.lib.encoding import get_preferred_output_encoding
@ -424,6 +424,14 @@ class Powerline(object):
Usually returns encoding of the current locale.
'''
def create_logger(self):
'''Create logger
This function is used to create logger unless it was already specified
at initialization.
'''
return create_logger(self.common_config, self.default_log_stream)
def create_renderer(self, load_main=False, load_colors=False, load_colorscheme=False, load_theme=False):
'''(Re)create renderer object. Can be used after Powerline object was
successfully initialized. If any of the below parameters except
@ -461,7 +469,7 @@ class Powerline(object):
self.import_paths = self.common_config['paths']
if not self.logger:
self.logger = create_logger(self.common_config, self.default_log_stream)
self.logger = self.create_logger()
if not self.pl:
self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext)

@ -12,10 +12,36 @@ except ImportError:
from powerline.lib.unicode import unicode
try:
vim_encoding = vim.eval('&encoding')
except AttributeError:
vim_encoding = 'utf-8'
if (
hasattr(vim, 'options')
and hasattr(vim, 'vvars')
and vim.vvars['version'] > 703
):
if sys.version_info < (3,):
def get_vim_encoding():
return vim.options['encoding'] or 'ascii'
else:
def get_vim_encoding():
return vim.options['encoding'].decode('ascii') or 'ascii'
elif hasattr(vim, 'eval'):
def get_vim_encoding():
return vim.eval('&encoding') or 'ascii'
else:
def get_vim_encoding():
return 'utf-8'
get_vim_encoding.__doc__ = (
'''Get encoding used for Vim strings
:return:
Value of ``&encoding``. If it is empty (i.e. Vim is compiled
without +multibyte) returns ``'ascii'``. When building documentation
outputs ``'utf-8'`` unconditionally.
'''
)
vim_encoding = get_vim_encoding()
python_to_vim_types = {

@ -9,9 +9,10 @@ import zsh
from powerline.shell import ShellPowerline
from powerline.lib import parsedotval
from powerline.lib.unicode import unicode
from powerline.lib.unicode import unicode, u
from powerline.lib.encoding import (get_preferred_output_encoding,
get_preferred_environment_encoding)
from powerline.lib.dict import mergeargs
used_powerlines = WeakValueDictionary()
@ -24,7 +25,7 @@ def shutdown():
def get_var_config(var):
try:
return [parsedotval(i) for i in zsh.getvalue(var).items()]
return mergeargs([parsedotval((u(k), u(v))) for k, v in zsh.getvalue(var).items()])
except:
return None
@ -36,17 +37,11 @@ class Args(object):
@property
def config(self):
try:
return get_var_config('POWERLINE_CONFIG')
except IndexError:
return None
return get_var_config('POWERLINE_CONFIG')
@property
def theme_option(self):
try:
return get_var_config('POWERLINE_THEME_CONFIG')
except IndexError:
return None
return get_var_config('POWERLINE_THEME_CONFIG')
@property
def config_path(self):
@ -132,6 +127,10 @@ class Prompt(object):
def __str__(self):
zsh.eval('_POWERLINE_PARSER_STATE="${(%):-%_}"')
zsh.eval('_POWERLINE_SHORTENED_PATH="${(%):-%~}"')
try:
mode = u(zsh.getvalue('_POWERLINE_MODE'))
except IndexError:
mode = None
segment_info = {
'args': self.args,
'environ': environ,
@ -139,6 +138,7 @@ class Prompt(object):
'local_theme': self.theme,
'parser_state': zsh.getvalue('_POWERLINE_PARSER_STATE'),
'shortened_path': zsh.getvalue('_POWERLINE_SHORTENED_PATH'),
'mode': mode,
}
zsh.setvalue('_POWERLINE_PARSER_STATE', None)
zsh.setvalue('_POWERLINE_SHORTENED_PATH', None)
@ -157,6 +157,7 @@ class Prompt(object):
width=zsh.columns(),
side=self.side,
segment_info=segment_info,
mode=mode,
)
if type(r) is not str:
if type(r) is bytes:
@ -189,6 +190,11 @@ def reload():
powerline.reload()
def reload_config():
for powerline in used_powerlines.values():
powerline.create_renderer(load_main=True, load_colors=True, load_colorscheme=True, load_theme=True)
def setup(zsh_globals):
powerline = ZshPowerline()
powerline.setup(zsh_globals)

@ -129,6 +129,11 @@ _powerline_setup_prompt() {
zpython '_powerline_reload()'
zpython 'del _powerline_reload'
}
powerline-reload-config() {
zpython 'from powerline.bindings.zsh import reload_config as _powerline_reload_config'
zpython '_powerline_reload_config()'
zpython 'del _powerline_reload_config'
}
else
if test -z "${POWERLINE_COMMAND}" ; then
POWERLINE_COMMAND="$($POWERLINE_CONFIG shell command)"

@ -5,7 +5,8 @@ from __future__ import (division, absolute_import, print_function)
import argparse
import sys
from powerline.lib import mergedicts, parsedotval
from powerline.lib import parsedotval
from powerline.lib.dict import mergeargs
from powerline.lib.encoding import get_preferred_arguments_encoding
@ -19,15 +20,6 @@ else:
return s
def mergeargs(argvalue):
if not argvalue:
return None
r = {}
for subval in argvalue:
mergedicts(r, dict([subval]))
return r
def finish_args(args):
if args.config:
args.config = mergeargs((parsedotval(v) for v in args.config))

@ -2,7 +2,7 @@
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline import Powerline
from powerline.lib import mergedicts
from powerline.lib.dict import mergedicts
from powerline.lib.unicode import string

@ -5,8 +5,7 @@ import json
from functools import wraps
REMOVE_THIS_KEY = object()
from powerline.lib.dict import REMOVE_THIS_KEY
def wraps_saveargs(wrapped):
@ -17,47 +16,6 @@ def wraps_saveargs(wrapped):
return dec
def mergedicts(d1, d2):
'''Recursively merge two dictionaries
First dictionary is modified in-place.
'''
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
mergedicts(d1[k], d2[k])
elif d2[k] is REMOVE_THIS_KEY:
d1.pop(k, None)
else:
d1[k] = d2[k]
def mergedefaults(d1, d2):
'''Recursively merge two dictionaries, keeping existing values
First dictionary is modified in-place.
'''
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
mergedefaults(d1[k], d2[k])
else:
d1.setdefault(k, d2[k])
def mergedicts_copy(d1, d2):
'''Recursively merge two dictionaries.
Dictionaries are not modified. Copying happens only if necessary. Assumes
that first dictionary supports .copy() method.
'''
ret = d1.copy()
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
ret[k] = mergedicts_copy(d1[k], d2[k])
else:
ret[k] = d2[k]
return ret
def add_divider_highlight_group(highlight_group):
def dec(func):
@wraps_saveargs(func)
@ -74,6 +32,31 @@ def add_divider_highlight_group(highlight_group):
return dec
def parse_value(s):
'''Convert string to Python object
Rules:
* Empty string means that corresponding key should be removed from the
dictionary.
* Strings that start with a minus, digit or with some character that starts
JSON collection or string object are parsed as JSON.
* JSON special values ``null``, ``true``, ``false`` (case matters) are
parsed as JSON.
* All other values are considered to be raw strings.
:param str s: Parsed string.
:return: Python object.
'''
if not s:
return REMOVE_THIS_KEY
elif s[0] in '"{[0193456789-' or s in ('null', 'true', 'false'):
return json.loads(s)
else:
return s
def keyvaluesplit(s):
if '=' not in s:
raise TypeError('Option must look like option=json_value')
@ -81,19 +64,14 @@ def keyvaluesplit(s):
raise ValueError('Option names must not start with `_\'')
idx = s.index('=')
o = s[:idx]
rest = s[idx + 1:]
if not rest:
val = REMOVE_THIS_KEY
elif rest[0] in '"{[0193456789' or rest in ('null', 'true', 'false'):
val = json.loads(s[idx + 1:])
else:
val = rest
val = parse_value(s[idx + 1:])
return (o, val)
def parsedotval(s):
if type(s) is tuple:
o, val = s
val = parse_value(val)
else:
o, val = keyvaluesplit(s)

55
powerline/lib/dict.py Normal file

@ -0,0 +1,55 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
REMOVE_THIS_KEY = object()
def mergeargs(argvalue):
if not argvalue:
return None
r = {}
for subval in argvalue:
mergedicts(r, dict([subval]))
return r
def mergedicts(d1, d2):
'''Recursively merge two dictionaries
First dictionary is modified in-place.
'''
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
mergedicts(d1[k], d2[k])
elif d2[k] is REMOVE_THIS_KEY:
d1.pop(k, None)
else:
d1[k] = d2[k]
def mergedefaults(d1, d2):
'''Recursively merge two dictionaries, keeping existing values
First dictionary is modified in-place.
'''
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
mergedefaults(d1[k], d2[k])
else:
d1.setdefault(k, d2[k])
def mergedicts_copy(d1, d2):
'''Recursively merge two dictionaries.
Dictionaries are not modified. Copying happens only if necessary. Assumes
that first dictionary supports .copy() method.
'''
ret = d1.copy()
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
ret[k] = mergedicts_copy(d1[k], d2[k])
else:
ret[k] = d2[k]
return ret

@ -9,7 +9,7 @@ from functools import partial
from powerline import generate_config_finder, get_config_paths, load_config
from powerline.segments.vim import vim_modes
from powerline.lib import mergedicts_copy
from powerline.lib.dict import mergedicts_copy
from powerline.lib.config import ConfigLoader
from powerline.lib.unicode import unicode
from powerline.lint.markedjson import load

@ -5,7 +5,7 @@ import sys
import vim
from powerline.bindings.vim import vim_get_func, vim_getoption, environ, current_tabpage
from powerline.bindings.vim import vim_get_func, vim_getoption, environ, current_tabpage, get_vim_encoding
from powerline.renderer import Renderer
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
from powerline.theme import Theme
@ -42,7 +42,7 @@ class VimRenderer(Renderer):
self.hl_groups = {}
self.prev_highlight = None
self.strwidth_error_name = register_strwidth_error(self.strwidth)
self.encoding = vim.eval('&encoding')
self.encoding = get_vim_encoding()
def shutdown(self):
self.theme.shutdown()

@ -220,6 +220,30 @@ def process_segment(pl, side, segment_info, parsed_segments, segment, mode, colo
always_true = lambda pl, segment_info, mode: True
get_fallback_segment = {
'name': 'fallback',
'type': 'string',
'highlight_group': 'background',
'divider_highlight_group': None,
'before': None,
'after': None,
'contents': '',
'priority': None,
'draw_soft_divider': True,
'draw_hard_divider': True,
'draw_inner_divider': True,
'display_condition': always_true,
'width': None,
'align': None,
'expand': None,
'truncate': None,
'startup': None,
'shutdown': None,
'_rendered_raw': '',
'_rendered_hl': '',
'_len': None,
'_contents_len': None,
}.copy
def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, get_module_attr, top_theme):
data = {

@ -110,7 +110,7 @@ def ctrlp_stl_right_prog(pl, progress):
'''
return [
{
'contents': progress,
'contents': str(progress),
'highlight_group': ['ctrlp.progress', 'file_name'],
},
]

@ -2,13 +2,12 @@
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline import Powerline
from powerline.lib import mergedicts
from powerline.lib.dict import mergedicts
class ShellPowerline(Powerline):
def init(self, args, **kwargs):
self.args = args
self.theme_option = args.theme_option
super(ShellPowerline, self).init(args.ext[0], args.renderer_module, **kwargs)
def load_main_config(self):
@ -19,8 +18,8 @@ class ShellPowerline(Powerline):
def load_theme_config(self, name):
r = super(ShellPowerline, self).load_theme_config(name)
if self.theme_option and name in self.theme_option:
mergedicts(r, self.theme_option[name])
if self.args.theme_option and name in self.args.theme_option:
mergedicts(r, self.args.theme_option[name])
return r
def get_config_paths(self):

@ -3,8 +3,8 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import itertools
from powerline.segment import gen_segment_getter, process_segment
from powerline.lib.unicode import u
from powerline.segment import gen_segment_getter, process_segment, get_fallback_segment
from powerline.lib.unicode import u, safe_unicode
def requires_segment_info(func):
@ -146,23 +146,36 @@ class Theme(object):
self.colorscheme,
)
for segment in parsed_segments:
width = segment['width']
align = segment['align']
if width == 'auto' and segment['expand'] is None:
segment['expand'] = expand_functions.get(align)
if segment['expand'] is None:
self.pl.error('Align argument must be “r”, “l” or “c”, not “{0}', align)
self.pl.prefix = segment['name']
try:
width = segment['width']
align = segment['align']
if width == 'auto' and segment['expand'] is None:
segment['expand'] = expand_functions.get(align)
if segment['expand'] is None:
self.pl.error('Align argument must be “r”, “l” or “c”, not “{0}', align)
segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after']
# Align segment contents
if segment['width'] and segment['width'] != 'auto':
if segment['align'] == 'l':
segment['contents'] = segment['contents'].ljust(segment['width'])
elif segment['align'] == 'r':
segment['contents'] = segment['contents'].rjust(segment['width'])
elif segment['align'] == 'c':
segment['contents'] = segment['contents'].center(segment['width'])
# We need to yield a copy of the segment, or else mode-dependent
# segment contents cant be cached correctly e.g. when caching
# non-current window contents for vim statuslines
yield segment.copy()
try:
segment['contents'] = segment['before'] + u(
segment['contents'] if segment['contents'] is not None else ''
) + segment['after']
except Exception as e:
self.pl.exception('Failed to compute segment contents: {0}', str(e))
segment['contents'] = safe_unicode(segment.get('contents'))
# Align segment contents
if segment['width'] and segment['width'] != 'auto':
if segment['align'] == 'l':
segment['contents'] = segment['contents'].ljust(segment['width'])
elif segment['align'] == 'r':
segment['contents'] = segment['contents'].rjust(segment['width'])
elif segment['align'] == 'c':
segment['contents'] = segment['contents'].center(segment['width'])
# We need to yield a copy of the segment, or else mode-dependent
# segment contents cant be cached correctly e.g. when caching
# non-current window contents for vim statuslines
yield segment.copy()
except Exception as e:
self.pl.exception('Failed to compute segment: {0}', str(e))
fallback = get_fallback_segment()
fallback.update(side=side)
yield fallback

@ -3,14 +3,16 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import sys
import json
import logging
from itertools import count
import vim
from powerline.bindings.vim import vim_get_func, vim_getvar
from powerline.bindings.vim import vim_get_func, vim_getvar, get_vim_encoding, python_to_vim
from powerline import Powerline, FailedUnicode
from powerline.lib import mergedicts
from powerline.lib.dict import mergedicts
from powerline.lib.unicode import u
def _override_from(config, override_varname):
@ -22,6 +24,24 @@ def _override_from(config, override_varname):
return config
class VimVarHandler(logging.Handler, object):
'''Vim-specific handler which emits messages to Vim global variables
Used variable: ``g:powerline_log_messages``.
'''
def __init__(self, *args, **kwargs):
super(VimVarHandler, self).__init__(*args, **kwargs)
vim.command('unlet! g:powerline_log_messages')
vim.command('let g:powerline_log_messages = []')
@staticmethod
def emit(record):
message = u(record.message)
if record.exc_text:
message += '\n' + u(record.exc_text)
vim.eval(b'add(g:powerline_log_messages, ' + python_to_vim(message) + b')')
class VimPowerline(Powerline):
def init(self, pyeval='PowerlinePyeval', **kwargs):
super(VimPowerline, self).init('vim', **kwargs)
@ -31,6 +51,18 @@ class VimPowerline(Powerline):
default_log_stream = sys.stdout
def create_logger(self):
logger = super(VimPowerline, self).create_logger()
try:
if int(vim_getvar('powerline_use_var_handler')):
formatter = logging.Formatter(self.common_config['log_format'])
handler = VimVarHandler(getattr(logging, self.common_config['log_level']))
handler.setFormatter(formatter)
logger.addHandler(handler)
except KeyError:
pass
return logger
def add_local_theme(self, key, config):
'''Add local themes at runtime (during vim session).
@ -73,9 +105,7 @@ class VimPowerline(Powerline):
self.setup_kwargs.setdefault('_local_themes', []).append((key, config))
return True
@staticmethod
def get_encoding():
return vim.eval('&encoding')
get_encoding = staticmethod(get_vim_encoding)
def load_main_config(self):
return _override_from(super(VimPowerline, self).load_main_config(), 'powerline_config_overrides')

@ -1,28 +1,56 @@
#!/bin/sh
pip install .
pip install psutil netifaces
if python -c 'import sys; sys.exit(1 * (sys.version_info[0] != 2))' ; then
# Python 2
if python -c 'import platform, sys; sys.exit(1 - (platform.python_implementation() == "CPython"))' ; then
# CPython
pip install mercurial
pip install --allow-external bzr --allow-unverified bzr bzr
fi
if python -c 'import sys; sys.exit(1 * (sys.version_info[1] >= 7))' ; then
# Python 2.6
pip install unittest2 argparse
else
# Python 2.7
pip install ipython
#!/bin/bash
git clone --depth=1 git://github.com/powerline/bot-ci tests/bot-ci
git clone --depth=1 git://github.com/powerline/deps tests/bot-ci/deps
. tests/bot-ci/scripts/common/main.sh
sudo apt-get install -qq libssl1.0.0
sudo apt-get install -qq screen zsh tcsh mksh busybox socat realpath bc
if test -n "$USE_UCS2_PYTHON" ; then
pip install virtualenvwrapper
set +e
. virtualenvwrapper.sh
set -e
archive="${PWD:-$(pwd)}/tests/bot-ci/deps/cpython-ucs2/cpython-ucs2-${UCS2_PYTHON_VARIANT}.tar.gz"
sudo sh -c "cd /opt && tar xzf $archive"
PYTHON="/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT/bin/python$UCS2_PYTHON_VARIANT"
export LD_LIBRARY_PATH="/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT/lib${LD_LIBRARY_PATH:+:}${LD_LIBRARY_PATH}"
set +e
mkvirtualenv -p "$PYTHON" cpython-ucs2-$UCS2_PYTHON_VARIANT
set -e
pip install .
if test "$UCS2_PYTHON_VARIANT" = "2.6" ; then
rm tests/bot-ci/deps/wheels/ucs2-CPython-${UCS2_PYTHON_VARIANT}*/pyuv*.whl
fi
pip install --no-deps tests/bot-ci/deps/wheels/ucs2-CPython-${UCS2_PYTHON_VARIANT}*/*.whl
else
# Python 3
if python -c 'import sys; sys.exit(1 * (sys.version_info < (3, 3)))' ; then
# Python 3.3+
pip install ipython
pip install .
# FIXME Uv watcher sometimes misses events and INotify is not available in
# Python-2.6, thus pyuv should be removed in order for VCS tests to
# pass.
if test "$PYTHON_VERSION_MAJOR" -eq 2 && test "$PYTHON_VERSION_MINOR" -lt 7 ; then
rm tests/bot-ci/deps/wheels/$PYTHON_SUFFIX/pyuv*.whl
fi
pip install --no-deps tests/bot-ci/deps/wheels/$PYTHON_SUFFIX/*.whl
if test "$PYTHON_IMPLEMENTATION" = "CPython" ; then
archive="${PWD:-$(pwd)}/tests/bot-ci/deps/zpython/zsh-${PYTHON_VERSION}.tar.gz"
sudo sh -c "cd /opt && tar xzf $archive"
fi
fi
sudo apt-get install -qq screen zsh tcsh mksh busybox socat
archive="${PWD:-$(pwd)}/tests/bot-ci/deps/fish/fish.tar.gz"
sudo sh -c "cd /opt && tar xzf $archive"
mkdir tests/vim-plugins
for archive in "$ROOT"/tests/bot-ci/deps/vim-plugins/*.tar.gz ; do
(
cd tests/vim-plugins
tar -xzvf "$archive"
)
done
# Travis has too outdated fish. It cannot be used for tests.
# sudo apt-get install fish
true

@ -1,11 +1,56 @@
#!/bin/sh
. tests/bot-ci/scripts/common/main.sh
FAILED=0
for script in tests/*.vim ; do
if ! vim -u NONE -S $script || test -f message.fail ; then
echo "Failed script $script" >&2
if test -z "$VIM" ; then
if test -n "$USE_UCS2_PYTHON" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/tip-$UCS2_PYTHON_VARIANT-double/vim"
opt_dir="/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT"
main_path="$opt_dir/lib/python$UCS2_PYTHON_VARIANT"
site_path="$main_path/site-packages"
venv_main_path="$VIRTUAL_ENV/lib/python$UCS2_PYTHON_VARIANT"
venv_site_path="$venv_main_path/site-packages"
new_paths="${main_path}:${site_path}:${venv_main_path}:${venv_site_path}"
export PYTHONPATH="$new_paths${PYTHONPATH:+:}$PYTHONPATH"
else
if test "$PYTHON_IMPLEMENTATION" != "CPython" ; then
exit 0
fi
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/tip-$PYTHON_VERSION/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7-0-112-$PYTHON_VERSION/vim"
if test -e "$OLD_VIM" ; then
VIMS="NEW_VIM OLD_VIM"
else
VIMS="NEW_VIM"
fi
fi
else
NEW_VIM="$VIM"
OLD_VIM="$VIM"
fi
test_script() {
local vim="$1"
local script="$2"
echo "Running script $script with $vim"
if ! "$vim" -u NONE -S $script || test -f message.fail ; then
echo "Failed script $script run with $VIM" >&2
cat message.fail >&2
rm message.fail
FAILED=1
fi
}
for script in tests/test_*.vim ; do
if test "${script%.old.vim}" = "${script}" ; then
test_script "$NEW_VIM" "$script"
fi
done
if test -e "$OLD_VIM" ; then
for script in tests/test_*.old.vim ; do
test_script "$OLD_VIM" "$script"
done
fi
exit $FAILED

@ -0,0 +1,18 @@
# vim:fileencoding=utf-8:noet
import json
import vim
from powerline.lib.unicode import u
_powerline_old_render = powerline.render # NOQA
def _powerline_test_render_function(*args, **kwargs):
ret = _powerline_old_render(*args, **kwargs)
vim.eval('add(g:statusline_values, %s)' % json.dumps(u(ret)))
return ret
powerline.render = _powerline_test_render_function # NOQA

@ -1,7 +1,24 @@
#!/bin/sh
#!/bin/bash
. tests/bot-ci/scripts/common/main.sh
FAILED=0
export PATH="/opt/fish/bin:${PATH}"
if test "$PYTHON_IMPLEMENTATION" = "CPython" ; then
export PATH="/opt/zsh-${PYTHON_VERSION}/bin:${PATH}"
fi
if test -n "$USE_UCS2_PYTHON" ; then
export LD_LIBRARY_PATH="/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT/lib${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
set +e
. virtualenvwrapper.sh
workon cpython-ucs2-$UCS2_PYTHON_VARIANT
set -e
fi
export PYTHON="${PYTHON:=python}"
export PYTHONPATH="${PYTHONPATH}:`realpath .`"
export PYTHONPATH="${PYTHONPATH}${PYTHONPATH:+:}`realpath .`"
for script in tests/run_*_tests.sh ; do
if ! sh $script ; then
echo "Failed $script"

17
tests/test_commandt_plugin.vim Executable file

@ -0,0 +1,17 @@
#!/usr/bin/vim -S
set nocompatible
set columns=80
execute 'source' fnameescape(expand('<sfile>:p:h').'/vim_utils.vim')
call EnablePlugins('command-t')
call SourcePowerline()
let g:statusline_values = []
call PyFile('setup_statusline_catcher')
execute 'CommandTBuffer'|call feedkeys("\<C-c>")
call RunPython('powerline.render = _powerline_old_render')
let g:expected_statusline = '%#Pl_231_16777215_240_5789784_bold# Command-T %#Pl_231_16777215_240_5789784_NONE# %#Pl_231_16777215_240_5789784_bold#BufferFinder %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE#                                                    '
if index(g:statusline_values, g:expected_statusline) == -1
call CheckStatuslineValue(get(g:statusline_values, -1, ''), g:expected_statusline)
cquit
endif
call CheckMessages()
qall

@ -8,7 +8,7 @@ from subprocess import check_call
from operator import add
from shutil import rmtree
from powerline.lib import mergedicts_copy as mdc
from powerline.lib.dict import mergedicts_copy as mdc
from powerline import Powerline
from tests import TestCase

17
tests/test_ctrlp_plugin.vim Executable file

@ -0,0 +1,17 @@
#!/usr/bin/vim -S
set nocompatible
set columns=80
execute 'source' fnameescape(expand('<sfile>:p:h').'/vim_utils.vim')
call EnablePlugins('ctrlp')
call SourcePowerline()
let g:statusline_values = []
call PyFile('setup_statusline_catcher')
execute 'CtrlP'|call feedkeys("\<C-c>")
call RunPython('powerline.render = _powerline_old_render')
let g:expected_statusline = '%#Pl_231_16777215_236_3158064_NONE# mru  %#Pl_236_3158064_240_5789784_NONE# %#Pl_231_16777215_240_5789784_bold#  files    %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE# buf                                          prt  path '
if index(g:statusline_values, g:expected_statusline) == -1
call CheckStatuslineValue(g:statusline_values[-1], g:expected_statusline)
cquit
endif
call CheckMessages()
qall

@ -0,0 +1,32 @@
#!/usr/bin/vim -S
if has('multibyte')
if empty(&encoding)
call writefile(['&encoding option value is empty, even though Vim has +multibyte'], 'message.fail')
cquit
endif
qall
endif
if !empty(&encoding)
call writefile(['&encoding option value is not empty, even though Vim does not have +multibyte'], 'message.fail')
cquit
endif
let g:powerline_config_paths = [expand('<sfile>:p:h:h') . '/powerline/config_files']
try
source powerline/bindings/vim/plugin/powerline.vim
catch
call writefile(['Unexpected exception:', v:exception], 'message.fail')
cquit
endtry
set ls=2
redrawstatus!
redir => g:messages
messages
redir END
let mess=split(g:messages, "\n")
if len(mess)>1
call writefile(['Unexpected message(s):']+mess, 'message.fail')
cquit
endif
qall!

@ -10,7 +10,8 @@ import shutil
from time import sleep
from subprocess import call, PIPE
from powerline.lib import mergedicts, add_divider_highlight_group, REMOVE_THIS_KEY
from powerline.lib import add_divider_highlight_group
from powerline.lib.dict import mergedicts, REMOVE_THIS_KEY
from powerline.lib.humanize_bytes import humanize_bytes
from powerline.lib.vcs import guess, get_fallback_create_watcher
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment

11
tests/test_nerdtree_plugin.vim Executable file

@ -0,0 +1,11 @@
#!/usr/bin/vim -S
set nocompatible
set columns=80
execute 'source' fnameescape(expand('<sfile>:p:h').'/vim_utils.vim')
call EnablePlugins('nerdtree')
call SourcePowerline()
NERDTree /home
redrawstatus
call CheckCurrentStatusline('%#Pl_231_16777215_240_5789784_bold# /home %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE#                      ')
call CheckMessages()
qall

@ -2,13 +2,31 @@ unset HOME
unsetopt promptsp notransientrprompt
setopt interactivecomments
setopt autonamedirs
# POWERLINE_CONFIG_PATH=$PWD/powerline/config_files
# POWERLINE_THEME_CONFIG=( default_leftonly.segment_data.hostname.args.only_if_ssh=false )
# POWERLINE_CONFIG=( ext.shell.theme=default_leftonly )
POWERLINE_NO_ZSH_ZPYTHON=1 # TODO: make tests work with zsh/zpython
if test -z "$POWERLINE_NO_ZSH_ZPYTHON" ; then
function set_theme_option() {
POWERLINE_THEME_CONFIG[$1]=$2
powerline-reload-config
}
function set_theme() {
typeset -A POWERLINE_CONFIG
POWERLINE_CONFIG=(
ext.shell.theme $1
)
powerline-reload-config
}
else
function set_theme_option() {
POWERLINE_COMMAND="$POWERLINE_COMMAND -t $1=$2"
}
function set_theme() {
POWERLINE_COMMAND="$POWERLINE_COMMAND -c ext.shell.theme=$1"
}
fi
source powerline/bindings/zsh/powerline.zsh
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false"
POWERLINE_COMMAND="$POWERLINE_COMMAND -c ext.shell.theme=default_leftonly"
typeset -gA POWERLINE_CONFIG POWERLINE_THEME_CONFIG
set_theme_option default_leftonly.segment_data.hostname.args.only_if_ssh false
set_theme_option default.segment_data.hostname.args.only_if_ssh false
set_theme default_leftonly
export VIRTUAL_ENV=
cd tests/shell/3rd
cd .git
@ -28,13 +46,13 @@ cd ../'$(echo)'
cd ../'`echo`'
cd ../'«Unicode!»'
cd ..
POWERLINE_COMMAND="${POWERLINE_COMMAND//_leftonly}" ; bindkey -v
bindkey -v ; set_theme default

echo abc
false
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.segment_data.hostname.display=false"
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.segment_data.user.display=false"
set_theme_option default.segment_data.hostname.display false
set_theme_option default.segment_data.user.display false
select abc in def ghi jkl
do
echo $abc
@ -44,7 +62,7 @@ done
cd .
cd .
hash -d foo=$PWD:h ; cd .
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.dividers.left.hard=\$ABC"
set_theme_option default.dividers.left.hard \$ABC
true
true is the last line
exit

@ -1,4 +1,5 @@
#!/bin/sh
set -e
: ${PYTHON:=python}
FAIL_SUMMARY=""
FAILED=0
@ -70,9 +71,11 @@ run() {
TEST_CLIENT="${TEST_CLIENT}" \
SH="${SH}" \
DIR1="${DIR1}" \
POWERLINE_NO_ZSH_ZPYTHON="$(test $TEST_TYPE = zpython || echo 1)" \
DIR2="${DIR2}" \
XDG_CONFIG_HOME="$PWD/tests/shell/fish_home" \
IPYTHONDIR="$PWD/tests/shell/ipython_home" \
PYTHONPATH="${PWD}${PYTHONPATH:+:}$PYTHONPATH" \
POWERLINE_SHELL_CONTINUATION=$additional_prompts \
POWERLINE_SHELL_SELECT=$additional_prompts \
POWERLINE_COMMAND="${POWERLINE_COMMAND} -p $PWD/powerline/config_files" \
@ -369,6 +372,16 @@ if ! test -z "$(cat tests/shell/daemon_log_2)" ; then
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}L"
fi
if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \
&& ( test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xzpython" ) \
&& zsh -f -c 'zmodload libzpython' 2>/dev/null; then
echo "> zpython"
if ! run_test zpython zpython zsh -f -i ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T zpython zsh -f -i"
fi
fi
if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xipython" ; then
if which ipython >/dev/null ; then
echo "> $(which ipython)"

@ -18,14 +18,14 @@
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  POWERLINE_COMMAND="${POWERLINE_COMMAND//_leftonly}" ; bindkey -v
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
abc
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.segment_data.hostname.display=false"
 INSERT  USER  ⋯  tests  shell  3rd  POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.segment_data.user.display=false"
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select                            do
 select                             echo $abc
@ -37,5 +37,5 @@ def
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.dividers.left.hard=\$ABC"
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue

@ -18,14 +18,14 @@
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  POWERLINE_COMMAND="${POWERLINE_COMMAND//_leftonly}" ; bindkey -v
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
abc
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.segment_data.hostname.display=false"
 INSERT  USER  ⋯  tests  shell  3rd  POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.segment_data.user.display=false"
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select  do
 select   echo $abc
@ -37,5 +37,5 @@ def
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  POWERLINE_COMMAND="$POWERLINE_COMMAND -t default.dividers.left.hard=\$ABC"
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue

@ -0,0 +1,41 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="/home/USER/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
[1] PID
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
[1] + terminated bgscript.sh
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
abc
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select                            do
 select                             echo $abc
 select                             break
 select                            done
1) def 2) ghi 3) jkl
                   Select variant  1
def
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue

@ -16,7 +16,7 @@ from powerline.lib.monotonic import monotonic
from tests import TestCase, SkipTest
INOTIFY_DIR = 'inotify' + os.environ.get('PYTHON', '')
INOTIFY_DIR = 'inotify' + os.path.basename(os.environ.get('PYTHON', ''))
def clear_dir(dir):

87
tests/vim_utils.vim Normal file

@ -0,0 +1,87 @@
let g:powerline_use_var_handler = 1
let g:root=expand('<sfile>:p:h:h')
let g:mf=g:root.'/message.fail'
command -nargs=1 LST :call writefile(<args>, g:mf) | cquit
command -nargs=1 ERR :LST [<args>]
command -nargs=1 EXC :ERR 'Unexpected exception', <q-args>, v:exception, v:throwpoint
function EnablePlugins(...)
let &runtimepath = join(map(copy(a:000), 'escape(g:root."/tests/vim-plugins/".v:val, "\\,")'), ',')
try
runtime! plugin/*.vim
silent doautocmd BufWinEnter
silent doautocmd BufEnter
silent doautocmd VimEnter
catch
EXC EnablePlugins
endtry
endfunction
function RecordStatusline()
let g:statusline = &l:statusline
if g:statusline[:1] is# '%!'
let g:statusline_value=eval(g:statusline[2:])
else
ERR 'Statusline does not start with %!', g:statusline
endif
return ''
endfunction
function SourcePowerline()
let g:powerline_config_paths = [g:root . '/powerline/config_files']
try
execute 'source' fnameescape(g:root . '/powerline/bindings/vim/plugin/powerline.vim')
catch
EXC SourcePowerline
endtry
endfunction
function NDiff(actual, expected)
return systemlist(shellescape(g:root.'/tests/bot-ci/scripts/ndiff-strings.py').' '.shellescape(a:actual).' '.shellescape(a:expected))
endfunction
function CheckStatuslineValue(actual, expected)
if a:actual isnot# a:expected
LST ['Expected different statusline value', a:actual, a:expected] + NDiff(a:actual, a:expected)
endif
endfunction
function CheckRecordedStatuslineValue(expected)
return CheckStatuslineValue(g:statusline_value, a:expected)
endfunction
function GetCurrentStatusline()
if &l:statusline[:1] isnot# '%!'
ERR 'Statusline does not start with %!', &l:statusline
endif
return eval(&l:statusline[2:])
endfunction
function CheckCurrentStatusline(expected)
return CheckStatuslineValue(GetCurrentStatusline(), a:expected)
endfunction
function CheckMessages()
if !empty(g:powerline_log_messages)
LST ['Unexpected messages in log'] + g:powerline_log_messages
endif
redir => mes
messages
redir END
let mesl = split(mes, "\n")[1:]
if !empty(mesl)
LST ['Unexpected messages'] + split(mes, "\n", 1)
endif
endfunction
function RunPython(s)
if has('python')
execute 'python' a:s
else
execute 'python3' a:s
endif
endfunction
function PyFile(f)
if has('python')
execute 'pyfile' fnameescape(g:root.'/tests/'.a:f.'.py')
else
execute 'py3file' fnameescape(g:root.'/tests/'.a:f.'.py')
endif
endfunction
for s:c in ['noremap', 'noremap!']
execute s:c '<special><expr>' '<Plug>(PowerlineTestRecordStatusline)' 'RecordStatusline()'
endfor