summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/__init__.py44
-rw-r--r--tests/docker_source.py150
-rw-r--r--tests/test_docker_source.py607
-rw-r--r--tests/test_file_source.py171
-rw-r--r--tests/test_progress.py112
-rw-r--r--tests/test_utils.py580
-rw-r--r--tests/test_virt_bootstrap.py464
7 files changed, 180 insertions, 1948 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
index e82c6d5..1b06616 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,22 +1,23 @@
-"""
- Test suite for virt-bootstrap
-
- Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
-
- Copyright (C) 2017 Radostin Stoyanov
+# -*- coding: utf-8 -*-
+# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
+#
+# Copyright (C) 2017 Radostin Stoyanov
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Test suite for virt-bootstrap
"""
import sys
@@ -27,13 +28,12 @@ try:
except ImportError:
import unittest.mock as mock
-sys.path += '../src' # noqa: E402
+sys.path.insert(0, '../src') # noqa: E402
-# pylint: disable=import-error
+# pylint: disable=import-error, wrong-import-position
from virtBootstrap import virt_bootstrap
from virtBootstrap import sources
from virtBootstrap import progress
from virtBootstrap import utils
-__all__ = ['unittest', 'mock',
- 'virt_bootstrap', 'sources', 'progress', 'utils']
+__all__ = ['virt_bootstrap', 'sources', 'progress', 'utils']
diff --git a/tests/docker_source.py b/tests/docker_source.py
new file mode 100644
index 0000000..60404e6
--- /dev/null
+++ b/tests/docker_source.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
+#
+# Copyright (C) 2017 Radostin Stoyanov
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tests which aim is to exercise creation of root file system with DockerSource.
+"""
+
+import unittest
+
+from . import mock
+from . import sources
+
+
+# pylint: disable=invalid-name
+class TestDockerSource(unittest.TestCase):
+ """
+ Unit tests for DockerSource
+ """
+ ###################################
+ # Tests for: retrieve_layers_info()
+ ###################################
+ def _mock_retrieve_layers_info(self, manifest, kwargs):
+ """
+ This method is gather common test pattern used in the following
+ two test cases which aim to return an instance of the class
+ DockerSource with some util functions being mocked.
+ """
+ with mock.patch.multiple('virtBootstrap.utils',
+ get_image_details=mock.DEFAULT,
+ get_image_dir=mock.DEFAULT) as m_utils:
+
+ m_utils['get_image_details'].return_value = manifest
+ m_utils['get_image_dir'].return_value = '/images_path'
+
+ patch_method = 'virtBootstrap.sources.DockerSource.gen_valid_uri'
+ with mock.patch(patch_method) as m_uri:
+ src_instance = sources.DockerSource(**kwargs)
+ return (src_instance, m_uri, m_utils)
+
+ def test_retrieve_layers_info_pass_arguments_to_get_image_details(self):
+ """
+ Ensures that retrieve_layers_info() calls get_image_details()
+ with all passed arguments.
+ """
+ src_kwargs = {
+ 'uri': '',
+ 'progress': mock.Mock()
+ }
+
+ manifest = {'schemaVersion': 2, 'layers': []}
+ (src_instance,
+ m_uri, m_utils) = self._mock_retrieve_layers_info(manifest,
+ src_kwargs)
+
+ kwargs = {
+ 'insecure': src_instance.insecure,
+ 'username': src_instance.username,
+ 'password': src_instance.password,
+ 'raw': True
+ }
+ m_utils['get_image_details'].assert_called_once_with(m_uri(), **kwargs)
+
+ def test_retrieve_layers_info_schema_version_1(self):
+ """
+ Ensures that retrieve_layers_info() extracts the layers' information
+ from manifest with schema version 1 a list with format:
+ ["digest", "sum_type", "file_path", "size"].
+ """
+ kwargs = {
+ 'uri': '',
+ 'progress': mock.Mock()
+ }
+
+ manifest = {
+ 'schemaVersion': 1,
+ 'fsLayers': [
+ {'blobSum': 'sha256:75c416ea'},
+ {'blobSum': 'sha256:c6ff40b6'},
+ {'blobSum': 'sha256:a7050fc1'}
+ ]
+ }
+
+ expected_result = [
+ ['sha256', 'a7050fc1', '/images_path/a7050fc1.tar', None],
+ ['sha256', 'c6ff40b6', '/images_path/c6ff40b6.tar', None],
+ ['sha256', '75c416ea', '/images_path/75c416ea.tar', None]
+ ]
+
+ with mock.patch('os.path.getsize') as m_getsize:
+ m_getsize.return_value = None
+ src_instance = self._mock_retrieve_layers_info(manifest, kwargs)[0]
+ self.assertEqual(src_instance.layers, expected_result)
+
+ def test_retrieve_layers_info_schema_version_2(self):
+ """
+ Ensures that retrieve_layers_info() extracts the layers' information
+ from manifest with schema version 2 a list with format:
+ ["digest", "sum_type", "file_path", "size"].
+ """
+ kwargs = {
+ 'uri': '',
+ 'progress': mock.Mock()
+ }
+
+ manifest = {
+ 'schemaVersion': 2,
+ "layers": [
+ {"size": 47103294, "digest": "sha256:75c416ea"},
+ {"size": 814, "digest": "sha256:c6ff40b6"},
+ {"size": 513, "digest": "sha256:a7050fc1"}
+ ]
+ }
+
+ expected_result = [
+ ['sha256', '75c416ea', '/images_path/75c416ea.tar', 47103294],
+ ['sha256', 'c6ff40b6', '/images_path/c6ff40b6.tar', 814],
+ ['sha256', 'a7050fc1', '/images_path/a7050fc1.tar', 513]
+ ]
+
+ src_instance = self._mock_retrieve_layers_info(manifest, kwargs)[0]
+ self.assertEqual(src_instance.layers, expected_result)
+
+ def test_retrieve_layers_info_raise_error_on_invalid_schema_version(self):
+ """
+ Ensures that retrieve_layers_info() calls get_image_details()
+ with all passed arguments.
+ """
+ kwargs = {
+ 'uri': '',
+ 'progress': mock.Mock()
+ }
+
+ manifest = {'schemaVersion': 3}
+ with self.assertRaises(ValueError):
+ self._mock_retrieve_layers_info(manifest, kwargs)
diff --git a/tests/test_docker_source.py b/tests/test_docker_source.py
deleted file mode 100644
index 4859e1b..0000000
--- a/tests/test_docker_source.py
+++ /dev/null
@@ -1,607 +0,0 @@
-# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
-#
-# Copyright (C) 2017 Radostin Stoyanov
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-"""
-Unit tests for methods defined in virtBootstrap.sources.DockerSource
-"""
-
-from tests import unittest
-from tests import mock
-from tests import sources
-
-try:
- from urlparse import urlparse
-except ImportError:
- from urllib.parse import urlparse
-
-
-# pylint: disable=invalid-name
-# pylint: disable=too-many-public-methods
-class TestDockerSource(unittest.TestCase):
- """
- Test cases for DockerSource
- """
- def _mock_docker_source(self):
- """
- This method returns an instance of Mock object
- that acts as the specification for the DockerSource.
- """
- m_self = mock.Mock(spec=sources.DockerSource)
- m_self.progress = mock.Mock()
- m_self.no_cache = False
- m_self.url = "docker://test"
- m_self.images_dir = "/images_path"
- m_self.insecure = True
- m_self.username = 'user'
- m_self.password = 'password'
- m_self.layers = [
- ['sha256', '75c416ea', '/images_path/75c416ea.tar', ''],
- ['sha256', 'a7050fc1', '/images_path/a7050fc1.tar', '']
- ]
- return m_self
-
- ###################################
- # Tests for: __init__()
- ###################################
- def test_argument_assignment(self):
- """
- Ensures that __init__() assigns the arguments' values to instance
- variables.
- """
- kwargs = {'uri': '',
- 'fmt': 'dir',
- 'not_secure': False,
- 'no_cache': False,
- 'progress': mock.Mock(),
- 'username': 'username',
- 'password': 'password'}
-
- with mock.patch('virtBootstrap.utils'
- '.get_image_dir') as m_get_image_dir:
- with mock.patch.multiple('virtBootstrap.sources.DockerSource',
- retrieve_layers_info=mock.DEFAULT,
- gen_valid_uri=mock.DEFAULT) as mocked:
- src_instance = sources.DockerSource(**kwargs)
-
- test_values = {
- src_instance.url: mocked['gen_valid_uri'].return_value,
- src_instance.progress: kwargs['progress'].update_progress,
- src_instance.username: kwargs['username'],
- src_instance.password: kwargs['password'],
- src_instance.output_format: kwargs['fmt'],
- src_instance.no_cache: kwargs['no_cache'],
- src_instance.insecure: kwargs['not_secure'],
- src_instance.images_dir: m_get_image_dir()
- }
- for value in test_values:
- self.assertIs(value, test_values[value])
-
- def test_source_password_is_required_if_username_specifed(self):
- """
- Ensures that __init__() calls getpass() to request password
- when username is specified and password is not.
- """
- test_password = 'secret'
-
- kwargs = {arg: '' for arg
- in ['uri', 'fmt', 'not_secure', 'password', 'no_cache']}
- kwargs['progress'] = mock.Mock()
- kwargs['username'] = 'test'
-
- with mock.patch('virtBootstrap.utils.get_image_dir'):
- with mock.patch('getpass.getpass') as m_getpass:
- m_getpass.return_value = test_password
- with mock.patch.multiple('virtBootstrap.sources.DockerSource',
- retrieve_layers_info=mock.DEFAULT,
- gen_valid_uri=mock.DEFAULT):
- src_instance = sources.DockerSource(**kwargs)
-
- m_getpass.assert_called_once()
- self.assertIs(test_password, src_instance.password)
-
- ###################################
- # Tests for: retrieve_layers_info()
- ###################################
- def _mock_retrieve_layers_info(self, manifest, kwargs):
- """
- This method is gather common test pattern used in the following
- two test cases.
- """
- with mock.patch.multiple('virtBootstrap.utils',
- get_image_details=mock.DEFAULT,
- get_image_dir=mock.DEFAULT) as m_utils:
-
- m_utils['get_image_details'].return_value = manifest
- m_utils['get_image_dir'].return_value = '/images_path'
-
- patch_method = 'virtBootstrap.sources.DockerSource.gen_valid_uri'
- with mock.patch(patch_method) as m_uri:
- src_instance = sources.DockerSource(**kwargs)
- return (src_instance, m_uri, m_utils)
-
- def test_retrieve_layers_info_pass_arguments_to_get_image_details(self):
- """
- Ensures that retrieve_layers_info() calls get_image_details()
- with all passed arguments.
- """
- src_kwargs = {
- 'uri': '',
- 'progress': mock.Mock()
- }
-
- manifest = {'schemaVersion': 2, 'layers': []}
- (src_instance,
- m_uri, m_utils) = self._mock_retrieve_layers_info(manifest,
- src_kwargs)
-
- kwargs = {
- 'insecure': src_instance.insecure,
- 'username': src_instance.username,
- 'password': src_instance.password,
- 'raw': True
- }
- m_utils['get_image_details'].assert_called_once_with(m_uri(), **kwargs)
-
- def test_retrieve_layers_info_schema_version_1(self):
- """
- Ensures that retrieve_layers_info() extracts the layers' information
- from manifest with schema version 1 a list with format:
- ["digest", "sum_type", "file_path", "size"].
- """
- kwargs = {
- 'uri': '',
- 'progress': mock.Mock()
- }
-
- manifest = {
- 'schemaVersion': 1,
- 'fsLayers': [
- {'blobSum': 'sha256:75c416ea'},
- {'blobSum': 'sha256:c6ff40b6'},
- {'blobSum': 'sha256:a7050fc1'}
- ]
- }
-
- expected_result = [
- ['sha256', 'a7050fc1', '/images_path/a7050fc1.tar', None],
- ['sha256', 'c6ff40b6', '/images_path/c6ff40b6.tar', None],
- ['sha256', '75c416ea', '/images_path/75c416ea.tar', None]
- ]
-
- src_instance = self._mock_retrieve_layers_info(manifest, kwargs)[0]
- self.assertEqual(src_instance.layers, expected_result)
-
- def test_retrieve_layers_info_schema_version_2(self):
- """
- Ensures that retrieve_layers_info() extracts the layers' information
- from manifest with schema version 2 a list with format:
- ["digest", "sum_type", "file_path", "size"].
- """
- kwargs = {
- 'uri': '',
- 'progress': mock.Mock()
- }
-
- manifest = {
- 'schemaVersion': 2,
- "layers": [
- {"size": 47103294, "digest": "sha256:75c416ea"},
- {"size": 814, "digest": "sha256:c6ff40b6"},
- {"size": 513, "digest": "sha256:a7050fc1"}
- ]
- }
-
- expected_result = [
- ['sha256', '75c416ea', '/images_path/75c416ea.tar', 47103294],
- ['sha256', 'c6ff40b6', '/images_path/c6ff40b6.tar', 814],
- ['sha256', 'a7050fc1', '/images_path/a7050fc1.tar', 513]
- ]
-
- src_instance = self._mock_retrieve_layers_info(manifest, kwargs)[0]
- self.assertEqual(src_instance.layers, expected_result)
-
- def test_retrieve_layers_info_raise_error_on_invalid_schema_version(self):
- """
- Ensures that retrieve_layers_info() calls get_image_details()
- with all passed arguments.
- """
- kwargs = {
- 'uri': '',
- 'progress': mock.Mock()
- }
-
- manifest = {'schemaVersion': 3}
- with self.assertRaises(ValueError):
- self._mock_retrieve_layers_info(manifest, kwargs)
-
- ###################################
- # Tests for: gen_valid_uri()
- ###################################
- def test_gen_valid_uri(self):
- """
- Validates the output of gen_valid_uri() for some test cases.
- """
- m_self = self._mock_docker_source()
- test_values = {
- 'docker:///repo': 'docker://repo',
- 'docker:/repo': 'docker://repo',
- 'docker://repo/': 'docker://repo',
- 'docker://repo/image/': 'docker://repo/image',
- 'docker:///repo/image/': 'docker://repo/image',
- }
- for uri in test_values:
- uri_obj = urlparse(uri)
- result = sources.DockerSource.gen_valid_uri(m_self, uri_obj)
- expected = test_values[uri]
- self.assertEqual(result, expected)
-
- ###################################
- # Tests for: download_image()
- ###################################
- def test_download_image(self):
- """
- Ensures that download_image() calls read_skopeo_progress() with
- expected skopeo copy command and removes tha leftover manifest file.
- """
- m_self = self._mock_docker_source()
- m_self.read_skopeo_progress = mock.Mock()
- manifest_path = "%s/manifest.json" % m_self.images_dir
- with mock.patch('os.remove') as m_remove:
- sources.DockerSource.download_image(m_self)
-
- expected_call = ["skopeo", "copy", m_self.url,
- "dir:" + m_self.images_dir,
- '--src-tls-verify=false',
- '--src-creds={}:{}'.format(m_self.username,
- m_self.password)]
- m_self.read_skopeo_progress.assert_called_once_with(expected_call)
- m_remove.assert_called_once_with(manifest_path)
-
- ###################################
- # Tests for: parse_output()
- ###################################
- def test_parse_output_return_false_on_fail(self):
- """
- Ensures that parse_output() returns False when process call
- exits with non-zero code.
- """
- m_self = mock.Mock(spec=sources.DockerSource)
- m_self.layers = []
- m_proc = mock.Mock()
- m_proc.returncode = 1
- self.assertFalse(sources.DockerSource.parse_output(m_self, m_proc))
-
- def test_parse_output(self):
- """
- Ensures that parse_output() recognises processing of different
- layers from the skopeo's output.
- """
- m_self = self._mock_docker_source()
- m_proc = mock.Mock()
- m_proc.poll.return_value = None
- m_proc.returncode = 0
- test_values = '\n'.join([
- 'Skipping fetch of repeat blob sha256:c6ff40',
- 'Copying blob sha256:75c416ea735c4',
- '40.00 MB / 44.92 MB [======================>------]',
- 'Copying config sha256:d355ed35',
- '40.00 MB / 44.92 MB [======================>------]'
- ])
-
- expected_progress_calls = [
- mock.call("Downloading layer (1/2)"),
- mock.call("Downloading layer (2/2)"),
- ]
-
- with mock.patch('select.select') as m_select:
- m_select.return_value = [[test_values], [], []]
- with mock.patch('virtBootstrap.utils.read_async') as m_read_async:
- m_read_async.return_value = test_values
- self.assertTrue(sources.DockerSource.parse_output(m_self,
- m_proc))
- m_select.assert_called_once_with([m_proc.stdout], [], [])
- m_read_async.assert_called_once_with(test_values)
- m_self.progress.assert_has_calls(expected_progress_calls)
- m_self.update_progress_from_output.assert_called_once()
- m_proc.wait.assert_called_once()
-
- ###################################
- # Tests for: update_progress_from_output()
- ###################################
- def _mock_update_progress_from_output(self, test_values):
- """
- This method is gather common test pattern used in the following
- two test cases.
- """
- m_self = self._mock_docker_source()
- test_method = sources.DockerSource.update_progress_from_output
- for line in test_values:
- test_method(m_self, line.split(), 1, len(test_values))
-
- return m_self.progress.call_args_list
-
- def test_update_progress_from_output(self):
- """
- Ensures that update_progress_from_output() recognises the current
- downloaded size, the total layer's size and calculates correct
- percentage value.
- """
- test_values = [
- '500.00 KB / 4.00 MB [======>------]',
- '25.00 MB / 24.10 MB [======>------]',
- '40.00 MB / 50.00 MB [======>------]',
- ]
- expected_values = [2, 17.33, 13.33]
-
- calls = self._mock_update_progress_from_output(test_values)
- for call, expected in zip(calls, expected_values):
- self.assertAlmostEqual(call[1]['value'], expected, places=1)
-
- def test_update_progress_from_output_ignore_failures(self):
- """
- Ensures that update_progress_from_output() ignores invalid lines
- from skopeo's output.
- """
- test_values = [
- 'a ',
- '1 ' * 5,
- '500.00 MB / 0.00 MB [======>------]',
- '00.00 MB / 00.00 MB [======>------]',
- ]
- self._mock_update_progress_from_output(test_values)
-
- ###################################
- # Tests for: read_skopeo_progress()
- ###################################
- def _mock_read_skopeo_progress(self, test_cmd, parse_output_return):
- """
- This method is gather common test pattern used in the following
- two test cases.
- """
- m_self = mock.Mock(spec=sources.DockerSource)
- m_self.parse_output.return_value = parse_output_return
- with mock.patch.multiple('virtBootstrap.sources.'
- 'docker_source.subprocess',
- Popen=mock.DEFAULT,
- PIPE=mock.DEFAULT) as mocked:
- with mock.patch('virtBootstrap.utils.make_async') as m_make_async:
- sources.DockerSource.read_skopeo_progress(m_self, test_cmd)
-
- return (mocked, m_make_async)
-
- def test_read_skopeo_progress(self):
- """
- Ensures that read_skopeo_progress() calls make_async() with
- the stdout pipe of skopeo's process.
- """
- test_cmd = 'test'
- mocked, m_make_async = self._mock_read_skopeo_progress(test_cmd, True)
-
- mocked['Popen'].assert_called_once_with(test_cmd,
- stdout=mocked['PIPE'],
- stderr=mocked['PIPE'],
- universal_newlines=True)
- m_make_async.assert_called_once_with(mocked['Popen']().stdout)
-
- def test_read_skopeo_progress_raise_error(self):
- """
- Ensures that read_skopeo_progress() raise CalledProcessError
- when parse_output() returns false.
- """
- with self.assertRaises(sources.docker_source
- .subprocess.CalledProcessError):
- self._mock_read_skopeo_progress('test', False)
-
- ###################################
- # Tests for: validate_image_layers()
- ###################################
- def _mock_validate_image_layers(self,
- checksum_return,
- path_exists_return,
- expected_result,
- check_calls=False):
- """
- This method is gather common test pattern used in the following
- three test cases.
- """
- m_self = self._mock_docker_source()
-
- with mock.patch('os.path.exists') as m_path_exists:
- with mock.patch('virtBootstrap.utils.checksum') as m_checksum:
- m_checksum.return_value = checksum_return
- m_path_exists.return_value = path_exists_return
- result = sources.DockerSource.validate_image_layers(m_self)
- self.assertEqual(result, expected_result)
-
- if check_calls:
- path_exists_expected_calls = []
- checksum_expected_calls = []
- # Generate expected calls
- for sum_type, hash_sum, path, _ignore in m_self.layers:
- path_exists_expected_calls.append(mock.call(path))
- checksum_expected_calls.append(
- mock.call(path, sum_type, hash_sum))
-
- m_path_exists.assert_has_calls(path_exists_expected_calls)
- m_checksum.assert_has_calls(checksum_expected_calls)
-
- def test_validate_image_layers_should_return_true(self):
- """
- Ensures that validate_image_layers() returns True when:
- - checksum() returns True for all layers
- - the file path of all layers exist
- - all layers are validated
- """
- self._mock_validate_image_layers(True, True, True, True)
-
- def test_validate_image_layers_return_false_if_path_not_exist(self):
- """
- Ensures that validate_image_layers() returns False when
- checksum() returns False.
- """
- self._mock_validate_image_layers(False, True, False)
-
- def test_validate_image_layers_return_false_if_checksum_fail(self):
- """
- Ensures that validate_image_layers() returns False when
- the file path of layer does not exist.
- """
- self._mock_validate_image_layers(True, False, False)
-
- ###################################
- # Tests for: fetch_layers()
- ###################################
- def _mock_fetch_layers(self, validate_return):
- """
- This method is gather common test pattern used in the following
- two test cases.
- """
- m_self = mock.Mock(spec=sources.DockerSource)
- m_self.validate_image_layers.return_value = validate_return
- sources.DockerSource.fetch_layers(m_self)
- return m_self
-
- def test_fetch_layers_should_call_download_image(self):
- """
- Ensures that fetch_layers() calls download_image()
- when validate_image_layers() returns False.
- """
- m_self = self._mock_fetch_layers(False)
- m_self.download_image.assert_called_once()
-
- def test_fetch_layers_should_not_call_download_image(self):
- """
- Ensures that fetch_layers() does not call download_image()
- when validate_image_layers() returns True.
- """
- m_self = self._mock_fetch_layers(True)
- m_self.download_image.assert_not_called()
-
- ###################################
- # Tests for: unpack()
- ###################################
- def _unpack_test_fmt(self, output_format, patch_method=None,
- side_effect=None, m_self=None):
- """
- This method is gather common test pattern used in the following
- two test cases.
- """
- m_self = m_self if m_self else self._mock_docker_source()
- m_self.output_format = output_format
- dest = 'foo'
-
- if patch_method:
- with mock.patch(patch_method) as mocked:
- if side_effect:
- mocked.side_effect = side_effect
- sources.DockerSource.unpack(m_self, dest)
-
- mocked.assert_called_once_with(m_self.layers, dest,
- m_self.progress)
- else:
- sources.DockerSource.unpack(m_self, dest)
-
- m_self.fetch_layers.assert_called_once()
-
- def test_unpack_dir_format(self):
- """
- Ensures that unpack() calls untar_layers() when the output format
- is set to 'dir'.
- """
- self._unpack_test_fmt('dir', 'virtBootstrap.utils.untar_layers')
-
- def test_unpack_qcow2_format(self):
- """
- Ensures that unpack() calls extract_layers_in_qcow2() when the
- output format is set to 'qcow2'.
- """
- self._unpack_test_fmt('qcow2',
- 'virtBootstrap.utils.extract_layers_in_qcow2')
-
- def unpack_raise_error_test(self,
- output_format,
- patch_method,
- side_effect=None,
- msg=None):
- """
- This method is gather common test pattern used in the following
- four test cases.
- """
- with self.assertRaises(Exception) as err:
- self._unpack_test_fmt(output_format, patch_method,
- side_effect)
- if msg:
- self.assertEqual(msg, str(err.exception))
-
- def test_unpack_raise_error_for_unknown_format(self):
- """
- Ensures that unpack() throws an Exception when called with
- invalid output format.
- """
- msg = 'Unknown format:foo'
- self.unpack_raise_error_test('foo', None, None, msg)
-
- def test_unpack_raise_error_if_untar_fail(self):
- """
- Ensures that unpack() throws an Exception when untar_layers()
- fails.
- """
- msg = 'Caught untar failure'
- side_effect = Exception(msg)
- patch_method = 'virtBootstrap.utils.untar_layers'
- self.unpack_raise_error_test('dir', patch_method, side_effect, msg)
-
- def test_unpack_raise_error_if_extract_in_qcow2_fail(self):
- """
- Ensures that unpack() throws an Exception when
- extract_layers_in_qcow2() fails.
- """
- msg = 'Caught extract_layers_in_qcow2 failure'
- side_effect = Exception(msg)
- patch_method = 'virtBootstrap.utils.extract_layers_in_qcow2'
- self.unpack_raise_error_test('qcow2', patch_method, side_effect, msg)
-
- def test_unpack_no_cache_clean_up(self):
- """
- Ensures that unpack() removes the folder which stores tar archives
- of image layers when no_cache is set to True.
- """
- output_formats = ['dir', 'qcow2']
- patch_methods = [
- 'virtBootstrap.utils.untar_layers',
- 'virtBootstrap.utils.extract_layers_in_qcow2'
- ]
- for fmt, patch_mthd in zip(output_formats, patch_methods):
- m_self = self._mock_docker_source()
- m_self.no_cache = True
- with mock.patch('shutil.rmtree') as m_shutil:
- self._unpack_test_fmt(fmt, patch_mthd, m_self=m_self)
- m_shutil.assert_called_once_with(m_self.images_dir)
-
- def test_unpack_no_cache_clean_up_on_failure(self):
- """
- Ensures that unpack() removes the folder which stores tar archives
- of image layers when no_cache is set to True and exception was
- raised.
- """
- m_self = self._mock_docker_source()
- m_self.no_cache = True
- with self.assertRaises(Exception):
- with mock.patch('shutil.rmtree') as m_rmtree:
- self._unpack_test_fmt('foo', None, m_self=m_self)
- m_rmtree.assert_called_once_with(m_self.images_dir)
diff --git a/tests/test_file_source.py b/tests/test_file_source.py
deleted file mode 100644
index 6e89aa2..0000000
--- a/tests/test_file_source.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
-#
-# Copyright (C) 2017 Radostin Stoyanov
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-"""
-Unit tests for methods defined in virtBootstrap.sources.FileSource
-"""
-
-from tests import unittest
-from tests import mock
-from tests import sources
-
-
-# pylint: disable=invalid-name
-class TestFileSource(unittest.TestCase):
- """
- Test cases for FileSource
- """
-
- ###################################
- # Tests for: __init__()
- ###################################
- def test_argument_assignment(self):
- """
- Ensures that __init__() assigns the arguments' values to instance
- variables.
- """
- kwargs = {'uri': mock.Mock(),
- 'fmt': 'dir',
- 'progress': mock.Mock()}
-
- src_instance = sources.FileSource(**kwargs)
-
- test_values = {
- src_instance.path: kwargs['uri'].path,
- src_instance.output_format: kwargs['fmt'],
- src_instance.progress: kwargs['progress'].update_progress
- }
- for value in test_values:
- self.assertIs(value, test_values[value])
-
- ###################################
- # Tests for: unpack()
- ###################################
- def test_unpack_invalid_source_raise_exception(self):
- """
- Ensures that unpack() throws an Exception when called with
- invalid file source.
- """
- m_self = mock.Mock(spec=sources.FileSource)
- m_self.path = 'foo'
- with mock.patch('os.path.isfile') as m_isfile:
- m_isfile.return_value = False
- with self.assertRaises(Exception) as err:
- sources.FileSource.unpack(m_self, 'bar')
- self.assertIn('Invalid file source', str(err.exception))
-
- def test_unpack_to_dir(self):
- """
- Ensures that unpack() calls safe_untar() when the output format
- is set to 'dir'.
- """
- m_self = mock.Mock(spec=sources.FileSource)
- m_self.progress = mock.Mock()
- m_self.path = 'foo'
- m_self.output_format = 'dir'
- dest = 'bar'
-
- with mock.patch('os.path.isfile') as m_isfile:
- m_isfile.return_value = True
- with mock.patch('virtBootstrap.utils.safe_untar') as m_untar:
- sources.FileSource.unpack(m_self, dest)
-
- m_untar.assert_called_once_with(m_self.path, dest)
-
- def test_unpack_to_qcow2(self):
- """
- Ensures that unpack() calls create_qcow2() when the output
- format is set to 'qcow2'.
- """
- m_self = mock.Mock(spec=sources.FileSource)
- m_self.progress = mock.Mock()
- m_self.path = 'foo'
- m_self.output_format = 'qcow2'
- dest = 'bar'
- qcow2_file_path = 'foobar'
-
- with mock.patch.multiple('os.path',
- isfile=mock.DEFAULT,
- realpath=mock.DEFAULT) as mocked:
-
- mocked['isfile'].return_value = True
- mocked['realpath'].return_value = qcow2_file_path
- with mock.patch('virtBootstrap.utils.create_qcow2') as m_qcow2:
- sources.FileSource.unpack(m_self, dest)
-
- m_qcow2.assert_called_once_with(m_self.path, qcow2_file_path)
-
- def _unpack_raise_error_test(self,
- output_format,
- side_effect=None,
- patch_method=None,
- msg=None):
- """
- This method is gather common test pattern used in the following
- three test cases.
- """
- m_self = mock.Mock(spec=sources.FileSource)
- m_self.progress = mock.Mock()
- m_self.path = 'foo'
- m_self.output_format = output_format
- dest = 'bar'
-
- with mock.patch.multiple('os.path',
- isfile=mock.DEFAULT,
- realpath=mock.DEFAULT) as m_path:
- m_path['isfile'].return_value = True
- with self.assertRaises(Exception) as err:
- if patch_method:
- with mock.patch(patch_method) as mocked_method:
- mocked_method.side_effect = side_effect
- sources.FileSource.unpack(m_self, dest)
- else:
- sources.FileSource.unpack(m_self, dest)
- if msg:
- self.assertEqual(msg, str(err.exception))
-
- def test_unpack_invalid_format_raise_exception(self):
- """
- Ensures that unpack() throws an Exception when called with
- invalid output format.
- """
- self._unpack_raise_error_test('foo', msg='Unknown format:foo')
-
- def test_unpack_raise_error_if_untar_fail(self):
- """
- Ensures that unpack() throws an Exception when safe_untar()
- fails.
- """
- msg = 'Caught untar failure'
- patch_method = 'virtBootstrap.utils.safe_untar'
- self._unpack_raise_error_test(output_format='dir',
- side_effect=Exception(msg),
- patch_method=patch_method,
- msg=msg)
-
- def test_unpack_raise_error_if_extract_in_qcow2_fail(self):
- """
- Ensures that unpack() throws an Exception when create_qcow2()
- fails.
- """
- msg = 'Caught extract_layers_in_qcow2 failure'
- patch_method = 'virtBootstrap.utils.create_qcow2'
- self._unpack_raise_error_test(output_format='qcow2',
- side_effect=Exception(msg),
- patch_method=patch_method,
- msg=msg)
diff --git a/tests/test_progress.py b/tests/test_progress.py
deleted file mode 100644
index 1f609d5..0000000
--- a/tests/test_progress.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
-#
-# Copyright (C) 2017 Radostin Stoyanov
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-"""
-Unit tests for methods defined in virtBootstrap.progress
-"""
-
-from tests import unittest
-from tests import mock
-from tests import progress
-
-
-# pylint: disable=invalid-name
-class TestFileSource(unittest.TestCase):
- """
- Test cases for Progress module
- """
-
- ###################################
- # Tests for: __init__()
- ###################################
- def test_progress_init(self):
- """
- Ensures that __init__() assigns the collback value to instance
- variable and creates dictionary with 'status', 'value' keys.
- """
- callback = mock.Mock()
- test_instance = progress.Progress(callback)
- for key in ['status', 'value']:
- self.assertIn(key, test_instance.progress)
- self.assertIs(callback, test_instance.callback)
-
- ###################################
- # Tests for: get_progress()
- ###################################
- def test_get_progress(self):
- """
- Ensures that get_progress() returns copy of the progress dictionary
- which has the same keys and values.
- """
- test_instance = progress.Progress()
- test_result = test_instance.get_progress()
- self.assertIsNot(test_instance.progress, test_result)
- self.assertDictEqual(test_instance.progress, test_result)
-
- ###################################
- # Tests for: update_progress()
- ###################################
- def test_update_progress_creates_log_record(self):
- """
- Ensures that update_progress() creates log record with info level
- and pass the status value as message.
- """
- test_instance = progress.Progress()
- logger = mock.Mock()
- status = "Test"
- test_instance.update_progress(status=status, logger=logger)
- logger.info.assert_called_once_with(status)
-
- def test_update_progress_update_status_and_value(self):
- """
- Ensures that update_progress() creates log record with info level
- and pass the status value as message.
- """
- test_instance = progress.Progress()
- test_instance.progress = {'status': '', 'value': 0}
- new_status = 'Test'
- new_value = 100
- new_progress = {'status': new_status, 'value': new_value}
- test_instance.update_progress(status=new_status, value=new_value)
- self.assertDictEqual(test_instance.progress, new_progress)
-
- def test_update_progress_update_raise_logger_error(self):
- """
- Ensures that update_progress() raise ValueError when creating
- log record has failed.
- """
- msg = 'test'
- test_instance = progress.Progress()
- logger = mock.Mock()
- logger.info.side_effect = Exception(msg)
- with self.assertRaises(ValueError) as err:
- test_instance.update_progress(logger=logger)
- self.assertIn(msg, str(err.exception))
-
- def test_update_progress_update_raise_callback_error(self):
- """
- Ensures that update_progress() raise ValueError when calling
- callback failed.
- """
- msg = 'test'
- callback = mock.Mock()
- callback.side_effect = Exception(msg)
- test_instance = progress.Progress(callback)
- with self.assertRaises(ValueError) as err:
- test_instance.update_progress('foo', 'bar')
- self.assertIn(msg, str(err.exception))
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 0b6ccc0..c2f55b5 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
#
# Copyright (C) 2017 Radostin Stoyanov
@@ -19,126 +20,16 @@
"""
Unit tests for functions defined in virtBootstrap.utils
"""
-
-from tests import unittest
-from tests import mock
-from tests import utils
-try:
- # pylint: disable=redefined-builtin
- from importlib import reload
-except ImportError:
- pass
+import unittest
+from . import utils
# pylint: disable=invalid-name
-# pylint: disable=too-many-public-methods
class TestUtils(unittest.TestCase):
"""
Ensures that functions defined in the utils module of virtBootstrap
work as expected.
"""
-
- ###################################
- # Tests for: checksum()
- ###################################
- def test_utils_checksum_return_false_on_invalid_hash(self):
- """
- Ensures that checksum() returns False if the actual and expected
- hash sum of file are not equal.
- """
- with mock.patch.multiple(utils,
- open=mock.DEFAULT,
- logger=mock.DEFAULT,
- hashlib=mock.DEFAULT) as mocked:
- path, sum_type, sum_expected = '/foo', 'sha256', 'bar'
- mocked['hashlib'].sha256.hexdigest.return_value = False
- self.assertFalse(utils.checksum(path, sum_type, sum_expected))
-
- def test_utils_checksum_return_false_if_file_could_not_be_opened(self):
- """
- Ensures that checksum() returns False if the file to be checked
- cannot be open for read.
- """
- with mock.patch.multiple(utils,
- open=mock.DEFAULT,
- logger=mock.DEFAULT,
- hashlib=mock.DEFAULT) as mocked:
- mocked['open'].side_effect = IOError()
- self.assertFalse(utils.checksum('foo', 'sha256', 'bar'))
-
- def test_utils_checksum_return_true_on_valid_hash(self):
- """
- Ensures that checksum() returns True when the actual and expected
- hash sum of file are equal.
- """
- with mock.patch.multiple(utils,
- open=mock.DEFAULT,
- logger=mock.DEFAULT,
- hashlib=mock.DEFAULT) as mocked:
- path, sum_type, sum_expected = '/foo', 'sha256', 'bar'
- mocked['hashlib'].sha256.return_value.hexdigest.return_value \
- = sum_expected
- self.assertTrue(utils.checksum(path, sum_type, sum_expected))
-
- ###################################
- # Tests for: execute()
- ###################################
- def test_utils_execute_logging_on_successful_proc_call(self):
- """
- Ensures that execute() creates log record of cmd, stdout and stderr
- when the exit code of process is 0.
- """
- with mock.patch.multiple(utils,
- logger=mock.DEFAULT,
- subprocess=mock.DEFAULT) as mocked:
- cmd = ['foo']
- output, err = 'test_out', 'test_err'
-
- mocked['subprocess'].Popen.return_value.returncode = 0
- (mocked['subprocess'].Popen.return_value
- .communicate.return_value) = (output.encode(), err.encode())
-
- utils.execute(cmd)
- mocked['logger'].debug.assert_any_call("Call command:\n%s", cmd[0])
- mocked['logger'].debug.assert_any_call("Stdout:\n%s", output)
- mocked['logger'].debug.assert_any_call("Stderr:\n%s", err)
-
- def test_utils_execute_raise_error_on_unsuccessful_proc_call(self):
- """
- Ensures that execute() raise CalledProcessError exception when the
- exit code of process is not 0.
- """
- with mock.patch('virtBootstrap.utils.subprocess.Popen') as m_popen:
- m_popen.return_value.returncode = 1
- m_popen.return_value.communicate.return_value = (b'output', b'err')
- with self.assertRaises(utils.subprocess.CalledProcessError):
- utils.execute(['foo'])
-
- ###################################
- # Tests for: safe_untar()
- ###################################
- def test_utils_safe_untar_calls_execute(self):
- """
- Ensures that safe_untar() calls execute with virt-sandbox
- command to extract source files to destination folder.
- Test for users with EUID 0 and 1000.
- """
- with mock.patch('virtBootstrap.utils.os.geteuid') as m_geteuid:
- for uid in [0, 1000]:
- m_geteuid.return_value = uid
- reload(utils)
- with mock.patch('virtBootstrap.utils.execute') as m_execute:
- src, dest = 'foo', 'bar'
- utils.safe_untar('foo', 'bar')
- cmd = ['virt-sandbox',
- '-c', utils.LIBVIRT_CONN,
- '-m', 'host-bind:/mnt=' + dest,
- '--',
- '/bin/tar', 'xf', src,
- '-C', '/mnt',
- '--exclude', 'dev/*']
- m_execute.assert_called_once_with(cmd)
-
###################################
# Tests for: bytes_to_size()
###################################
@@ -172,241 +63,6 @@ class TestUtils(unittest.TestCase):
i += 1
###################################
- # Tests for: log_layer_extract()
- ###################################
- def test_utils_log_layer_extract(self):
- """
- Ensures that log_layer_extract() updates the progress and creates
- log record with debug level.
- """
- m_progress = mock.Mock()
- layer = ['sum_type', 'sum_value', 'layer_file', 'layer_size']
- with mock.patch.multiple(utils, logger=mock.DEFAULT,
- bytes_to_size=mock.DEFAULT) as mocked:
- utils.log_layer_extract(layer, 'foo', 'bar', m_progress)
- mocked['bytes_to_size'].assert_called_once_with('layer_size')
- mocked['logger'].debug.assert_called_once()
- m_progress.assert_called_once()
-
- ###################################
- # Tests for: get_mime_type()
- ###################################
- @mock.patch('virtBootstrap.utils.subprocess.Popen')
- def test_utils_get_mime_type(self, m_popen):
- """
- Ensures that get_mime_type() returns the detected MIME type
- of /usr/bin/file.
- """
- path = "foo"
- mime = "application/x-gzip"
- stdout = ('%s: %s' % (path, mime)).encode()
- m_popen.return_value.stdout.read.return_value = stdout
- self.assertEqual(utils.get_mime_type(path), mime)
- m_popen.assert_called_once_with(
- ["/usr/bin/file", "--mime-type", path],
- stdout=utils.subprocess.PIPE
- )
-
- ###################################
- # Tests for: untar_layers()
- ###################################
- def test_utils_untar_all_layers_in_order(self):
- """
- Ensures that untar_layers() iterates through all passed layers
- in order.
- """
- layers = ['l1', 'l2', 'l3']
- layers_list = [['', '', layer] for layer in layers]
- dest_dir = '/foo'
- expected_calls = [mock.call(layer, dest_dir) for layer in layers]
- with mock.patch.multiple(utils,
- safe_untar=mock.DEFAULT,
- log_layer_extract=mock.DEFAULT) as mocked:
- utils.untar_layers(layers_list, dest_dir, mock.Mock())
- mocked['safe_untar'].assert_has_calls(expected_calls)
-
- ###################################
- # Tests for: create_qcow2()
- ###################################
- def _apply_test_to_create_qcow2(self, expected_calls, *args):
- """
- This method contains common test pattern used in the next two
- test cases.
- """
- with mock.patch.multiple(utils,
- execute=mock.DEFAULT,
- logger=mock.DEFAULT,
- get_mime_type=mock.DEFAULT) as mocked:
- mocked['get_mime_type'].return_value = 'application/x-gzip'
- utils.create_qcow2(*args)
- mocked['execute'].assert_has_calls(expected_calls)
-
- def test_utils_create_qcow2_base_layer(self):
- """
- Ensures that create_qcow2() creates base layer when
- backing_file = None.
- """
- tar_file = 'foo'
- layer_file = 'bar'
- size = '5G'
- backing_file = None
-
- expected_calls = [
- mock.call(["qemu-img", "create", "-f", "qcow2", layer_file, size]),
-
- mock.call(['virt-format',
- '--format=qcow2',
- '--partition=none',
- '--filesystem=ext3',
- '-a', layer_file]),
-
- mock.call(['guestfish',
- '-a', layer_file,
- '-m', '/dev/sda',
- 'tar-in', tar_file, '/', 'compress:gzip'])
- ]
-
- self._apply_test_to_create_qcow2(expected_calls, tar_file, layer_file,
- backing_file, size)
-
- def test_utils_create_qcow2_layer_with_backing_chain(self):
- """
- Ensures that create_qcow2() creates new layer with backing chains
- when backing_file is specified.
- """
- tar_file = 'foo'
- layer_file = 'bar'
- backing_file = 'base'
- size = '5G'
-
- expected_calls = [
- mock.call(['qemu-img', 'create',
- '-b', backing_file,
- '-f', 'qcow2',
- layer_file, size]),
-
- mock.call(['guestfish',
- '-a', layer_file,
- '-m', '/dev/sda',
- 'tar-in', tar_file, '/', 'compress:gzip'])
- ]
-
- self._apply_test_to_create_qcow2(expected_calls, tar_file, layer_file,
- backing_file, size)
-
- ###################################
- # Tests for: extract_layers_in_qcow2()
- ###################################
- def test_utils_if_all_layers_extracted_in_order_in_qcow2(self):
- """
- Ensures that extract_layers_in_qcow2() iterates through all
- layers in order.
- """
- layers = ['l1', 'l2', 'l3']
- layers_list = [['', '', layer] for layer in layers]
- dest_dir = '/foo'
-
- # Generate expected calls
- expected_calls = []
- qcow2_backing_file = None
- for index, layer in enumerate(layers):
- qcow2_layer_file = dest_dir + "/layer-%s.qcow2" % index
- expected_calls.append(
- mock.call(layer, qcow2_layer_file, qcow2_backing_file))
- qcow2_backing_file = qcow2_layer_file
-
- # Mocking out and execute
- with mock.patch.multiple(utils,
- create_qcow2=mock.DEFAULT,
- log_layer_extract=mock.DEFAULT) as mocked:
- utils.extract_layers_in_qcow2(layers_list, dest_dir, mock.Mock())
-
- # Check actual calls
- mocked['create_qcow2'].assert_has_calls(expected_calls)
-
- ###################################
- # Tests for: get_image_dir()
- ###################################
- def test_utils_getimage_dir(self):
- """
- Ensures that get_image_dir() returns path to DEFAULT_IMG_DIR
- if the no_cache argument is set to False and create it if
- does not exist.
- """
- # Perform this test for UID 0 and 1000
- for uid in [0, 1000]:
- with mock.patch('os.geteuid') as m_geteuid:
- m_geteuid.return_value = uid
- reload(utils)
- with mock.patch('os.makedirs') as m_makedirs:
- with mock.patch('os.path.exists') as m_path_exists:
- m_path_exists.return_value = False
- self.assertEqual(utils.get_image_dir(False),
- utils.DEFAULT_IMG_DIR)
- m_makedirs.assert_called_once_with(utils.DEFAULT_IMG_DIR)
-
- @mock.patch('tempfile.mkdtemp')
- def test_utils_getimage_dir_no_cache(self, m_mkdtemp):
- """
- Ensures that get_image_dir() returns temporary file path created
- by tempfile.mkdtemp.
- """
- m_mkdtemp.return_value = 'foo'
- self.assertEqual(utils.get_image_dir(True), 'foo')
- m_mkdtemp.assert_called_once()
-
- ###################################
- # Tests for: get_image_details()
- ###################################
- @mock.patch('virtBootstrap.utils.subprocess.Popen')
- def test_utils_get_image_details_raise_error_on_fail(self, m_popen):
- """
- Ensures that get_image_details() throws ValueError exception
- when stderr from skopeo is provided.
- """
- src = 'docker://foo'
- m_popen.return_value.communicate.return_value = [b'', b'Error']
- with self.assertRaises(ValueError):
- utils.get_image_details(src)
-
- @mock.patch('virtBootstrap.utils.subprocess.Popen')
- def test_utils_get_image_details_return_json_obj_on_success(self, m_popen):
- """
- Ensures that get_image_details() returns python dictionary which
- represents the data provided from stdout of skopeo when stderr
- is not present.
- """
- src = 'docker://foo'
- json_dict = {'foo': 'bar'}
- stdout = utils.json.dumps(json_dict).encode()
- m_popen.return_value.communicate.return_value = [stdout, '']
- self.assertDictEqual(utils.get_image_details(src), json_dict)
-
- def test_utils_get_image_details_all_argument_passed(self):
- """
- Ensures that get_image_details() pass all argument values to
- skopeo inspect.
- """
- src = 'docker://foo'
- raw, insecure = True, True
- username, password = 'user', 'password'
- cmd = ['skopeo', 'inspect', src,
- '--raw',
- '--tls-verify=false',
- "--creds=%s:%s" % (username, password)]
-
- with mock.patch.multiple(utils.subprocess,
- Popen=mock.DEFAULT,
- PIPE=mock.DEFAULT) as mocked:
- mocked['Popen'].return_value.communicate.return_value = [b'{}',
- b'']
- utils.get_image_details(src, raw, insecure, username, password)
-
- mocked['Popen'].assert_called_once_with(cmd,
- stdout=mocked['PIPE'],
- stderr=mocked['PIPE'])
-
- ###################################
# Tests for: is_new_layer_message()
###################################
def test_utils_is_new_layer_message(self):
@@ -459,10 +115,11 @@ class TestUtils(unittest.TestCase):
Ensures that make_async() sets O_NONBLOCK flag on PIPE.
"""
- pipe = utils.subprocess.Popen(
+ proc = utils.subprocess.Popen(
["echo"],
stdout=utils.subprocess.PIPE
- ).stdout
+ )
+ pipe = proc.stdout
fd = pipe.fileno()
F_GETFL = utils.fcntl.F_GETFL
@@ -471,36 +128,8 @@ class TestUtils(unittest.TestCase):
self.assertFalse(utils.fcntl.fcntl(fd, F_GETFL) & O_NONBLOCK)
utils.make_async(fd)
self.assertTrue(utils.fcntl.fcntl(fd, F_GETFL) & O_NONBLOCK)
-
- ###################################
- # Tests for: read_async()
- ###################################
- def test_utils_read_async_successful_read(self):
- """
- Ensures that read_async() calls read() of passed file descriptor.
- """
- m_fd = mock.MagicMock()
- utils.read_async(m_fd)
- m_fd.read.assert_called_once()
-
- def test_utils_read_async_return_empty_str_on_EAGAIN_error(self):
- """
- Ensures that read_async() ignores EAGAIN errors and returns
- empty string.
- """
- m_fd = mock.MagicMock()
- m_fd.read.side_effect = IOError(utils.errno.EAGAIN, '')
- self.assertEqual(utils.read_async(m_fd), '')
-
- def test_utils_read_async_raise_errors(self):
- """
- Ensures that read_async() does not ignore IOError which is different
- than EAGAIN and throws an exception.
- """
- m_fd = mock.MagicMock()
- m_fd.read.side_effect = IOError()
- with self.assertRaises(IOError):
- utils.read_async(m_fd)
+ proc.wait()
+ pipe.close()
###################################
# Tests for: str2float()
@@ -512,196 +141,3 @@ class TestUtils(unittest.TestCase):
test_values = {'1': 1.0, 'test': None, '0': 0.0, '1.25': 1.25}
for test in test_values:
self.assertEqual(utils.str2float(test), test_values[test])
-
- ###################################
- # Tests for: set_root_password_in_rootfs()
- ###################################
- def test_utils_set_root_password_in_rootfs_restore_permissions(self):
- """
- Ensures that set_root_password_in_rootfs() restore shadow
- file permissions after edit.
- """
- permissions = 700
- rootfs_path = '/foo'
- shadow_file = '%s/etc/shadow' % rootfs_path
-
- m_open = mock.mock_open(read_data='')
- with mock.patch('virtBootstrap.utils.open', m_open, create=True):
- with mock.patch('virtBootstrap.utils.os') as m_os:
- m_os.stat.return_value = [permissions]
- m_os.path.join.return_value = shadow_file
- utils.set_root_password_in_rootfs(rootfs_path, 'password')
-
- expected_calls = [
- mock.call.path.join(rootfs_path, 'etc/shadow'),
- mock.call.stat(shadow_file),
- mock.call.chmod(shadow_file, 438),
- mock.call.chmod(shadow_file, permissions)
- ]
- m_os.assert_has_calls(expected_calls)
-
- def test_utils_set_root_password_in_rootfs_restore_permissions_fail(self):
- """
- Ensures that set_root_password_in_rootfs() restore shadow file
- permissions in case of failure.
- """
- permissions = 700
- rootfs_path = '/foo'
- shadow_file = '%s/etc/shadow' % rootfs_path
-
- m_open = mock.mock_open(read_data='')
- with mock.patch('virtBootstrap.utils.open', m_open, create=True):
- with mock.patch('virtBootstrap.utils.os') as m_os:
- m_os.stat.return_value = [permissions]
- m_os.path.join.return_value = shadow_file
-
- with self.assertRaises(Exception):
- m_open.side_effect = Exception
- utils.set_root_password_in_rootfs(rootfs_path, 'password')
-
- expected_calls = [
- mock.call.path.join(rootfs_path, 'etc/shadow'),
- mock.call.stat(shadow_file),
- mock.call.chmod(shadow_file, 438),
- mock.call.chmod(shadow_file, permissions)
- ]
- m_os.assert_has_calls(expected_calls)
-
- def test_utils_set_root_password_in_rootfs_store_hash(self):
- """
- Ensures that set_root_password_in_rootfs() stores the hashed
- root password in shadow file.
- """
- rootfs_path = '/foo'
- password = 'secret'
- initial_value = '!locked'
- hashed_password = 'hashed_password'
- shadow_content = '\n'.join([
- "root:%s::0:99999:7:::",
- "bin:*:17004:0:99999:7:::"
- "daemon:*:17004:0:99999:7:::",
- "adm:*:17004:0:99999:7:::"
- ])
-
- m_open = mock.mock_open(read_data=shadow_content % initial_value)
- with mock.patch('virtBootstrap.utils.open', m_open, create=True):
- with mock.patch('virtBootstrap.utils.os'):
- with mock.patch('passlib.hosts.linux_context.hash') as m_hash:
- m_hash.return_value = hashed_password
- utils.set_root_password_in_rootfs(rootfs_path, password)
-
- m_hash.assert_called_once_with(password)
- m_open().write.assert_called_once_with(shadow_content
- % hashed_password)
-
- ###################################
- # Tests for: set_root_password_in_image()
- ###################################
- @mock.patch('virtBootstrap.utils.execute')
- def test_utils_set_root_password_in_image(self, m_execute):
- """
- Ensures that set_root_password_in_image() calls virt-edit
- with correct arguments.
- """
- image, password = 'foo', 'password'
- password_hash = ('$6$rounds=656000$PaQ/H4c/k8Ix9YOM$'
- 'cyD47r9PtAE2LhnkpdbVzsiQbM0/h2S/1Bv'
- 'u/sXqUtCg.3Ijp7TQy/8tEVstxMy5k5v4mh'
- 'CGFqnVv7S6wd.Ah/')
-
- expected_call = [
- 'virt-edit',
- '-a', image, '/etc/shadow',
- '-e', 's,^root:.*?:,root:%s:,' % utils.re.escape(password_hash)]
-
- hash_function = 'virtBootstrap.utils.passlib.hosts.linux_context.hash'
- with mock.patch(hash_function) as m_hash:
- m_hash.return_value = password_hash
- utils.set_root_password_in_image(image, password)
-
- m_execute.assert_called_once_with(expected_call)
-
- ###################################
- # Tests for: set_root_password()
- ###################################
- @mock.patch('virtBootstrap.utils.set_root_password_in_rootfs')
- def test_utils_set_root_password_dir(self, m_set_root_password_in_rootfs):
- """
- Ensures that set_root_password() calls set_root_password_in_rootfs()
- when the format is set to "dir".
- """
- fmt, dest, root_password = 'dir', 'dest', 'root_password'
- utils.set_root_password(fmt, dest, root_password)
-
- m_set_root_password_in_rootfs.assert_called_once_with(
- dest, root_password
- )
-
- @mock.patch('virtBootstrap.utils.set_root_password_in_image')
- def test_utils_set_root_password_qcow2(self, m_set_root_password_in_image):
- """
- Ensures that set_root_password() calls set_root_password_in_image()
- when the format is set to "qcow2" with the path to the last
- extracted layer.
- """
- fmt, dest, root_password = 'qcow2', 'dest', 'root_password'
- layers = ['layer-0.qcow2', 'layer-1.qcow2']
-
- with mock.patch('os.listdir') as m_listdir:
- m_listdir.return_value = layers
- utils.set_root_password(fmt, dest, root_password)
-
- m_set_root_password_in_image.assert_called_once_with(
- utils.os.path.join(dest, max(layers)),
- root_password
- )
-
- ###################################
- # Tests for: write_progress()
- ###################################
- def test_utils_write_progress_fill_terminal_width(self):
- """
- Ensures that write_progress() outputs a message with length
- equal to terminal width and last symbol '\r'.
- """
- terminal_width = 120
- prog = {'status': 'status', 'value': 0}
- with mock.patch.multiple(utils,
- subprocess=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
-
- (mocked['subprocess'].Popen.return_value.stdout
- .read.return_value) = ("20 %s" % terminal_width).encode()
-
- utils.write_progress(prog)
-
- mocked['subprocess'].Popen.assert_called_once_with(
- ["stty", "size"],
- stdout=mocked['subprocess'].PIPE
- )
- output_message = mocked['sys'].stdout.write.call_args[0][0]
- mocked['sys'].stdout.write.assert_called_once()
- self.assertEqual(len(output_message), terminal_width + 1)
- self.assertEqual(output_message[-1], '\r')
-
- def test_utils_write_progress_use_default_term_width_on_failure(self):
- """
- Ensures that write_progress() outputs a message with length equal
- to default terminal width (80) when the detecting terminal width
- has failed.
- """
- default_terminal_width = 80
- prog = {'status': 'status', 'value': 0}
- with mock.patch.multiple(utils,
- subprocess=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['subprocess'].Popen.side_effect = Exception()
- utils.write_progress(prog)
-
- self.assertEqual(len(mocked['sys'].stdout.write.call_args[0][0]),
- default_terminal_width + 1)
- mocked['sys'].stdout.write.assert_called_once()
-
-
-if __name__ == '__main__':
- unittest.main(exit=False)
diff --git a/tests/test_virt_bootstrap.py b/tests/test_virt_bootstrap.py
deleted file mode 100644
index ff744f7..0000000
--- a/tests/test_virt_bootstrap.py
+++ /dev/null
@@ -1,464 +0,0 @@
-# Authors: Radostin Stoyanov <rstoyanov1@gmail.com>
-#
-# Copyright (C) 2017 Radostin Stoyanov
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-"""
-Unit tests for functions defined in virtBootstrap.virt-bootstrap
-"""
-
-from tests import unittest
-from tests import mock
-from tests import virt_bootstrap
-from tests import sources
-
-
-# pylint: disable=invalid-name
-class TestVirtBootstrap(unittest.TestCase):
- """
- Test cases for virt_bootstrap module
- """
-
- ###################################
- # Tests for: get_source(source_type)
- ###################################
- def test_get_invaid_source_type_should_fail(self):
- """
- Ensures that get_source() throws an Exception when invalid source
- name was specified.
- """
- with self.assertRaises(Exception) as source:
- virt_bootstrap.get_source('invalid')
- self.assertIn('invalid', str(source.exception))
-
- def test_get_docker_source(self):
- """
- Ensures that get_source() returns DockerSource when source name
- "docker" is requested.
- """
- self.assertIs(virt_bootstrap.get_source('docker'),
- sources.DockerSource)
-
- def test_get_file_source(self):
- """
- Ensures that get_source() returns FileSource when source name
- "file" is requested.
- """
- self.assertIs(virt_bootstrap.get_source('file'),
- sources.FileSource)
-
- ###################################
- # Tests for: mapping_uid_gid()
- ###################################
- def test_mapping_uid_gid(self):
- """
- Ensures that mapping_uid_gid() calls map_id() with
- correct parameters.
- """
- dest = '/path'
- calls = [
- { # Call 1
- 'dest': dest,
- 'uid': [[0, 1000, 10]],
- 'gid': [[0, 1000, 10]]
- },
- { # Call 2
- 'dest': dest,
- 'uid': [],
- 'gid': [[0, 1000, 10]]
- },
- { # Call 3
- 'dest': dest,
- 'uid': [[0, 1000, 10]],
- 'gid': []
- },
- { # Call 4
- 'dest': dest,
- 'uid': [[0, 1000, 10], [500, 500, 10]],
- 'gid': [[0, 1000, 10]]
- }
- ]
-
- expected_calls = [
- # Expected from call 1
- mock.call(dest, [0, 1000, 10], [0, 1000, 10]),
- # Expected from call 2
- mock.call(dest, None, [0, 1000, 10]),
- # Expected from call 3
- mock.call(dest, [0, 1000, 10], None),
- # Expected from call 4
- mock.call(dest, [0, 1000, 10], [0, 1000, 10]),
- mock.call(dest, [500, 500, 10], None)
-
- ]
- with mock.patch('virtBootstrap.virt_bootstrap.map_id') as m_map_id:
- for args in calls:
- virt_bootstrap.mapping_uid_gid(args['dest'],
- args['uid'],
- args['gid'])
-
- m_map_id.assert_has_calls(expected_calls)
-
- ###################################
- # Tests for: map_id()
- ###################################
- @mock.patch('os.path.realpath')
- def test_map_id(self, m_realpath):
- """
- Ensures that the UID/GID mapping applies to all files
- and directories in root file system.
- """
- root_path = '/root'
- files = ['foo1', 'foo2']
- m_realpath.return_value = root_path
-
- map_uid = [0, 1000, 10]
- map_gid = [0, 1000, 10]
- new_id = 'new_id'
-
- expected_calls = [
- mock.call('/root', new_id, new_id),
- mock.call('/root/foo1', new_id, new_id),
- mock.call('/root/foo2', new_id, new_id)
- ]
-
- with mock.patch.multiple('os',
- lchown=mock.DEFAULT,
- lstat=mock.DEFAULT,
- walk=mock.DEFAULT) as mocked:
-
- mocked['walk'].return_value = [(root_path, [], files)]
- mocked['lstat']().st_uid = map_uid[0]
- mocked['lstat']().st_gid = map_gid[0]
-
- get_map_id = 'virtBootstrap.virt_bootstrap.get_map_id'
- with mock.patch(get_map_id) as m_get_map_id:
- m_get_map_id.return_value = new_id
- virt_bootstrap.map_id(root_path, map_uid, map_gid)
-
- mocked['lchown'].assert_has_calls(expected_calls)
-
- ###################################
- # Tests for: get_mapping_opts()
- ###################################
- def test_get_mapping_opts(self):
- """
- Ensures that get_mapping_opts() returns correct options for
- mapping value.
- """
- test_values = [
- {
- 'mapping': [0, 1000, 10],
- 'expected_result': {'first': 0, 'last': 10, 'offset': 1000},
- },
- {
- 'mapping': [0, 1000, 10],
- 'expected_result': {'first': 0, 'last': 10, 'offset': 1000},
- },
- {
- 'mapping': [500, 1500, 1],
- 'expected_result': {'first': 500, 'last': 501, 'offset': 1000},
- },
- {
- 'mapping': [-1, -1, -1],
- 'expected_result': {'first': 0, 'last': 1, 'offset': 0},
- }
- ]
-
- for test in test_values:
- res = virt_bootstrap.get_mapping_opts(test['mapping'])
- self.assertEqual(test['expected_result'], res)
-
- ###################################
- # Tests for: get_map_id()
- ###################################
- def test_get_map_id(self):
- """
- Ensures that get_map_id() returns correct UID/GID mapping value.
- """
- test_values = [
- {
- 'old_id': 0,
- 'mapping': [0, 1000, 10],
- 'expected_result': 1000
- },
- {
- 'old_id': 5,
- 'mapping': [0, 500, 10],
- 'expected_result': 505
- },
- {
- 'old_id': 10,
- 'mapping': [0, 100, 10],
- 'expected_result': -1
- },
- ]
- for test in test_values:
- opts = virt_bootstrap.get_mapping_opts(test['mapping'])
- res = virt_bootstrap.get_map_id(test['old_id'], opts)
- self.assertEqual(test['expected_result'], res)
-
- ###################################
- # Tests for: parse_idmap()
- ###################################
- def test_parse_idmap(self):
- """
- Ensures that parse_idmap() returns correct UID/GID mapping value.
- """
- test_values = [
- {
- 'mapping': ['0:1000:10', '0:100:10'],
- 'expected_result': [[0, 1000, 10], [0, 100, 10]],
- },
- {
- 'mapping': ['0:1000:10'],
- 'expected_result': [[0, 1000, 10]],
- },
- {
- 'mapping': ['500:1500:1'],
- 'expected_result': [[500, 1500, 1]],
- },
- {
- 'mapping': ['-1:-1:-1'],
- 'expected_result': [[-1, -1, -1]],
- },
- {
- 'mapping': [],
- 'expected_result': None,
- }
- ]
- for test in test_values:
- res = virt_bootstrap.parse_idmap(test['mapping'])
- self.assertEqual(test['expected_result'], res)
-
- def test_parse_idmap_raise_exception_on_invalid_mapping_value(self):
- """
- Ensures that parse_idmap() raise ValueError on mapping value.
- """
- with self.assertRaises(ValueError):
- virt_bootstrap.parse_idmap(['invalid'])
-
- ###################################
- # Tests for: bootstrap()
- ###################################
- def test_bootsrap_creates_directory_if_does_not_exist(self):
- """
- Ensures that bootstrap() creates destination directory if
- it does not exists.
- """
- src, dest = 'foo', 'bar'
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = False
- virt_bootstrap.bootstrap(src, dest)
- mocked['os'].path.exists.assert_called_once_with(dest)
- mocked['os'].makedirs.assert_called_once_with(dest)
-
- def test_bootstrap_exit_if_dest_is_invalid(self):
- """
- Ensures that bootstrap() exits with code 1 when the destination
- path exists but it is not directory.
- """
- src, dest = 'foo', 'bar'
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- logger=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = True
- mocked['os'].path.isdir.return_value = False
- virt_bootstrap.bootstrap(src, dest)
- mocked['os'].path.isdir.assert_called_once_with(dest)
- mocked['sys'].exit.assert_called_once_with(1)
-
- def test_bootsrap_exit_if_no_write_access_on_dest(self):
- """
- Ensures that bootstrap() exits with code 1 when the current user
- has not write permissions on the destination folder.
- """
- src, dest = 'foo', 'bar'
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- logger=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = True
- mocked['os'].path.isdir.return_value = True
- mocked['os'].access.return_value = False
- virt_bootstrap.bootstrap(src, dest)
- mocked['os'].access.assert_called_once_with(dest,
- mocked['os'].W_OK)
- mocked['sys'].exit.assert_called_once_with(1)
-
- def test_bootstrap_use_file_source_if_none_was_specified(self):
- """
- Ensures that bootstrap() calls get_source() with argument
- 'file' when source format is not specified.
- """
- src, dest = 'foo', 'bar'
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- virt_bootstrap.bootstrap(src, dest)
- mocked['get_source'].assert_called_once_with('file')
-
- def test_bootstrap_successful_call(self):
- """
- Ensures that bootstrap() creates source instance and calls the
- unpack method with destination path as argument.
- """
- src, dest = 'foo', 'bar'
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = True
- mocked['os'].path.isdir.return_value = True
- mocked['os'].access.return_value = True
- mocked_source = mock.Mock()
- mocked_unpack = mock.Mock()
- mocked_source.return_value.unpack = mocked_unpack
- mocked['get_source'].return_value = mocked_source
- virt_bootstrap.bootstrap(src, dest)
- # sys.exit should not be called
- mocked['sys'].exit.assert_not_called()
- mocked_source.assert_called_once()
- mocked_unpack.assert_called_once_with(dest)
-
- def test_bootstrap_all_params_are_passed_to_source_instance(self):
- """
- Ensures that bootstrap() is passing all arguments to newly created
- source instance.
- """
- params_list = ['dest', 'fmt', 'username', 'password', 'root_password',
- 'not_secure', 'no_cache', 'progress_cb']
- params = {param: param for param in params_list}
-
- for kw_param in params_list:
- params[kw_param] = kw_param
-
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- urlparse=mock.DEFAULT,
- progress=mock.DEFAULT,
- utils=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = True
- mocked['os'].path.isdir.return_value = True
- mocked['os'].access.return_value = True
-
- mocked['progress'].Progress.return_value = params['progress_cb']
-
- mocked_source = mock.Mock()
- mocked_unpack = mock.Mock()
- mocked_source.return_value.unpack = mocked_unpack
- mocked['get_source'].return_value = mocked_source
-
- mocked_uri = mock.Mock()
- mocked['urlparse'].return_value = mocked_uri
- params['uri'] = mocked_uri
-
- virt_bootstrap.bootstrap(**params)
- # sys.exit should not be called
- mocked['sys'].exit.assert_not_called()
-
- mocked_source.assert_called_once()
- mocked_unpack.assert_called_once_with(params['dest'])
-
- called_with_args, called_with_kwargs = mocked_source.call_args
- self.assertEqual(called_with_args, ())
-
- del params['dest']
- del params['root_password']
- params['progress'] = params.pop('progress_cb')
- for kwarg in params:
- self.assertEqual(called_with_kwargs[kwarg], params[kwarg])
-
- def test_if_bootstrap_calls_set_root_password(self):
- """
- Ensures that bootstrap() calls set_root_password() when the argument
- root_password is specified.
- """
- src, fmt, dest, root_password = 'foo', 'fmt', 'bar', 'root_password'
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- utils=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = True
- mocked['os'].path.isdir.return_value = True
- mocked['os'].access.return_value = True
-
- virt_bootstrap.bootstrap(src, dest,
- fmt=fmt,
- root_password=root_password)
-
- mocked['utils'].set_root_password.assert_called_once_with(
- fmt, dest, root_password)
-
- def test_if_bootstrap_calls_set_mapping_uid_gid(self):
- """
- Ensures that bootstrap() calls mapping_uid_gid() when the argument
- uid_map or gid_map is specified.
- """
- src, dest, uid_map, gid_map = 'foo', 'bar', 'id', 'id'
- expected_calls = [
- mock.call('bar', None, 'id'),
- mock.call('bar', 'id', None),
- mock.call('bar', 'id', 'id')
- ]
-
- with mock.patch.multiple(virt_bootstrap,
- get_source=mock.DEFAULT,
- os=mock.DEFAULT,
- mapping_uid_gid=mock.DEFAULT,
- utils=mock.DEFAULT,
- sys=mock.DEFAULT) as mocked:
- mocked['os'].path.exists.return_value = True
- mocked['os'].path.isdir.return_value = True
- mocked['os'].access.return_value = True
-
- virt_bootstrap.bootstrap(src, dest, gid_map=gid_map)
- virt_bootstrap.bootstrap(src, dest, uid_map=uid_map)
- virt_bootstrap.bootstrap(src, dest,
- uid_map=uid_map, gid_map=gid_map)
- mocked['mapping_uid_gid'].assert_has_calls(expected_calls)
-
- ###################################
- # Tests for: set_logging_conf()
- ###################################
- def test_if_logging_level_format_handler_are_set(self):
- """
- Ensures that set_logging_conf() sets log level and adds new stream
- handler with formatting.
- """
- with mock.patch('virtBootstrap.virt_bootstrap.logging') as m_logging:
- mocked_stream_hdlr = mock.Mock()
- m_logger = mock.Mock()
- m_logging.getLogger.return_value = m_logger
- m_logging.StreamHandler.return_value = mocked_stream_hdlr
- virt_bootstrap.set_logging_conf()
- m_logging.getLogger.assert_called_once_with('virtBootstrap')
- mocked_stream_hdlr.setFormatter.assert_called_once()
- m_logger.addHandler.assert_called_once_with(mocked_stream_hdlr)
- m_logger.setLevel.assert_called_once()
-
-
-if __name__ == '__main__':
- unittest.main(exit=False)