132 lines
4.9 KiB
Python
132 lines
4.9 KiB
Python
import os
|
|
|
|
from unittest import TestCase
|
|
from mock import (
|
|
MagicMock,
|
|
patch,
|
|
mock_open,
|
|
Mock,
|
|
ANY
|
|
)
|
|
from charmhelpers.fetch import (
|
|
archiveurl,
|
|
UnhandledSource,
|
|
)
|
|
|
|
import six
|
|
if six.PY3:
|
|
from urllib.parse import urlparse
|
|
from urllib.error import URLError
|
|
else:
|
|
from urllib2 import URLError
|
|
from urlparse import urlparse
|
|
|
|
|
|
class ArchiveUrlFetchHandlerTest(TestCase):
|
|
|
|
def setUp(self):
|
|
super(ArchiveUrlFetchHandlerTest, 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",
|
|
)
|
|
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",
|
|
"bzr+ssh://example.com/foo.tar.gz",
|
|
"lp:example/foo.tgz",
|
|
"file//example.com/foo.tar.bz2",
|
|
"garbage",
|
|
)
|
|
self.fh = archiveurl.ArchiveUrlFetchHandler()
|
|
|
|
def test_handles_archive_urls(self):
|
|
for url in self.valid_urls:
|
|
result = self.fh.can_handle(url)
|
|
self.assertEqual(result, True, url)
|
|
for url in self.invalid_urls:
|
|
result = self.fh.can_handle(url)
|
|
self.assertNotEqual(result, True, url)
|
|
|
|
@patch('charmhelpers.fetch.archiveurl.urlopen')
|
|
def test_downloads(self, _urlopen):
|
|
for url in self.valid_urls:
|
|
response = MagicMock()
|
|
response.read.return_value = "bar"
|
|
_urlopen.return_value = response
|
|
|
|
_open = mock_open()
|
|
with patch('charmhelpers.fetch.archiveurl.open',
|
|
_open, create=True):
|
|
self.fh.download(url, "foo")
|
|
|
|
response.read.assert_called_with()
|
|
_open.assert_called_once_with("foo", 'wb')
|
|
_open().write.assert_called_with("bar")
|
|
|
|
@patch('charmhelpers.fetch.archiveurl.check_hash')
|
|
@patch('charmhelpers.fetch.archiveurl.mkdir')
|
|
@patch('charmhelpers.fetch.archiveurl.extract')
|
|
def test_installs(self, _extract, _mkdir, _check_hash):
|
|
self.fh.download = MagicMock()
|
|
|
|
for url in self.valid_urls:
|
|
filename = urlparse(url).path
|
|
dest = os.path.join('foo', 'fetched', os.path.basename(filename))
|
|
_extract.return_value = dest
|
|
with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
|
|
where = self.fh.install(url, checksum='deadbeef')
|
|
self.fh.download.assert_called_with(url, dest)
|
|
_extract.assert_called_with(dest, None)
|
|
_check_hash.assert_called_with(dest, 'deadbeef', 'sha1')
|
|
self.assertEqual(where, dest)
|
|
_check_hash.reset_mock()
|
|
|
|
url = "http://www.example.com/archive.tar.gz"
|
|
|
|
self.fh.download.side_effect = URLError('fail')
|
|
with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
|
|
self.assertRaises(UnhandledSource, self.fh.install, url)
|
|
|
|
self.fh.download.side_effect = OSError('fail')
|
|
with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
|
|
self.assertRaises(UnhandledSource, self.fh.install, url)
|
|
|
|
@patch('charmhelpers.fetch.archiveurl.check_hash')
|
|
@patch('charmhelpers.fetch.archiveurl.mkdir')
|
|
@patch('charmhelpers.fetch.archiveurl.extract')
|
|
def test_install_with_hash_in_url(self, _extract, _mkdir, _check_hash):
|
|
self.fh.download = MagicMock()
|
|
url = "file://example.com/foo.tar.bz2#sha512=beefdead"
|
|
with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
|
|
self.fh.install(url)
|
|
_check_hash.assert_called_with(ANY, 'beefdead', 'sha512')
|
|
|
|
@patch('charmhelpers.fetch.archiveurl.mkdir')
|
|
@patch('charmhelpers.fetch.archiveurl.extract')
|
|
def test_install_with_duplicate_hash_in_url(self, _extract, _mkdir):
|
|
self.fh.download = MagicMock()
|
|
url = "file://example.com/foo.tar.bz2#sha512=a&sha512=b"
|
|
with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
|
|
with self.assertRaisesRegexp(
|
|
TypeError, "Expected 1 hash value, not 2"):
|
|
self.fh.install(url)
|
|
|
|
@patch('charmhelpers.fetch.archiveurl.urlretrieve')
|
|
@patch('charmhelpers.fetch.archiveurl.check_hash')
|
|
def test_download_and_validate(self, vfmock, urlmock):
|
|
urlmock.return_value = ('/tmp/tmpebM9Hv', Mock())
|
|
dlurl = 'http://example.com/foo.tgz'
|
|
dlhash = '988881adc9fc3655077dc2d4d757d480b5ea0e11'
|
|
self.fh.download_and_validate(dlurl, dlhash)
|
|
vfmock.assert_called_with('/tmp/tmpebM9Hv', dlhash, 'sha1')
|