Refactor config_mock module to not use globals and fix tests

This commit is contained in:
ZyX 2014-08-05 13:39:01 +04:00
parent 66e0999147
commit 0f4e1bafda
5 changed files with 420 additions and 392 deletions

View File

@ -3,37 +3,53 @@ from threading import Lock
from powerline.renderer import Renderer
from powerline.lib.config import ConfigLoader
from powerline import Powerline
from tests.lib import Args, replace_attr
from copy import deepcopy
from time import sleep
from functools import wraps
import os
access_log = []
access_lock = Lock()
class TestHelpers(object):
def __init__(self, config):
self.config = config
self.access_log = []
self.access_lock = Lock()
def loader_condition(self, path):
return (path in self.config) and path
def load_json_config(config_file_path, *args, **kwargs):
global access_log
with access_lock:
access_log.append(config_file_path)
try:
return deepcopy(config_container['config'][config_file_path])
except KeyError:
raise IOError(config_file_path)
def find_config_files(self, cfg_path, config_loader, loader_callback):
if cfg_path.endswith('.json'):
cfg_path = cfg_path[:-5]
if cfg_path.startswith('/'):
cfg_path = cfg_path.lstrip('/')
with self.access_lock:
self.access_log.append('check:' + cfg_path)
if cfg_path in self.config:
yield cfg_path
else:
if config_loader:
config_loader.register_missing(self.loader_condition, loader_callback, cfg_path)
raise IOError(('fcf:' if cfg_path.endswith('raise') else '') + cfg_path)
def load_json_config(self, config_file_path, *args, **kwargs):
if config_file_path.endswith('.json'):
config_file_path = config_file_path[:-5]
if config_file_path.startswith('/'):
config_file_path = config_file_path.lstrip('/')
with self.access_lock:
self.access_log.append('load:' + config_file_path)
try:
return deepcopy(self.config[config_file_path])
except KeyError:
raise IOError(config_file_path)
def _find_config_file(config, search_paths, config_file):
if config_file.endswith('raise') and config_file not in config:
raise IOError('fcf:' + config_file)
return config_file
def pop_events():
global access_log
with access_lock:
r = access_log[:]
access_log = []
return r
def pop_events(self):
with self.access_lock:
r = self.access_log[:]
self.access_log = []
return r
def log_call(func):
@ -44,7 +60,7 @@ def log_call(func):
return ret
class Watcher(object):
class TestWatcher(object):
events = set()
lock = Lock()
@ -109,20 +125,46 @@ class EvenSimplerRenderer(Renderer):
class TestPowerline(Powerline):
_created = False
def __init__(self, _helpers, **kwargs):
super(TestPowerline, self).__init__(**kwargs)
self._helpers = _helpers
self.find_config_files = _helpers.find_config_files
@staticmethod
def get_local_themes(local_themes):
return local_themes
@staticmethod
def get_config_paths():
return ['']
def _will_create_renderer(self):
return self.cr_kwargs
def _pop_events(self):
return self._helpers.pop_events()
renderer = EvenSimplerRenderer
def get_powerline(**kwargs):
class TestConfigLoader(ConfigLoader):
def __init__(self, _helpers, **kwargs):
watcher = TestWatcher()
super(TestConfigLoader, self).__init__(
load=_helpers.load_json_config,
watcher=watcher,
watcher_type='test',
**kwargs
)
def get_powerline(config, **kwargs):
helpers = TestHelpers(config)
return get_powerline_raw(
helpers,
TestPowerline,
_helpers=helpers,
ext='test',
renderer_module='tests.lib.config_mock',
logger=Logger(),
@ -130,45 +172,42 @@ def get_powerline(**kwargs):
)
def get_powerline_raw(PowerlineClass, **kwargs):
def select_renderer(simpler_renderer=False):
global renderer
watcher = Watcher()
if kwargs.pop('simpler_renderer', False):
renderer = EvenSimplerRenderer
else:
renderer = SimpleRenderer
renderer = EvenSimplerRenderer if simpler_renderer else SimpleRenderer
def get_powerline_raw(helpers, PowerlineClass, **kwargs):
if not isinstance(helpers, TestHelpers):
helpers = TestHelpers(helpers)
select_renderer(kwargs.pop('simpler_renderer', False))
pl = PowerlineClass(
config_loader=ConfigLoader(
load=load_json_config,
watcher=watcher,
watcher_type='test',
config_loader=TestConfigLoader(
_helpers=helpers,
run_once=kwargs.get('run_once')
),
**kwargs
)
pl._watcher = watcher
pl._watcher = pl.config_loader.watcher
return pl
config_container = None
def swap_attributes(cfg_container, powerline_module, replaces):
global config_container
config_container = cfg_container
if not replaces:
replaces = {
'_find_config_file': lambda *args: _find_config_file(config_container['config'], *args),
}
for attr, val in replaces.items():
old_val = getattr(powerline_module, attr)
setattr(powerline_module, attr, val)
replaces[attr] = old_val
return replaces
def swap_attributes(config, powerline_module):
return replace_attr(powerline_module, 'os', Args(
path=Args(
isfile=lambda path: path.lstrip('/').replace('.json', '') in config,
join=os.path.join,
expanduser=lambda path: path,
realpath=lambda path: path,
dirname=os.path.dirname,
),
environ={},
))
def add_watcher_events(p, *args, **kwargs):
p._watcher._reset(args)
if isinstance(p._watcher, TestWatcher):
p._watcher._reset(args)
while not p._will_create_renderer():
sleep(kwargs.get('interval', 0.1))
if not kwargs.get('wait', True):

View File

@ -71,6 +71,7 @@ class TestParser(TestCase):
'-c', 'common.spaces=4',
'-t', 'default.segment_data.hostname.before=H:',
'-p', '.',
'-p', '..',
'-R', 'smth={"abc":"def"}',
], {
'ext': ['shell'],
@ -90,7 +91,7 @@ class TestParser(TestCase):
}
}
},
'config_path': ['.'],
'config_path': ['.', '..'],
'renderer_arg': {'smth': {'abc': 'def'}},
}),
(['shell', '-R', 'arg=true'], {'ext': ['shell'], 'renderer_arg': {'arg': True}}),

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
from powerline import Powerline
from tests import TestCase
from tests.lib.config_mock import select_renderer
from shutil import rmtree
import os
import json
@ -114,6 +115,7 @@ class WithConfigTree(object):
mkdir_recursive(os.path.dirname(fname))
with open(fname, 'w') as F:
json.dump(v, F)
select_renderer(simpler_renderer=True)
self.p = TestPowerline(
ext='test',
renderer_module='tests.lib.config_mock',

View File

@ -1,11 +1,12 @@
# vim:fileencoding=utf-8:noet
from __future__ import unicode_literals
import powerline as powerline_module
from time import sleep
from tests import TestCase
from tests.lib import replace_item
from tests.lib.config_mock import swap_attributes, get_powerline, pop_events, add_watcher_events
from copy import deepcopy
from functools import wraps
from tests import TestCase
from tests.lib.config_mock import get_powerline, add_watcher_events
config = {
@ -93,201 +94,192 @@ config = {
}
def with_new_config(func):
@wraps(func)
def f(self):
return func(self, deepcopy(config))
return f
class TestConfigReload(TestCase):
def assertAccessEvents(self, *args):
self.assertEqual(set(pop_events()), set(args))
def assertAccessEvents(self, p, *args):
events = set()
for event in args:
if ':' not in event:
events.add('check:' + event)
events.add('load:' + event)
else:
events.add(event)
self.assertEqual(set(p._pop_events()), events)
def test_noreload(self):
with get_powerline(run_once=True) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['common']['spaces'] = 1
add_watcher_events(p, 'config', wait=False, interval=0.05)
# When running once thread should not start
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents()
self.assertEqual(p.logger._pop_msgs(), [])
# Without the following assertion test_reload_colors may fail for
# unknown reason (with AssertionError telling about “config” accessed
# one more time then needed)
pop_events()
@with_new_config
def test_noreload(self, config):
with get_powerline(config, run_once=True) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['common']['spaces'] = 1
add_watcher_events(p, 'config', wait=False, interval=0.05)
# When running once thread should not start
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p)
self.assertEqual(p.logger._pop_msgs(), [])
def test_reload_main(self):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_reload_main(self, config):
with get_powerline(config, run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['common']['spaces'] = 1
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['common']['spaces'] = 1
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['theme'] = 'nonexistent'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config', 'themes/test/nonexistent')
# It should normally handle file missing error
self.assertEqual(p.logger._pop_msgs(), ['exception:test:powerline:Failed to create renderer: themes/test/nonexistent'])
config['config']['ext']['test']['theme'] = 'nonexistent'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'check:themes/test/nonexistent')
# It should normally handle file missing error
self.assertEqual(p.logger._pop_msgs(), ['exception:test:powerline:Failed to create renderer: themes/test/nonexistent'])
config['config']['ext']['test']['theme'] = 'default'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config', 'themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['theme'] = 'default'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config', 'colorschemes/nonexistent', 'colorschemes/test/__main__', 'colorschemes/test/nonexistent')
# It should normally handle file missing error
self.assertEqual(p.logger._pop_msgs(), [
'exception:test:powerline:Failed to load colorscheme: colorschemes/nonexistent',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/__main__',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/nonexistent',
'exception:test:powerline:Failed to create renderer: colorschemes/test/nonexistent'
])
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'check:colorschemes/nonexistent', 'check:colorschemes/test/__main__', 'check:colorschemes/test/nonexistent')
# It should normally handle file missing error
self.assertEqual(p.logger._pop_msgs(), [
'exception:test:powerline:Failed to load colorscheme: colorschemes/nonexistent',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/__main__',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/nonexistent',
'exception:test:powerline:Failed to create renderer: colorschemes/test/nonexistent'
])
config['config']['ext']['test']['colorscheme'] = '2'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> s <3 4 False>>><1 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config', 'colorschemes/2', 'colorschemes/test/__main__', 'colorschemes/test/2')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['colorscheme'] = '2'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> s <3 4 False>>><1 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'check:colorschemes/2', 'check:colorschemes/test/__main__', 'colorschemes/test/2')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['theme'] = '2'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> t <3 4 False>>><1 4 4>b <4 False False>>><None None None>')
self.assertAccessEvents('config', 'themes/test/2')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['theme'] = '2'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> t <3 4 False>>><1 4 4>b <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'themes/test/2')
self.assertEqual(p.logger._pop_msgs(), [])
self.assertEqual(p.renderer.local_themes, None)
config['config']['ext']['test']['local_themes'] = 'something'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> t <3 4 False>>><1 4 4>b <4 False False>>><None None None>')
self.assertAccessEvents('config')
self.assertEqual(p.logger._pop_msgs(), [])
self.assertEqual(p.renderer.local_themes, 'something')
pop_events()
self.assertEqual(p.renderer.local_themes, None)
config['config']['ext']['test']['local_themes'] = 'something'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> t <3 4 False>>><1 4 4>b <4 False False>>><None None None>')
self.assertAccessEvents(p, 'config')
self.assertEqual(p.logger._pop_msgs(), [])
self.assertEqual(p.renderer.local_themes, 'something')
def test_reload_unexistent(self):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_reload_unexistent(self, config):
with get_powerline(config, run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['ext']['test']['colorscheme'] = 'nonexistentraise'
add_watcher_events(p, 'config')
# It may appear that p.logger._pop_msgs() is called after given
# exception is added to the mesagges, but before config_loader
# exception was added (this one:
# “exception:test:config_loader:Error while running condition
# function for key colorschemes/test/nonexistentraise:
# fcf:colorschemes/test/nonexistentraise”).
# sleep(0.1)
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
# For colorschemes/{test/,}*raise find_config_file raises
# IOError, but it does not do so for colorschemes/test/__main__,
# so powerline is trying to load this, but not other
# colorschemes/*
self.assertAccessEvents('config', 'colorschemes/test/__main__')
self.assertIn('exception:test:powerline:Failed to create renderer: fcf:colorschemes/test/nonexistentraise', p.logger._pop_msgs())
config['config']['ext']['test']['colorscheme'] = 'nonexistentraise'
add_watcher_events(p, 'config')
# It may appear that p.logger._pop_msgs() is called after given
# exception is added to the mesagges, but before config_loader
# exception was added (this one:
# “exception:test:config_loader:Error while running condition
# function for key colorschemes/test/nonexistentraise:
# fcf:colorschemes/test/nonexistentraise”).
# sleep(0.1)
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
# For colorschemes/{test/,}*raise find_config_file raises
# IOError, but it does not do so for check:colorschemes/test/__main__,
# so powerline is trying to load this, but not other
# colorschemes/*
self.assertAccessEvents(p, 'config', 'check:colorschemes/test/__main__', 'check:colorschemes/nonexistentraise', 'check:colorschemes/test/nonexistentraise')
self.assertIn('exception:test:powerline:Failed to create renderer: fcf:colorschemes/test/nonexistentraise', p.logger._pop_msgs())
config['colorschemes/nonexistentraise'] = {}
config['colorschemes/test/nonexistentraise'] = {
'groups': {
"str1": {"fg": "col1", "bg": "col3", "attr": ["bold"]},
"str2": {"fg": "col2", "bg": "col4", "attr": ["underline"]},
},
}
while not p._will_create_renderer():
sleep(0.1)
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><2 4 4>g<4 False False>>><None None None>')
# Same as above
self.assertAccessEvents('colorschemes/nonexistentraise', 'colorschemes/test/nonexistentraise', 'colorschemes/test/__main__')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
config['colorschemes/nonexistentraise'] = {}
config['colorschemes/test/nonexistentraise'] = {
'groups': {
"str1": {"fg": "col1", "bg": "col3", "attr": ["bold"]},
"str2": {"fg": "col2", "bg": "col4", "attr": ["underline"]},
},
}
while not p._will_create_renderer():
sleep(0.1)
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><2 4 4>g<4 False False>>><None None None>')
# Same as above
self.assertAccessEvents(p, 'colorschemes/nonexistentraise', 'colorschemes/test/nonexistentraise', 'check:colorschemes/test/__main__')
self.assertEqual(p.logger._pop_msgs(), [])
def test_reload_colors(self):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_reload_colors(self, config):
with get_powerline(config, run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['colors']['colors']['col1'] = 5
add_watcher_events(p, 'colors')
self.assertEqual(p.render(), '<5 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('colors')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
config['colors']['colors']['col1'] = 5
add_watcher_events(p, 'colors')
self.assertEqual(p.render(), '<5 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'colors')
self.assertEqual(p.logger._pop_msgs(), [])
def test_reload_colorscheme(self):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_reload_colorscheme(self, config):
with get_powerline(config, run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['colorschemes/test/default']['groups']['str1']['bg'] = 'col3'
add_watcher_events(p, 'colorschemes/test/default')
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
config['colorschemes/test/default']['groups']['str1']['bg'] = 'col3'
add_watcher_events(p, 'colorschemes/test/default')
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
def test_reload_theme(self):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_reload_theme(self, config):
with get_powerline(config, run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default')
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default')
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
def test_reload_theme_main(self):
with replace_item(globals(), 'config', deepcopy(config)):
config['config']['common']['interval'] = None
with get_powerline(run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_reload_theme_main(self, config):
config['config']['common']['interval'] = None
with get_powerline(config, run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
self.assertTrue(p._watcher._calls)
pop_events()
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
self.assertTrue(p._watcher._calls)
def test_run_once_no_theme_reload(self):
with replace_item(globals(), 'config', deepcopy(config)):
config['config']['common']['interval'] = None
with get_powerline(run_once=True) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
@with_new_config
def test_run_once_no_theme_reload(self, config):
config['config']['common']['interval'] = None
with get_powerline(config, run_once=True) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents()
self.assertEqual(p.logger._pop_msgs(), [])
self.assertEqual(p._watcher._calls, [])
pop_events()
replaces = {}
def setUpModule():
global replaces
replaces = swap_attributes(globals(), powerline_module, replaces)
tearDownModule = setUpModule
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents(p)
self.assertEqual(p.logger._pop_msgs(), [])
if __name__ == '__main__':

View File

@ -1,11 +1,8 @@
# vim:fileencoding=utf-8:noet
from __future__ import unicode_literals, absolute_import, division
import tests.vim as vim_module
import powerline as powerline_module
from tests import TestCase
from tests.lib import replace_item
from tests.lib.config_mock import swap_attributes, get_powerline
from tests.lib.config_mock import get_powerline_raw
from tests.lib.config_mock import get_powerline, get_powerline_raw, swap_attributes
from functools import wraps
from copy import deepcopy
import sys
@ -123,11 +120,19 @@ config = {
}
def add_p_arg(func):
def with_new_config(func):
@wraps(func)
def f(self):
with get_powerline(run_once=True, simpler_renderer=True) as p:
func(self, p)
return func(self, deepcopy(config))
return f
def add_args(func):
@wraps(func)
def f(self):
new_config = deepcopy(config)
with get_powerline(new_config, run_once=True, simpler_renderer=True) as p:
func(self, p, new_config)
return f
@ -140,166 +145,158 @@ class TestRender(TestCase):
class TestLines(TestRender):
@add_p_arg
def test_without_above(self, p):
@add_args
def test_without_above(self, p, config):
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}<{344}f {--}')
self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}<{344}f {--}', width=10)
# self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}<{344} f {--}', width=11)
self.assertEqual(list(p.render_above_lines()), [])
def test_with_above(self):
with replace_item(globals(), 'config', deepcopy(config)):
old_segments = deepcopy(config['themes/test/default']['segments'])
config['themes/test/default']['segments']['above'] = [old_segments]
with get_powerline(run_once=True, simpler_renderer=True) as p:
self.assertRenderLinesEqual(p, [
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
])
self.assertRenderLinesEqual(p, [
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
], width=10)
@with_new_config
def test_with_above(self, config):
old_segments = deepcopy(config['themes/test/default']['segments'])
config['themes/test/default']['segments']['above'] = [old_segments]
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
self.assertRenderLinesEqual(p, [
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
])
self.assertRenderLinesEqual(p, [
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
], width=10)
config['themes/test/default']['segments']['above'] = [old_segments] * 2
with get_powerline(run_once=True, simpler_renderer=True) as p:
self.assertRenderLinesEqual(p, [
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
])
self.assertRenderLinesEqual(p, [
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
], width=10)
config['themes/test/default']['segments']['above'] = [old_segments] * 2
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
self.assertRenderLinesEqual(p, [
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
])
self.assertRenderLinesEqual(p, [
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
], width=10)
class TestSegments(TestRender):
@add_p_arg
def test_display(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
config['themes/test/default']['segments']['left'][0]['display'] = False
config['themes/test/default']['segments']['left'][1]['display'] = True
config['themes/test/default']['segments']['right'][0]['display'] = False
self.assertRenderEqual(p, '{344} g{4-}>>{--}')
@add_args
def test_display(self, p, config):
config['themes/test/default']['segments']['left'][0]['display'] = False
config['themes/test/default']['segments']['left'][1]['display'] = True
config['themes/test/default']['segments']['right'][0]['display'] = False
self.assertRenderEqual(p, '{344} g{4-}>>{--}')
class TestColorschemesHierarchy(TestRender):
@add_p_arg
def test_group_redirects(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('a', 'd1', draw_hard_divider=False),
highlighted_string('b', 'd2', draw_hard_divider=False),
highlighted_string('c', 'd3', draw_hard_divider=False),
highlighted_string('A', 'm1', draw_hard_divider=False),
highlighted_string('B', 'm2', draw_hard_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{78} a{910}b{1112}c{56}A{910}B{1112}C{56}1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_args
def test_group_redirects(self, p, config):
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('a', 'd1', draw_hard_divider=False),
highlighted_string('b', 'd2', draw_hard_divider=False),
highlighted_string('c', 'd3', draw_hard_divider=False),
highlighted_string('A', 'm1', draw_hard_divider=False),
highlighted_string('B', 'm2', draw_hard_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{78} a{910}b{1112}c{56}A{910}B{1112}C{56}1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_p_arg
def test_group_redirects_no_main(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/test/__main__']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('a', 'd1', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{78} a{56}1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_args
def test_group_redirects_no_main(self, p, config):
del config['colorschemes/test/__main__']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('a', 'd1', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{78} a{56}1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_p_arg
def test_group_redirects_no_top_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('c', 'd3', draw_soft_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{1112} c{1112}C{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_args
def test_group_redirects_no_top_default(self, p, config):
del config['colorschemes/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('c', 'd3', draw_soft_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{1112} c{1112}C{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_p_arg
def test_group_redirects_no_test_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('A', 'm1', draw_hard_divider=False),
highlighted_string('B', 'm2', draw_hard_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{56} A{910}B{1112}C{56}1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_args
def test_group_redirects_no_test_default(self, p, config):
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('A', 'm1', draw_hard_divider=False),
highlighted_string('B', 'm2', draw_hard_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{56} A{910}B{1112}C{56}1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_p_arg
def test_group_redirects_only_main(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/default']
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('C', 'm3', draw_hard_divider=False),
],
'right': [],
}
# Powerline is not able to work without default colorscheme
# somewhere, thus it will output error string
self.assertRenderEqual(p, 'colorschemes/test/default')
self.assertEqual(p.logger._pop_msgs(), [
'exception:test:powerline:Failed to load colorscheme: colorschemes/default',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/default',
'exception:test:powerline:Failed to create renderer: colorschemes/test/default',
'exception:test:powerline:Failed to render: colorschemes/test/default',
])
@add_args
def test_group_redirects_only_main(self, p, config):
del config['colorschemes/default']
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('C', 'm3', draw_hard_divider=False),
],
'right': [],
}
# Powerline is not able to work without default colorscheme
# somewhere, thus it will output error string
self.assertRenderEqual(p, 'colorschemes/test/default')
self.assertEqual(p.logger._pop_msgs(), [
'exception:test:powerline:Failed to load colorscheme: colorschemes/default',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/default',
'exception:test:powerline:Failed to create renderer: colorschemes/test/default',
'exception:test:powerline:Failed to render: colorschemes/test/default',
])
@add_p_arg
def test_group_redirects_only_top_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/test/__main__']
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{56} 1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_args
def test_group_redirects_only_top_default(self, p, config):
del config['colorschemes/test/__main__']
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{56} 1{78}2{910}3{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_p_arg
def test_group_redirects_only_test_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/default']
del config['colorschemes/test/__main__']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('s', 'str1', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{121} s{--}')
self.assertEqual(p.logger._pop_msgs(), [])
@add_args
def test_group_redirects_only_test_default(self, p, config):
del config['colorschemes/default']
del config['colorschemes/test/__main__']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('s', 'str1', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{121} s{--}')
self.assertEqual(p.logger._pop_msgs(), [])
class TestVim(TestCase):
@ -307,28 +304,25 @@ class TestVim(TestCase):
# Regression test: test that segment obtains environment from vim, not
# from os.environ.
from powerline.vim import VimPowerline
with vim_module._with('environ', TEST='abc'):
with get_powerline_raw(VimPowerline) as powerline:
window = vim_module.current.window
window_id = 1
winnr = window.number
self.assertEqual(powerline.render(window, window_id, winnr), '%#Pl_3_8404992_4_192_underline#\xa0abc%#Pl_4_192_NONE_None_NONE#>>')
vim_module._environ['TEST'] = 'def'
self.assertEqual(powerline.render(window, window_id, winnr), '%#Pl_3_8404992_4_192_underline#\xa0def%#Pl_4_192_NONE_None_NONE#>>')
replaces = {}
import powerline as powerline_module
import vim
vim.vars['powerline_config_path'] = '/'
with swap_attributes(config, powerline_module):
with vim_module._with('environ', TEST='abc'):
with get_powerline_raw(config, VimPowerline) as powerline:
window = vim_module.current.window
window_id = 1
winnr = window.number
self.assertEqual(powerline.render(window, window_id, winnr), '%#Pl_3_8404992_4_192_underline#\xa0abc%#Pl_4_192_NONE_None_NONE#>>')
vim_module._environ['TEST'] = 'def'
self.assertEqual(powerline.render(window, window_id, winnr), '%#Pl_3_8404992_4_192_underline#\xa0def%#Pl_4_192_NONE_None_NONE#>>')
def setUpModule():
global replaces
replaces = swap_attributes(globals(), powerline_module, replaces)
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
def tearDownModule():
global replaces
replaces = swap_attributes(globals(), powerline_module, replaces)
sys.path.pop(0)