Charmed-Kubernetes/nrpe/mod/charmhelpers/tests/fetch/test_fetch.py

270 lines
8.8 KiB
Python

import six
import os
import yaml
from testtools import TestCase
from mock import (
patch,
MagicMock,
call,
)
from charmhelpers import fetch
if six.PY3:
from urllib.parse import urlparse
builtin_open = 'builtins.open'
else:
from urlparse import urlparse
builtin_open = '__builtin__.open'
FAKE_APT_CACHE = {
# an installed package
'vim': {
'current_ver': '2:7.3.547-6ubuntu5'
},
# a uninstalled installation candidate
'emacs': {
}
}
def fake_apt_cache(in_memory=True, progress=None):
def _get(package):
pkg = MagicMock()
if package not in FAKE_APT_CACHE:
raise KeyError
pkg.name = package
if 'current_ver' in FAKE_APT_CACHE[package]:
pkg.current_ver.ver_str = FAKE_APT_CACHE[package]['current_ver']
else:
pkg.current_ver = None
return pkg
cache = MagicMock()
cache.__getitem__.side_effect = _get
return cache
def getenv(update=None):
# return a copy of os.environ with update applied.
# this was necessary because some modules modify os.environment directly
copy = os.environ.copy()
if update is not None:
copy.update(update)
return copy
class FetchTest(TestCase):
@patch('charmhelpers.fetch.log')
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_single_source(self, add_source, config, log):
config.side_effect = ['source', 'key']
fetch.configure_sources()
add_source.assert_called_with('source', 'key')
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_null_source(self, add_source, config):
config.side_effect = [None, None]
fetch.configure_sources()
self.assertEqual(add_source.call_count, 0)
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_empty_source(self, add_source, config):
config.side_effect = ['', '']
fetch.configure_sources()
self.assertEqual(add_source.call_count, 0)
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_single_source_no_key(self, add_source, config):
config.side_effect = ['source', None]
fetch.configure_sources()
add_source.assert_called_with('source', None)
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_multiple_sources(self, add_source, config):
sources = ["sourcea", "sourceb"]
keys = ["keya", None]
config.side_effect = [
yaml.dump(sources),
yaml.dump(keys)
]
fetch.configure_sources()
add_source.assert_has_calls([
call('sourcea', 'keya'),
call('sourceb', None)
])
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_missing_keys(self, add_source, config):
sources = ["sourcea", "sourceb"]
keys = ["keya"] # Second key is missing
config.side_effect = [
yaml.dump(sources),
yaml.dump(keys)
]
self.assertRaises(fetch.SourceConfigError, fetch.configure_sources)
@patch.object(fetch, '_fetch_update')
@patch.object(fetch, 'config')
@patch.object(fetch, 'add_source')
def test_configure_sources_update_called_ubuntu(self, add_source, config,
update):
config.side_effect = ['source', 'key']
fetch.configure_sources(update=True)
add_source.assert_called_with('source', 'key')
self.assertTrue(update.called)
class InstallTest(TestCase):
def setUp(self):
super(InstallTest, self).setUp()
self.valid_urls = (
"http://example.com/foo.tar.gz",
"http://example.com/foo.tgz",
"http://example.com/foo.tar.bz2",
"http://example.com/foo.tbz2",
"http://example.com/foo.zip",
"http://example.com/foo.zip?bar=baz&x=y#whee",
"ftp://example.com/foo.tar.gz",
"https://example.com/foo.tgz",
"file://example.com/foo.tar.bz2",
"bzr+ssh://example.com/branch-name",
"bzr+ssh://example.com/branch-name/",
"lp:branch-name",
"lp:example/branch-name",
)
self.invalid_urls = (
"git://example.com/foo.tar.gz",
"http://example.com/foo",
"http://example.com/foobar=baz&x=y#tar.gz",
"http://example.com/foobar?h=baz.zip",
"abc:example",
"file//example.com/foo.tar.bz2",
"garbage",
)
@patch('charmhelpers.fetch.log')
@patch('charmhelpers.fetch.plugins')
def test_installs_remote(self, _plugins, _log):
h1 = MagicMock(name="h1")
h1.can_handle.return_value = "Nope"
h2 = MagicMock(name="h2")
h2.can_handle.return_value = True
h2.install.side_effect = fetch.UnhandledSource()
h3 = MagicMock(name="h3")
h3.can_handle.return_value = True
h3.install.return_value = "foo"
_plugins.return_value = [h1, h2, h3]
for url in self.valid_urls:
result = fetch.install_remote(url)
h1.can_handle.assert_called_with(url)
h2.can_handle.assert_called_with(url)
h3.can_handle.assert_called_with(url)
h1.install.assert_not_called()
h2.install.assert_called_with(url)
h3.install.assert_called_with(url)
self.assertEqual(result, "foo")
fetch.install_remote('url', extra_arg=True)
h2.install.assert_called_with('url', extra_arg=True)
@patch('charmhelpers.fetch.install_remote')
@patch('charmhelpers.fetch.config')
def test_installs_from_config(self, _config, _instrem):
for url in self.valid_urls:
_config.return_value = {"foo": url}
fetch.install_from_config("foo")
_instrem.assert_called_with(url)
class PluginTest(TestCase):
@patch('charmhelpers.fetch.importlib.import_module')
def test_imports_plugins(self, import_):
fetch_handlers = ['a.foo', 'b.foo', 'c.foo']
module = MagicMock()
import_.return_value = module
plugins = fetch.plugins(fetch_handlers)
self.assertEqual(len(fetch_handlers), len(plugins))
module.foo.assert_has_calls(([call()] * len(fetch_handlers)))
@patch('charmhelpers.fetch.importlib.import_module')
def test_imports_plugins_default(self, import_):
module = MagicMock()
import_.return_value = module
plugins = fetch.plugins()
self.assertEqual(len(fetch.FETCH_HANDLERS), len(plugins))
for handler in fetch.FETCH_HANDLERS:
classname = handler.rsplit('.', 1)[-1]
getattr(module, classname).assert_called_with()
@patch('charmhelpers.fetch.log')
@patch('charmhelpers.fetch.importlib.import_module')
def test_skips_and_logs_missing_plugins(self, import_, log_):
fetch_handlers = ['a.foo', 'b.foo', 'c.foo']
import_.side_effect = (NotImplementedError, NotImplementedError,
MagicMock())
plugins = fetch.plugins(fetch_handlers)
self.assertEqual(1, len(plugins))
self.assertEqual(2, log_.call_count)
@patch('charmhelpers.fetch.log')
@patch.object(fetch.importlib, 'import_module')
def test_plugins_are_valid(self, import_module, log_):
plugins = fetch.plugins()
self.assertEqual(len(fetch.FETCH_HANDLERS), len(plugins))
class BaseFetchHandlerTest(TestCase):
def setUp(self):
super(BaseFetchHandlerTest, self).setUp()
self.test_urls = (
"http://example.com/foo?bar=baz&x=y#blarg",
"https://example.com/foo",
"ftp://example.com/foo",
"file://example.com/foo",
"git://github.com/foo/bar",
"bzr+ssh://bazaar.launchpad.net/foo/bar",
"bzr+http://bazaar.launchpad.net/foo/bar",
"garbage",
)
self.fh = fetch.BaseFetchHandler()
def test_handles_nothing(self):
for url in self.test_urls:
self.assertNotEqual(self.fh.can_handle(url), True)
def test_install_throws_unhandled(self):
for url in self.test_urls:
self.assertRaises(fetch.UnhandledSource, self.fh.install, url)
def test_parses_urls(self):
sample_url = "http://example.com/foo?bar=baz&x=y#blarg"
p = self.fh.parse_url(sample_url)
self.assertEqual(p, urlparse(sample_url))
def test_returns_baseurl(self):
sample_url = "http://example.com/foo?bar=baz&x=y#blarg"
expected_url = "http://example.com/foo"
u = self.fh.base_url(sample_url)
self.assertEqual(u, expected_url)