This allows us to do more of the data loading that might fail safely in the mopidy.ext module instead of having things spread all over the place. Note that only minimal changes have been made to __main__ to make things work. Further refactoring should follow.
182 lines
4.9 KiB
Python
182 lines
4.9 KiB
Python
from __future__ import absolute_import, unicode_literals
|
|
|
|
import mock
|
|
|
|
import pkg_resources
|
|
|
|
import pytest
|
|
|
|
from mopidy import config, exceptions, ext
|
|
|
|
from tests import IsA, any_unicode
|
|
|
|
|
|
class TestExtension(ext.Extension):
|
|
dist_name = 'Mopidy-Foobar'
|
|
ext_name = 'foobar'
|
|
version = '1.2.3'
|
|
|
|
def get_default_config(self):
|
|
return '[foobar]\nenabled = true'
|
|
|
|
|
|
any_testextension = IsA(TestExtension)
|
|
|
|
|
|
# ext.Extension
|
|
|
|
@pytest.fixture
|
|
def extension():
|
|
return ext.Extension()
|
|
|
|
|
|
def test_dist_name_is_none(extension):
|
|
assert extension.dist_name is None
|
|
|
|
|
|
def test_ext_name_is_none(extension):
|
|
assert extension.ext_name is None
|
|
|
|
|
|
def test_version_is_none(extension):
|
|
assert extension.version is None
|
|
|
|
|
|
def test_get_default_config_raises_not_implemented(extension):
|
|
with pytest.raises(NotImplementedError):
|
|
extension.get_default_config()
|
|
|
|
|
|
def test_get_config_schema_returns_extension_schema(extension):
|
|
schema = extension.get_config_schema()
|
|
assert isinstance(schema['enabled'], config.Boolean)
|
|
|
|
|
|
def test_validate_environment_does_nothing_by_default(extension):
|
|
assert extension.validate_environment() is None
|
|
|
|
|
|
def test_setup_raises_not_implemented(extension):
|
|
with pytest.raises(NotImplementedError):
|
|
extension.setup(None)
|
|
|
|
|
|
# ext.load_extensions
|
|
|
|
|
|
@mock.patch('pkg_resources.iter_entry_points')
|
|
def test_load_extensions_no_extenions(mock_entry_points):
|
|
mock_entry_points.return_value = []
|
|
assert [] == ext.load_extensions()
|
|
|
|
|
|
@mock.patch('pkg_resources.iter_entry_points')
|
|
def test_load_extensions(mock_entry_points):
|
|
mock_entry_point = mock.Mock()
|
|
mock_entry_point.load.return_value = TestExtension
|
|
|
|
mock_entry_points.return_value = [mock_entry_point]
|
|
|
|
expected = ext.ExtensionData(
|
|
any_testextension, mock_entry_point, IsA(config.ConfigSchema),
|
|
any_unicode, None)
|
|
|
|
assert ext.load_extensions() == [expected]
|
|
|
|
|
|
@mock.patch('pkg_resources.iter_entry_points')
|
|
def test_load_extensions_gets_wrong_class(mock_entry_points):
|
|
|
|
class WrongClass(object):
|
|
pass
|
|
|
|
mock_entry_point = mock.Mock()
|
|
mock_entry_point.load.return_value = WrongClass
|
|
|
|
mock_entry_points.return_value = [mock_entry_point]
|
|
|
|
assert [] == ext.load_extensions()
|
|
|
|
|
|
@mock.patch('pkg_resources.iter_entry_points')
|
|
def test_load_extensions_gets_instance(mock_entry_points):
|
|
mock_entry_point = mock.Mock()
|
|
mock_entry_point.load.return_value = TestExtension()
|
|
|
|
mock_entry_points.return_value = [mock_entry_point]
|
|
|
|
assert [] == ext.load_extensions()
|
|
|
|
|
|
@mock.patch('pkg_resources.iter_entry_points')
|
|
def test_load_extensions_creating_instance_fails(mock_entry_points):
|
|
mock_extension = mock.Mock(spec=ext.Extension)
|
|
mock_extension.side_effect = Exception
|
|
|
|
mock_entry_point = mock.Mock()
|
|
mock_entry_point.load.return_value = mock_extension
|
|
|
|
mock_entry_points.return_value = [mock_entry_point]
|
|
assert [] == ext.load_extensions()
|
|
|
|
|
|
# ext.validate_extension
|
|
|
|
@pytest.fixture
|
|
def ext_data():
|
|
extension = TestExtension()
|
|
|
|
entry_point = mock.Mock()
|
|
entry_point.name = extension.ext_name
|
|
|
|
schema = extension.get_config_schema()
|
|
defaults = extension.get_default_config()
|
|
command = extension.get_command()
|
|
|
|
return ext.ExtensionData(extension, entry_point, schema, defaults, command)
|
|
|
|
|
|
def test_validate_extension_name_mismatch(ext_data):
|
|
ext_data.entry_point.name = 'barfoo'
|
|
assert not ext.validate_extension(ext_data.extension, ext_data.entry_point)
|
|
|
|
|
|
def test_validate_extension_distribution_not_found(ext_data):
|
|
error = pkg_resources.DistributionNotFound
|
|
ext_data.entry_point.require.side_effect = error
|
|
assert not ext.validate_extension(ext_data.extension, ext_data.entry_point)
|
|
|
|
|
|
def test_validate_extension_version_conflict(ext_data):
|
|
ext_data.entry_point.require.side_effect = pkg_resources.VersionConflict
|
|
assert not ext.validate_extension(ext_data.extension, ext_data.entry_point)
|
|
|
|
|
|
def test_validate_extension_exception(ext_data):
|
|
ext_data.entry_point.require.side_effect = Exception
|
|
|
|
# We trust that entry points are well behaved, so exception will bubble.
|
|
with pytest.raises(Exception):
|
|
assert not ext.validate_extension(
|
|
ext_data.extension, ext_data.entry_point)
|
|
|
|
|
|
def test_validate_extension_instance_validate_env_ext_error(ext_data):
|
|
extension = ext_data.extension
|
|
with mock.patch.object(extension, 'validate_environment') as validate:
|
|
validate.side_effect = exceptions.ExtensionError('error')
|
|
|
|
assert not ext.validate_extension(
|
|
ext_data.extension, ext_data.entry_point)
|
|
validate.assert_called_once_with()
|
|
|
|
|
|
def test_validate_extension_instance_validate_env_exception(ext_data):
|
|
extension = ext_data.extension
|
|
with mock.patch.object(extension, 'validate_environment') as validate:
|
|
validate.side_effect = Exception
|
|
|
|
assert not ext.validate_extension(
|
|
ext_data.extension, ext_data.entry_point)
|
|
validate.assert_called_once_with()
|