summaryrefslogtreecommitdiffstats
path: root/dovetail/tests
diff options
context:
space:
mode:
Diffstat (limited to 'dovetail/tests')
-rw-r--r--dovetail/tests/unit/cli/__init__.py0
-rw-r--r--dovetail/tests/unit/cli/commands/__init__.py0
-rw-r--r--dovetail/tests/unit/cli/commands/test_cli_testcase.py228
-rw-r--r--dovetail/tests/unit/cli/test_cli_base.py55
-rw-r--r--dovetail/tests/unit/cmd_config.yml41
-rw-r--r--dovetail/tests/unit/test_container.py489
-rw-r--r--dovetail/tests/unit/test_parser.py45
-rw-r--r--dovetail/tests/unit/test_report.py1671
-rw-r--r--dovetail/tests/unit/test_run.py655
-rw-r--r--dovetail/tests/unit/test_test_runner.py712
-rw-r--r--dovetail/tests/unit/test_testcase.py658
-rw-r--r--dovetail/tests/unit/test_testcase.yaml11
-rw-r--r--dovetail/tests/unit/utils/__init__.py0
-rw-r--r--dovetail/tests/unit/utils/test_dovetail_config.py53
-rw-r--r--dovetail/tests/unit/utils/test_dovetail_logger.py98
-rw-r--r--dovetail/tests/unit/utils/test_dovetail_utils.py1402
-rw-r--r--dovetail/tests/unit/utils/test_openstack_utils.py87
17 files changed, 6198 insertions, 7 deletions
diff --git a/dovetail/tests/unit/cli/__init__.py b/dovetail/tests/unit/cli/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dovetail/tests/unit/cli/__init__.py
diff --git a/dovetail/tests/unit/cli/commands/__init__.py b/dovetail/tests/unit/cli/commands/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dovetail/tests/unit/cli/commands/__init__.py
diff --git a/dovetail/tests/unit/cli/commands/test_cli_testcase.py b/dovetail/tests/unit/cli/commands/test_cli_testcase.py
new file mode 100644
index 00000000..324db640
--- /dev/null
+++ b/dovetail/tests/unit/cli/commands/test_cli_testcase.py
@@ -0,0 +1,228 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import io
+import unittest
+from mock import patch, call, Mock
+import yaml
+
+from dovetail import constants
+from dovetail.cli.commands.cli_testcase import CliTestcase
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class CliTestcaseTesting(unittest.TestCase):
+
+ @patch('os.path')
+ @patch('os.pardir')
+ @patch('dovetail.cli.commands.cli_testcase.dt_utils')
+ def test_run(self, mock_utils, mock_pardir, mock_path):
+ run_args = ('arga', 'argb')
+ options = ' '.join(run_args)
+ repo_dir = 'repo_dir'
+ mock_path.abspath.return_value = repo_dir
+
+ testcase = CliTestcase()
+ testcase.run(options)
+
+ mock_path.dirname.assert_called_once()
+ cmd = 'python3 %s/run.py %s' % (repo_dir, options)
+ mock_utils.exec_cmd.assert_called_once_with(
+ cmd, exit_on_error=True, exec_msg_on=False, info=True)
+
+ @patch('dovetail.cli.commands.cli_testcase.constants')
+ @patch('os.path')
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ def test_show_testcase_not_exist(self, mock_click, mock_path,
+ mock_constants):
+ testcase_name = 'name'
+ testcase_path = 'path'
+ mock_constants.TESTCASE_PATH = 'path'
+ testcase_whole_path = '{}/{}.yaml'.format(testcase_name,
+ testcase_path)
+ mock_path.join.return_value = testcase_whole_path
+ mock_path.isfile.return_value = False
+
+ testcase = CliTestcase()
+ testcase.show_testcase(testcase_name)
+
+ mock_path.join.assert_called_once_with(
+ testcase_path, '{}.yml'.format(testcase_name))
+ mock_path.isfile.assert_called_once_with(testcase_whole_path)
+ mock_click.echo.assert_called_once_with(
+ 'testcase %s not exist or not supported' % testcase_name)
+
+ @patch('builtins.open')
+ @patch('dovetail.cli.commands.cli_testcase.constants')
+ @patch('os.path')
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ def test_show_testcase(self, mock_click, mock_path, mock_constants,
+ mock_open):
+ testcase_name = 'name'
+ testcase_path = 'path'
+ mock_constants.TESTCASE_PATH = 'path'
+ testcase_whole_path = '{}/{}.yaml'.format(testcase_name,
+ testcase_path)
+ mock_path.join.return_value = testcase_whole_path
+ mock_path.isfile.return_value = True
+ file_data = u'file data'
+ mock_open.return_value.__enter__.return_value = io.StringIO(file_data)
+
+ testcase = CliTestcase()
+ testcase.show_testcase(testcase_name)
+
+ mock_open.assert_called_once_with(testcase_whole_path, 'r')
+ mock_path.join.assert_called_once_with(
+ testcase_path, '{}.yml'.format(testcase_name))
+ mock_path.isfile.assert_called_once_with(testcase_whole_path)
+ mock_click.echo.assert_called_once_with(file_data)
+
+ @patch('builtins.open')
+ @patch('dovetail.cli.commands.cli_testcase.constants')
+ @patch('os.path')
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ def test_show_testcase_exception(self, mock_click, mock_path,
+ mock_constants, mock_open):
+ testcase_name = 'name'
+ testcase_path = 'path'
+ mock_constants.TESTCASE_PATH = 'path'
+ testcase_whole_path = '{}/{}.yaml'.format(testcase_name,
+ testcase_path)
+ mock_path.join.return_value = testcase_whole_path
+ mock_path.isfile.return_value = True
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ exception = yaml.YAMLError()
+ file_obj.read.side_effect = exception
+
+ testcase = CliTestcase()
+ testcase.show_testcase(testcase_name)
+
+ mock_open.assert_called_once_with(testcase_whole_path, 'r')
+ mock_path.join.assert_called_once_with(
+ testcase_path, '{}.yml'.format(testcase_name))
+ mock_path.isfile.assert_called_once_with(testcase_whole_path)
+ mock_click.echo.assert_called_once_with(exception)
+
+ @patch.object(CliTestcase, 'testsuite_load')
+ @patch.object(CliTestcase, 'list_one_testsuite')
+ def test_list_suites_single(self, mock_list_one, mock_load):
+ testsuite = 'suite'
+
+ testcase = CliTestcase()
+ testcase.list_testsuites(testsuite)
+
+ mock_load.assert_called_once_with()
+ mock_list_one.assert_called_once_with(testsuite)
+
+ @patch.object(CliTestcase, 'testsuite_load')
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ @patch('dovetail.testcase.Testsuite.get_all')
+ def test_list_suites_no_suites(self, mock_get_all, mock_click, mock_load):
+ testsuite = None
+ mock_get_all.return_value = None
+
+ testcase = CliTestcase()
+ testcase.list_testsuites(testsuite)
+
+ mock_load.assert_called_once_with()
+ mock_get_all.assert_called_once_with()
+ mock_click.echo.assert_called_once_with(
+ 'No testsuite defined yet in dovetail!!!')
+
+ @patch.object(CliTestcase, 'testsuite_load')
+ @patch.object(CliTestcase, 'list_one_testsuite')
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ @patch('dovetail.testcase.Testsuite.get_all')
+ def test_list_suites_many(self, mock_get_all, mock_click, mock_list_one,
+ mock_load):
+ testsuite = None
+ suite_name = 'suite'
+ mock_get_all.return_value = {suite_name: 'A'}
+
+ testcase = CliTestcase()
+ testcase.list_testsuites(testsuite)
+
+ mock_load.assert_called_once_with()
+ mock_get_all.assert_called_once_with()
+ mock_click.echo.assert_has_calls([
+ call('--------------------------'),
+ call('Test Suite {}'.format(suite_name)),
+ call('--------------------------')])
+ mock_list_one.assert_called_once_with(suite_name)
+
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ @patch('dovetail.testcase.Testsuite.get')
+ def test_list_one_testsuite_not_exist(self, mock_get, mock_click):
+ testsuite = 'suite'
+ mock_get.return_value = None
+
+ testcase = CliTestcase()
+ testcase.list_one_testsuite(testsuite)
+
+ mock_get.assert_called_once_with(testsuite)
+ mock_click.echo.assert_called_once_with(
+ 'testsuite {} does not exist'.format(testsuite))
+
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ @patch('dovetail.testcase.Testsuite.get')
+ @patch('dovetail.cli.commands.cli_testcase.dt_utils')
+ def test_list_one_testsuite(self, mock_utils, mock_get, mock_click):
+ testsuite = 'suite'
+ testsuite_obj = Mock()
+ mock_get.return_value = testsuite_obj
+ testcase_a = 'testcaseA'
+ testcase_b = 'testcaseB'
+ mock_utils.get_value_from_dict.side_effect = [
+ [testcase_a], [testcase_b]]
+
+ testcase = CliTestcase()
+ testcase.list_one_testsuite(testsuite)
+
+ mock_get.assert_called_once_with(testsuite)
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('testcases_list.mandatory', testsuite_obj),
+ call('testcases_list.optional', testsuite_obj)])
+ mock_click.echo.assert_has_calls([
+ call('- mandatory'),
+ call(' {}'.format(testcase_a)),
+ call('- optional'),
+ call(' {}'.format(testcase_b))])
+
+ @patch('dovetail.cli.commands.cli_testcase.click')
+ @patch('dovetail.testcase.Testsuite.get')
+ @patch('dovetail.cli.commands.cli_testcase.dt_utils')
+ def test_list_one_testsuite_no_testcases(self, mock_utils, mock_get,
+ mock_click):
+ testsuite = 'suite'
+ testsuite_obj = Mock()
+ mock_get.return_value = testsuite_obj
+ mock_utils.get_value_from_dict.return_value = []
+
+ testcase = CliTestcase()
+ testcase.list_one_testsuite(testsuite)
+
+ mock_get.assert_called_once_with(testsuite)
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('testcases_list.mandatory', testsuite_obj),
+ call('testcases_list.optional', testsuite_obj)])
+ mock_click.echo.assert_called_once_with(
+ 'No testcase in testsuite {}'.format(testsuite))
+
+ @patch('dovetail.cli.commands.cli_testcase.dt_cfg')
+ @patch('dovetail.testcase.Testsuite.load')
+ @patch.object(constants, 'CONF_PATH')
+ def test_testsuite_load(self, mock_path, mock_load, mock_config):
+ testcase = CliTestcase()
+ testcase.testsuite_load()
+
+ mock_config.load_config_files.assert_called_once_with(mock_path)
+ mock_load.assert_called_once_with()
diff --git a/dovetail/tests/unit/cli/test_cli_base.py b/dovetail/tests/unit/cli/test_cli_base.py
new file mode 100644
index 00000000..9b06426c
--- /dev/null
+++ b/dovetail/tests/unit/cli/test_cli_base.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import unittest
+from mock import patch
+
+from click.testing import CliRunner
+from dovetail.cli import cli_base
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+@patch.object(cli_base, '_testcase')
+class CliBaseTesting(unittest.TestCase):
+
+ def test_cli(self, mock_testcase):
+ runner = CliRunner()
+ result = runner.invoke(cli_base.cli, [])
+
+ self.assertEqual(result.exit_code, 0)
+
+ def test_testcase_list(self, mock_testcase):
+ testsuite = 'suite'
+
+ runner = CliRunner()
+ result = runner.invoke(cli_base.testcase_list, [testsuite])
+
+ mock_testcase.list_testsuites.assert_called_once_with(testsuite)
+ self.assertEqual(result.exit_code, 0)
+
+ def test_testcase_show(self, mock_testcase):
+ testcase = 'case'
+
+ runner = CliRunner()
+ result = runner.invoke(cli_base.testcase_show, [testcase])
+
+ mock_testcase.show_testcase.assert_called_once_with(testcase)
+ self.assertEqual(result.exit_code, 0)
+
+ def test_testcase_run(self, mock_testcase):
+ run_args = ('arga', 'argb')
+
+ runner = CliRunner()
+ result = runner.invoke(cli_base.testcase_run, run_args)
+
+ expected = ' '.join(run_args)
+ mock_testcase.run.assert_called_once_with(expected)
+ self.assertEqual(result.exit_code, 0)
diff --git a/dovetail/tests/unit/cmd_config.yml b/dovetail/tests/unit/cmd_config.yml
new file mode 100644
index 00000000..405aabce
--- /dev/null
+++ b/dovetail/tests/unit/cmd_config.yml
@@ -0,0 +1,41 @@
+##############################################################################
+# Copyright (c) 2019 opnfv.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+---
+cli:
+ arguments:
+ config:
+ docker_tag:
+ flags: 'docker_tag'
+ path:
+ - 'functest/docker_tag'
+ control:
+
+ options:
+ config:
+ control:
+ testsuite:
+ flags:
+ - '--testsuite'
+ debug:
+ flags:
+ - '--debug'
+ is_flag: 'True'
+ report:
+ flags:
+ - '--report'
+ is_flag: 'True'
+ opnfvci:
+ flags:
+ - '--opnfv-ci'
+ is_flag: 'True'
+ noapivalidation:
+ flags:
+ - '--no-api-validation'
+ is_flag: 'True'
diff --git a/dovetail/tests/unit/test_container.py b/dovetail/tests/unit/test_container.py
new file mode 100644
index 00000000..86da9d3c
--- /dev/null
+++ b/dovetail/tests/unit/test_container.py
@@ -0,0 +1,489 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import unittest
+from mock import patch, call, Mock
+import docker
+
+from dovetail.container import Container
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class ContainerTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.patcher1 = patch.object(docker, 'from_env')
+ testcase = patch.object(Container, 'testcase')
+ testcase.testcase = {'validate': {
+ 'type': 'bottlenecks'}}
+ test_name_obj = Mock()
+ test_name_obj.return_value = 'name'
+ testcase.name = test_name_obj
+ val_type_obj = Mock()
+ val_type_obj.return_value = 'bottlenecks'
+ testcase.validate_type = val_type_obj
+ self.client = self.patcher1.start().return_value
+ self.container = Container(testcase)
+ self.logger = Mock()
+ self.container.logger = self.logger
+
+ def tearDown(self):
+ self.patcher1.stop()
+
+ @patch('dovetail.container.dt_cfg')
+ @patch.object(Container, 'copy_file')
+ def test_copy_files_in_container(self, mock_copy, mock_config):
+ source_file = 'source'
+ destination_file = 'destination_file'
+ mock_config.dovetail_config = {
+ 'bottlenecks': {
+ 'copy_file_in_container': [{
+ 'src_file': source_file,
+ 'dest_file': destination_file}]}}
+
+ self.container.copy_files_in_container()
+
+ mock_copy.assert_called_once_with(
+ source_file, destination_file)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch.object(Container, 'copy_file')
+ def test_copy_files_in_container_no_file(self, mock_copy, mock_config):
+ mock_config.dovetail_config = {
+ 'bottlenecks': {
+ 'copy_file_in_container': []}}
+
+ self.container.copy_files_in_container()
+
+ mock_copy.assert_not_called()
+
+ @patch('dovetail.container.dt_cfg')
+ @patch.object(Container, 'copy_file')
+ def test_copy_files_in_container_no_key(self, mock_copy, mock_config):
+ mock_config.dovetail_config = {
+ 'bottlenecks': {}}
+
+ self.container.copy_files_in_container()
+
+ mock_copy.assert_not_called()
+
+ def test_copy_file_error(self):
+ expected = (1, 'src_path or dest_path is empty')
+ result = self.container.copy_file(None, None)
+
+ self.assertEqual(expected, result)
+
+ @patch.object(Container, 'exec_cmd')
+ def test_copy_file(self, mock_exec):
+ expected = (0, 'success')
+ mock_exec.return_value = expected
+ result = self.container.copy_file('source', 'dest')
+
+ mock_exec.assert_called_once_with(
+ 'cp source dest', False)
+ self.assertEqual(expected, result)
+
+ def test_exec_cmd_error(self):
+ expected = (1, 'sub_cmd is empty')
+ result = self.container.exec_cmd('')
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch('dovetail.container.dt_utils')
+ def test_exec_cmd(self, mock_utils, mock_config):
+ expected = (0, 'success')
+ mock_utils.get_value_from_dict.return_value = 'shell'
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ container_obj = Mock()
+ container_obj.exec_run.return_value = expected
+ self.container.container = container_obj
+
+ result = self.container.exec_cmd('command')
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch('dovetail.container.dt_utils')
+ @patch('sys.exit')
+ def test_exec_cmd_exception(self, mock_exit, mock_utils, mock_config):
+ mock_utils.get_value_from_dict.return_value = 'shell'
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ container_obj = Mock()
+ response_obj = Mock()
+ response_obj.status_code = 1
+ container_obj.exec_run.side_effect = \
+ docker.errors.APIError('error', response=response_obj)
+ self.container.container = container_obj
+
+ expected = (1, 'error')
+ result = self.container.exec_cmd('command', exit_on_error=True)
+
+ self.assertEqual(expected, result)
+ mock_exit.assert_called_once_with(1)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch('dovetail.container.dt_utils')
+ def test_exec_cmd_no_shell(self, mock_utils, mock_config):
+ expected = (1, 'shell is empty')
+ mock_utils.exec_cmd.return_value = expected
+ mock_utils.get_value_from_dict.return_value = None
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ result = self.container.exec_cmd('command')
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch('dovetail.container.dt_utils')
+ @patch.object(Container, 'get_container')
+ def test_clean(self, mock_check, mock_utils, mock_config):
+ container_name = 'container'
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ mock_utils.get_value_from_dict.return_value = [container_name]
+ self.container.container = Mock()
+ mock_check.return_value = Mock()
+
+ self.container.clean()
+
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'extra_container', 'value')
+ mock_check.assert_called_once_with(container_name)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch('dovetail.container.dt_utils')
+ @patch.object(Container, 'get_container')
+ def test_clean_extra_error(self, mock_check, mock_utils, mock_config):
+ container_name = 'container'
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ mock_utils.get_value_from_dict.return_value = [container_name]
+ container_obj = Mock()
+ container_obj.remove.side_effect = docker.errors.APIError('error')
+ self.container.container = Mock()
+ mock_check.return_value = container_obj
+
+ self.container.clean()
+
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'extra_container', 'value')
+ mock_check.assert_called_once_with(container_name)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch('dovetail.container.dt_utils')
+ def test_clean_no_extra_container(self, mock_utils, mock_config):
+ mock_utils.get_value_from_dict.return_value = None
+ container_obj = Mock()
+ container_obj.remove.side_effect = docker.errors.APIError('error')
+ self.container.container = container_obj
+ self.container.clean()
+ mock_utils.get_value_from_dict.assert_called_once()
+
+ def test_get_container_exist_true(self):
+ container_name = 'container'
+ expected = Mock()
+ self.client.containers.get.return_value = expected
+
+ result = self.container.get_container(container_name)
+
+ self.assertEqual(expected, result)
+
+ def test_get_container_none(self):
+ container_name = 'container'
+ self.client.containers.get.side_effect = \
+ docker.errors.APIError('error')
+
+ result = self.container.get_container(container_name)
+
+ self.assertEqual(None, result)
+
+ def test_pull_image_none(self):
+ result = self.container.pull_image(None)
+ self.assertEqual(None, result)
+
+ @patch.object(Container, 'pull_image_only')
+ @patch.object(Container, 'get_image_id')
+ def test_pull_image_no_pull(self, mock_get, mock_pull):
+ docker_image = 'image'
+ mock_pull.return_value = None
+
+ result = self.container.pull_image(docker_image)
+
+ mock_get.assert_called_once_with(docker_image)
+ mock_pull.assert_called_once_with(docker_image)
+ self.assertEqual(None, result)
+
+ @patch.object(Container, 'pull_image_only')
+ @patch.object(Container, 'get_image_id')
+ def test_pull_image_no_new_id(self, mock_get, mock_pull):
+ docker_image = 'image'
+ mock_get.return_value = None
+ mock_pull.return_value = Mock()
+
+ result = self.container.pull_image(docker_image)
+
+ mock_pull.assert_called_once_with(docker_image)
+ mock_get.assert_has_calls([
+ call(docker_image), call(docker_image)])
+ self.logger.error.assert_called_once_with(
+ 'Failed to get the id of image {}.'.format(docker_image))
+ self.assertEqual(None, result)
+
+ @patch.object(Container, 'pull_image_only')
+ @patch.object(Container, 'get_image_id')
+ def test_pull_image_no_old_id(self, mock_get, mock_pull):
+ docker_image = 'image'
+ mock_get.side_effect = [None, Mock()]
+ mock_pull.return_value = Mock()
+
+ result = self.container.pull_image(docker_image)
+
+ mock_pull.assert_called_once_with(docker_image)
+ mock_get.assert_has_calls([
+ call(docker_image), call(docker_image)])
+ self.assertEqual(docker_image, result)
+
+ @patch.object(Container, 'pull_image_only')
+ @patch.object(Container, 'get_image_id')
+ def test_pull_image_same_id(self, mock_get, mock_pull):
+ docker_image = 'image'
+ mock_get.return_value = Mock()
+ mock_pull.return_value = Mock()
+
+ result = self.container.pull_image(docker_image)
+
+ mock_pull.assert_called_once_with(docker_image)
+ mock_get.assert_has_calls([
+ call(docker_image), call(docker_image)])
+ self.logger.debug.assert_called_once_with(
+ 'Image {} has no changes, no need to remove.'.format(docker_image))
+ self.assertEqual(docker_image, result)
+
+ @patch.object(Container, 'remove_image')
+ @patch.object(Container, 'pull_image_only')
+ @patch.object(Container, 'get_image_id')
+ def test_pull_image_different_id(self, mock_get, mock_pull, mock_remove):
+ docker_image = 'image'
+ old_obj = Mock()
+ mock_get.side_effect = [old_obj, Mock()]
+ mock_pull.return_value = Mock()
+
+ result = self.container.pull_image(docker_image)
+
+ mock_pull.assert_called_once_with(docker_image)
+ mock_get.assert_has_calls([
+ call(docker_image), call(docker_image)])
+ mock_remove.assert_called_once_with(old_obj)
+ self.assertEqual(docker_image, result)
+
+ def test_pull_image_only(self):
+ docker_image = 'image'
+
+ result = self.container.pull_image_only(docker_image)
+
+ self.logger.debug.assert_called_once_with(
+ 'Success to pull docker image {}!'.format(docker_image))
+ self.assertEqual(True, result)
+
+ def test_pull_image_only_error(self):
+ docker_image = 'image'
+ self.client.images.pull.side_effect = docker.errors.APIError('error')
+
+ result = self.container.pull_image_only(docker_image)
+
+ self.logger.error.assert_called_once_with(
+ 'Failed to pull docker image {}!'.format(docker_image))
+ self.assertEqual(False, result)
+
+ def test_remove_image(self):
+ image_id = 'image_id'
+ self.client.containers.list.side_effect = \
+ docker.errors.APIError('error')
+
+ result = self.container.remove_image(image_id)
+
+ self.logger.debug.assert_has_calls([
+ call('Remove image {}.'.format(image_id)),
+ call('Remove image {} successfully.'.format(image_id))])
+ self.assertEqual(True, result)
+
+ def test_remove_image_ancestors(self):
+ image_id = 'image_id'
+ self.client.containers.list.return_value = ['cont_a']
+
+ result = self.container.remove_image(image_id)
+
+ self.logger.debug.assert_called_once_with(
+ 'Image {} has containers, skip.'.format(image_id))
+ self.assertEqual(True, result)
+
+ def test_remove_image_error(self):
+ image_id = 'image_id'
+ self.client.containers.list.return_value = []
+ self.client.images.remove.side_effect = \
+ docker.errors.ImageNotFound('error')
+
+ result = self.container.remove_image(image_id)
+
+ self.logger.debug.assert_called_once_with(
+ 'Remove image {}.'.format(image_id))
+ self.logger.error.assert_called_once_with(
+ 'Failed to remove image {}.'.format(image_id))
+ self.assertEqual(False, result)
+
+ def test_get_image_id(self):
+ image_name = 'image_id'
+ mock_img = Mock()
+ mock_img.id = image_name
+ self.client.images.get.return_value = mock_img
+
+ result = self.container.get_image_id(image_name)
+
+ self.assertEqual(image_name, result)
+
+ def test_get_image_id_error(self):
+ image_name = 'image_id'
+ self.client.images.get.side_effect = \
+ docker.errors.ImageNotFound('error')
+
+ result = self.container.get_image_id(image_name)
+
+ self.assertEqual(None, result)
+
+ @patch('dovetail.container.dt_utils')
+ def test_get_config(self, mock_utils):
+ expected = 'value'
+ mock_utils.get_value_from_dict.return_value = expected
+
+ result = self.container._get_config('a', 'b', 'c')
+
+ mock_utils.get_value_from_dict.assert_called_once_with('a', 'c')
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.container.dt_utils')
+ def test_get_config_none(self, mock_utils):
+ mock_utils.get_value_from_dict.return_value = None
+
+ result = self.container._get_config('a', 'b', 'c')
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('a', 'c'), call('a', 'b')])
+ self.logger.error.assert_called_once_with(
+ "Couldn't find key {}.".format('a'))
+ self.assertEqual(None, result)
+
+ @patch('dovetail.container.dt_cfg')
+ @patch.object(Container, '_get_config')
+ def test_get_docker_image(self, mock_get_conf, mock_config):
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ mock_get_conf.side_effect = ['name', 'tag']
+
+ expected = 'name:tag'
+ result = self.container.get_docker_image()
+
+ mock_get_conf.assert_has_calls([
+ call('image_name', 'value', {'type': 'bottlenecks'}),
+ call('docker_tag', 'value', {'type': 'bottlenecks'})])
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.container.dt_logger')
+ def test_create_log(self, mock_logger):
+ log_obj = Mock()
+ log_obj.getLogger.return_value = self.logger
+ mock_logger.Logger.return_value = log_obj
+
+ self.container.create_log()
+
+ self.assertEqual(self.logger, self.container.logger)
+
+ @patch('dovetail.container.dt_utils')
+ @patch('dovetail.container.dt_cfg')
+ def test_create(self, mock_config, mock_utils):
+ docker_image = 'docker_image'
+ container_id = 'container_id'
+ mock_utils.get_value_from_dict.side_effect = [
+ {'key': 'value'}, 'shell', 'envs', ['volume_one', 'volume_two']]
+ mock_utils.get_mount_list.side_effect = [['mount', 'list'], 'success']
+ mock_utils.get_hosts_info.return_value = 'host_info'
+ container_obj = Mock()
+ container_obj.id = container_id
+ self.client.containers.run.return_value = container_obj
+ project_config = {}
+ mock_config.dovetail_config = {'bottlenecks': project_config}
+
+ expected = container_id
+ result, msg = self.container.create(docker_image)
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('opts', project_config),
+ call('shell', project_config),
+ call('envs', project_config),
+ call('volumes', project_config)])
+ mock_utils.get_hosts_info.assert_called_once_with(self.logger)
+ self.assertEqual(expected, result)
+ self.assertEqual('Successfully to create container.', msg)
+
+ @patch('dovetail.container.dt_utils')
+ @patch('dovetail.container.dt_cfg')
+ def test_create_no_shell(self, mock_config, mock_utils):
+ docker_image = 'docker_image'
+ mock_config.dovetail_config = {'bottlenecks': 'value'}
+ mock_utils.get_value_from_dict.side_effect = ['opts', None]
+ mock_utils.get_hosts_info.return_value = 'host_info'
+
+ result, msg = self.container.create(docker_image)
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('opts', 'value'),
+ call('shell', 'value')])
+ self.assertEqual(None, result)
+ self.assertEqual("Lacking of key word 'shell' in config file.", msg)
+
+ @patch('dovetail.container.dt_utils')
+ @patch('dovetail.container.dt_cfg')
+ def test_create_mounts_none(self, mock_config, mock_utils):
+ docker_image = 'docker_image'
+ project_config = {}
+ mock_config.dovetail_config = {'bottlenecks': project_config}
+ mock_utils.get_value_from_dict.side_effect = [
+ {'key': 'value'}, 'shell', ['envs'], ['volume_one']]
+ mock_utils.get_mount_list.side_effect = [[None, 'error']]
+ mock_utils.get_hosts_info.return_value = 'host_info'
+
+ result, msg = self.container.create(docker_image)
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('opts', project_config), call('shell', project_config),
+ call('envs', project_config), call('volumes', project_config)])
+ self.assertEqual(None, result)
+ self.assertEqual('error', msg)
+
+ @patch('dovetail.container.dt_utils')
+ @patch('dovetail.container.dt_cfg')
+ def test_create_error(self, mock_config, mock_utils):
+ docker_image = 'docker_image'
+ mock_utils.get_value_from_dict.side_effect = [
+ {'key': 'value'}, 'shell', ['envs'], ['volume_one']]
+ mock_utils.get_mount_list.side_effect = [['mount', 'list'], 'success']
+ mock_utils.get_hosts_info.return_value = 'host_info'
+ mock_utils.check_https_enabled.return_value = True
+ self.client.containers.run.side_effect = \
+ docker.errors.ImageNotFound('error')
+ project_config = {}
+ mock_config.dovetail_config = {'bottlenecks': project_config}
+ result, msg = self.container.create(docker_image)
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('opts', project_config),
+ call('shell', project_config),
+ call('envs', project_config),
+ call('volumes', project_config)])
+ mock_utils.get_hosts_info.assert_called_once_with(self.logger)
+ self.assertEqual(None, result)
+ self.assertEqual('error', str(docker.errors.ImageNotFound('error')))
diff --git a/dovetail/tests/unit/test_parser.py b/dovetail/tests/unit/test_parser.py
index 53484400..4f164772 100644
--- a/dovetail/tests/unit/test_parser.py
+++ b/dovetail/tests/unit/test_parser.py
@@ -39,31 +39,62 @@ class TestParser(unittest.TestCase):
def test_parser_cmd(self, mock_logger):
"""Test whether the command is correctly parsed."""
- mock_cmd = "python /functest/ci/run_tests.py "\
+ mock_cmd = "python3 /functest/ci/run_tests.py "\
"-t {{validate_testcase}} -r"
with open(os.path.join(self.test_path, 'test_testcase.yaml')) as f:
mock_testcase_yaml = yaml.safe_load(f)
MockTestcase = type('Testcase', (object,), {})
mock_testcase = MockTestcase()
- mock_testcase.testcase = mock_testcase_yaml.values()[0]
+ mock_testcase.testcase = list(mock_testcase_yaml.values())[0]
output = parser.Parser.parse_cmd(mock_cmd, mock_testcase)
- expected_output = ("python /functest/ci/run_tests.py -t "
+ expected_output = ("python3 /functest/ci/run_tests.py -t "
"tempest_smoke_serial -r")
self.assertEqual(expected_output, output)
def test_parser_cmd_fail(self, mock_logger):
"""Test whether the command is correctly parsed."""
- mock_cmd = "python /functest/ci/run_tests.py "\
+ mock_cmd = "python3 /functest/ci/run_tests.py "\
"-t {{validate_testcase}} -r"
mock_testcase_yaml = {}
MockTestcase = type('Testcase', (object,), {})
mock_testcase = MockTestcase()
mock_testcase.testcase = mock_testcase_yaml.values()
output = parser.Parser.parse_cmd(mock_cmd, mock_testcase)
- expected_output = ("python /functest/ci/run_tests.py -t "
+ expected_output = ("python3 /functest/ci/run_tests.py -t "
"None -r")
self.assertEqual(expected_output, output)
+ @mock.patch('dovetail.parser.jinja2')
+ def test_parse_cmd_exception(self, mock_jinja, mock_logger):
+ errorMSG = 'Exception was raised'
+ exception = Exception(errorMSG)
+ command = 'cmd'
+ undefined_obj = mock.Mock()
+ mock_jinja.StrictUndefined = undefined_obj
+ mock_jinja.Template.side_effect = exception
-if __name__ == '__main__':
- unittest.main()
+ expected = None
+ dovetail_parser = parser.Parser()
+ exception_obj = mock.Mock()
+ dovetail_parser.logger.exception = exception_obj
+ result = dovetail_parser.parse_cmd(command, 'testcase')
+
+ mock_jinja.Template.assert_called_once_with(command,
+ undefined=undefined_obj)
+ exception_obj.assert_called_once_with(
+ 'Failed to parse cmd {}, exception: {}'.format(command, errorMSG))
+ self.assertEqual(expected, result)
+
+ @mock.patch('dovetail.parser.dt_logger.Logger')
+ def test_create_log(self, mock_dt_logger, mock_logger):
+ mock_dt_logger_obj = mock.Mock()
+ logger_obj = mock.Mock()
+ mock_dt_logger_obj.getLogger.return_value = logger_obj
+ mock_dt_logger.return_value = mock_dt_logger_obj
+
+ dovetail_parser = parser.Parser()
+ dovetail_parser.create_log()
+
+ mock_dt_logger.assert_called_once_with('dovetail.parser.Parser')
+ mock_dt_logger_obj.getLogger.assert_called_once_with()
+ self.assertEqual(dovetail_parser.logger, logger_obj)
diff --git a/dovetail/tests/unit/test_report.py b/dovetail/tests/unit/test_report.py
new file mode 100644
index 00000000..41d70d2f
--- /dev/null
+++ b/dovetail/tests/unit/test_report.py
@@ -0,0 +1,1671 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import json
+import os
+import unittest
+import yaml
+from mock import patch, call, Mock
+
+import dovetail.report as dt_report
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class ReportTesting(unittest.TestCase):
+
+ def setUp(self):
+ test_path = os.path.dirname(os.path.realpath(__file__))
+ with open(os.path.join(test_path, 'test_testcase.yaml')) as f:
+ self.testcase_yaml = yaml.safe_load(f)
+
+ def tearDown(self):
+ pass
+
+ def teardown_method(self, method):
+ dt_report.FunctestCrawler.logger = None
+ dt_report.FunctestK8sCrawler.logger = None
+ dt_report.YardstickCrawler.logger = None
+ dt_report.BottlenecksCrawler.logger = None
+ dt_report.OnapVtpCrawler.logger = None
+ dt_report.OnapVvpCrawler.logger = None
+ dt_report.FunctestChecker.logger = None
+ dt_report.FunctestK8sChecker.logger = None
+ dt_report.YardstickChecker.logger = None
+ dt_report.BottlenecksChecker.logger = None
+ dt_report.OnapVtpChecker.logger = None
+ dt_report.OnapVvpChecker.logger = None
+ dt_report.Report.logger = None
+ dt_report.Report.results = {
+ 'functest': {}, 'yardstick': {}, 'functest-k8s': {},
+ 'bottlenecks': {}, 'shell': {}, 'onap-vtp': {},
+ 'onap-vvp': {}}
+
+ def _produce_report_initial_text(self, report_data):
+ report_txt = ''
+ report_txt += '\n\nDovetail Report\n'
+ report_txt += 'Version: %s\n' % report_data['version']
+ report_txt += 'Build Tag: %s\n' % report_data['build_tag']
+ report_txt += 'Test Date: %s\n' % report_data['test_date']
+ report_txt += 'Duration: %.2f s\n\n' % report_data['duration']
+ return report_txt
+
+ @patch('dovetail.report.dt_logger')
+ def test_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.Report.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.Report.logger)
+
+ @patch('dovetail.report.os.path')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.dt_utils')
+ @patch.object(dt_report.Report, 'get_result')
+ @patch.object(dt_report.Report, 'check_result')
+ def test_check_tc_result(self, mock_check, mock_get, mock_utils,
+ mock_config, mock_path):
+ report = dt_report.Report()
+ logger_obj = Mock()
+ report.logger = logger_obj
+ testcase_obj = Mock()
+ inner_testcase_obj = Mock()
+ testcase_obj.testcase = inner_testcase_obj
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ mock_utils.get_value_from_dict.return_value = ['check_results_file']
+ mock_path.join.return_value = 'results_file'
+ mock_path.isfile.return_value = True
+ mock_get.return_value = 'result'
+
+ result = report.check_tc_result(testcase_obj)
+
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'report.check_results_files', inner_testcase_obj)
+ mock_path.join.assert_called_once_with(
+ 'result_dir', 'check_results_file')
+ mock_path.isfile.assert_called_once_with('results_file')
+ logger_obj.info.assert_called_once_with(
+ 'Results have been stored with files: [\'results_file\'].')
+ mock_get.assert_called_once_with(testcase_obj, ['results_file'])
+ mock_check.assert_called_once_with(testcase_obj, 'result')
+ self.assertEqual('result', result)
+
+ @patch('dovetail.report.os.path')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.dt_utils')
+ @patch.object(dt_report.Report, 'get_result')
+ @patch.object(dt_report.Report, 'check_result')
+ def test_check_tc_result_no_file(self, mock_check, mock_get, mock_utils,
+ mock_config, mock_path):
+ report = dt_report.Report()
+ logger_obj = Mock()
+ report.logger = logger_obj
+ testcase_obj = Mock()
+ inner_testcase_obj = Mock()
+ testcase_obj.testcase = inner_testcase_obj
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ mock_utils.get_value_from_dict.return_value = ['check_results_file']
+ mock_path.join.return_value = 'results_file'
+ mock_path.isfile.return_value = False
+
+ result = report.check_tc_result(testcase_obj)
+
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'report.check_results_files', inner_testcase_obj)
+ mock_path.join.assert_called_once_with(
+ 'result_dir', 'check_results_file')
+ mock_path.isfile.assert_called_once_with('results_file')
+ logger_obj.error.assert_called_once_with(
+ 'Failed to store results with file results_file.')
+ mock_check.assert_called_once_with(testcase_obj)
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.os.path')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.dt_utils')
+ @patch.object(dt_report.Report, 'get_result')
+ @patch.object(dt_report.Report, 'check_result')
+ def test_check_tc_result_no_check(self, mock_check, mock_get, mock_utils,
+ mock_config, mock_path):
+ report = dt_report.Report()
+ logger_obj = Mock()
+ report.logger = logger_obj
+ testcase_obj = Mock()
+ inner_testcase_obj = Mock()
+ testcase_obj.testcase = inner_testcase_obj
+ testcase_obj.name.return_value = 'name'
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ mock_utils.get_value_from_dict.return_value = None
+
+ result = report.check_tc_result(testcase_obj)
+
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'report.check_results_files', inner_testcase_obj)
+ logger_obj.error.assert_called_once_with(
+ "Failed to get 'check_results_files' from config "
+ "file of test case name")
+ mock_check.assert_called_once_with(testcase_obj)
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.CheckerFactory')
+ def test_check_result(self, mock_factory):
+ testcase_obj = Mock()
+ testcase_obj.validate_type.return_value = 'type'
+ checker_obj = Mock()
+ mock_factory.create.return_value = checker_obj
+
+ dt_report.Report.check_result(testcase_obj)
+
+ testcase_obj.validate_type.assert_called_once_with()
+ mock_factory.create.assert_called_once_with('type')
+ checker_obj.check.assert_called_once_with(testcase_obj, None)
+
+ @patch('dovetail.report.os.getenv')
+ @patch.object(dt_report.Report, 'get_checksum')
+ @patch('dovetail.report.Testcase')
+ @patch('dovetail.report.datetime.datetime')
+ @patch('dovetail.report.dt_cfg')
+ def test_generate_json(self, mock_config, mock_datetime, mock_testcase,
+ mock_checksum, mock_env):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_list = ['ta.tb.tc', 'td.te.tf']
+ duration = 42
+ mock_config.dovetail_config = {
+ 'build_tag': 'build_tag',
+ 'version': '2018.09'
+ }
+ mock_env.return_value = 'enabled'
+ utc_obj = Mock()
+ utc_obj.strftime.return_value = '2018-01-13 13:13:13 UTC'
+ mock_datetime.utcnow.return_value = utc_obj
+ testcase_obj = Mock()
+ testcase_obj.passed.return_value = 'PASS'
+ testcase_obj.objective.return_value = 'objective'
+ mock_checksum.return_value = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
+ testcase_obj.is_mandatory = True
+ testcase_obj.portal_key_file.return_value = 'a/b.log'
+ testcase_obj.vnf_type.return_value = 'tosca'
+ testcase_obj.sub_testcase.return_value = ['subt_a']
+ testcase_obj.sub_testcase_passed.return_value = 'PASS'
+ mock_testcase.get.side_effect = [testcase_obj, None]
+
+ result = report.generate_json(testcase_list, duration)
+ expected = {
+ 'version': '2018.09',
+ 'build_tag': 'build_tag',
+ 'vnf_type': 'tosca',
+ 'vnf_checksum': 'da39a3ee5e6b4b0d3255bfef95601890afd80709',
+ 'test_date': '2018-01-13 13:13:13 UTC',
+ 'duration': duration,
+ 'validation': 'enabled',
+ 'testcases_list': [
+ {
+ 'name': 'ta.tb.tc',
+ 'result': 'PASS',
+ 'objective': 'objective',
+ 'mandatory': True,
+ 'portal_key_file': 'a/b.log',
+ 'sub_testcase': [{
+ 'name': 'subt_a',
+ 'result': 'PASS'
+ }]
+ },
+ {
+ 'name': 'td.te.tf',
+ 'result': 'Undefined',
+ 'objective': '',
+ 'mandatory': False,
+ 'portal_key_file': '',
+ 'sub_testcase': []
+ }
+ ]
+ }
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.os.getenv')
+ @patch('dovetail.report.Testcase')
+ @patch('dovetail.report.datetime.datetime')
+ @patch('dovetail.report.dt_cfg')
+ def test_generate_json_noVNF(self, mock_config, mock_datetime,
+ mock_testcase, mock_env):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_list = ['ta.tb.tc', 'td.te.tf']
+ duration = 42
+ mock_config.dovetail_config = {
+ 'build_tag': 'build_tag',
+ 'version': '2018.09'
+ }
+ mock_env.return_value = 'disabled'
+ utc_obj = Mock()
+ utc_obj.strftime.return_value = '2018-01-13 13:13:13 UTC'
+ mock_datetime.utcnow.return_value = utc_obj
+ testcase_obj = Mock()
+ testcase_obj.passed.return_value = 'PASS'
+ testcase_obj.objective.return_value = 'objective'
+ testcase_obj.is_mandatory = True
+ testcase_obj.vnf_type.return_value = None
+ testcase_obj.portal_key_file.return_value = 'a/b.log'
+ testcase_obj.sub_testcase.return_value = ['subt_a']
+ testcase_obj.sub_testcase_passed.return_value = 'PASS'
+ mock_testcase.get.side_effect = [testcase_obj, None]
+
+ result = report.generate_json(testcase_list, duration)
+ expected = {
+ 'version': '2018.09',
+ 'build_tag': 'build_tag',
+ 'test_date': '2018-01-13 13:13:13 UTC',
+ 'duration': duration,
+ 'validation': 'disabled',
+ 'testcases_list': [
+ {
+ 'name': 'ta.tb.tc',
+ 'result': 'PASS',
+ 'objective': 'objective',
+ 'mandatory': True,
+ 'portal_key_file': 'a/b.log',
+ 'sub_testcase': [{
+ 'name': 'subt_a',
+ 'result': 'PASS'
+ }]
+ },
+ {
+ 'name': 'td.te.tf',
+ 'result': 'Undefined',
+ 'objective': '',
+ 'mandatory': False,
+ 'portal_key_file': '',
+ 'sub_testcase': []
+ }
+ ]
+ }
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.os.getenv')
+ @patch('dovetail.report.Testcase')
+ @patch('dovetail.report.datetime.datetime')
+ @patch('dovetail.report.dt_cfg')
+ def test_generate_json_noVNF_inTestCase(self, mock_config, mock_datetime,
+ mock_testcase, mock_env):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_list = ['ta.tb.tc', 'td.te.tf']
+ duration = 42
+ mock_config.dovetail_config = {
+ 'build_tag': 'build_tag',
+ 'version': '2018.09'
+ }
+ mock_env.return_value = 'enabled'
+ utc_obj = Mock()
+ utc_obj.strftime.return_value = '2018-01-13 13:13:13 UTC'
+ mock_datetime.utcnow.return_value = utc_obj
+ testcase_obj = Mock()
+ testcase_obj.passed.return_value = 'PASS'
+ testcase_obj.objective.return_value = 'objective'
+ testcase_obj.is_mandatory = True
+ testcase_obj.portal_key_file.return_value = 'a/b.log'
+ testcase_obj.vnf_type.side_effect = Exception()
+ testcase_obj.sub_testcase.return_value = ['subt_a']
+ testcase_obj.sub_testcase_passed.return_value = 'PASS'
+ mock_testcase.get.side_effect = [testcase_obj, None]
+
+ result = report.generate_json(testcase_list, duration)
+ expected = {
+ 'version': '2018.09',
+ 'build_tag': 'build_tag',
+ 'test_date': '2018-01-13 13:13:13 UTC',
+ 'duration': duration,
+ 'validation': 'enabled',
+ 'testcases_list': [
+ {
+ 'name': 'ta.tb.tc',
+ 'result': 'PASS',
+ 'objective': 'objective',
+ 'mandatory': True,
+ 'portal_key_file': 'a/b.log',
+ 'sub_testcase': [{
+ 'name': 'subt_a',
+ 'result': 'PASS'
+ }]
+ },
+ {
+ 'name': 'td.te.tf',
+ 'result': 'Undefined',
+ 'objective': '',
+ 'mandatory': False,
+ 'portal_key_file': '',
+ 'sub_testcase': []
+ }
+ ]
+ }
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.datetime.datetime')
+ @patch('dovetail.report.dt_cfg')
+ @patch.object(dt_report.Report, 'get_checksum')
+ def test_generate_json_no_list(self, mock_checksum, mock_config,
+ mock_datetime):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ duration = 42
+ mock_config.dovetail_config = {
+ 'build_tag': 'build_tag',
+ 'version': '2018.09',
+ 'vnf_type': 'tosca'
+ }
+ utc_obj = Mock()
+ utc_obj.strftime.return_value = '2018-01-13 13:13:13 UTC'
+ mock_datetime.utcnow.return_value = utc_obj
+ mock_checksum.return_value = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
+
+ result = report.generate_json([], duration)
+ expected = {
+ 'version': '2018.09',
+ 'build_tag': 'build_tag',
+ 'vnf_type': 'tosca',
+ 'vnf_checksum': 'da39a3ee5e6b4b0d3255bfef95601890afd80709',
+ 'test_date': '2018-01-13 13:13:13 UTC',
+ 'duration': duration,
+ 'testcases_list': []
+ }
+
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.dt_cfg')
+ @patch.object(dt_report.Report, 'generate_json')
+ @patch.object(dt_report.Report, 'save_json_results')
+ def test_generate(self, mock_save, mock_generate, mock_config):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_list = ['ta.tb.tc', 'td.te.tf']
+ duration = 42
+ report_data = {
+ 'version': 'v2',
+ 'build_tag': '2.0.0',
+ 'test_date': '2018-01-13 13:13:13 UTC',
+ 'duration': 42.42,
+ 'testcases_list': [
+ {
+ 'name': 'ta.tb.tc',
+ 'result': 'PASS',
+ 'sub_testcase': [{
+ 'name': 'subt_a',
+ 'result': 'PASS'
+ }]
+ },
+ {
+ 'name': 'td.te.tf',
+ 'result': 'SKIP'
+ }
+ ]
+ }
+ mock_generate.return_value = report_data
+
+ result = report.generate(testcase_list, duration)
+ expected = self._produce_report_initial_text(report_data)
+ expected += 'Pass Rate: 100.00% (1/1)\n'
+ expected += '%-25s pass rate %.2f%%\n' % ('tb:', 100)
+ expected += '-%-25s %s\n' % ('ta.tb.tc', 'PASS')
+ expected += '\t%-110s %s\n' % ('subt_a', 'PASS')
+ expected += '%-25s all skipped\n' % 'te'
+ expected += '-%-25s %s\n' % ('td.te.tf', 'SKIP')
+
+ mock_generate.assert_called_once_with(testcase_list, duration)
+ mock_save.assert_called_once_with(report_data)
+ report.logger.info.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.dt_cfg')
+ @patch.object(dt_report.Report, 'generate_json')
+ @patch.object(dt_report.Report, 'save_json_results')
+ def test_generate_no_cases(self, mock_save, mock_generate, mock_config):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ duration = 42
+ report_data = {
+ 'version': 'v2',
+ 'build_tag': '2.0.0',
+ 'test_date': '2018-01-13 13:13:13 UTC',
+ 'duration': 42.42,
+ 'testcases_list': []
+ }
+ mock_generate.return_value = report_data
+
+ result = report.generate([], duration)
+ expected = self._produce_report_initial_text(report_data) +\
+ 'no testcase or all testcases are skipped in this testsuite\n'
+
+ mock_generate.assert_called_once_with([], duration)
+ mock_save.assert_called_once_with(report_data)
+ report.logger.info.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json')
+ @patch('dovetail.report.os.path')
+ @patch('dovetail.report.dt_cfg')
+ def test_save_json_results(self, mock_config, mock_path, mock_json,
+ mock_open):
+ mock_config.dovetail_config = {
+ 'result_dir': 'a',
+ 'result_file': 'b'
+ }
+ mock_path.join.return_value = 'result_file'
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_json.dumps.return_value = 'results text'
+
+ report = dt_report.Report()
+ report.save_json_results('results')
+
+ mock_path.join.assert_called_once_with('a', 'b')
+ mock_open.assert_called_once_with('result_file', 'w')
+ mock_json.dumps.assert_called_once_with('results')
+ file_obj.write.assert_called_once_with('results text\n')
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json')
+ @patch('dovetail.report.os.path')
+ @patch('dovetail.report.dt_cfg')
+ def test_save_json_results_exception(self, mock_config, mock_path,
+ mock_json, mock_open):
+ report = dt_report.Report()
+ logger_obj = Mock()
+ report.logger = logger_obj
+ mock_config.dovetail_config = {
+ 'result_dir': 'a',
+ 'result_file': 'b'
+ }
+ mock_path.join.return_value = 'result_file'
+ mock_open.return_value.__enter__.side_effect = Exception('error')
+
+ report.save_json_results('results')
+
+ mock_path.join.assert_called_once_with('a', 'b')
+ mock_open.assert_called_once_with('result_file', 'w')
+ report.logger.exception.assert_called_once_with(
+ 'Failed to add result to file result_file, exception: error')
+
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.time')
+ @patch('dovetail.report.os')
+ @patch('dovetail.report.tarfile')
+ def test_save_logs(self, mock_tar, mock_os, mock_time, mock_config):
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ local_time_obj = Mock()
+ mock_time.localtime.return_value = local_time_obj
+ mock_time.strftime.return_value = '20180113_13:13'
+ mock_os.getcwd.return_value = 'cwd'
+ tar_obj = Mock()
+ tar_file_obj = Mock()
+ mock_tar.open.return_value.__enter__.return_value = tar_file_obj
+ mock_os.path.join.side_effect = ['one', tar_obj, 'three']
+ mock_os.listdir.return_value = ['file']
+
+ dt_report.Report.save_logs()
+
+ mock_time.localtime.assert_called_once_with()
+ mock_time.strftime.assert_called_once_with('%Y%m%d_%H%M',
+ local_time_obj)
+ mock_os.getcwd.assert_called_once_with()
+ mock_os.path.join.assert_has_calls([
+ call('result_dir', '..'),
+ call('result_dir', '..', 'logs_20180113_13:13.tar.gz'),
+ call('results', 'file')])
+ mock_tar.open.assert_called_once_with(tar_obj, 'w:gz')
+ mock_os.listdir.assert_called_once_with('result_dir')
+ tar_file_obj.add.assert_called_once_with('three')
+ mock_os.chdir.assert_has_calls([call('one'), call('cwd')])
+
+ @patch('dovetail.report.CrawlerFactory')
+ def test_get_result(self, mock_crawler):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_obj = Mock()
+ crawler_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'validate'
+ testcase_obj.validate_type.return_value = 'functest'
+ mock_crawler.create.return_value = crawler_obj
+ crawler_obj.crawl.return_value = 'result'
+
+ result = report.get_result(testcase_obj, 'check_results_files')
+
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.validate_type.assert_called_once_with()
+ mock_crawler.create.assert_called_once_with('functest')
+ crawler_obj.crawl.assert_called_once_with(
+ testcase_obj, 'check_results_files')
+ logger_obj.debug.assert_called_once_with(
+ 'Test case: validate -> result acquired')
+ self.assertEqual({'validate': 'result'},
+ dt_report.Report.results['functest'])
+ self.assertEqual('result', result)
+
+ @patch('dovetail.report.CrawlerFactory')
+ def test_get_result_no_result(self, mock_crawler):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_obj = Mock()
+ crawler_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'validate'
+ testcase_obj.validate_type.return_value = 'functest'
+ testcase_obj.increase_retry.return_value = 'retry'
+ mock_crawler.create.return_value = crawler_obj
+ crawler_obj.crawl.return_value = None
+
+ result = report.get_result(testcase_obj, 'check_results_files')
+
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.validate_type.assert_called_once_with()
+ mock_crawler.create.assert_called_once_with('functest')
+ crawler_obj.crawl.assert_called_once_with(
+ testcase_obj, 'check_results_files')
+ testcase_obj.increase_retry.assert_called_once_with()
+ logger_obj.debug.assert_called_once_with(
+ 'Test case: validate -> result acquired retry: retry')
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.CrawlerFactory')
+ def test_get_result_no_crawler(self, mock_crawler):
+ logger_obj = Mock()
+ report = dt_report.Report()
+ report.logger = logger_obj
+ testcase_obj = Mock()
+ testcase_obj.name.return_value = 'name'
+ testcase_obj.validate_testcase.return_value = 'validate'
+ testcase_obj.validate_type.return_value = 'functest'
+ mock_crawler.create.return_value = None
+
+ result = report.get_result(testcase_obj, 'check_results_files')
+
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.validate_type.assert_called_once_with()
+ mock_crawler.create.assert_called_once_with('functest')
+ logger_obj.error.assert_called_once_with(
+ 'Crawler is None: name')
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.dt_logger')
+ def test_functest_crawler_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.FunctestCrawler.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.FunctestCrawler.logger)
+
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.os.path')
+ def test_functest_crawler_crawl_not_exists(self, mock_path, mock_config):
+ logger_obj = Mock()
+ mock_config.dovetail_config = {'build_tag': 'tag'}
+ dt_report.FunctestCrawler.logger = logger_obj
+ mock_path.exists.return_value = False
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'validate'
+ testcase_obj.name.return_value = 'name'
+
+ crawler = dt_report.FunctestCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.name.assert_called_once_with()
+ logger_obj.error.assert_called_once_with(
+ 'Result file not found: {}'.format(file_path))
+ self.assertEqual(None, result)
+
+ def test_functest_crawler_get_details_exception(self):
+ logger_obj = Mock()
+ dt_report.FunctestCrawler.logger = logger_obj
+ data = None
+ crawler = dt_report.FunctestCrawler()
+
+ excepted = None
+ result = crawler.get_details(data)
+ logger_obj.exception.assert_called_once()
+ self.assertEqual(excepted, result)
+
+ def test_functest_crawler_get_rally_details_exception(self):
+ logger_obj = Mock()
+ dt_report.FunctestCrawler.logger = logger_obj
+ data = None
+ crawler = dt_report.FunctestCrawler()
+
+ excepted = None
+ result = crawler.get_rally_details(data)
+ logger_obj.exception.assert_called_once()
+ self.assertEqual(excepted, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.dt_utils')
+ @patch('dovetail.report.os.path')
+ def test_functest_crawler_crawl(self, mock_path, mock_utils, mock_config,
+ mock_json, mock_open):
+ logger_obj = Mock()
+ mock_config.dovetail_config = {'build_tag': 'tag'}
+ dt_report.FunctestCrawler.logger = logger_obj
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'name'
+ testcase_obj.name.return_value = 'name'
+ testcase_obj.sub_testcase.return_value = ['subt_a']
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'case_name': 'name',
+ 'build_tag': 'tag-name',
+ 'criteria': 'criteria',
+ 'start_date': 'start_date',
+ 'stop_date': 'stop_date',
+ 'details': {
+ 'tests_number': 'tests_number',
+ 'failures_number': 'failures_number',
+ 'success': 'success',
+ 'failures': 'failures',
+ 'skipped': 'skipped'
+ }
+ }
+ mock_json.loads.return_value = data_dict
+ mock_utils.get_duration.return_value = 'duration'
+
+ crawler = dt_report.FunctestCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'criteria', 'timestart': 'start_date',
+ 'timestop': 'stop_date', 'duration': 'duration',
+ 'details': {
+ 'tests': 'tests_number', 'failures': 'failures_number',
+ 'success': 'success', 'errors': 'failures',
+ 'skipped': 'skipped'}}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_json.loads.assert_called_once_with(file_obj)
+ mock_utils.get_duration.assert_called_once_with(
+ 'start_date', 'stop_date', logger_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.sub_testcase.assert_called_once_with()
+ testcase_obj.name.assert_called_once_with()
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.dt_utils')
+ @patch('dovetail.report.os.path')
+ def test_functest_rally_crawler_crawl(self, mock_path, mock_utils,
+ mock_config, mock_json, mock_open):
+ logger_obj = Mock()
+ mock_config.dovetail_config = {'build_tag': 'tag'}
+ dt_report.FunctestCrawler.logger = logger_obj
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'rally_full'
+ testcase_obj.name.return_value = 'name'
+ testcase_obj.sub_testcase.return_value = ['subt_a', 'subt_b', 'subt_c']
+ file_obj = Mock()
+ mock_open.return_value.__enter__.side_effect = [[file_obj], file_obj]
+ data_dict = {
+ 'case_name': 'rally_full',
+ 'build_tag': 'tag-name',
+ 'criteria': 'criteria',
+ 'start_date': 'start_date',
+ 'stop_date': 'stop_date',
+ 'details': {
+ 'modules': [
+ {
+ 'details': {
+ 'success': ['subt_a'],
+ 'failures': ['subt_b', 'subt_c']
+ },
+ 'module': 'module'
+ }
+ ]
+ }
+ }
+
+ mock_json.loads.return_value = data_dict
+ mock_utils.get_duration.return_value = 'duration'
+
+ crawler = dt_report.FunctestCrawler()
+ result = crawler.crawl(testcase_obj, [file_path, file_path])
+ expected = {'criteria': 'criteria', 'timestart': 'start_date',
+ 'timestop': 'stop_date', 'duration': 'duration',
+ 'details': {
+ 'tests': 3, 'failures': 2,
+ 'success': ['subt_a'], 'errors': ['subt_b', 'subt_c'],
+ 'skipped': []}}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_with(file_path, 'r')
+ mock_json.loads.assert_called_with(file_obj)
+ mock_utils.get_duration.assert_called_once_with(
+ 'start_date', 'stop_date', logger_obj)
+ testcase_obj.set_results.assert_called_with(expected)
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.sub_testcase.assert_called_once_with()
+ testcase_obj.name.assert_called_once_with()
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.dt_utils')
+ @patch('dovetail.report.os.path')
+ def test_functest_crawler_crawl_errors(self, mock_path, mock_utils,
+ mock_config, mock_load, mock_open):
+ logger_obj = Mock()
+ mock_config.dovetail_config = {'build_tag': 'tag'}
+ dt_report.FunctestCrawler.logger = logger_obj
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'name'
+ testcase_obj.name.return_value = 'name'
+ testcase_obj.sub_testcase.return_value = ['subt_a']
+ file_a = Mock()
+ file_b = Mock()
+ mock_open.return_value.__enter__.return_value = [file_a, file_b]
+ mock_load.side_effect = [ValueError(), {}]
+ mock_utils.get_duration.return_value = 'duration'
+
+ crawler = dt_report.FunctestCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_load.assert_has_calls([call(file_a), call(file_b)])
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.sub_testcase.assert_called_once_with()
+ testcase_obj.name.assert_called_once_with()
+ logger_obj.exception.assert_called_once_with(
+ "Result data don't have key 'case_name'.")
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.dt_logger')
+ def test_functestk8s_crawler_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.FunctestK8sCrawler.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.FunctestK8sCrawler.logger)
+
+ @patch('dovetail.report.FunctestK8sCrawler.crawl_from_file')
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.os.path')
+ def test_functestk8s_crawler_crawl_none(self, mock_path, mock_config,
+ mock_crawl):
+ logger_obj = Mock()
+ dt_report.FunctestK8sCrawler.logger = logger_obj
+ mock_crawl.return_value = None
+ testcase = 'testcase'
+ file_path = 'file_path'
+
+ crawler = dt_report.FunctestK8sCrawler()
+
+ result = crawler.crawl(testcase, [file_path])
+
+ dt_report.FunctestK8sCrawler.crawl_from_file.assert_called_once_with(
+ 'testcase', 'file_path')
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.dt_logger')
+ def test_yardstick_crawler_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.YardstickCrawler.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.YardstickCrawler.logger)
+
+ @patch('dovetail.report.os.path')
+ def test_yardstick_crawler_crawl_not_exists(self, mock_path):
+ logger_obj = Mock()
+ dt_report.YardstickCrawler.logger = logger_obj
+ mock_path.exists.return_value = False
+ file_path = 'file_path'
+
+ crawler = dt_report.YardstickCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ logger_obj.error.assert_called_once_with(
+ 'Result file not found: {}'.format(file_path))
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.dt_utils')
+ @patch('dovetail.report.os.path')
+ def test_yardstick_crawler_crawl(self, mock_path, mock_utils, mock_loads,
+ mock_open):
+ dt_report.YardstickCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'name'
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'result': {
+ 'testcases': {
+ 'name': {
+ 'tc_data': [{
+ 'data': {
+ 'sla_pass': 0
+ }
+ }]
+ }
+ }
+ }
+ }
+ mock_loads.return_value = data_dict
+ mock_utils.get_value_from_dict.return_value = 'PASS'
+
+ crawler = dt_report.YardstickCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'result.criteria', data_dict)
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.dt_utils')
+ @patch('dovetail.report.os.path')
+ def test_yardstick_crawler_crawl_key_error(self, mock_path, mock_utils,
+ mock_loads, mock_open):
+ logger_obj = Mock()
+ dt_report.YardstickCrawler.logger = logger_obj
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ testcase_obj.validate_testcase.return_value = 'name'
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+
+ mock_loads.return_value = {}
+ mock_utils.get_value_from_dict.return_value = 'PASS'
+
+ crawler = dt_report.YardstickCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'PASS'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'result.criteria', {})
+ testcase_obj.validate_testcase.assert_called_once_with()
+ testcase_obj.set_results.assert_called_once_with(expected)
+ logger_obj.exception.assert_called_once_with(
+ "Pass flag not found 'result'")
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.dt_logger')
+ def test_bottlenecks_crawler_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.BottlenecksCrawler.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.BottlenecksCrawler.logger)
+
+ @patch('dovetail.report.os.path')
+ def test_bottlenecks_crawler_crawl_not_exists(self, mock_path):
+ logger_obj = Mock()
+ dt_report.BottlenecksCrawler.logger = logger_obj
+ mock_path.exists.return_value = False
+ file_path = 'file_path'
+
+ crawler = dt_report.BottlenecksCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ logger_obj.error.assert_called_once_with(
+ 'Result file not found: {}'.format(file_path))
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_bottlenecks_crawler_crawl_pass(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.BottlenecksCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'data_body': {
+ 'result': 'PASS'
+ }
+ }
+ mock_loads.return_value = data_dict
+
+ crawler = dt_report.BottlenecksCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'PASS'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_bottlenecks_crawler_crawl_fail(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.BottlenecksCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'data_body': {
+ 'result': 'FAIL'
+ }
+ }
+ mock_loads.return_value = data_dict
+
+ crawler = dt_report.BottlenecksCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_bottlenecks_crawler_crawl_key_error(self, mock_path, mock_loads,
+ mock_open):
+ logger_obj = Mock()
+ dt_report.BottlenecksCrawler.logger = logger_obj
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+
+ mock_loads.return_value = {}
+
+ crawler = dt_report.BottlenecksCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ logger_obj.exception.assert_called_once_with(
+ "Pass flag not found 'data_body'")
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.report.os.path')
+ def test_shell_crawler_crawl_not_exists(self, mock_path):
+ mock_path.exists.return_value = False
+ file_path = 'file_path'
+
+ crawler = dt_report.ShellCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.os.path')
+ def test_shell_crawler_crawl_exception(self, mock_path, mock_open):
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ mock_open.return_value.__enter__.return_value = Exception()
+
+ crawler = dt_report.ShellCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.load')
+ @patch('dovetail.report.os.path')
+ def test_shell_crawler_crawl(self, mock_path, mock_load,
+ mock_open):
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = 'result'
+
+ crawler = dt_report.ShellCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_load.assert_called_once_with(file_obj)
+ self.assertEqual('result', result)
+
+ @patch('dovetail.report.dt_logger')
+ def test_onapvtp_crawler_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.OnapVtpCrawler.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.OnapVtpCrawler.logger)
+
+ @patch('dovetail.report.dt_logger')
+ def test_onapvvp_crawler_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.OnapVvpCrawler.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.OnapVvpCrawler.logger)
+
+ @patch('dovetail.report.os.path')
+ def test_onapvtp_crawler_crawl_not_exists(self, mock_path):
+ logger_obj = Mock()
+ dt_report.OnapVtpCrawler.logger = logger_obj
+ mock_path.exists.return_value = False
+ file_path = 'file_path'
+
+ crawler = dt_report.OnapVtpCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ logger_obj.error.assert_called_once_with(
+ 'Result file not found: {}'.format(file_path))
+ self.assertEqual(None, result)
+
+ @patch('dovetail.report.os.path')
+ def test_onapvvp_crawler_crawl_not_exists(self, mock_path):
+ logger_obj = Mock()
+ dt_report.OnapVvpCrawler.logger = logger_obj
+ mock_path.exists.return_value = False
+ file_path = 'file_path'
+
+ crawler = dt_report.OnapVvpCrawler()
+ result = crawler.crawl(None, [file_path])
+
+ mock_path.exists.assert_called_once_with(file_path)
+ logger_obj.error.assert_called_once_with(
+ 'Result file not found: {}'.format(file_path))
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.os.path')
+ def test_onapvvp_crawler_crawl_pass(self, mock_path,
+ mock_open):
+ dt_report.OnapVvpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ file_obj.read.return_value = json.dumps({'outcome': 'PASS'})
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ crawler = dt_report.OnapVvpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'PASS'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ file_obj.read.assert_called_once_with()
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.os.path')
+ def test_onapvvp_crawler_crawl_fail(self, mock_path,
+ mock_open):
+ dt_report.OnapVvpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ file_obj.read.return_value = json.dumps({'outcome': 'FAIL'})
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ crawler = dt_report.OnapVvpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ file_obj.read.assert_called_once_with()
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.os.path')
+ def test_onapvvp_crawler_crawl_value_exception(self, mock_path,
+ mock_open):
+ dt_report.OnapVvpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ file_obj.read.return_value = 'error'
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ crawler = dt_report.OnapVvpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ file_obj.read.assert_called_once_with()
+ dt_report.OnapVvpCrawler.logger.exception.assert_called_once_with(
+ 'Result file has invalid format')
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.os.path')
+ def test_onapvvp_crawler_crawl_key_exception(self, mock_path,
+ mock_open):
+ dt_report.OnapVvpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ file_obj.read.return_value = json.dumps({'key': 'value'})
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ crawler = dt_report.OnapVvpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ file_obj.read.assert_called_once_with()
+ dt_report.OnapVvpCrawler.logger.exception.assert_called_once_with(
+ "Outcome field not found 'outcome'")
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_onapvtp_crawler_crawl_pass(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.OnapVtpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'results': [
+ {"property": "results", "value": "{value=SUCCESS}"},
+ {"property": "build_tag", "value": "test-name"},
+ {"property": "criteria", "value": "PASS"}
+ ]
+ }
+ mock_loads.return_value = data_dict
+
+ crawler = dt_report.OnapVtpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'PASS'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_onapvtp_crawler_crawl_fail(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.OnapVtpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'results': [
+ {"property": "results", "value": "{value=file doesn't exist}"},
+ {"property": "build_tag", "value": "test-name"},
+ {"property": "criteria", "value": "FAILED"}
+ ]
+ }
+ mock_loads.return_value = data_dict
+
+ crawler = dt_report.OnapVtpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_onapvtp_crawler_crawl_no_criteria(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.OnapVtpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'results': [
+ {"property": "results", "value": "{value=file doesn't exist}"},
+ {"property": "build_tag", "value": "test-name"},
+ {"property": "error_criteria", "value": "FAILED"}
+ ]
+ }
+ mock_loads.return_value = data_dict
+
+ crawler = dt_report.OnapVtpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ dt_report.OnapVtpCrawler.logger.error.assert_called_once_with(
+ 'There is no property criteria.')
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_onapvtp_crawler_crawl_exception(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.OnapVtpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ data_dict = {
+ 'error_results': [
+ {"property": "results", "value": "{value=file doesn't exist}"},
+ {"property": "build_tag", "value": "test-name"},
+ {"property": "error_criteria", "value": "FAILED"}
+ ]
+ }
+ mock_loads.return_value = data_dict
+
+ crawler = dt_report.OnapVtpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ dt_report.OnapVtpCrawler.logger.exception.assert_called_once_with(
+ "Pass flag not found 'results'")
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.report.json.loads')
+ @patch('dovetail.report.os.path')
+ def test_onapvtp_crawler_crawl_value_error(self, mock_path, mock_loads,
+ mock_open):
+ dt_report.OnapVtpCrawler.logger = Mock()
+ mock_path.exists.return_value = True
+ file_path = 'file_path'
+ testcase_obj = Mock()
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = [file_obj]
+ mock_loads.side_effect = ValueError('No JSON object could be decoded')
+
+ crawler = dt_report.OnapVtpCrawler()
+ result = crawler.crawl(testcase_obj, [file_path])
+ expected = {'criteria': 'FAIL'}
+
+ mock_path.exists.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_loads.assert_called_once_with(file_obj)
+ testcase_obj.set_results.assert_called_once_with(expected)
+ self.assertEqual(expected, result)
+
+ def test_crawler_factory(self):
+ result = dt_report.CrawlerFactory.create('shell')
+ self.assertEqual(dt_report.ShellCrawler, result.__class__)
+
+ def test_crawler_factory_none(self):
+ self.assertEqual(None, dt_report.CrawlerFactory.create('other'))
+
+ def test_result_checker(self):
+ self.assertEqual('PASS', dt_report.ResultChecker.check())
+
+ @patch('dovetail.report.dt_logger')
+ def test_functest_checker_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.FunctestChecker.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.FunctestChecker.logger)
+
+ def test_functest_get_sub_testcase_no_result(self):
+ self.assertEqual(
+ False, dt_report.FunctestChecker.get_sub_testcase(None, None))
+
+ def test_functest_get_sub_testcase_simple_match(self):
+ self.assertEqual(
+ True,
+ dt_report.FunctestChecker.get_sub_testcase('subt_a',
+ ['subt_b', 'subt_a']))
+
+ def test_functest_get_sub_testcase_extended_match(self):
+ self.assertEqual(
+ True,
+ dt_report.FunctestChecker.get_sub_testcase('subt_a',
+ ['subt_b', 'subt_a+']))
+
+ def test_functest_get_sub_testcase_class_match(self):
+ self.assertEqual(
+ True,
+ dt_report.FunctestChecker.get_sub_testcase('subclass_a.subt_a',
+ ['subclass_a',
+ 'subclass_b.subt_b']))
+
+ def test_functest_get_sub_testcase_class_no_match(self):
+ self.assertEqual(
+ False,
+ dt_report.FunctestChecker.get_sub_testcase('subclass_a.subt_a',
+ ['subclass_a.subt_a_a',
+ 'subclass_b.subt_b']))
+
+ def test_functest_get_sub_no_match(self):
+ self.assertEqual(
+ False,
+ dt_report.FunctestChecker.get_sub_testcase('subt_a',
+ ['subt_b']))
+
+ def test_functest_check_no_db_results(self):
+ testcase_obj = Mock()
+ testcase_obj.sub_testcase.return_value = ['subt_a']
+
+ checker = dt_report.FunctestChecker()
+ checker.check(testcase_obj, None)
+
+ testcase_obj.sub_testcase.assert_called_once_with()
+ testcase_obj.sub_testcase_passed.assert_called_once_with(
+ 'subt_a', 'FAIL')
+
+ def test_functest_check_no_subtestcases(self):
+ testcase_obj = Mock()
+ testcase_obj.sub_testcase.return_value = None
+
+ checker = dt_report.FunctestChecker()
+ checker.check(testcase_obj, {'criteria': 'PASS'})
+
+ testcase_obj.sub_testcase.assert_called_once_with()
+ testcase_obj.passed.assert_called_once_with('PASS')
+
+ @patch.object(dt_report.FunctestChecker, 'get_sub_testcase')
+ def test_functest_check(self, mock_get):
+ testcase_obj = Mock()
+ testcase_obj.sub_testcase.return_value = [
+ 'subt_a', 'subt_b', 'subt_c', 'subt_d']
+ logger_obj = Mock()
+ dt_report.FunctestChecker.logger = logger_obj
+ db_result = {
+ 'criteria': 'PASS',
+ 'details': {
+ 'success': True,
+ 'skipped': False
+ }
+ }
+ mock_get.side_effect = [True, False, True, False, False, KeyError()]
+
+ checker = dt_report.FunctestChecker()
+ checker.check(testcase_obj, db_result)
+
+ testcase_obj.sub_testcase.assert_called_once_with()
+ testcase_obj.passed.assert_has_calls([call('PASS'), call('FAIL')])
+
+ @patch('dovetail.report.dt_logger')
+ def test_functestk8s_checker_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.FunctestK8sChecker.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.FunctestK8sChecker.logger)
+
+ @patch('dovetail.report.dt_logger')
+ def test_yardstick_checker_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.YardstickChecker.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.YardstickChecker.logger)
+
+ def test_yardstick_check_result(self):
+ testcase_obj = Mock()
+ result = {'criteria': 'PASS'}
+
+ dt_report.YardstickChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('PASS')
+
+ def test_yardstick_check_result_none(self):
+ testcase_obj = Mock()
+ result = {}
+
+ dt_report.YardstickChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('FAIL')
+
+ @patch('dovetail.report.dt_logger')
+ def test_bottlenecks_checker_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.BottlenecksChecker.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.BottlenecksChecker.logger)
+
+ def test_bottlenecks_check_result(self):
+ testcase_obj = Mock()
+ result = {'criteria': 'PASS'}
+
+ dt_report.BottlenecksChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('PASS')
+
+ def test_bottlenecks_check_result_none(self):
+ testcase_obj = Mock()
+ result = {}
+
+ dt_report.BottlenecksChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('FAIL')
+
+ def test_shell_check_result(self):
+ testcase_obj = Mock()
+ result = {'pass': True}
+
+ dt_report.ShellChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with(True)
+
+ def test_shell_check_result_exception(self):
+ testcase_obj = Mock()
+ result = {}
+
+ dt_report.ShellChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with(False)
+
+ def test_checker_factory(self):
+ result = dt_report.CheckerFactory.create('shell')
+ self.assertEqual(dt_report.ShellChecker, result.__class__)
+
+ def test_checker_factory_none(self):
+ self.assertEqual(None, dt_report.CheckerFactory.create('other'))
+
+ @patch('dovetail.report.dt_logger')
+ def test_onapvtp_checker_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.OnapVtpChecker.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.OnapVtpChecker.logger)
+
+ def test_onapvtp_check_result_none(self):
+ testcase_obj = Mock()
+ result = {}
+
+ dt_report.OnapVtpChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('FAIL')
+
+ def test_onapvtp_check_result(self):
+ testcase_obj = Mock()
+ result = {'criteria': 'PASS'}
+
+ dt_report.OnapVtpChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('PASS')
+
+ @patch('dovetail.report.dt_logger')
+ def test_onapvvp_checker_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ dt_report.OnapVvpChecker.create_log()
+
+ self.assertEqual(getlogger_obj, dt_report.OnapVvpChecker.logger)
+
+ def test_onapvvp_check_result_none(self):
+ testcase_obj = Mock()
+ result = {}
+
+ dt_report.OnapVvpChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('FAIL')
+
+ def test_onapvvp_check_result(self):
+ testcase_obj = Mock()
+ result = {'criteria': 'PASS'}
+
+ dt_report.OnapVvpChecker.check(testcase_obj, result)
+
+ testcase_obj.passed.assert_called_once_with('PASS')
+
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.os.path')
+ @patch('builtins.open')
+ @patch('dovetail.report.os.getenv')
+ def test_get_checksum_tosca(self, mock_env, mock_open, mock_path,
+ mock_config):
+ mock_config.dovetail_config = {
+ 'config_dir': 'config_dir'
+ }
+ mock_env.return_value = 'csar_file'
+ file_obj = Mock()
+ file_obj.read.return_value = 'info'
+ file_obj.__exit__ = Mock()
+ file_obj.__enter__ = Mock()
+ mock_open.return_value = file_obj
+ mock_path.isdir.return_value = False
+ mock_path.isfile.return_value = True
+
+ dt_report.Report.get_checksum('tosca')
+
+ @patch('dovetail.report.dt_cfg')
+ @patch('dovetail.report.os.path')
+ @patch('dovetail.report.os.walk')
+ @patch('builtins.open')
+ @patch('dovetail.report.os.getenv')
+ def test_get_checksum_heat(self, mock_env, mock_open, mock_walk, mock_path,
+ mock_config):
+ mock_config.dovetail_config = {
+ 'config_dir': 'config_dir'
+ }
+ mock_env.return_value = 'heat_templates_archive'
+ file_obj = Mock()
+ file_obj.read.return_value = 'info'
+ file_obj.__exit__ = Mock()
+ file_obj.__enter__ = Mock()
+ mock_open.return_value = file_obj
+ mock_path.isdir.return_value = True
+ mock_walk.return_value = [('root', ['dir'], ['file'])]
+
+ dt_report.Report.get_checksum('heat')
diff --git a/dovetail/tests/unit/test_run.py b/dovetail/tests/unit/test_run.py
new file mode 100644
index 00000000..c1e37116
--- /dev/null
+++ b/dovetail/tests/unit/test_run.py
@@ -0,0 +1,655 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import os
+import unittest
+import yaml
+from mock import patch, call, Mock
+from _pytest.monkeypatch import MonkeyPatch
+
+from dovetail.utils.dovetail_config import DovetailConfig
+
+monkeypatch = MonkeyPatch()
+conf_path = os.path.abspath(
+ os.path.join(os.path.dirname(__file__)))
+file_path = os.path.join(os.path.dirname(__file__), 'cmd_config.yml')
+with open(file_path) as f:
+ extra_config = yaml.safe_load(f)
+monkeypatch.setattr(DovetailConfig, 'load_config_files', Mock())
+monkeypatch.setattr(DovetailConfig, 'dovetail_config', extra_config)
+from dovetail import run as dt_run # noqa: E402
+monkeypatch.undo()
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class RunTesting(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ @patch('dovetail.run.dt_testcase.Testsuite')
+ def test_load_testsuite(self, mock_testsuite):
+ mock_testsuite.get.return_value = 'suite_a'
+
+ result = dt_run.load_testsuite('testsuite')
+
+ mock_testsuite.load.assert_called_once_with()
+ mock_testsuite.get.assert_called_once_with('testsuite')
+ self.assertEqual('suite_a', result)
+
+ @patch('dovetail.run.dt_report.Report')
+ def test_run_test_no_list(self, mock_report):
+ logger = Mock()
+ mock_report.return_value = Mock()
+
+ dt_run.run_test([], False, logger)
+ logger.warning.assert_called_once_with(
+ "No test case will be executed.")
+
+ @patch('dovetail.run.datetime')
+ @patch('dovetail.run.dt_utils')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_report.Report')
+ @patch('dovetail.run.dt_testcase.Testcase')
+ @patch('dovetail.run.time')
+ @patch('os.getenv')
+ def test_run_test(self, mock_getenv, mock_time, mock_testcase, mock_report,
+ mock_config, mock_utils, mock_datetime):
+ logger = Mock()
+ report_obj = Mock()
+ mock_report.return_value = report_obj
+ mock_time.time.side_effect = [42, 43, 83, 84]
+ datetime_obj = Mock()
+ mock_datetime.fromtimestamp.return_value = datetime_obj
+ datetime_obj.strftime.side_effect = ['1969-12-31 19:00:43',
+ '1969-12-31 19:01:23']
+ testcase_name = 'testcase'
+ testcase_obj = Mock()
+ mock_testcase.get.return_value = testcase_obj
+ mock_config.dovetail_config = {'stop': True}
+ mock_getenv.return_value = 'true'
+ report_obj.check_tc_result.return_value = {'criteria': 'PASS'}
+ mock_utils.push_results_to_db.return_value = True
+
+ dt_run.run_test([testcase_name], True, logger)
+
+ mock_time.time.assert_has_calls([call(), call(), call(), call()])
+ logger.info.assert_called_once_with(
+ '>>[testcase]: {}'.format(testcase_name))
+ mock_testcase.get.assert_called_once_with(testcase_name)
+ testcase_obj.run.assert_called_once_with()
+ report_obj.check_tc_result.assert_called_once_with(testcase_obj)
+ mock_utils.push_results_to_db.assert_called_once_with(
+ case_name=testcase_name,
+ start_date='1969-12-31 19:00:43',
+ stop_date='1969-12-31 19:01:23',
+ details={'criteria': 'PASS'},
+ logger=logger)
+ report_obj.generate.assert_called_once_with([testcase_name], 42)
+ report_obj.save_logs.assert_called_once_with()
+
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_report.Report')
+ @patch('dovetail.run.dt_testcase.Testcase')
+ @patch('dovetail.run.time')
+ def test_run_test_fail(self, mock_time, mock_testcase, mock_report,
+ mock_config):
+ logger = Mock()
+ report_obj = Mock()
+ mock_report.return_value = report_obj
+ testcase_name = 'testcase'
+ testcase_obj = Mock()
+ mock_testcase.get.return_value = testcase_obj
+ mock_config.dovetail_config = {'stop': True}
+ report_obj.check_tc_result.return_value = {'criteria': 'FAIL'}
+
+ dt_run.run_test([testcase_name], True, logger)
+
+ mock_time.time.assert_has_calls([call(), call(), call().__float__(),
+ call(), call().__float__()])
+ logger.info.assert_has_calls([
+ call('>>[testcase]: {}'.format(testcase_name)),
+ call('Stop because {} failed'.format(testcase_name))])
+ mock_testcase.get.assert_called_once_with(testcase_name)
+ testcase_obj.run.assert_called_once_with()
+ report_obj.check_tc_result.assert_called_once_with(testcase_obj)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_report.Report')
+ @patch('dovetail.run.dt_testcase.Testcase')
+ @patch('dovetail.run.time')
+ def test_run_test_fail_key_error(self, mock_time, mock_testcase,
+ mock_report, mock_config):
+ logger = Mock()
+ report_obj = Mock()
+ mock_report.return_value = report_obj
+ mock_time.time.return_value = 42
+ testcase_name = 'testcase'
+ testcase_obj = Mock()
+ mock_testcase.get.return_value = testcase_obj
+ mock_config.dovetail_config = {'stop': True}
+ report_obj.check_tc_result.return_value = {'key': 'value'}
+
+ dt_run.run_test([testcase_name], True, logger)
+
+ mock_time.time.assert_has_calls([call(), call(), call()])
+ logger.info.assert_has_calls([
+ call('>>[testcase]: {}'.format(testcase_name)),
+ call('Stop because {} failed'.format(testcase_name))])
+ logger.error.assert_called_once_with("There is no key 'criteria'.")
+ mock_testcase.get.assert_called_once_with(testcase_name)
+ testcase_obj.run.assert_called_once_with()
+ report_obj.check_tc_result.assert_called_once_with(testcase_obj)
+
+ @patch('dovetail.run.dt_cfg')
+ def test_filter_config(self, mock_config):
+ mock_config.dovetail_config = {
+ 'cli': {
+ 'key_a': {
+ 'config': {
+ 'config_key': {'path': 'a'},
+ 'KEY_UPPER': {'path': 'b'}
+ }
+ },
+ 'key_b': {},
+ 'key_c': {
+ 'config': None
+ },
+ 'key_d': {
+ 'invalid': {}
+ }
+ }
+ }
+ input_dict = {
+ 'config_key': 'c',
+ 'key_upper': 'd'
+ }
+ expected_dict = {
+ 'config_key': {'path': 'a', 'value': 'c'},
+ 'KEY_UPPER': {'path': 'b', 'value': 'd'}
+ }
+
+ result = dt_run.filter_config(input_dict, Mock())
+
+ self.assertEqual(expected_dict, result)
+
+ @patch('dovetail.run.dt_cfg')
+ def test_filter_config_none(self, mock_config):
+ mock_config.dovetail_config = {'cli': {}}
+ result = dt_run.filter_config({}, Mock())
+
+ self.assertEqual(None, result)
+
+ @patch('dovetail.run.dt_cfg')
+ def test_filter_config_keyerror(self, mock_config):
+ mock_config.dovetail_config = {
+ 'cli': {
+ 'key_a': {
+ 'config': {
+ 'config_key': {'invalid': 'a'}
+ }
+ }
+ }
+ }
+ input_dict = {'config_key': 'c'}
+ logger = Mock()
+
+ with self.assertRaises(SystemExit) as cm:
+ dt_run.filter_config(input_dict, logger)
+
+ logger.exception.assert_called_once_with("KeyError 'path'.")
+ expected = cm.exception
+ self.assertEqual(expected.code, 2)
+
+ @patch('dovetail.run.Container')
+ @patch('dovetail.run.Parser')
+ @patch('dovetail.run.dt_report')
+ @patch('dovetail.run.dt_test_runner')
+ @patch('dovetail.run.dt_testcase')
+ def test_create_logs(self, mock_testcase, mock_test_runner, mock_report,
+ mock_parser, mock_container):
+
+ dt_run.create_logs()
+
+ mock_container.create_log.assert_called_once_with()
+ mock_parser.create_log.assert_called_once_with()
+ mock_report.Report.create_log.assert_called_once_with()
+ mock_report.FunctestCrawler.create_log.assert_called_once_with()
+ mock_report.YardstickCrawler.create_log.assert_called_once_with()
+ mock_report.BottlenecksCrawler.create_log.assert_called_once_with()
+ mock_report.FunctestChecker.create_log.assert_called_once_with()
+ mock_report.YardstickChecker.create_log.assert_called_once_with()
+ mock_report.BottlenecksChecker.create_log.assert_called_once_with()
+ mock_testcase.Testcase.create_log.assert_called_once_with()
+ mock_testcase.Testsuite.create_log.assert_called_once_with()
+ mock_test_runner.DockerRunner.create_log.assert_called_once_with()
+ mock_test_runner.ShellRunner.create_log.assert_called_once_with()
+
+ @patch('dovetail.run.dt_utils')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.os')
+ def test_clean_results_dir(self, mock_os, mock_config, mock_utils):
+ mock_config.dovetail_config = {'result_dir': 'value'}
+ mock_os.path.exists.return_value = True
+ mock_os.path.isdir.return_value = True
+
+ dt_run.clean_results_dir()
+
+ mock_os.path.exists.assert_called_once_with('value')
+ mock_os.path.isdir.assert_called_once_with('value')
+ mock_utils.exec_cmd.assert_called_once_with(
+ 'rm -rf value/*', exit_on_error=False, exec_msg_on=False)
+
+ @patch('dovetail.run.dt_utils')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.os')
+ def test_clean_results_dir_error(self, mock_os, mock_config, mock_utils):
+ mock_config.dovetail_config = {'result_dir': 'value'}
+ mock_os.path.exists.return_value = True
+ mock_os.path.isdir.return_value = False
+
+ with self.assertRaises(SystemExit) as cm:
+ dt_run.clean_results_dir()
+
+ mock_os.path.exists.assert_called_once_with('value')
+ mock_os.path.isdir.assert_called_once_with('value')
+ expected = cm.exception
+ self.assertEqual(expected.code, 2)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.os')
+ def test_get_result_path(self, mock_os, mock_config):
+ dovetail_home = 'dovetail_home'
+ mock_os.environ = {'DOVETAIL_HOME': dovetail_home}
+ mock_os.path.join.side_effect = [
+ 'result_path', 'images_dir', 'pre_config_path', 'patch_set_path',
+ 'userconfig_dir']
+ mock_config.dovetail_config = {}
+
+ result = dt_run.get_result_path()
+
+ mock_os.path.join.assert_has_calls([
+ call(dovetail_home, 'results'),
+ call(dovetail_home, 'images'),
+ call(dovetail_home, 'pre_config'),
+ call(dovetail_home, 'patches'),
+ call(dovetail_home, 'userconfig')])
+ expected_dict = {
+ 'result_dir': 'result_path',
+ 'images_dir': 'images_dir',
+ 'config_dir': 'pre_config_path',
+ 'patch_dir': 'patch_set_path',
+ 'userconfig_dir': 'userconfig_dir'}
+ self.assertEqual(expected_dict, mock_config.dovetail_config)
+ self.assertEqual(dovetail_home, result)
+
+ @patch('dovetail.run.os')
+ def test_get_result_path_exception(self, mock_os):
+ mock_os.environ = {}
+
+ result = dt_run.get_result_path()
+
+ self.assertEqual(None, result)
+
+ @patch('dovetail.run.constants')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_utils')
+ @patch('dovetail.run.os')
+ def test_copy_userconfig_files(self, mock_os, mock_utils, mock_config,
+ mock_constants):
+ mock_config.dovetail_config = {'userconfig_dir': 'value'}
+ mock_os.path.isdir.return_value = False
+ mock_constants.USERCONF_PATH = 'value'
+ logger = Mock()
+
+ dt_run.copy_userconfig_files(logger)
+
+ mock_os.path.isdir.assert_called_once_with('value')
+ mock_os.makedirs.assert_called_once_with('value')
+ mock_utils.exec_cmd.assert_called_once_with(
+ 'cp -r value/* value', logger, exit_on_error=False)
+
+ @patch('dovetail.run.constants')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_utils')
+ @patch('dovetail.run.os')
+ def test_copy_patch_files(self, mock_os, mock_utils, mock_config,
+ mock_constants):
+ mock_config.dovetail_config = {'patch_dir': 'value'}
+ mock_os.path.isdir.return_value = False
+ mock_constants.PATCH_PATH = 'value'
+ logger = Mock()
+
+ dt_run.copy_patch_files(logger)
+
+ mock_os.path.isdir.assert_called_once_with('value')
+ mock_os.makedirs.assert_called_once_with('value')
+ mock_utils.exec_cmd.assert_called_once_with(
+ 'cp -a -r value/* value', logger, exit_on_error=False)
+
+ @patch('dovetail.run.os')
+ def test_update_deploy_scenario(self, mock_os):
+ logger = Mock()
+ mock_os.environ = {}
+
+ dt_run.update_deploy_scenario(logger, deploy_scenario='a')
+
+ logger.info.assert_called_once_with('DEPLOY_SCENARIO : %s', 'a')
+ self.assertEqual({'DEPLOY_SCENARIO': 'a'}, mock_os.environ)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch.object(dt_run, 'filter_config')
+ def test_cli_no_validation(self, mock_filter, mock_config):
+ mock_config.dovetail_config = {}
+ logger = Mock()
+
+ dt_run.parse_cli(logger=logger,
+ offline='a',
+ no_clean='b',
+ stop='c',
+ mandatory='d',
+ optional='e',
+ no_api_validation=True)
+ expected_dict = {
+ 'offline': 'a',
+ 'noclean': 'b',
+ 'stop': 'c',
+ 'mandatory': 'd',
+ 'optional': 'e',
+ 'no_api_validation': True
+ }
+
+ logger.warning.assert_called_once_with(
+ 'Strict API response validation DISABLED.')
+ self.assertEqual(expected_dict, mock_config.dovetail_config)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch.object(dt_run, 'filter_config')
+ def test_cli_with_validation(self, mock_filter, mock_config):
+ mock_config.dovetail_config = {}
+
+ dt_run.parse_cli(offline='a',
+ no_clean='b',
+ stop='c',
+ mandatory='d',
+ optional='e',
+ no_api_validation=False)
+ expected_dict = {
+ 'offline': 'a',
+ 'noclean': 'b',
+ 'stop': 'c',
+ 'mandatory': 'd',
+ 'optional': 'e',
+ 'no_api_validation': False
+ }
+
+ self.assertEqual(expected_dict, mock_config.dovetail_config)
+
+ def test_check_testcase_list_not_in_list(self):
+ logger = Mock()
+
+ result = dt_run.check_testcase_list(['testcase'], logger)
+
+ logger.error.assert_called_once_with(
+ 'Test case testcase is not defined.')
+ self.assertEqual(None, result)
+
+ def test_check_testcase_list_none(self):
+ logger = Mock()
+ result = dt_run.check_testcase_list(None, logger)
+
+ logger.error.assert_called_once_with(
+ 'There is no test case to be executed.')
+ self.assertEqual(None, result)
+
+ @patch('dovetail.run.dt_testcase.Testcase')
+ def test_check_testcase_list(self, mock_testcase):
+ testcase_list = ['testcase']
+ mock_testcase.testcase_list = testcase_list
+
+ result = dt_run.check_testcase_list(testcase_list)
+
+ self.assertEqual(testcase_list, result)
+
+ @patch('dovetail.run.dt_testcase.Testcase')
+ @patch.object(dt_run, 'check_testcase_list')
+ def test_get_testcase_list_check(self, mock_check, mock_testcase):
+ testcase_list = ['testcase']
+ mock_check.return_value = testcase_list
+
+ result = dt_run.get_testcase_list(testcase=testcase_list)
+
+ mock_check.assert_called_once_with(testcase_list, None)
+ mock_testcase.load.assert_called_once_with()
+ self.assertEqual(testcase_list, result)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_testcase.Testcase')
+ @patch.object(dt_run, 'check_testcase_list')
+ @patch.object(dt_run, 'load_testsuite')
+ def test_get_testcase_list(self, mock_load, mock_check, mock_testcase,
+ mock_config):
+ mock_config.dovetail_config = {'testsuite_supported': ['suite']}
+ testcase_list = ['testcase']
+ mock_testcase.check_testarea.return_value = (True, 'area')
+ mock_load.return_value = 'testsuite_yaml'
+ mock_testcase.get_testcases_for_testsuite.return_value = testcase_list
+ mock_check.return_value = testcase_list
+
+ result = dt_run.get_testcase_list(
+ testcase=None, testsuite='suite', testarea='area')
+
+ mock_testcase.load.assert_called_once_with()
+ mock_testcase.check_testarea.assert_called_once_with('area')
+ mock_load.assert_called_once_with('suite')
+ mock_testcase.get_testcases_for_testsuite.assert_called_once_with(
+ 'testsuite_yaml', 'area')
+ mock_check.assert_called_once_with(testcase_list, None)
+ self.assertEqual(testcase_list, result)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_testcase.Testcase')
+ def test_get_testcase_list_no_testsuite(self, mock_testcase, mock_config):
+ logger = Mock()
+ mock_config.dovetail_config = {'testsuite_supported': []}
+ mock_testcase.check_testarea.return_value = (True, 'area')
+
+ result = dt_run.get_testcase_list(
+ logger, testcase=None, testsuite='suite', testarea='area')
+
+ mock_testcase.load.assert_called_once_with()
+ mock_testcase.check_testarea.assert_called_once_with('area')
+ logger.error.assert_called_once_with(
+ 'Test suite suite is not defined.')
+ self.assertEqual(None, result)
+
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_testcase.Testcase')
+ def test_get_testcase_list_no_testarea(self, mock_testcase, mock_config):
+ logger = Mock()
+ mock_config.dovetail_config = {'testsuite_supported': ['suite']}
+ mock_testcase.check_testarea.return_value = (False, 'area')
+
+ result = dt_run.get_testcase_list(
+ logger, testcase=None, testsuite='suite', testarea='area')
+
+ mock_testcase.load.assert_called_once_with()
+ mock_testcase.check_testarea.assert_called_once_with('area')
+ logger.error.assert_called_once_with(
+ 'Test area area is not defined.')
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.run.os')
+ @patch('dovetail.run.json')
+ @patch('dovetail.run.uuid')
+ @patch('dovetail.run.dt_logger')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_utils')
+ @patch.object(dt_run, 'get_result_path')
+ @patch.object(dt_run, 'clean_results_dir')
+ @patch.object(dt_run, 'parse_cli')
+ @patch.object(dt_run, 'update_deploy_scenario')
+ @patch.object(dt_run, 'copy_userconfig_files')
+ @patch.object(dt_run, 'copy_patch_files')
+ @patch.object(dt_run, 'get_testcase_list')
+ @patch.object(dt_run, 'run_test')
+ @patch.object(dt_run, 'create_logs')
+ def test_main(self, mock_create_logs, mock_run, mock_get_list,
+ mock_copy_patch, mock_copy_userconf, mock_update, mock_parse,
+ mock_clean, mock_get_result, mock_utils, mock_config,
+ mock_logger, mock_uuid, mock_json, mock_os, mock_open):
+ mock_config.dovetail_config = {}
+ mock_os.environ = {'DOVETAIL_HOME': 'dovetail_home'}
+ logger_obj = Mock()
+ logger_temp_obj = Mock()
+ file_obj = Mock()
+ logger_temp_obj.getLogger.return_value = logger_obj
+ mock_logger.Logger.return_value = logger_temp_obj
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_json.dumps.return_value = 'results text'
+ mock_uuid.uuid1.return_value = 42
+ mock_get_result.return_value = True
+ testcase_list = ['testcase']
+ mock_get_list.return_value = testcase_list
+ kwargs_dict = {
+ 'debug': True,
+ 'opnfv_ci': True,
+ 'report': True,
+ 'testsuite': 'testsuite',
+ 'docker_tag': '2.0.0',
+ 'no_api_validation': False
+ }
+
+ with self.assertRaises(SystemExit) as cm:
+ dt_run.main(['--testsuite=testsuite', '--debug', '--report',
+ '2.0.0', '--opnfv-ci'])
+ expected = cm.exception
+
+ logger_temp_obj.getLogger.assert_called_once_with()
+ mock_logger.Logger.assert_called_once_with('run')
+ mock_uuid.uuid1.assert_called_once_with()
+ self.assertEqual({'build_tag': 'daily-master-42'},
+ mock_config.dovetail_config)
+ mock_get_result.assert_called_once_with()
+ mock_clean.assert_called_once_with()
+ self.assertEqual({'DOVETAIL_HOME': 'dovetail_home', 'DEBUG': 'true',
+ 'OPNFV_CI': 'true', 'validation': 'enabled'},
+ mock_os.environ)
+ mock_create_logs.assert_called_once_with()
+ logger_obj.info.assert_has_calls([
+ call('================================================'),
+ call('Dovetail compliance: testsuite!'),
+ call('================================================'),
+ call('Build tag: daily-master-42')])
+ mock_parse.assert_called_once_with(logger_obj, **kwargs_dict)
+ mock_update.assert_called_once_with(logger_obj, **kwargs_dict)
+ mock_copy_userconf.assert_called_once_with(logger_obj)
+ mock_copy_patch.assert_called_once_with(logger_obj)
+ mock_utils.check_docker_version.assert_called_once_with(logger_obj)
+ mock_get_list.assert_called_once_with(logger_obj, **kwargs_dict)
+ mock_run.assert_called_once_with(
+ testcase_list, kwargs_dict['report'], logger_obj)
+ self.assertEqual(expected.code, 0)
+
+ @patch('dovetail.run.uuid')
+ @patch('dovetail.run.dt_cfg')
+ @patch.object(dt_run, 'get_result_path')
+ def test_main_no_results_path(self, mock_get_result, mock_config,
+ mock_uuid):
+ mock_config.dovetail_config = {}
+ mock_uuid.uuid1.return_value = 42
+ mock_get_result.return_value = False
+
+ with self.assertRaises(SystemExit) as cm:
+ dt_run.main(['2.0.0'])
+ expected = cm.exception
+
+ mock_uuid.uuid1.assert_called_once_with()
+ self.assertEqual({'build_tag': 'daily-master-42'},
+ mock_config.dovetail_config)
+ mock_get_result.assert_called_once_with()
+ self.assertEqual(expected.code, 0)
+
+ @patch('builtins.open')
+ @patch('dovetail.run.json')
+ @patch('dovetail.run.os')
+ @patch('dovetail.run.uuid')
+ @patch('dovetail.run.dt_logger')
+ @patch('dovetail.run.dt_cfg')
+ @patch('dovetail.run.dt_utils')
+ @patch.object(dt_run, 'get_result_path')
+ @patch.object(dt_run, 'clean_results_dir')
+ @patch.object(dt_run, 'update_deploy_scenario')
+ @patch.object(dt_run, 'copy_userconfig_files')
+ @patch.object(dt_run, 'copy_patch_files')
+ @patch.object(dt_run, 'get_testcase_list')
+ @patch.object(dt_run, 'parse_cli')
+ @patch.object(dt_run, 'run_test')
+ @patch.object(dt_run, 'create_logs')
+ def test_main_no_testcaselist(self, mock_create_logs, mock_run, mock_parse,
+ mock_get_list, mock_copy_patch,
+ mock_copy_userconf, mock_update, mock_clean,
+ mock_get_result, mock_utils, mock_config,
+ mock_logger, mock_uuid, mock_os, mock_json,
+ mock_open):
+ mock_config.dovetail_config = {}
+ mock_os.environ = {'DOVETAIL_HOME': 'dovetail_home'}
+ logger_obj = Mock()
+ logger_temp_obj = Mock()
+ file_obj = Mock()
+ logger_temp_obj.getLogger.return_value = logger_obj
+ mock_logger.Logger.return_value = logger_temp_obj
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_json.dumps.return_value = 'results text'
+ mock_uuid.uuid1.return_value = 42
+ mock_get_result.return_value = True
+ mock_get_list.return_value = None
+ kwargs_dict = {
+ 'debug': True,
+ 'opnfv_ci': False,
+ 'report': True,
+ 'testsuite': 'testsuite',
+ 'docker_tag': '2.0.0',
+ 'no_api_validation': False
+ }
+
+ with self.assertRaises(SystemExit) as cm:
+ dt_run.main([
+ '--testsuite=testsuite', '--debug', '--report', '2.0.0'])
+ expected = cm.exception
+ self.assertEqual(expected.code, 2)
+
+ logger_temp_obj.getLogger.assert_called_once_with()
+ mock_logger.Logger.assert_called_once_with('run')
+ mock_uuid.uuid1.assert_called_once_with()
+ self.assertEqual({'build_tag': 'daily-master-42'},
+ mock_config.dovetail_config)
+ mock_get_result.assert_called_once_with()
+ mock_clean.assert_called_once_with()
+ self.assertEqual({'DOVETAIL_HOME': 'dovetail_home', 'DEBUG': 'true',
+ 'OPNFV_CI': 'false', 'validation': 'enabled'},
+ mock_os.environ)
+ mock_create_logs.assert_called_once_with()
+ logger_obj.info.assert_has_calls([
+ call('================================================'),
+ call('Dovetail compliance: testsuite!'),
+ call('================================================'),
+ call('Build tag: daily-master-42')])
+ mock_parse.assert_called_once_with(logger_obj, **kwargs_dict)
+ mock_update.assert_called_once_with(logger_obj, **kwargs_dict)
+ mock_copy_userconf.assert_called_once_with(logger_obj)
+ mock_copy_patch.assert_called_once_with(logger_obj)
+ mock_utils.check_docker_version.assert_called_once_with(logger_obj)
+ mock_get_list.assert_called_once_with(logger_obj, **kwargs_dict)
diff --git a/dovetail/tests/unit/test_test_runner.py b/dovetail/tests/unit/test_test_runner.py
new file mode 100644
index 00000000..232de7b1
--- /dev/null
+++ b/dovetail/tests/unit/test_test_runner.py
@@ -0,0 +1,712 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import unittest
+from mock import patch, call, Mock
+
+import dovetail.test_runner as t_runner
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class TestRunnerTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.patcher1 = patch.object(t_runner, 'dt_logger')
+ self.patcher2 = patch.object(t_runner.DockerRunner,
+ '_update_config')
+
+ self.logger = self.patcher1.start().return_value
+ self._update_config = self.patcher2.start().return_value
+
+ self.testcase = Mock()
+ self.testcase_name = 'testcase_name'
+ self.testcase_type = 'functest'
+ self.testcase_dict = {}
+ self.testcase_valid = 'validate_testcase'
+
+ self.testcase.testcase = self.testcase_dict
+ self.testcase.name.return_value = self.testcase_name
+ self.testcase.validate_testcase.return_value = self.testcase_valid
+ self.testcase.validate_type.return_value = self.testcase_type
+
+ def tearDown(self):
+ self.patcher1.stop()
+ self.patcher2.stop()
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.Container')
+ def test_run_offline_not_exist(self, mock_container, mock_config,
+ mock_utils):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'offline': True, 'result_dir': 'result_dir'
+ }
+ docker_runner = t_runner.TestRunnerFactory.create(self.testcase)
+
+ container_obj = Mock()
+ docker_img_obj = Mock()
+ container_obj.get_docker_image.return_value = docker_img_obj
+ container_obj.get_image_id.return_value = False
+ mock_container.return_value = container_obj
+
+ docker_runner.run()
+
+ mock_container.assert_called_once_with(self.testcase)
+ container_obj.get_docker_image.assert_called_once_with()
+ container_obj.get_image_id.assert_called_once_with(docker_img_obj)
+ docker_runner.logger.error.assert_called_once_with(
+ "{} image doesn't exist, can't run offline.".format(
+ self.testcase_type))
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.Container')
+ def test_run__not_offline_no_pull(self, mock_container, mock_config,
+ mock_utils):
+ t_runner.YardstickRunner.create_log()
+ mock_config.dovetail_config = {
+ 'offline': False, 'result_dir': 'result_dir'
+ }
+ docker_runner = t_runner.YardstickRunner(self.testcase)
+
+ container_obj = Mock()
+ docker_img_obj = Mock()
+ container_obj.get_docker_image.return_value = docker_img_obj
+ container_obj.pull_image.return_value = False
+ mock_container.return_value = container_obj
+
+ docker_runner.run()
+
+ mock_container.assert_called_once_with(self.testcase)
+ container_obj.get_docker_image.assert_called_once_with()
+ container_obj.pull_image.assert_called_once_with(docker_img_obj)
+ docker_runner.logger.error.assert_called_once_with(
+ 'Failed to pull the image.')
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.Container')
+ def test_run__not_offline_no_create(self, mock_container, mock_config,
+ mock_utils):
+ t_runner.BottlenecksRunner.create_log()
+ mock_config.dovetail_config = {
+ 'offline': False, 'result_dir': 'result_dir'
+ }
+ docker_runner = t_runner.BottlenecksRunner(self.testcase)
+
+ container_obj = Mock()
+ docker_img_obj = Mock()
+ container_obj.get_docker_image.return_value = docker_img_obj
+ container_obj.pull_image.return_value = True
+ container_obj.create.return_value = [None, 'error']
+ mock_container.return_value = container_obj
+
+ docker_runner.run()
+
+ mock_container.assert_called_once_with(self.testcase)
+ container_obj.get_docker_image.assert_called_once_with()
+ container_obj.pull_image.assert_called_once_with(docker_img_obj)
+ container_obj.create.assert_called_once_with(docker_img_obj)
+ docker_runner.logger.error.assert_has_calls([
+ call('Failed to create container.'), call('error')])
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.Container')
+ def test_run__not_offline_no_prepare(self, mock_container,
+ mock_config, mock_utils):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'offline': False,
+ 'noclean': False,
+ 'result_dir': 'result_dir'
+ }
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+
+ container_obj = Mock()
+ docker_img_obj = Mock()
+ container_obj.get_docker_image.return_value = docker_img_obj
+ container_obj.pull_image.return_value = True
+ container_id = '12345'
+ container_msg = 'Successfully to create container.'
+ container_obj.create.return_value = [container_id, container_msg]
+ mock_container.return_value = container_obj
+ self.testcase.pre_condition.return_value = ['cmd']
+ self.testcase.prepare_cmd.return_value = False
+ self.testcase.post_condition.return_value = ['cmd']
+ container_obj.exec_cmd.return_value = (1, 'error')
+
+ docker_runner.run()
+
+ mock_container.assert_called_once_with(self.testcase)
+ container_obj.get_docker_image.assert_called_once_with()
+ container_obj.pull_image.assert_called_once_with(docker_img_obj)
+ container_obj.create.assert_called_once_with(docker_img_obj)
+ docker_runner.logger.debug.assert_called_with(
+ 'container id: {}'.format(container_id))
+ self.testcase.pre_condition.assert_called_once_with()
+ container_obj.exec_cmd.assert_has_calls([
+ call('cmd'), call('cmd')])
+ self.testcase.prepare_cmd.assert_called_once_with(self.testcase_type)
+ self.testcase.post_condition.assert_called_once_with()
+ docker_runner.logger.error.assert_has_calls([
+ call('Failed to exec all pre_condition cmds.'),
+ call('Failed to prepare test case: {}'
+ .format(self.testcase_name))])
+ container_obj.clean.assert_called_once_with()
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.Container')
+ def test_run__not_offline_prepare(self, mock_container,
+ mock_config, mock_utils):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'offline': False,
+ 'noclean': False,
+ 'result_dir': 'result_dir'
+ }
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ container_obj = Mock()
+ docker_img_obj = Mock()
+ container_obj.get_docker_image.return_value = docker_img_obj
+ container_obj.pull_image.return_value = True
+ container_id = '12345'
+ container_msg = 'Successfully to create container.'
+ container_obj.create.return_value = [container_id, container_msg]
+ mock_container.return_value = container_obj
+ self.testcase.pre_condition.return_value = ['cmd']
+ self.testcase.prepare_cmd.return_value = True
+ self.testcase.post_condition.return_value = ['cmd']
+ self.testcase.cmds = ['cmd']
+ container_obj.exec_cmd.return_value = (1, 'error')
+
+ docker_runner.run()
+
+ mock_container.assert_called_once_with(self.testcase)
+ container_obj.get_docker_image.assert_called_once_with()
+ container_obj.pull_image.assert_called_once_with(docker_img_obj)
+ container_obj.create.assert_called_once_with(docker_img_obj)
+ docker_runner.logger.debug.assert_called_with(
+ 'container id: {}'.format(container_id))
+ self.testcase.pre_condition.assert_called_once_with()
+ container_obj.exec_cmd.assert_has_calls([
+ call('cmd'), call('cmd'), call('cmd')])
+ self.testcase.prepare_cmd.assert_called_once_with(self.testcase_type)
+ self.testcase.post_condition.assert_called_once_with()
+ docker_runner.logger.error.assert_has_calls([
+ call('Failed to exec all pre_condition cmds.'),
+ call('Failed to exec {}, ret: {}, msg: {}'
+ .format('cmd', 1, 'error'))])
+ container_obj.clean.assert_called_once_with()
+
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os')
+ def test_archive_logs_no_files(self, mock_os, mock_utils, mock_config):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_os.environ = {'DOVETAIL_HOME': 'dovetail_home'}
+ mock_utils.get_value_from_dict.return_value = []
+
+ result = docker_runner.archive_logs()
+
+ mock_os.path.join.assert_has_calls([call('dovetail_home', 'results')])
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('report.source_archive_files', self.testcase_dict),
+ call('report.dest_archive_files', self.testcase_dict)])
+ self.assertEqual(True, result)
+
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os')
+ def test_archive_logs_difference_in_files(self, mock_os, mock_utils,
+ mock_config):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_os.environ = {'DOVETAIL_HOME': 'dovetail_home'}
+ mock_utils.get_value_from_dict.side_effect = [[], ['file']]
+
+ result = docker_runner.archive_logs()
+
+ mock_os.path.join.assert_has_calls([call('dovetail_home', 'results')])
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('report.source_archive_files', self.testcase_dict),
+ call('report.dest_archive_files', self.testcase_dict)])
+ docker_runner.logger.error.assert_called_once_with(
+ "Can't find corresponding 'result_dest_files' "
+ "for 'result_source_files' with testcase {}"
+ .format(self.testcase_name))
+ self.assertEqual(False, result)
+
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os')
+ def test_archive_logs_src_file_error(self, mock_os, mock_utils,
+ mock_config):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_os.environ = {'DOVETAIL_HOME': 'dovetail_home'}
+ mock_utils.get_value_from_dict.side_effect = [['src_file'],
+ ['dst_file']]
+ mock_os.path.join.side_effect = ['result_path', 'src_file_path',
+ 'dest_file_path']
+ mock_os.path.isfile.return_value = False
+
+ result = docker_runner.archive_logs()
+
+ mock_os.path.join.assert_has_calls([
+ call('dovetail_home', 'results'),
+ call('result_path', 'src_file'),
+ call('result_path', 'dst_file')])
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('report.source_archive_files', self.testcase_dict),
+ call('report.dest_archive_files', self.testcase_dict)])
+ mock_os.path.isfile.assert_has_calls([call('src_file_path')])
+ docker_runner.logger.error.assert_called_once_with(
+ "Can't find file {}.".format('src_file_path'))
+ self.assertEqual(False, result)
+
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os')
+ def test_archive_logs_src_file_exists(self, mock_os, mock_utils,
+ mock_config):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {'result_dir': 'result_dir'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_os.environ = {'DOVETAIL_HOME': 'dovetail_home'}
+ mock_utils.get_value_from_dict.side_effect = [['src_file'],
+ ['dst_file']]
+ mock_os.path.join.side_effect = ['result_path', 'src_file_path',
+ 'dest_file_path']
+ mock_os.path.isfile.return_value = True
+
+ result = docker_runner.archive_logs()
+
+ mock_os.path.join.assert_has_calls([
+ call('dovetail_home', 'results'),
+ call('result_path', 'src_file'),
+ call('result_path', 'dst_file')])
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('report.source_archive_files', self.testcase_dict),
+ call('report.dest_archive_files', self.testcase_dict)])
+ mock_os.path.isfile.assert_has_calls([call('src_file_path')])
+ mock_os.renames.assert_called_once_with(
+ 'src_file_path', 'dest_file_path')
+ self.assertEqual(True, result)
+
+ @patch('dovetail.test_runner.jinja2')
+ def test_render(self, mock_jinja):
+ render_obj = Mock()
+ template_obj = Mock()
+ mock_jinja.Template.return_value = template_obj
+ template_obj.render.return_value = render_obj
+
+ result = t_runner.FunctestRunner._render('task_template')
+
+ mock_jinja.Template.assert_called_once_with('task_template')
+ template_obj.render.assert_called_with()
+ self.assertEqual(render_obj, result)
+
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.os')
+ def test_add_testcase_info(self, mock_os, mock_config):
+ mock_os.getenv.side_effect = ['os_insecure', 'dovetail_home', 'debug',
+ 'os_cacert', 'host_url', 'csar_file',
+ 'heat_templates_archive']
+ mock_os.environ = {'DEPLOY_SCENARIO': 'deploy_scenario'}
+ mock_config.dovetail_config = {'build_tag': 'build_tag'}
+
+ expected = {
+ 'validate_testcase': 'validate_testcase',
+ 'testcase': 'testcase_name', 'os_insecure': 'os_insecure',
+ 'deploy_scenario': 'deploy_scenario',
+ 'dovetail_home': 'dovetail_home', 'debug': 'debug',
+ 'build_tag': 'build_tag', 'cacert': 'os_cacert',
+ 'host_url': 'host_url', 'csar_file': 'csar_file',
+ 'heat_templates_archive': 'heat_templates_archive'
+ }
+ result = t_runner.FunctestRunner._add_testcase_info(self.testcase)
+
+ self.testcase.validate_testcase.assert_called_once_with()
+ self.testcase.name.assert_called_once_with()
+ mock_os.getenv.assert_has_calls([
+ call('OS_INSECURE'), call('DOVETAIL_HOME'), call('DEBUG'),
+ call('OS_CACERT'), call('HOST_URL'), call('CSAR_FILE'),
+ call('VNF_ARCHIVE_NAME')])
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.constants')
+ def test_update_config_no_task_template(self, mock_const, mock_path,
+ mock_config, mock_utils):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'config_dir': 'one', 'pod_file': 'two', 'result_dir': 'three'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_path.join.side_effect = ['config_file', 'pod_file']
+ mock_utils.read_yaml_file.return_value = 'pod_info'
+ mock_utils.read_plain_file.return_value = None
+ mock_const.CONF_PATH = 'conf_path'
+
+ self.patcher2.stop()
+ result = docker_runner._update_config(self.testcase)
+ self.patcher2.start()
+
+ mock_path.join.assert_has_calls([
+ call('three', 'endpoint_info.json'),
+ call('conf_path', docker_runner.config_file_name)])
+ mock_utils.read_plain_file.assert_called_once_with(
+ 'config_file', docker_runner.logger)
+ self.assertEqual(None, result)
+
+ @patch('dovetail.test_runner.yaml.safe_load')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.constants')
+ @patch.object(t_runner.DockerRunner, '_add_testcase_info')
+ @patch.object(t_runner.DockerRunner, '_render')
+ def test_update_config_pod_info_key_err(self, mock_render, mock_add_info,
+ mock_const, mock_path, mock_config,
+ mock_utils, mock_load):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'config_dir': 'one', 'pod_file': 'two', 'result_dir': 'three'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_path.join.side_effect = ['config_file', 'pod_file']
+ mock_utils.read_yaml_file.return_value = {'key': 'value'}
+ mock_utils.read_plain_file.return_value = True
+ mock_const.CONF_PATH = 'conf_path'
+ mock_add_info.return_value = {'config_item': 'item'}
+ mock_render.return_value = 'full_task'
+ mock_load.return_value = {'full_task_yaml': 'full_value'}
+
+ self.patcher2.stop()
+ result = docker_runner._update_config(self.testcase)
+ self.patcher2.start()
+
+ mock_path.join.assert_has_calls([
+ call('three', 'endpoint_info.json'),
+ call('conf_path', docker_runner.config_file_name),
+ call('one', 'two')])
+ mock_add_info.assert_called_once_with(self.testcase)
+ mock_render.assert_called_once_with(True, config_item='item')
+ mock_load.assert_called_once_with('full_task')
+ self.assertEqual(
+ {'config_dir': 'one',
+ 'pod_file': 'two',
+ 'full_task_yaml': 'full_value',
+ 'result_dir': 'three'},
+ result)
+
+ @patch('dovetail.test_runner.yaml.safe_load')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.constants')
+ @patch.object(t_runner.DockerRunner, '_add_testcase_info')
+ @patch.object(t_runner.DockerRunner, '_render')
+ def test_update_config_pod_info_no_info(self, mock_render, mock_add_info,
+ mock_const, mock_path, mock_config,
+ mock_utils, mock_load):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'config_dir': 'one', 'pod_file': 'two', 'result_dir': 'three'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_path.join.side_effect = ['config_file', 'pod_file']
+ mock_utils.read_yaml_file.return_value = False
+ mock_utils.read_plain_file.return_value = True
+ mock_const.CONF_PATH = 'conf_path'
+ mock_add_info.return_value = {'config_item': 'item'}
+ mock_render.return_value = 'full_task'
+ mock_load.return_value = {'full_task_yaml': 'full_value'}
+
+ self.patcher2.stop()
+ result = docker_runner._update_config(self.testcase)
+ self.patcher2.start()
+
+ mock_path.join.assert_has_calls([
+ call('three', 'endpoint_info.json'),
+ call('conf_path', docker_runner.config_file_name),
+ call('one', 'two')])
+ mock_add_info.assert_called_once_with(self.testcase)
+ mock_render.assert_called_once_with(True, config_item='item')
+ mock_load.assert_called_once_with('full_task')
+ self.assertEqual(
+ {'config_dir': 'one',
+ 'pod_file': 'two',
+ 'full_task_yaml': 'full_value',
+ 'result_dir': 'three'},
+ result)
+
+ @patch('dovetail.test_runner.yaml.safe_load')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.constants')
+ @patch.object(t_runner.DockerRunner, '_add_testcase_info')
+ @patch.object(t_runner.DockerRunner, '_render')
+ def test_update_config_pod_info(self, mock_render, mock_add_info,
+ mock_const, mock_path, mock_config,
+ mock_utils, mock_load):
+ t_runner.FunctestRunner.create_log()
+ mock_config.dovetail_config = {
+ 'config_dir': 'one', 'pod_file': 'two', 'result_dir': 'three'}
+ docker_runner = t_runner.FunctestRunner(self.testcase)
+ mock_path.join.side_effect = ['config_file', 'pod_file']
+ mock_utils.read_yaml_file.return_value = {
+ 'process_info': [
+ {'key': 'value'}, {'testcase_name': self.testcase_name}
+ ]}
+ mock_utils.read_plain_file.return_value = True
+ mock_const.CONF_PATH = 'conf_path'
+ mock_add_info.return_value = {'config_item': 'item'}
+ mock_render.return_value = 'full_task'
+ mock_load.return_value = {'full_task_yaml': 'full_value'}
+
+ self.patcher2.stop()
+ result = docker_runner._update_config(self.testcase)
+ self.patcher2.start()
+
+ mock_path.join.assert_has_calls([
+ call('three', 'endpoint_info.json'),
+ call('conf_path', docker_runner.config_file_name),
+ call('one', 'two')])
+ mock_add_info.assert_called_once_with(
+ self.testcase, {'testcase_name': self.testcase_name})
+ docker_runner.logger.error.assert_called_once_with(
+ "Need key '{}' in {}".format('testcase_name', {'key': 'value'}))
+ mock_render.assert_called_once_with(True, config_item='item')
+ mock_load.assert_called_once_with('full_task')
+ self.assertEqual(
+ {'config_dir': 'one',
+ 'pod_file': 'two',
+ 'full_task_yaml': 'full_value',
+ 'result_dir': 'three'},
+ result)
+
+ @patch('builtins.open')
+ @patch('dovetail.test_runner.json')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ def test_shell_run_prepare_cmd(self, mock_path, mock_utils, mock_config,
+ mock_json, mock_open):
+ t_runner.ShellRunner.create_log()
+ docker_runner = t_runner.ShellRunner(self.testcase)
+ self.testcase.cmds = ['cmd']
+ self.testcase.pre_condition.return_value = ['cmd']
+ self.testcase.post_condition.return_value = ['cmd']
+ self.testcase.prepare_cmd.return_value = True
+ mock_utils.exec_cmd.return_value = (1, 'error')
+ mock_path.join.return_value = 'join_path'
+ mock_config.dovetail_config = {'result_dir': 'result'}
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ dump_obj = Mock()
+ mock_json.dumps.return_value = dump_obj
+
+ docker_runner.run()
+
+ self.testcase.pre_condition.assert_called_once_with()
+ self.testcase.prepare_cmd.assert_called_once_with(docker_runner.type)
+ docker_runner.logger.error.assert_called_once_with(
+ 'Failed to execute all pre_condition cmds.')
+ mock_utils.exec_cmd.assert_has_calls([
+ call('cmd', docker_runner.logger),
+ call('cmd', docker_runner.logger),
+ call('cmd', docker_runner.logger)])
+ self.testcase.post_condition.assert_called_once_with()
+ mock_path.join.assert_called_once_with(
+ 'result', self.testcase_name)
+ docker_runner.logger.debug.assert_called_with(
+ 'Save result: {}'.format('join_path.out'))
+ mock_open.assert_called_once_with('join_path.out', 'w')
+ mock_json.dumps.assert_called_once_with(
+ {'results': [
+ ('cmd', 1, 'error'),
+ ('cmd', 1, 'error'),
+ ('cmd', 1, 'error')],
+ 'pass': 'FAIL'})
+ file_obj.write.assert_called_once_with(dump_obj)
+
+ @patch('builtins.open')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ def test_shell_run_no_prepare_cmd_and_exception(self, mock_path,
+ mock_utils, mock_config,
+ mock_open):
+ t_runner.ShellRunner.create_log()
+ docker_runner = t_runner.ShellRunner(self.testcase)
+ self.testcase.cmds = ['cmd']
+ self.testcase.pre_condition.return_value = ['cmd']
+ self.testcase.post_condition.return_value = ['cmd']
+ self.testcase.prepare_cmd.return_value = False
+ mock_utils.exec_cmd.return_value = (1, 'error')
+ mock_path.join.return_value = 'join_path'
+ mock_config.dovetail_config = {'result_dir': 'result'}
+ mock_open.return_value.__enter__.side_effect = Exception('error')
+
+ docker_runner.run()
+
+ self.testcase.pre_condition.assert_called_once_with()
+ self.testcase.prepare_cmd.assert_called_once_with(docker_runner.type)
+ docker_runner.logger.error.assert_has_calls([
+ call('Failed to execute all pre_condition cmds.'),
+ call('Failed to prepare cmd: {}'.format(self.testcase_name))])
+ mock_utils.exec_cmd.assert_has_calls([
+ call('cmd', docker_runner.logger),
+ call('cmd', docker_runner.logger)])
+ self.testcase.post_condition.assert_called_once_with()
+ mock_path.join.assert_called_once_with(
+ 'result', self.testcase_name)
+ docker_runner.logger.debug.assert_called_with(
+ 'Save result: {}'.format('join_path.out'))
+ mock_open.assert_called_once_with('join_path.out', 'w')
+
+ def test_factory_error(self):
+ self.testcase.validate_type.return_value = 'unknown'
+ docker_runner = t_runner.TestRunnerFactory()
+
+ result = docker_runner.create(self.testcase)
+
+ self.assertEqual(None, result)
+
+ @patch('dovetail.test_runner.constants')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ def test_k8s_update_config_no_task_template(self, mock_path, mock_utils,
+ mock_const):
+ t_runner.FunctestK8sRunner.create_log()
+ mock_utils.read_plain_file.return_value = None
+ mock_path.join.side_effect = ['config_file']
+ mock_const.CONF_PATH = 'conf_path'
+ docker_runner = t_runner.FunctestK8sRunner(self.testcase)
+
+ self.patcher2.stop()
+ result = docker_runner._update_config(self.testcase, update_pod=False)
+ self.patcher2.start()
+
+ mock_path.join.assert_has_calls([
+ call('conf_path', docker_runner.config_file_name)])
+ mock_utils.read_plain_file.assert_has_calls([
+ call('config_file', docker_runner.logger)])
+ self.assertEqual(None, result)
+
+ @patch('dovetail.test_runner.yaml.safe_load')
+ @patch('dovetail.test_runner.constants')
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.dt_cfg')
+ @patch.object(t_runner.DockerRunner, '_add_testcase_info')
+ @patch.object(t_runner.DockerRunner, '_render')
+ def test_k8s_update_config(self, mock_render, mock_add_info, mock_config,
+ mock_path, mock_utils, mock_const, mock_load):
+ t_runner.FunctestK8sRunner.create_log()
+ mock_utils.read_plain_file.return_value = True
+ mock_path.join.side_effect = ['config_file', 'config_file']
+ mock_const.CONF_PATH = 'conf_path'
+ mock_add_info.return_value = {'config_item': 'item'}
+ mock_render.return_value = 'full_task'
+ mock_load.return_value = {'full_task_yaml': 'full_value'}
+ mock_config.dovetail_config = {
+ 'config_dir': 'one', 'pod_file': 'two'}
+
+ docker_runner = t_runner.FunctestK8sRunner(self.testcase)
+ self.patcher2.stop()
+ result = docker_runner._update_config(self.testcase, update_pod=False)
+ self.patcher2.start()
+
+ mock_path.join.assert_has_calls([
+ call('conf_path', docker_runner.config_file_name)])
+ mock_utils.read_plain_file.assert_has_calls([
+ call('config_file', docker_runner.logger)])
+ mock_add_info.assert_has_calls([call(self.testcase)])
+ mock_render.assert_has_calls([call(True, config_item='item')])
+ mock_load.assert_has_calls([call('full_task')])
+ self.assertEqual(
+ {'config_dir': 'one',
+ 'pod_file': 'two',
+ 'full_task_yaml': 'full_value'},
+ result)
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.dt_cfg')
+ def test_init_onapvtprunner_no_env_file(self, mock_config, mock_path,
+ mock_utils):
+ t_runner.OnapVtpRunner.create_log()
+ mock_path.join.side_effect = ['env_file']
+ mock_config.dovetail_config = {'config_dir': 'one', 'env_file': 'two'}
+ mock_path.isfile.return_value = False
+
+ docker_runner = t_runner.OnapVtpRunner(self.testcase)
+
+ mock_path.join.assert_has_calls([call('one', 'two')])
+ mock_path.isfile.assert_called_once()
+ docker_runner.logger.error.assert_called_once_with(
+ 'File env_file does not exist.')
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.dt_cfg')
+ def test_init_onapvtprunner(self, mock_config, mock_path, mock_utils):
+ t_runner.OnapVtpRunner.create_log()
+ mock_path.join.side_effect = ['env_file']
+ mock_config.dovetail_config = {'config_dir': 'one', 'env_file': 'two'}
+ mock_path.isfile.return_value = True
+
+ t_runner.OnapVtpRunner(self.testcase)
+
+ mock_path.join.assert_has_calls([call('one', 'two')])
+ mock_path.isfile.assert_called_once()
+ mock_utils.source_env.assert_called_once_with('env_file')
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.dt_cfg')
+ def test_init_onapvvprunner_no_env_file(self, mock_config, mock_path,
+ mock_utils):
+ t_runner.OnapVvpRunner.create_log()
+ mock_path.join.side_effect = ['env_file']
+ mock_config.dovetail_config = {'config_dir': 'one', 'env_file': 'two'}
+ mock_path.isfile.return_value = False
+
+ docker_runner = t_runner.OnapVvpRunner(self.testcase)
+
+ mock_path.join.assert_has_calls([call('one', 'two')])
+ mock_path.isfile.assert_called_once()
+ docker_runner.logger.error.assert_called_once_with(
+ 'File env_file does not exist.')
+
+ @patch('dovetail.test_runner.dt_utils')
+ @patch('dovetail.test_runner.os.path')
+ @patch('dovetail.test_runner.dt_cfg')
+ def test_init_onapvvprunner(self, mock_config, mock_path, mock_utils):
+ t_runner.OnapVvpRunner.create_log()
+ mock_path.join.side_effect = ['env_file']
+ mock_config.dovetail_config = {'config_dir': 'one', 'env_file': 'two'}
+ mock_path.isfile.return_value = True
+
+ t_runner.OnapVvpRunner(self.testcase)
+
+ mock_path.join.assert_has_calls([call('one', 'two')])
+ mock_path.isfile.assert_called_once()
+ mock_utils.source_env.assert_called_once_with('env_file')
diff --git a/dovetail/tests/unit/test_testcase.py b/dovetail/tests/unit/test_testcase.py
new file mode 100644
index 00000000..81a8de39
--- /dev/null
+++ b/dovetail/tests/unit/test_testcase.py
@@ -0,0 +1,658 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import os
+import unittest
+import yaml
+from mock import patch, call, Mock
+
+import dovetail.testcase as tcase
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class TestcaseTesting(unittest.TestCase):
+
+ def setUp(self):
+ test_path = os.path.dirname(os.path.realpath(__file__))
+ with open(os.path.join(test_path, 'test_testcase.yaml')) as f:
+ self.testcase_yaml = yaml.safe_load(f)
+
+ def tearDown(self):
+ pass
+
+ def teardown_method(self, method):
+ tcase.Testcase.logger = None
+ tcase.Testcase.validate_testcase_list = {}
+ tcase.Testcase.testcase_list = {}
+ tcase.Testsuite.testsuite_list = {}
+
+ @patch('dovetail.testcase.dt_logger')
+ def test_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ tcase.Testcase.create_log()
+
+ self.assertEqual(getlogger_obj, tcase.Testcase.logger)
+
+ @patch('dovetail.testcase.Parser')
+ def test_parse_cmd_no_lines(self, mock_parser):
+ testcase = tcase.YardstickTestcase(self.testcase_yaml)
+ cmds_list = ['cmd']
+ mock_parser.parse_cmd.return_value = None
+
+ result = testcase.parse_cmd(cmds_list)
+
+ mock_parser.parse_cmd.assert_called_once_with(
+ 'cmd', testcase)
+ self.assertEqual(False, result)
+
+ @patch('dovetail.testcase.Parser')
+ def test_parse_cmd(self, mock_parser):
+ testcase = tcase.BottlenecksTestcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ cmds_list = ['cmd']
+ mock_parser.parse_cmd.return_value = 'cmd_lines'
+
+ result = testcase.parse_cmd(cmds_list)
+
+ mock_parser.parse_cmd.assert_called_once_with(
+ 'cmd', testcase)
+ logger_obj.debug.assert_called_once_with("cmds: ['cmd_lines']")
+ self.assertEqual(['cmd_lines'], testcase.cmds)
+ self.assertEqual(True, result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_prepare_cmd_no_cmds(self, mock_config):
+ testcase = tcase.ShellTestcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ mock_config.dovetail_config = {}
+
+ result = testcase.prepare_cmd('type')
+
+ logger_obj.error.assert_called_once_with(
+ 'Test case {} has no cmds.'.format(testcase.name()))
+ self.assertEqual(False, result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ @patch.object(tcase.Testcase, 'parse_cmd')
+ def test_prepare_cmd_testcase_cmd(self, mock_parse, mock_config):
+ testcase = tcase.ShellTestcase(self.testcase_yaml)
+ testcase.testcase['validate']['cmds'] = ['cmd']
+ mock_config.dovetail_config = {}
+ mock_parse.return_value = True
+
+ result = testcase.prepare_cmd('type')
+
+ mock_parse.assert_called_once_with(['cmd'])
+ self.assertEqual(True, result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ @patch.object(tcase.Testcase, 'parse_cmd')
+ def test_prepare_cmd_config_cmd(self, mock_parse, mock_config):
+ testcase = tcase.TestcaseFactory.create('yardstick',
+ self.testcase_yaml)
+ mock_config.dovetail_config = {'type': {'cmds': ['cmd']}}
+ mock_parse.return_value = True
+
+ result = testcase.prepare_cmd('type')
+
+ mock_parse.assert_called_once_with(['cmd'])
+ self.assertEqual(True, result)
+
+ def test_str(self):
+ testcase = tcase.OnapVtpTestcase(self.testcase_yaml)
+
+ result = testcase.__str__()
+
+ self.assertEqual(testcase.testcase, result)
+
+ def test_objective(self):
+ testcase = tcase.OnapVvpTestcase(self.testcase_yaml)
+ testcase.testcase['objective'] = 'objective'
+
+ result = testcase.objective()
+
+ self.assertEqual('objective', result)
+
+ @patch('dovetail.testcase.dt_utils')
+ def test_sub_testcase(self, mock_utils):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ mock_utils.get_value_from_dict.return_value = 'value'
+
+ result = testcase.sub_testcase()
+
+ mock_utils.get_value_from_dict.assert_called_once_with(
+ 'report.sub_testcase_list', testcase.testcase)
+ self.assertEqual('value', result)
+
+ def test_sub_testcase_passed(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+
+ result = testcase.sub_testcase_passed('name', 'passed')
+
+ self.assertEqual('passed', result)
+
+ def test_validate_type(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+
+ result = testcase.validate_type()
+
+ self.assertEqual('functest', result)
+
+ def test_validate_testcase(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+
+ result = testcase.validate_testcase()
+
+ self.assertEqual('tempest_smoke_serial', result)
+
+ def test_portal_key_file(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+
+ result = testcase.portal_key_file()
+
+ self.assertEqual('tempest_logs/tempest_smoke_serial.html', result)
+
+ def test_vnf_type(self):
+ testcase = tcase.OnapVtpTestcase(self.testcase_yaml)
+
+ result = testcase.vnf_type()
+
+ self.assertEqual('tosca', result)
+
+ def test_passed(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+
+ result = testcase.passed('passed')
+
+ self.assertEqual('passed', result)
+
+ def test_set_get_results(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+
+ testcase.set_results('results')
+
+ self.assertEqual('results', testcase.get_results())
+
+ def test_pre_condition_exists(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ testcase.testcase['validate']['pre_condition'] = 'pre_condition'
+
+ result = testcase.pre_condition()
+
+ self.assertEqual('pre_condition', result)
+
+ @patch.object(tcase.Testcase, 'pre_condition_cls')
+ def test_pre_condition_not_exists(self, mock_pre_condition):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ mock_pre_condition.return_value = False
+
+ result = testcase.pre_condition()
+
+ mock_pre_condition.assert_called_once_with('functest')
+ logger_obj.debug.assert_called_once_with(
+ 'Test case: {} pre_condition is empty.'.format(testcase.name()))
+ self.assertEqual(False, result)
+
+ def test_pre_copy_path(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ testcase.testcase['validate']['pre_copy'] = {'key': 'value'}
+
+ result = testcase.pre_copy_path('key')
+
+ self.assertEqual('value', result)
+
+ def test_pre_copy_path_error(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+
+ result = testcase.pre_copy_path('key')
+
+ self.assertEqual(None, result)
+
+ def test_post_condition_exists(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ testcase.testcase['validate']['post_condition'] = 'post_condition'
+
+ result = testcase.post_condition()
+
+ self.assertEqual('post_condition', result)
+
+ @patch.object(tcase.Testcase, 'post_condition_cls')
+ def test_post_condition_not_exists(self, mock_post_condition):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ mock_post_condition.return_value = False
+
+ result = testcase.post_condition()
+
+ mock_post_condition.assert_called_once_with('functest')
+ logger_obj.debug.assert_called_once_with(
+ 'Test case: {} post_condition is empty.'.format(testcase.name()))
+ self.assertEqual(False, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.testcase.os.path')
+ @patch('dovetail.testcase.dt_cfg')
+ @patch.object(tcase.Testcase, 'sub_testcase')
+ def test_mk_src_file(self, mock_sub_testcase, mock_config,
+ mock_path, mock_open):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ mock_config.dovetail_config = {'result_dir': 'value'}
+ sub_test = 'sub_test'
+ file_path = 'file_path'
+ mock_path.join.return_value = file_path
+ mock_sub_testcase.return_value = [sub_test]
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ result = testcase.mk_src_file()
+
+ mock_path.join.assert_called_once_with('value', 'tempest_custom.txt')
+ mock_open.assert_called_once_with(file_path, 'w+')
+ file_obj.write.assert_called_once_with(sub_test + '\n')
+ logger_obj.debug.assert_called_once_with(
+ 'Save test cases to {}'.format(file_path))
+ self.assertEqual(file_path, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.testcase.os.path')
+ @patch('dovetail.testcase.dt_cfg')
+ @patch.object(tcase.Testcase, 'sub_testcase')
+ def test_mk_src_file_exception(self, mock_sub_testcase,
+ mock_config, mock_path, mock_open):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ mock_config.dovetail_config = {'result_dir': 'value'}
+ sub_test = 'sub_test'
+ file_path = 'file_path'
+ mock_path.join.return_value = file_path
+ mock_sub_testcase.return_value = [sub_test]
+ mock_open.return_value.__enter__.side_effect = Exception()
+
+ result = testcase.mk_src_file()
+
+ mock_path.join.assert_called_once_with('value', 'tempest_custom.txt')
+ mock_open.assert_called_once_with(file_path, 'w+')
+ logger_obj.exception('Failed to save: {}'.format(file_path))
+ self.assertEqual(None, result)
+
+ @patch('dovetail.testcase.TestRunnerFactory')
+ def test_run(self, mock_factory):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ runner_obj = Mock()
+ mock_factory.create.return_value = runner_obj
+ error_msg = 'An error happened!'
+ runner_obj.archive_logs.side_effect = AttributeError(error_msg)
+
+ testcase.run()
+
+ runner_obj.run.assert_called_once_with()
+ runner_obj.archive_logs.assert_called_once_with()
+ logger_obj.exception.assert_called_once_with(
+ 'Test case: {} Exception: {}'.format(testcase.name, error_msg))
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_pre_condition_cls(self, mock_config):
+ mock_config.dovetail_config = {'type': {'pre_condition': 'value'}}
+
+ result = tcase.Testcase.pre_condition_cls('type')
+ self.assertEqual('value', result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_pre_condition_cls_key_error(self, mock_config):
+ mock_config.dovetail_config = {}
+
+ result = tcase.Testcase.pre_condition_cls('type')
+ self.assertEqual(None, result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_post_condition_cls(self, mock_config):
+ mock_config.dovetail_config = {'type': {'post_condition': 'value'}}
+
+ result = tcase.Testcase.post_condition_cls('type')
+ self.assertEqual('value', result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_post_condition_cls_key_error(self, mock_config):
+ mock_config.dovetail_config = {}
+
+ result = tcase.Testcase.post_condition_cls('type')
+ self.assertEqual(None, result)
+
+ def test_increase_retry(self):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ tcase.Testcase.validate_testcase_list[
+ 'tempest_smoke_serial'] = {'retry': 0}
+
+ for _ in range(0, 42):
+ result = testcase.increase_retry()
+ self.assertEqual(42, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.testcase.yaml')
+ @patch('dovetail.testcase.os')
+ @patch('dovetail.testcase.TestcaseFactory')
+ @patch('dovetail.testcase.constants')
+ def test_load(self, mock_constants, mock_factory, mock_os, mock_yaml,
+ mock_open):
+ testcase = tcase.Testcase(self.testcase_yaml)
+ mock_constants.TESTCASE_PATH = 'abs_path'
+ mock_os.walk.return_value = [('root', ['dir'], ['file'])]
+ mock_os.path.join.return_value = 'testcase_path'
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ yaml_dict = {'key': {'validate': {'type': 'value'}}}
+ mock_yaml.safe_load.return_value = yaml_dict
+ runner_obj = Mock()
+ mock_factory.create.return_value = runner_obj
+
+ testcase.load()
+
+ mock_os.walk.assert_called_once_with('abs_path')
+ mock_os.path.join.assert_called_with('root', 'file')
+ mock_open.assert_called_once_with('testcase_path')
+ mock_yaml.safe_load.assert_called_once_with(file_obj)
+ mock_factory.create.assert_called_once_with('value', yaml_dict)
+ self.assertEqual(runner_obj, tcase.Testcase.get('key'))
+
+ @patch('builtins.open')
+ @patch('dovetail.testcase.yaml')
+ @patch('dovetail.testcase.os')
+ @patch('dovetail.testcase.TestcaseFactory')
+ @patch('dovetail.testcase.constants')
+ def test_load_no_testcase(self, mock_constants, mock_factory, mock_os,
+ mock_yaml, mock_open):
+ logger_obj = Mock()
+ tcase.Testcase.logger = logger_obj
+ mock_constants.TESTCASE_PATH = 'abs_path'
+ mock_os.walk.return_value = [('root', ['dir'], ['file'])]
+ mock_os.path.join.return_value = 'testcase_path'
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ yaml_dict = {'key': {'validate': {'type': 'value'}}}
+ mock_yaml.safe_load.return_value = yaml_dict
+ mock_factory.create.return_value = None
+
+ tcase.Testcase.load()
+
+ mock_os.walk.assert_called_once_with('abs_path')
+ mock_os.path.join.assert_called_with('root', 'file')
+ mock_open.assert_called_once_with('testcase_path')
+ mock_yaml.safe_load.assert_called_once_with(file_obj)
+ mock_factory.create.assert_called_once_with('value', yaml_dict)
+ logger_obj.error.assert_called_once_with(
+ 'Failed to create test case: file')
+
+ def test_get_none(self):
+ self.assertEqual(None, tcase.Testcase.get('unknown'))
+
+ def test_check_testarea_none(self):
+ self.assertEqual((True, ['full']),
+ tcase.Testcase.check_testarea(None))
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_check_testarea_full(self, mock_config):
+ self.assertEqual((True, ['full']),
+ tcase.Testcase.check_testarea(['full']))
+
+ @patch('dovetail.testcase.dt_cfg')
+ def test_check_testarea(self, mock_config):
+ self.assertEqual((True, ['area']),
+ tcase.Testcase.check_testarea(['area']))
+
+ def test_check_testcase_area(self):
+ self.assertEqual(False,
+ tcase.Testcase.check_testcase_area(None, None))
+
+ def test_check_testcase_area_full_or_in_testcase(self):
+ self.assertEqual(True,
+ tcase.Testcase.check_testcase_area(['full'], 'full'))
+
+ def test_check_testcase_area_not_in_testcase_or_full(self):
+ self.assertEqual(False,
+ tcase.Testcase.check_testcase_area(['full'], 'half'))
+
+ @patch('dovetail.testcase.dt_utils')
+ def test_get_testcases_for_testsuite_no_testcases(self, mock_utils):
+ mock_utils.get_value_from_dict.return_value = None
+
+ result = tcase.Testcase.get_testcases_for_testsuite('suite', 'area')
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('testcases_list', 'suite'),
+ call('mandatory', None),
+ call('optional', None)])
+ self.assertEqual([], result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ @patch('dovetail.testcase.dt_utils')
+ def test_get_testcases_for_testsuite_no_selected_testcases(self,
+ mock_utils,
+ mock_config):
+ logger_obj = Mock()
+ tcase.Testcase.logger = logger_obj
+ testcases_obj = Mock()
+ mock_utils.get_value_from_dict.side_effect = [
+ testcases_obj, None, None]
+ mock_config.dovetail_config = {
+ 'mandatory': True,
+ 'optional': True
+ }
+ testsuite = {'name': 'test_name'}
+
+ result = tcase.Testcase.get_testcases_for_testsuite(testsuite, 'area')
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('testcases_list', testsuite),
+ call('mandatory', testcases_obj),
+ call('optional', testcases_obj)])
+ logger_obj.error.assert_has_calls([
+ call('There is no mandatory test case in test suite {}'
+ .format(testsuite['name'])),
+ call('There is no optional test case in test suite {}'
+ .format(testsuite['name']))])
+ self.assertEqual(None, result)
+
+ @patch('dovetail.testcase.dt_cfg')
+ @patch('dovetail.testcase.dt_utils')
+ @patch.object(tcase.Testcase, 'check_testcase_area')
+ def test_get_testcases_for_testsuite(self, mock_check, mock_utils,
+ mock_config):
+ logger_obj = Mock()
+ tcase.Testcase.logger = logger_obj
+ testcases_obj = Mock()
+ mock_utils.get_value_from_dict.side_effect = [
+ testcases_obj, ['mandatory'], ['optional']]
+ mock_config.dovetail_config = {
+ 'mandatory': True,
+ 'optional': True
+ }
+ mock_check.return_value = True
+ testsuite = {'name': 'test_name'}
+ testarea = ['area']
+
+ mandatory_obj = Mock()
+ tcase.Testcase.testcase_list['mandatory'] = mandatory_obj
+ optional_obj = Mock()
+ tcase.Testcase.testcase_list['optional'] = optional_obj
+ result = tcase.Testcase.get_testcases_for_testsuite(
+ testsuite, testarea)
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('testcases_list', testsuite),
+ call('mandatory', testcases_obj),
+ call('optional', testcases_obj)])
+ mock_check.assert_has_calls([
+ call('mandatory', 'area'),
+ call('optional', 'area')])
+ self.assertEqual(['mandatory', 'optional'], result)
+ self.assertEqual(
+ True, tcase.Testcase.testcase_list['mandatory'].is_mandatory)
+ self.assertEqual(
+ False, tcase.Testcase.testcase_list['optional'].is_mandatory)
+
+ @patch('dovetail.testcase.dt_cfg')
+ @patch('dovetail.testcase.dt_utils')
+ @patch.object(tcase.Testcase, 'check_testcase_area')
+ def test_get_testcases_for_testsuite_no_conf(self, mock_check, mock_utils,
+ mock_config):
+ logger_obj = Mock()
+ tcase.Testcase.logger = logger_obj
+ testcases_obj = Mock()
+ mock_utils.get_value_from_dict.side_effect = [
+ testcases_obj, ['mandatory'], ['optional']]
+ mock_config.dovetail_config = {
+ 'mandatory': False,
+ 'optional': False
+ }
+ mock_check.return_value = True
+ testsuite = {'name': 'test_name'}
+ testarea = ['area']
+
+ mandatory_obj = Mock()
+ tcase.Testcase.testcase_list['mandatory'] = mandatory_obj
+ optional_obj = Mock()
+ tcase.Testcase.testcase_list['optional'] = optional_obj
+ result = tcase.Testcase.get_testcases_for_testsuite(testsuite,
+ testarea)
+
+ mock_utils.get_value_from_dict.assert_has_calls([
+ call('testcases_list', testsuite),
+ call('mandatory', testcases_obj),
+ call('optional', testcases_obj)])
+ mock_check.assert_has_calls([
+ call('mandatory', 'area'),
+ call('optional', 'area')])
+ self.assertEqual(['mandatory', 'optional'], result)
+ self.assertEqual(True,
+ tcase.Testcase.testcase_list['mandatory']
+ .is_mandatory)
+ self.assertEqual(False,
+ tcase.Testcase.testcase_list['optional'].is_mandatory)
+
+ @patch.object(tcase.Testcase, 'prepare_cmd')
+ def test_functest_case_prepare_cmd_false(self, mock_prepare):
+ testcase = tcase.FunctestTestcase(self.testcase_yaml)
+ mock_prepare.return_value = False
+
+ result = testcase.prepare_cmd('type')
+
+ mock_prepare.assert_called_once_with('type')
+ self.assertEqual(False, result)
+
+ @patch('dovetail.testcase.os.path')
+ @patch('dovetail.testcase.dt_cfg')
+ @patch.object(tcase.Testcase, 'prepare_cmd')
+ def test_functest_case_prepare_cmd(self, mock_prepare, mock_config,
+ mock_path):
+ testcase = tcase.FunctestTestcase(self.testcase_yaml)
+ logger_obj = Mock()
+ testcase.logger = logger_obj
+ mock_prepare.return_value = True
+ mock_config.dovetail_config = {
+ 'no_api_validation': True,
+ 'functest': {'patches_dir': 'value'}}
+ mock_path.join.return_value = 'patch_cmd'
+
+ result = testcase.prepare_cmd('type')
+
+ mock_path.join.assert_called_once_with(
+ 'value', 'functest', 'disable-api-validation', 'apply.sh')
+ logger_obj.debug.assert_called_once_with(
+ 'Updated list of commands for test run with '
+ 'disabled API response validation: {}'
+ .format(testcase.cmds))
+ self.assertEqual(['patch_cmd'], testcase.cmds)
+ self.assertEqual(True, result)
+
+ def test_testfactory_error(self):
+ self.assertEqual(None,
+ tcase.TestcaseFactory.create('unknown',
+ self.testcase_yaml))
+
+ def test_testfactory_k8s(self):
+ k8s_testcase = tcase.TestcaseFactory.create('functest-k8s',
+ self.testcase_yaml)
+ self.assertEqual('functest-k8s', k8s_testcase.type)
+
+ @patch('dovetail.testcase.dt_logger')
+ def test_testsuite_create_log(self, mock_logger):
+ getlogger_obj = Mock()
+ logger_obj = Mock()
+ logger_obj.getLogger.return_value = getlogger_obj
+ mock_logger.Logger.return_value = logger_obj
+
+ tcase.Testsuite.create_log()
+
+ self.assertEqual(getlogger_obj, tcase.Testsuite.logger)
+
+ def test_testsuite_get_test(self):
+ suite = tcase.Testsuite('suite')
+ suite.testcase_list['testcase'] = 'value'
+
+ result = suite.get_test('testcase')
+
+ self.assertEqual('value', result)
+
+ def test_testsuite_get_test_not_exists(self):
+ suite = tcase.Testsuite('suite')
+
+ result = suite.get_test('testcase')
+
+ self.assertEqual(None, result)
+
+ @patch('builtins.open')
+ @patch('dovetail.testcase.yaml')
+ @patch('dovetail.testcase.os')
+ @patch('dovetail.testcase.constants')
+ def test_testsuite_load(self, mock_constants, mock_os, mock_yaml,
+ mock_open):
+ mock_constants.COMPLIANCE_PATH = 'abs_path'
+ mock_os.walk.return_value = [('root', ['dir'], ['file'])]
+ mock_os.path.join.return_value = 'file_path'
+ mock_yaml.safe_load.return_value = {'testsuite': 'value'}
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ tcase.Testsuite.load()
+
+ mock_os.walk.assert_called_once_with('abs_path')
+ mock_os.path.join.assert_called_with('root', 'file')
+ mock_open.assert_called_once_with('file_path')
+ mock_yaml.safe_load.assert_called_once_with(file_obj)
+ self.assertEqual({'testsuite': 'value'},
+ tcase.Testsuite.testsuite_list)
+
+ def test_testsuite_get_none(self):
+ self.assertEqual(None, tcase.Testsuite.get('unknown'))
+
+ def test_testsuite_get(self):
+ tcase.Testsuite.testsuite_list.update({'key': 'value'})
+ self.assertEqual('value', tcase.Testsuite.get('key'))
+
+ def test_testsuite_get_all(self):
+ tcase.Testsuite.testsuite_list.update({'key': 'value'})
+ self.assertEqual({'key': 'value'}, tcase.Testsuite.get_all())
diff --git a/dovetail/tests/unit/test_testcase.yaml b/dovetail/tests/unit/test_testcase.yaml
index cb947cd9..b4cd3b1d 100644
--- a/dovetail/tests/unit/test_testcase.yaml
+++ b/dovetail/tests/unit/test_testcase.yaml
@@ -1,11 +1,22 @@
+##############################################################################
+# Copyright (c) 2019 opnfv.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
---
dovetail.ipv6.tc001:
name: dovetail.ipv6.tc001
objective: VIM ipv6 operations, to create/delete network, port and subnet in bulk operation
+ vnf_type: tosca
validate:
type: functest
testcase: tempest_smoke_serial
report:
+ portal_key_file: tempest_logs/tempest_smoke_serial.html
sub_testcase_list:
- tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_network
- tempest.api.network.test_networks.BulkNetworkOpsIpV7Test.test_bulk_create_delete_port
diff --git a/dovetail/tests/unit/utils/__init__.py b/dovetail/tests/unit/utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dovetail/tests/unit/utils/__init__.py
diff --git a/dovetail/tests/unit/utils/test_dovetail_config.py b/dovetail/tests/unit/utils/test_dovetail_config.py
new file mode 100644
index 00000000..8e835f49
--- /dev/null
+++ b/dovetail/tests/unit/utils/test_dovetail_config.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import unittest
+from mock import patch
+
+from dovetail.utils.dovetail_config import DovetailConfig
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class DovetailConfigTesting(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ @patch.object(DovetailConfig, 'update_non_envs')
+ def test_update_config(self, mock_non_envs):
+ config_dict = {'key': {'path': ['aa / bb/ cc'], 'value': 'val'}}
+ dovetail_cfg = DovetailConfig()
+
+ dovetail_cfg.update_config(config_dict)
+
+ mock_non_envs.assert_called_once_with(['aa', 'bb', 'cc'], 'val')
+
+ def test_set_leaf_dict(self):
+ dict_to_test = {}
+ dovetail_cfg = DovetailConfig()
+
+ dovetail_cfg.set_leaf_dict(dict_to_test, ['aa', 'bb', 'cc'], 'val')
+
+ self.assertEqual({'aa': {'bb': {'cc': 'val'}}}, dict_to_test)
+
+ @patch.object(DovetailConfig, 'set_leaf_dict')
+ @patch.object(DovetailConfig, 'dovetail_config')
+ def test_update_non_envs(self, mock_cfg, mock_set_leaf):
+ path = ['aa', 'bb', 'cc']
+ value = 'val'
+ dovetail_cfg = DovetailConfig()
+
+ dovetail_cfg.update_non_envs(path, value)
+
+ mock_set_leaf.assert_called_once_with(mock_cfg, path, value)
diff --git a/dovetail/tests/unit/utils/test_dovetail_logger.py b/dovetail/tests/unit/utils/test_dovetail_logger.py
new file mode 100644
index 00000000..a70c0503
--- /dev/null
+++ b/dovetail/tests/unit/utils/test_dovetail_logger.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import unittest
+from mock import patch, call, Mock
+
+from dovetail.utils import dovetail_utils
+from dovetail.utils.dovetail_logger import Logger
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class DovetailLoggerTesting(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ @patch('sys.stdout')
+ @patch('dovetail.utils.dovetail_logger.os')
+ @patch('dovetail.utils.dovetail_logger.logging')
+ def test_logger_info(self, mock_logging, mock_os, mock_stdout):
+ file_path = 'file_path'
+ level_const_info = 'INFO'
+ level_const_debug = 'DEBUG'
+ logger = Mock()
+ mock_os.getenv.return_value = 'False'
+ mock_logging.INFO = level_const_info
+ mock_logging.DEBUG = level_const_debug
+ mock_logging.getLogger.return_value = logger
+ dovetail_utils.dt_cfg.dovetail_config = {'result_dir': file_path}
+ mock_os.path.exists.return_value = False
+ stream_handler_obj = Mock()
+ formatter_obj = Mock()
+ file_handler_obj = Mock()
+ mock_logging.StreamHandler.return_value = stream_handler_obj
+ mock_logging.Formatter.return_value = formatter_obj
+ mock_logging.FileHandler.return_value = file_handler_obj
+
+ logger_name = 'name'
+ dovetail_logger = Logger(logger_name)
+ mock_logging.getLogger.assert_called_once_with(logger_name)
+ self.assertEqual(dovetail_logger.logger.propagate, 0)
+ logger.setLevel.assert_called_once_with(level_const_debug)
+ mock_os.path.exists.assert_called_once_with(file_path)
+ # mock_os.makedirs.assert_called_once_with(file_path)
+ mock_logging.Formatter.assert_called_once_with(
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ stream_handler_obj.setFormatter.assert_called_once_with(formatter_obj)
+ stream_handler_obj.setLevel.assert_called_once_with(level_const_info)
+ file_handler_obj.setLevel.assert_called_once_with(level_const_info)
+ logger.addHandler.assert_has_calls([
+ call(stream_handler_obj), call(file_handler_obj)])
+ self.assertEqual(dovetail_logger.getLogger(), logger)
+
+ @patch('sys.stdout')
+ @patch('dovetail.utils.dovetail_logger.os')
+ @patch('dovetail.utils.dovetail_logger.logging')
+ def test_logger_debug(self, mock_logging, mock_os, mock_stdout):
+ file_path = 'file_path'
+ level_const_debug = 'DEBUG'
+ logger = Mock()
+ mock_os.getenv.return_value = 'True'
+ mock_logging.DEBUG = level_const_debug
+ mock_logging.getLogger.return_value = logger
+ dovetail_utils.dt_cfg.dovetail_config = {'result_dir': file_path}
+ mock_os.path.exists.return_value = False
+ stream_handler_obj = Mock()
+ formatter_obj = Mock()
+ file_handler_obj = Mock()
+ mock_logging.StreamHandler.return_value = stream_handler_obj
+ mock_logging.Formatter.return_value = formatter_obj
+ mock_logging.FileHandler.return_value = file_handler_obj
+
+ logger_name = 'name'
+ dovetail_logger = Logger(logger_name)
+ mock_logging.getLogger.assert_called_once_with(logger_name)
+ self.assertEqual(dovetail_logger.logger.propagate, 0)
+ logger.setLevel.assert_called_once_with(level_const_debug)
+ mock_os.path.exists.assert_called_once_with(file_path)
+ # mock_os.makedirs.assert_called_once_with(file_path)
+ mock_logging.Formatter.assert_called_once_with(
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ stream_handler_obj.setFormatter.assert_called_once_with(formatter_obj)
+ stream_handler_obj.setLevel.assert_called_once_with(level_const_debug)
+ file_handler_obj.setLevel.assert_called_once_with(level_const_debug)
+ logger.addHandler.assert_has_calls([
+ call(stream_handler_obj), call(file_handler_obj)])
+ self.assertEqual(dovetail_logger.getLogger(), logger)
diff --git a/dovetail/tests/unit/utils/test_dovetail_utils.py b/dovetail/tests/unit/utils/test_dovetail_utils.py
new file mode 100644
index 00000000..7d1fddc1
--- /dev/null
+++ b/dovetail/tests/unit/utils/test_dovetail_utils.py
@@ -0,0 +1,1402 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import io
+import unittest
+from mock import patch, call, Mock
+
+from dovetail import constants
+from dovetail.utils import dovetail_utils
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class DovetailUtilsTesting(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ @patch('sys.stdout')
+ @patch('builtins.print')
+ def test_exec_log_no_verbose(self, mock_print, mock_stdout):
+ dovetail_utils.exec_log(verbose=False, logger=None, msg='',
+ level='info', flush=True)
+
+ mock_print.assert_not_called()
+ mock_stdout.flush.assert_not_called()
+
+ @patch('sys.stdout')
+ @patch('builtins.print')
+ def test_exec_log_no_logger_flush(self, mock_print, mock_stdout):
+ message = 'message'
+
+ dovetail_utils.exec_log(verbose=True, logger=False, msg=message,
+ level='info', flush=True)
+
+ mock_print.assert_has_calls([call(message)])
+ mock_stdout.flush.assert_called_once()
+
+ @patch('sys.stdout')
+ @patch('builtins.print')
+ def test_exec_log_no_logger_no_flush(self, mock_print, mock_stdout):
+ message = 'message'
+
+ dovetail_utils.exec_log(verbose=True, logger=False, msg=message,
+ level='info', flush=False)
+
+ mock_print.assert_has_calls([call(message)])
+ mock_stdout.flush.assert_not_called()
+
+ def test_exec_log_logger_info(self):
+ message = 'message'
+ logger = Mock()
+
+ dovetail_utils.exec_log(verbose=True, logger=logger, msg=message,
+ level='info', flush=True)
+
+ logger.info.assert_called_once_with(message)
+
+ def test_exec_log_logger_error(self):
+ message = 'message'
+ logger = Mock()
+
+ dovetail_utils.exec_log(verbose=True, logger=logger, msg=message,
+ level='error', flush=True)
+
+ logger.error.assert_called_once_with(message)
+
+ def test_exec_log_logger_debug(self):
+ message = 'message'
+ logger = Mock()
+
+ dovetail_utils.exec_log(verbose=True, logger=logger, msg=message,
+ level='debug', flush=True)
+
+ logger.debug.assert_called_once_with(message)
+
+ def test_get_value_from_dict(self):
+ key_path = 'a.b'
+ input_dict = {'a': {'b': 'c'}}
+
+ expected = 'c'
+ result = dovetail_utils.get_value_from_dict(key_path, input_dict)
+
+ self.assertEqual(expected, result)
+
+ def test_get_value_from_dict_key_path_not_str(self):
+ key_path = 1
+ input_dict = {'a': {'b': 'c'}}
+
+ expected = None
+ result = dovetail_utils.get_value_from_dict(key_path, input_dict)
+
+ self.assertEqual(expected, result)
+
+ def test_get_value_from_dict_input_dict_not_dict(self):
+ key_path = 'a.b'
+ input_dict = 'dictionary'
+
+ expected = None
+ result = dovetail_utils.get_value_from_dict(key_path, input_dict)
+
+ self.assertEqual(expected, result)
+
+ def test_get_value_from_dict_no_value_for_key_in_key_path(self):
+ key_path = 'a.b'
+ input_dict = {'a': {'c': 'b'}}
+
+ expected = None
+ result = dovetail_utils.get_value_from_dict(key_path, input_dict)
+
+ self.assertEqual(expected, result)
+
+ @patch('os.path', autospec=True)
+ def test_read_plain_file_not_exist(self, mock_path):
+ file_path = 'unknown_file'
+ logger = Mock()
+ mock_path.isfile.return_value = False
+
+ expected = None
+ result = dovetail_utils.read_plain_file(file_path, logger)
+
+ mock_path.isfile.assert_called_once_with(file_path)
+ logger.error.assert_called_once_with("File {} doesn't exist."
+ .format(file_path))
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_read_plain_file(self, mock_path, mock_open):
+ file_path = 'known_file'
+ file_data = u'file data'
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.return_value = io.StringIO(file_data)
+
+ expected = file_data
+ result = dovetail_utils.read_plain_file(file_path)
+
+ mock_path.isfile.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_read_plain_file_raised_exception(self, mock_path, mock_open):
+ logger = Mock()
+ file_path = 'known_file'
+ errorMSG = 'Exception was raised'
+ exception = Exception(errorMSG)
+ mock_open.side_effect = exception
+
+ expected = None
+ result = dovetail_utils.read_plain_file(file_path, logger)
+
+ mock_open.assert_called_once_with(file_path, 'r')
+ logger.exception.assert_called_once_with(
+ 'Failed to read file {}, exception: {}'
+ .format(file_path, exception))
+ self.assertEqual(expected, result)
+
+ @patch('os.path', autospec=True)
+ def test_read_yaml_file_not_exist(self, mock_path):
+ file_path = 'unknown_file'
+ logger = Mock()
+ mock_path.isfile.return_value = False
+
+ expected = None
+ result = dovetail_utils.read_yaml_file(file_path, logger)
+
+ mock_path.isfile.assert_called_once_with(file_path)
+ logger.error.assert_called_once_with("File {} doesn't exist."
+ .format(file_path))
+ self.assertEqual(expected, result)
+
+ @patch('yaml.safe_load')
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_read_yaml_file(self, mock_path, mock_open, mock_load):
+ file_obj = Mock()
+ file_path = 'known_file'
+ file_data = 'file data'
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = file_data
+
+ expected = file_data
+ result = dovetail_utils.read_yaml_file(file_path)
+
+ mock_path.isfile.assert_called_once_with(file_path)
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_load.assert_called_once_with(file_obj)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_read_yaml_file_raised_exception(self, mock_path, mock_open):
+ logger = Mock()
+ file_path = 'known_file'
+ errorMSG = 'Exception was raised'
+ exception = Exception(errorMSG)
+ mock_open.side_effect = exception
+
+ expected = None
+ result = dovetail_utils.read_yaml_file(file_path, logger)
+
+ mock_open.assert_called_once_with(file_path, 'r')
+ logger.exception.assert_called_once_with(
+ 'Failed to read file {}, exception: {}'
+ .format(file_path, exception))
+ self.assertEqual(expected, result)
+
+ @patch('os.path', autospec=True)
+ def test_get_hosts_info_not_exist(self, mock_path):
+ file_path = 'file_path'
+ file_complete_name = '/'.join((file_path, 'hosts.yaml'))
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_path.isfile.return_value = False
+ logger = Mock()
+
+ expected = {}
+ result = dovetail_utils.get_hosts_info(logger)
+
+ mock_path.join.assert_called_once_with(file_path, 'hosts.yaml')
+ mock_path.isfile.assert_called_once_with(file_complete_name)
+ self.assertEqual(expected, result)
+
+ @patch('yaml.safe_load')
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_get_hosts_info_not_yaml(self, mock_path, mock_open, mock_load):
+ file_path = 'file_path'
+ file_complete_name = '/'.join((file_path, 'hosts.yaml'))
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_path.isfile.return_value = True
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = None
+ logger = Mock()
+
+ expected = {}
+ result = dovetail_utils.get_hosts_info(logger)
+
+ mock_path.join.assert_called_once_with(file_path, 'hosts.yaml')
+ mock_path.isfile.assert_called_once_with(file_complete_name)
+ mock_open.assert_called_once_with(file_complete_name)
+ mock_load.assert_called_once_with(file_obj)
+ logger.debug.assert_called_once_with(
+ 'File {} is empty.'.format(file_complete_name))
+ self.assertEqual(expected, result)
+
+ @patch('yaml.safe_load')
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_get_hosts_info_no_hosts_info(self, mock_path, mock_open,
+ mock_load):
+ file_path = 'file_path'
+ file_complete_name = '/'.join((file_path, 'hosts.yaml'))
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_path.isfile.return_value = True
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = {'a': 'b'}
+ logger = Mock()
+
+ expected = {}
+ result = dovetail_utils.get_hosts_info(logger)
+
+ mock_path.join.assert_called_once_with(file_path, 'hosts.yaml')
+ mock_path.isfile.assert_called_once_with(file_complete_name)
+ mock_open.assert_called_once_with(file_complete_name)
+ mock_load.assert_called_once_with(file_obj)
+ logger.error.assert_called_once_with(
+ 'There is no key hosts_info in file {}'
+ .format(file_complete_name))
+ self.assertEqual(expected, result)
+
+ @patch('yaml.safe_load')
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_get_hosts_info_no_hostname(self, mock_path, mock_open, mock_load):
+ file_path = 'file_path'
+ file_complete_name = '/'.join((file_path, 'hosts.yaml'))
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_path.isfile.return_value = True
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = {'hosts_info': {'127.0.0.1': []}}
+
+ expected = {}
+ result = dovetail_utils.get_hosts_info()
+
+ mock_path.join.assert_called_once_with(file_path, 'hosts.yaml')
+ mock_path.isfile.assert_called_once_with(file_complete_name)
+ mock_open.assert_called_once_with(file_complete_name)
+ mock_load.assert_called_once_with(file_obj)
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.utils.dovetail_utils.add_hosts_info')
+ @patch('yaml.safe_load')
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_get_hosts_info_no_valid_hostname(self, mock_path, mock_open,
+ mock_load, mock_fn):
+ file_path = 'file_path'
+ file_complete_name = '/'.join((file_path, 'hosts.yaml'))
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_path.isfile.return_value = True
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ hosts_info = {'127.0.0.1': [None]}
+ mock_load.return_value = {'hosts_info': hosts_info}
+
+ expected = {}
+ result = dovetail_utils.get_hosts_info()
+
+ mock_path.join.assert_called_once_with(file_path, 'hosts.yaml')
+ mock_path.isfile.assert_called_once_with(file_complete_name)
+ mock_open.assert_called_once_with(file_complete_name)
+ mock_load.assert_called_once_with(file_obj)
+ mock_fn.assert_called_once_with(list(hosts_info.keys())[0],
+ list(hosts_info.values())[0])
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.utils.dovetail_utils.add_hosts_info')
+ @patch('yaml.safe_load')
+ @patch('builtins.open')
+ @patch('os.path', autospec=True)
+ def test_get_hosts_info(self, mock_path, mock_open, mock_load, mock_fn):
+ file_path = 'file_path'
+ file_complete_name = '/'.join((file_path, 'hosts.yaml'))
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_path.isfile.return_value = True
+ file_obj = Mock()
+ mock_open.return_value.__enter__.return_value = file_obj
+ hosts_ip = '127.0.0.1'
+ hostnames = ['host_one', 'host_two']
+ mock_load.return_value = {'hosts_info': {hosts_ip: hostnames}}
+ logger = Mock()
+
+ names_str = ' '.join(hostnames)
+ expected = {names_str: hosts_ip}
+ result = dovetail_utils.get_hosts_info(logger)
+
+ mock_path.join.assert_called_once_with(file_path, 'hosts.yaml')
+ mock_path.isfile.assert_called_once_with(file_complete_name)
+ mock_open.assert_called_once_with(file_complete_name)
+ mock_load.assert_called_once_with(file_obj)
+ mock_fn.assert_called_once_with(hosts_ip, hostnames)
+ logger.debug.assert_called_once_with('Get hosts info {}:{}.'
+ .format(hosts_ip, names_str))
+ self.assertEqual(expected, result)
+
+ @patch('os.path', autospec=True)
+ def test_check_cacert_false(self, mock_path):
+ file_one_path = 'path_one'
+ file_two_path = 'path_two'
+ logger = Mock()
+ mock_path.isfile.return_value = True
+ mock_path.dirname.return_value = file_one_path
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_two_path}
+
+ expected = False
+ result = dovetail_utils.check_cacert_file(file_one_path, logger)
+
+ mock_path.isfile.assert_called_once_with(file_one_path)
+ mock_path.dirname.assert_called_once_with(file_one_path)
+ logger.error.assert_called_once_with(
+ 'Credential file must be put under {}, '
+ 'which can be mounted into other container.'
+ .format(file_two_path))
+ self.assertEqual(expected, result)
+
+ @patch('os.path', autospec=True)
+ def test_check_cacert_true(self, mock_path):
+ file_path = 'path_one'
+ mock_path.isfile.return_value = True
+ mock_path.dirname.return_value = file_path
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': file_path}
+
+ expected = True
+ result = dovetail_utils.check_cacert_file(file_path)
+
+ mock_path.isfile.assert_called_once_with(file_path)
+ mock_path.dirname.assert_called_once_with(file_path)
+ self.assertEqual(expected, result)
+
+ @patch('os.path', autospec=True)
+ def test_check_cacert_not_exist(self, mock_path):
+ file_path = 'path_one'
+ mock_path.isfile.return_value = False
+ logger = Mock()
+
+ expected = False
+ result = dovetail_utils.check_cacert_file(file_path, logger)
+
+ mock_path.isfile.assert_called_once_with(file_path)
+ logger.error.assert_called_once_with(
+ 'OS_CACERT is {}, but the file does not exist.'
+ .format(file_path))
+ self.assertEqual(expected, result)
+
+ @patch('sys.stdout')
+ def test_show_progress_bar(self, mock_stdout):
+ length = 99
+ max_length = 50
+ expect_length = length % max_length
+ calls = [call('Running ' + ' ' * max_length + '\r'),
+ call('Running ' + '.' * expect_length + '\r')]
+
+ dovetail_utils.show_progress_bar(length)
+ mock_stdout.write.assert_has_calls(calls)
+ mock_stdout.flush.assert_has_calls([call(), call()])
+
+ def test_get_duration(self):
+ date = '2018-08-10 05:12:27'
+ logger = Mock()
+
+ expected = '0.0m0s'
+ result = dovetail_utils.get_duration(date, date, logger)
+
+ self.assertEqual(expected, result)
+
+ def test_get_duration_invalid_time(self):
+ date = 'invalid'
+ logger = Mock()
+
+ expected = None
+ result = dovetail_utils.get_duration(date, date, logger)
+
+ logger.exception.assert_called_once()
+ self.assertEqual(expected, result)
+
+ @patch('os.getenv')
+ def test_check_https_enabled(self, mock_getenv):
+ auth_url = 'https://valid-url.com'
+ mock_getenv.return_value = auth_url
+ logger = Mock()
+
+ expected = True
+ result = dovetail_utils.check_https_enabled(logger)
+
+ logger.debug.assert_has_calls(
+ [call('Checking if https enabled or not...'),
+ call('https is enabled')])
+ self.assertEqual(expected, result)
+
+ @patch('os.getenv')
+ def test_check_https_disabled(self, mock_getenv):
+ auth_url = 'invalid'
+ mock_getenv.return_value = auth_url
+ logger = Mock()
+
+ expected = False
+ result = dovetail_utils.check_https_enabled(logger)
+
+ logger.debug.assert_has_calls(
+ [call('Checking if https enabled or not...'),
+ call('https is not enabled')])
+ self.assertEqual(expected, result)
+
+ @patch('python_hosts.Hosts', autospec=True)
+ @patch('python_hosts.HostsEntry', autospec=True)
+ def test_add_hosts_info_no_ip(self, mock_python_h_entry,
+ mock_python_hosts):
+ dovetail_utils.add_hosts_info(None, ['host_one'])
+
+ mock_python_hosts.assert_called_once_with(path='/etc/hosts')
+ mock_python_h_entry.assert_not_called()
+
+ @patch('python_hosts.Hosts', autospec=True)
+ @patch('python_hosts.HostsEntry', autospec=True)
+ def test_add_hosts_info_no_hosts(self, mock_python_h_entry,
+ mock_python_hosts):
+ dovetail_utils.add_hosts_info('127.0.0.1', [])
+
+ mock_python_hosts.assert_called_once_with(path='/etc/hosts')
+ mock_python_h_entry.assert_not_called()
+
+ @patch('python_hosts.Hosts', autospec=True)
+ @patch('python_hosts.HostsEntry', autospec=True)
+ def test_add_hosts_info(self, mock_python_h_entry, mock_python_hosts):
+ ip = '127.0.0.1'
+ hostnames = ['host_one']
+ hosts_obj = Mock()
+ entry_obj = Mock()
+ mock_python_hosts.return_value = hosts_obj
+ mock_python_h_entry.return_value = entry_obj
+
+ dovetail_utils.add_hosts_info(ip, hostnames)
+
+ mock_python_hosts.assert_called_once_with(path='/etc/hosts')
+ mock_python_h_entry.assert_called_once_with(entry_type='ipv4',
+ address=ip,
+ names=hostnames)
+ hosts_obj.add.assert_called_once_with([entry_obj])
+ hosts_obj.write.assert_called_once()
+
+ def test_get_obj_by_path(self):
+ obj = {'list': ['a', 'b'], 'name': 'name'}
+ dst_path = ('name',)
+
+ expected = 'name'
+ result = dovetail_utils.get_obj_by_path(obj, dst_path)
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.utils.dovetail_utils.objwalk')
+ def test_get_obj_by_path_none(self, mock_walk):
+ path = 'path'
+ dist_path = 'dst_path'
+ obj = 'obj'
+ mock_walk.return_value = [(path, obj)]
+
+ expected = None
+ result = dovetail_utils.get_obj_by_path(obj, dist_path)
+
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.environ')
+ def test_source_env(self, mock_env, mock_open):
+ file_path = 'file_path'
+ env_name = 'name'
+ env_value = 'value'
+ file_data = u'export %s=%s' % (env_name, env_value)
+ mock_open.return_value.__enter__.return_value = io.StringIO(file_data)
+
+ dovetail_utils.source_env(file_path)
+
+ mock_open.assert_called_once_with(file_path, 'r')
+ mock_env.update.assert_called_once_with({env_name: env_value})
+
+ @patch('dovetail.utils.dovetail_utils.docker')
+ def test_check_docker_version(self, mock_docker):
+ server_version = '1.12.3'
+ client_obj = Mock()
+ mock_docker.from_env.return_value = client_obj
+ client_obj.version.return_value = {'Version': server_version}
+ logger = Mock()
+
+ dovetail_utils.check_docker_version(logger)
+
+ logger.debug.assert_has_calls(
+ [call('Docker server version: {}'.format(server_version))])
+
+ @patch('dovetail.utils.dovetail_utils.docker')
+ def test_check_docker_version_error(self, mock_docker):
+ client_obj = Mock()
+ mock_docker.from_env.return_value = client_obj
+ client_obj.version.return_value = {}
+ logger = Mock()
+
+ dovetail_utils.check_docker_version(logger)
+
+ logger.error.assert_has_calls(
+ [call("Don't support this Docker server version. "
+ "Docker server should be updated to at least 1.12.3.")])
+
+ @patch('dovetail.utils.dovetail_utils.docker')
+ def test_check_docker_version_less_than(self, mock_docker):
+ server_version = '1.12.1'
+ client_obj = Mock()
+ mock_docker.from_env.return_value = client_obj
+ client_obj.version.return_value = {'Version': server_version}
+ logger = Mock()
+
+ dovetail_utils.check_docker_version(logger)
+
+ logger.error.assert_has_calls(
+ [call("Don't support this Docker server version. "
+ "Docker server should be updated to at least 1.12.3.")])
+
+ @patch('builtins.open')
+ @patch('os.path')
+ @patch('os.listdir')
+ @patch('json.load')
+ @patch('json.dumps')
+ def test_combine_files(self, mock_dumps, mock_load, mock_listdir,
+ mock_path, mock_open):
+ file_path = 'file_path'
+ file_name = 'file_name'
+ file_complete_name = '/'.join([file_path, file_name])
+ file_content_dict = {'key': 'value'}
+ file_content_str = '{"key": "value"}'
+ file_obj = Mock()
+ mock_listdir.return_value = [file_name]
+ mock_path.join.return_value = file_complete_name
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = file_content_dict
+ mock_dumps.return_value = file_content_str
+ logger = Mock()
+
+ expected = 'result_file'
+ result = dovetail_utils.combine_files(file_path, expected, logger)
+
+ mock_listdir.assert_called_once_with(file_path)
+ mock_path.join.assert_called_once_with(file_path, file_name)
+ mock_open.assert_any_call(file_complete_name, 'r')
+ mock_load.assert_called_once_with(file_obj)
+ mock_open.assert_any_call(expected, 'w')
+ mock_dumps.assert_called_once_with({file_name: file_content_dict})
+ file_obj.write.assert_called_once_with(file_content_str)
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.path')
+ @patch('os.listdir')
+ def test_combine_files_read_exception(self, mock_listdir, mock_path,
+ mock_open):
+ file_path = 'file_path'
+ file_name = 'file_name'
+ file_complete_name = '/'.join([file_path, file_name])
+ mock_listdir.return_value = [file_name]
+ mock_path.join.return_value = file_complete_name
+ mock_open.side_effect = Exception()
+ logger = Mock()
+
+ expected = None
+ result = dovetail_utils.combine_files(file_path, expected, logger)
+
+ mock_listdir.assert_called_once_with(file_path)
+ mock_path.join.assert_called_once_with(file_path, file_name)
+ mock_open.assert_any_call(file_complete_name, 'r')
+ logger.error.assert_called_once_with(
+ 'Failed to read file {}.'.format(file_complete_name))
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.path')
+ @patch('os.listdir')
+ @patch('json.load')
+ @patch('json.dumps')
+ def test_combine_files_write_exception(self, mock_dumps, mock_load,
+ mock_listdir, mock_path, mock_open):
+ file_path = 'file_path'
+ file_name = 'file_name'
+ file_complete_name = '/'.join([file_path, file_name])
+ file_content_dict = {'key': 'value'}
+ file_content_str = '{"key": "value"}'
+ file_obj = Mock()
+ file_obj.write.side_effect = Exception()
+ mock_listdir.return_value = [file_name]
+ mock_path.join.return_value = file_complete_name
+ mock_open.return_value.__enter__.return_value = file_obj
+ mock_load.return_value = file_content_dict
+ mock_dumps.return_value = file_content_str
+ logger = Mock()
+
+ expected = None
+ result = dovetail_utils.combine_files(file_path, expected, logger)
+
+ mock_listdir.assert_called_once_with(file_path)
+ mock_path.join.assert_called_once_with(file_path, file_name)
+ mock_open.assert_any_call(file_complete_name, 'r')
+ mock_load.assert_called_once_with(file_obj)
+ mock_open.assert_any_call(expected, 'w')
+ mock_dumps.assert_called_once_with({file_name: file_content_dict})
+ file_obj.write.assert_called_once_with(file_content_str)
+ logger.exception.assert_called_once_with(
+ 'Failed to write file {}.'.format(expected))
+ self.assertEqual(expected, result)
+
+ @patch('json.dump')
+ @patch('builtins.open')
+ @patch('os.path')
+ @patch('dovetail.utils.dovetail_utils.check_https_enabled')
+ @patch('os.getenv')
+ @patch('dovetail.utils.dovetail_utils.OS_Utils', autospec=True)
+ def test_get_openstack_endpoint(self, mock_utils, mock_getenv,
+ mock_https_check, mock_path, mock_open,
+ mock_dump):
+ mock_https_check.return_value = True
+ mock_getenv.return_value = 'True'
+ endpoints_ret = True
+ endpoint_url = 'http://www.abc.com'
+ endpoint_enabled = True
+ service_id = '123456789'
+ service_type = 'type'
+ service_name = 'name'
+ endpoints = [{'url': endpoint_url,
+ 'enabled': endpoint_enabled,
+ 'service_id': service_id}]
+ services_ret = True
+ services = [{'service_type': service_type,
+ 'name': service_name}]
+ file_path = 'file_path'
+ file_name = 'endpoint_info.json'
+ file_complete_name = '/'.join([file_path, file_name])
+ utils_obj = Mock()
+ file_obj = Mock()
+ logger = Mock()
+ mock_utils.return_value = utils_obj
+ utils_obj.search_endpoints.return_value = (endpoints_ret, endpoints)
+ utils_obj.search_services.return_value = (services_ret, services)
+ dovetail_utils.dt_cfg.dovetail_config = {'result_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ mock_open.return_value.__enter__.return_value = file_obj
+
+ expected = [{'Service Type': service_type,
+ 'URL': endpoint_url,
+ 'Enabled': endpoint_enabled,
+ 'Service Name': service_name}]
+ result = dovetail_utils.get_openstack_endpoint(logger=logger)
+
+ mock_https_check.assert_called_once_with(logger)
+ mock_getenv.assert_called_once_with('OS_INSECURE')
+ mock_utils.assert_called_once_with(verify=False)
+ utils_obj.search_endpoints.assert_called_once()
+ utils_obj.search_services.assert_called_once_with(
+ service_id=service_id)
+ mock_path.join.assert_called_once_with(file_path, file_name)
+ mock_open.assert_any_call(file_complete_name, 'w')
+ mock_dump.assert_called_once_with(expected, file_obj)
+ logger.debug.assert_called_once_with(
+ 'Record all endpoint info into file {}.'
+ .format(file_complete_name))
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.utils.dovetail_utils.check_https_enabled')
+ @patch('os.getenv')
+ @patch('dovetail.utils.dovetail_utils.OS_Utils', autospec=True)
+ def test_get_openstack_endpoint_no_endpoints(self, mock_utils, mock_getenv,
+ mock_https_check):
+ mock_https_check.return_value = True
+ mock_getenv.return_value = 'True'
+ endpoints_ret = False
+ endpoints_exception_msg = 'An exception occured'
+ utils_obj = Mock()
+ logger = Mock()
+ mock_utils.return_value = utils_obj
+ utils_obj.search_endpoints.return_value = (endpoints_ret,
+ endpoints_exception_msg)
+
+ expected = None
+ result = dovetail_utils.get_openstack_endpoint(logger=logger)
+
+ mock_https_check.assert_called_once_with(logger)
+ mock_getenv.assert_called_once_with('OS_INSECURE')
+ mock_utils.assert_called_once_with(verify=False)
+ utils_obj.search_endpoints.assert_called_once()
+ logger.error.assert_called_once_with(
+ 'Failed to list endpoints. Exception message, {}'
+ .format(endpoints_exception_msg))
+ self.assertEqual(expected, result)
+
+ @patch('dovetail.utils.dovetail_utils.check_https_enabled')
+ @patch('os.getenv')
+ @patch('dovetail.utils.dovetail_utils.OS_Utils', autospec=True)
+ def test_get_openstack_endpoint_no_services(self, mock_utils, mock_getenv,
+ mock_https_check):
+ mock_https_check.return_value = True
+ mock_getenv.return_value = 'True'
+ endpoints_ret = True
+ endpoint_url = 'http://www.abc.com'
+ endpoint_enabled = True
+ service_id = '123456789'
+ endpoints = [{'url': endpoint_url,
+ 'enabled': endpoint_enabled,
+ 'service_id': service_id}]
+ services_ret = False
+ services_exception_msg = 'An exception occured'
+ utils_obj = Mock()
+ logger = Mock()
+ mock_utils.return_value = utils_obj
+ utils_obj.search_endpoints.return_value = (endpoints_ret, endpoints)
+ utils_obj.search_services.return_value = (services_ret,
+ services_exception_msg)
+
+ expected = None
+ result = dovetail_utils.get_openstack_endpoint(logger=logger)
+
+ mock_https_check.assert_called_once_with(logger)
+ mock_getenv.assert_called_once_with('OS_INSECURE')
+ mock_utils.assert_called_once_with(verify=False)
+ utils_obj.search_endpoints.assert_called_once()
+ utils_obj.search_services.assert_called_once_with(
+ service_id=service_id)
+ logger.error.assert_called_once_with(
+ 'Failed to list services. Exception message, {}'
+ .format(services_exception_msg))
+ self.assertEqual(expected, result)
+
+ @patch('builtins.open')
+ @patch('os.path')
+ @patch('dovetail.utils.dovetail_utils.check_https_enabled')
+ @patch('os.getenv')
+ @patch('dovetail.utils.dovetail_utils.OS_Utils', autospec=True)
+ def test_get_openstack_endpoint_exception(self, mock_utils, mock_getenv,
+ mock_https_check, mock_path,
+ mock_open):
+ mock_https_check.return_value = False
+ mock_getenv.return_value = 'True'
+ endpoints_ret = True
+ endpoint_url = 'http://www.abc.com'
+ endpoint_enabled = True
+ service_id = '123456789'
+ service_type = 'type'
+ service_name = 'name'
+ endpoints = [{'url': endpoint_url,
+ 'enabled': endpoint_enabled,
+ 'service_id': service_id}]
+ services_ret = True
+ services = [{'service_type': service_type,
+ 'name': service_name}]
+ file_path = 'file_path'
+ file_name = 'endpoint_info.json'
+ file_complete_name = '/'.join([file_path, file_name])
+ utils_obj = Mock()
+ logger = Mock()
+ mock_utils.return_value = utils_obj
+ utils_obj.search_endpoints.return_value = (endpoints_ret, endpoints)
+ utils_obj.search_services.return_value = (services_ret, services)
+ dovetail_utils.dt_cfg.dovetail_config = {'result_dir': file_path}
+ mock_path.join.return_value = file_complete_name
+ errorMSG = 'Exception was raised'
+ exception = Exception(errorMSG)
+ mock_open.side_effect = exception
+
+ expected = None
+ result = dovetail_utils.get_openstack_endpoint(logger=logger)
+
+ mock_https_check.assert_called_once_with(logger)
+ mock_getenv.assert_called_once_with('OS_INSECURE')
+ mock_utils.assert_called_once_with()
+ utils_obj.search_endpoints.assert_called_once()
+ utils_obj.search_services.assert_called_once_with(
+ service_id=service_id)
+ mock_path.join.assert_called_once_with(file_path, file_name)
+ mock_open.assert_any_call(file_complete_name, 'w')
+ logger.exception.assert_called_once_with(
+ 'Failed to write endpoint info into file.')
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('dovetail.utils.dovetail_utils.get_inventory_file')
+ @patch('dovetail.utils.dovetail_utils.exec_cmd')
+ @patch('dovetail.utils.dovetail_utils.combine_files')
+ def test_get_hardware_info(self, mock_combine, mock_cmd, mock_inventory,
+ mock_path):
+ logger = Mock()
+ config_dir = 'config_dir'
+ result_dir = 'result_dir'
+ pod_file = 'pod_file'
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': config_dir,
+ 'result_dir': result_dir,
+ 'pod_file': pod_file}
+ mock_inventory.return_value = Mock()
+ ret = 0
+ msg = ''
+ mock_cmd.return_value = (ret, msg)
+ inventory_file = '/'.join([result_dir, 'inventory.ini'])
+ info_file_path = '/'.join([result_dir, 'sut_hardware_info'])
+ all_info_file = '/'.join([result_dir, 'all_hosts_info.json'])
+ mock_path.join.side_effect = [
+ '/'.join([config_dir, pod_file]),
+ info_file_path,
+ all_info_file,
+ inventory_file]
+ mock_path.exists.return_value = True
+ mock_combine.return_value = True
+
+ expected = all_info_file
+ result = dovetail_utils.get_hardware_info(logger=logger)
+
+ join_calls = [call(config_dir, pod_file),
+ call(result_dir, 'sut_hardware_info'),
+ call(result_dir, 'all_hosts_info.json'),
+ call(result_dir, 'inventory.ini')]
+ mock_path.join.assert_has_calls(join_calls)
+ log_calls = [
+ call('Get hardware info of all nodes list in file {} ...'
+ .format('/'.join([config_dir, pod_file]))),
+ call('Hardware info of all nodes are stored in file {}.'
+ .format(expected))]
+ logger.info.assert_has_calls(log_calls)
+ mock_cmd.assert_called_once_with(
+ 'cd {} && ansible all -m setup -i {} --tree {}'
+ .format(constants.USERCONF_PATH, inventory_file, info_file_path),
+ verbose=False)
+ mock_path.exists.assert_called_once_with(info_file_path)
+ mock_combine.assert_called_once_with(info_file_path, all_info_file,
+ logger)
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('dovetail.utils.dovetail_utils.get_inventory_file')
+ def test_get_hardware_info_no_inventory(self, mock_inventory,
+ mock_path):
+ logger = Mock()
+ config_dir = 'config_dir'
+ result_dir = 'result_dir'
+ pod_file = 'pod_file'
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': config_dir,
+ 'result_dir': result_dir,
+ 'pod_file': pod_file}
+ mock_inventory.return_value = None
+ mock_path.join.side_effect = [
+ '/'.join([config_dir, pod_file]),
+ '/'.join([result_dir, 'sut_hardware_info']),
+ '/'.join([result_dir, 'all_hosts_info.json']),
+ '/'.join([result_dir, 'inventory.ini'])]
+
+ expected = None
+ result = dovetail_utils.get_hardware_info(logger=logger)
+
+ join_calls = [call(config_dir, pod_file),
+ call(result_dir, 'sut_hardware_info'),
+ call(result_dir, 'all_hosts_info.json'),
+ call(result_dir, 'inventory.ini')]
+ mock_path.join.assert_has_calls(join_calls)
+ logger.info.assert_called_once_with(
+ 'Get hardware info of all nodes list in file {} ...'
+ .format('/'.join([config_dir, pod_file])))
+ logger.error.assert_called_once_with(
+ 'Failed to get SUT hardware info.')
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('dovetail.utils.dovetail_utils.get_inventory_file')
+ @patch('dovetail.utils.dovetail_utils.exec_cmd')
+ def test_get_hardware_info_no_info(self, mock_cmd, mock_inventory,
+ mock_path):
+ logger = Mock()
+ config_dir = 'config_dir'
+ result_dir = 'result_dir'
+ pod_file = 'pod_file'
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': config_dir,
+ 'result_dir': result_dir,
+ 'pod_file': pod_file}
+ mock_inventory.return_value = Mock()
+ ret = 0
+ msg = ''
+ mock_cmd.return_value = (ret, msg)
+ inventory_file = '/'.join([result_dir, 'inventory.ini'])
+ info_file_path = '/'.join([result_dir, 'sut_hardware_info'])
+ all_info_file = '/'.join([result_dir, 'all_hosts_info.json'])
+ mock_path.join.side_effect = [
+ '/'.join([config_dir, pod_file]),
+ info_file_path,
+ all_info_file,
+ inventory_file]
+ mock_path.exists.return_value = False
+
+ expected = None
+ result = dovetail_utils.get_hardware_info(logger=logger)
+
+ join_calls = [call(config_dir, pod_file),
+ call(result_dir, 'sut_hardware_info'),
+ call(result_dir, 'all_hosts_info.json'),
+ call(result_dir, 'inventory.ini')]
+ mock_path.join.assert_has_calls(join_calls)
+ logger.info.assert_called_once_with(
+ 'Get hardware info of all nodes list in file {} ...'
+ .format('/'.join([config_dir, pod_file])))
+ logger.error.assert_called_once_with(
+ 'Failed to get SUT hardware info.')
+ mock_cmd.assert_called_once_with(
+ 'cd {} && ansible all -m setup -i {} --tree {}'
+ .format(constants.USERCONF_PATH, inventory_file, info_file_path),
+ verbose=False)
+ mock_path.exists.assert_called_once_with(info_file_path)
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('dovetail.utils.dovetail_utils.get_inventory_file')
+ @patch('dovetail.utils.dovetail_utils.exec_cmd')
+ @patch('dovetail.utils.dovetail_utils.combine_files')
+ def test_get_hardware_info_no_combine(self, mock_combine, mock_cmd,
+ mock_inventory, mock_path):
+ logger = Mock()
+ config_dir = 'config_dir'
+ result_dir = 'result_dir'
+ pod_file = 'pod_file'
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': config_dir,
+ 'result_dir': result_dir,
+ 'pod_file': pod_file}
+ mock_inventory.return_value = Mock()
+ ret = 0
+ msg = ''
+ mock_cmd.return_value = (ret, msg)
+ inventory_file = '/'.join([result_dir, 'inventory.ini'])
+ info_file_path = '/'.join([result_dir, 'sut_hardware_info'])
+ all_info_file = '/'.join([result_dir, 'all_hosts_info.json'])
+ mock_path.join.side_effect = [
+ '/'.join([config_dir, pod_file]),
+ info_file_path,
+ all_info_file,
+ inventory_file]
+ mock_path.exists.return_value = True
+ mock_combine.return_value = False
+
+ expected = None
+ result = dovetail_utils.get_hardware_info(logger=logger)
+
+ join_calls = [call(config_dir, pod_file),
+ call(result_dir, 'sut_hardware_info'),
+ call(result_dir, 'all_hosts_info.json'),
+ call(result_dir, 'inventory.ini')]
+ mock_path.join.assert_has_calls(join_calls)
+ logger.info.assert_called_once_with(
+ 'Get hardware info of all nodes list in file {} ...'
+ .format('/'.join([config_dir, pod_file])))
+ logger.error.assert_called_once_with(
+ 'Failed to get all hardware info.')
+ mock_cmd.assert_called_once_with(
+ 'cd {} && ansible all -m setup -i {} --tree {}'
+ .format(constants.USERCONF_PATH, inventory_file, info_file_path),
+ verbose=False)
+ mock_path.exists.assert_called_once_with(info_file_path)
+ mock_combine.assert_called_once_with(info_file_path, all_info_file,
+ logger)
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('builtins.open')
+ @patch('yaml.safe_load')
+ def test_get_inventory_password(self, mock_load, mock_open, mock_path):
+ name = 'name'
+ ip = 'ip'
+ user = 'user'
+ password = 'password'
+ pod_file_data = {'nodes': [{'name': name,
+ 'ip': ip,
+ 'user': user,
+ 'password': password}]}
+ inventory_file_name = 'inventory'
+ pod_file_name = 'pod'
+ logger = Mock()
+ pod_file_obj = Mock()
+ inventory_file_obj = Mock()
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.side_effect = [pod_file_obj,
+ inventory_file_obj]
+ mock_load.return_value = pod_file_data
+
+ expected = True
+ result = dovetail_utils.get_inventory_file(pod_file_name,
+ inventory_file_name,
+ logger=logger)
+
+ mock_path.isfile.assert_called_once_with(pod_file_name)
+ mock_open.assert_any_call(pod_file_name, 'r')
+ mock_open.assert_any_call(inventory_file_name, 'w')
+ mock_load.assert_called_once_with(pod_file_obj)
+ inventory_file_obj.write.assert_called_once_with(
+ '{name} ansible_host={ip} ansible_user={user} '
+ 'ansible_ssh_pass={password}\n'
+ .format(name=name, ip=ip, user=user, password=password))
+ logger.debug.assert_called_once_with(
+ 'Ansible inventory file is {}.'.format(inventory_file_name))
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('builtins.open')
+ @patch('yaml.safe_load')
+ def test_get_inventory_key_filename(self, mock_load, mock_open, mock_path):
+ name = 'name'
+ ip = 'ip'
+ user = 'user'
+ password = 'password'
+ pod_file_data = {'nodes': [{'name': name,
+ 'ip': ip,
+ 'user': user,
+ 'key_filename': password}]}
+ inventory_file_name = 'inventory'
+ pod_file_name = 'pod'
+ logger = Mock()
+ pod_file_obj = Mock()
+ inventory_file_obj = Mock()
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.side_effect = [pod_file_obj,
+ inventory_file_obj]
+ mock_load.return_value = pod_file_data
+ config_dir = 'config_dir'
+ key_file = '/'.join([config_dir, 'id_rsa'])
+ dovetail_utils.dt_cfg.dovetail_config = {'config_dir': config_dir}
+ mock_path.join.return_value = key_file
+
+ expected = True
+ result = dovetail_utils.get_inventory_file(pod_file_name,
+ inventory_file_name,
+ logger=logger)
+
+ mock_path.isfile.assert_called_once_with(pod_file_name)
+ mock_open.assert_any_call(pod_file_name, 'r')
+ mock_open.assert_any_call(inventory_file_name, 'w')
+ mock_load.assert_called_once_with(pod_file_obj)
+ mock_path.join.assert_called_once_with(config_dir, 'id_rsa')
+ inventory_file_obj.write.assert_called_once_with(
+ '{name} ansible_host={ip} ansible_user={user} '
+ 'ansible_ssh_private_key_file={key_file}\n'
+ .format(name=name, ip=ip, user=user, key_file=key_file))
+ logger.debug.assert_called_once_with(
+ 'Ansible inventory file is {}.'.format(inventory_file_name))
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('builtins.open')
+ @patch('yaml.safe_load')
+ def test_get_inventory_other(self, mock_load, mock_open, mock_path):
+ name = 'name'
+ ip = 'ip'
+ user = 'user'
+ pod_file_data = {'nodes': [{'name': name,
+ 'ip': ip,
+ 'user': user}]}
+ inventory_file_name = 'inventory'
+ pod_file_name = 'pod'
+ logger = Mock()
+ pod_file_obj = Mock()
+ inventory_file_obj = Mock()
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.side_effect = [pod_file_obj,
+ inventory_file_obj]
+ mock_load.return_value = pod_file_data
+
+ expected = False
+ result = dovetail_utils.get_inventory_file(pod_file_name,
+ inventory_file_name,
+ logger=logger)
+
+ mock_path.isfile.assert_called_once_with(pod_file_name)
+ mock_open.assert_any_call(pod_file_name, 'r')
+ mock_open.assert_any_call(inventory_file_name, 'w')
+ mock_load.assert_called_once_with(pod_file_obj)
+ logger.error.assert_called_once_with(
+ 'No password or key_filename in file {}.'.format(pod_file_name))
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('builtins.open')
+ @patch('yaml.safe_load')
+ def test_get_inventory_keyerror(self, mock_load, mock_open, mock_path):
+ name = 'name'
+ ip = 'ip'
+ pod_file_data = {'nodes': [{'name': name,
+ 'ip': ip}]}
+ inventory_file_name = 'inventory'
+ pod_file_name = 'pod'
+ logger = Mock()
+ pod_file_obj = Mock()
+ inventory_file_obj = Mock()
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.side_effect = [pod_file_obj,
+ inventory_file_obj]
+ mock_load.return_value = pod_file_data
+
+ expected = False
+ result = dovetail_utils.get_inventory_file(pod_file_name,
+ inventory_file_name,
+ logger=logger)
+
+ mock_path.isfile.assert_called_once_with(pod_file_name)
+ mock_open.assert_any_call(pod_file_name, 'r')
+ mock_open.assert_any_call(inventory_file_name, 'w')
+ mock_load.assert_called_once_with(pod_file_obj)
+ logger.exception.assert_called_once_with(
+ "KeyError 'user'.")
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ @patch('builtins.open')
+ def test_get_inventory_exception(self, mock_open, mock_path):
+ inventory_file_name = 'inventory'
+ pod_file_name = 'pod'
+ logger = Mock()
+ mock_path.isfile.return_value = True
+ mock_open.return_value.__enter__.side_effect = Exception()
+
+ expected = False
+ result = dovetail_utils.get_inventory_file(pod_file_name,
+ inventory_file_name,
+ logger=logger)
+
+ mock_path.isfile.assert_called_once_with(pod_file_name)
+ mock_open.assert_called_once_with(pod_file_name, 'r')
+ logger.exception.assert_called_once_with(
+ 'Failed to read file {}.'.format(pod_file_name))
+ self.assertEqual(expected, result)
+
+ @patch('os.path')
+ def test_get_inventory_invalid_pod_file(self, mock_path):
+ inventory_file_name = 'inventory'
+ pod_file_name = 'pod'
+ logger = Mock()
+ mock_path.isfile.return_value = False
+
+ expected = False
+ result = dovetail_utils.get_inventory_file(pod_file_name,
+ inventory_file_name,
+ logger=logger)
+
+ mock_path.isfile.assert_called_once_with(pod_file_name)
+ logger.error.assert_called_once_with(
+ "File {} doesn't exist.".format(pod_file_name))
+ self.assertEqual(expected, result)
+
+ @patch('subprocess.Popen')
+ @patch('subprocess.PIPE')
+ @patch('subprocess.STDOUT')
+ @patch('os.getenv')
+ @patch('dovetail.utils.dovetail_utils.exec_log')
+ @patch('dovetail.utils.dovetail_utils.show_progress_bar')
+ def test_exec_cmd(self, mock_bar, mock_log, mock_getenv, mock_stdout,
+ mock_pipe, mock_open):
+ logger = Mock()
+ cmd = 'cmd'
+ verbose = True
+ subprocess_obj = Mock()
+ cmd_output = 'line'
+ mock_open.return_value = subprocess_obj
+ pip_obj = Mock()
+ stdout_obj = Mock()
+ mock_pipe.return_value = pip_obj
+ mock_stdout.return_value = stdout_obj
+ subp_stdout = Mock()
+ subprocess_obj.stdout = subp_stdout
+ subprocess_obj.wait.return_value = 0
+ subp_stdout.readline.side_effect = [cmd_output.encode()]
+
+ expected = (0, "b'line'")
+ result = dovetail_utils.exec_cmd(
+ cmd, logger=logger, exit_on_error=True, info=False,
+ exec_msg_on=True, err_msg='', verbose=verbose,
+ progress_bar=True)
+
+ log_calls = [
+ call(verbose, logger, "Executing command: '%s'" % cmd, 'debug'),
+ call(verbose, logger, cmd_output, 'debug', True)]
+ mock_log.assert_has_calls(log_calls)
+ mock_open.assert_called_once_with(cmd, shell=True, stdout=mock_pipe,
+ stderr=mock_stdout)
+ subp_stdout.readline.assert_has_calls([call(), call()])
+ subp_stdout.close.assert_called_once_with()
+ subprocess_obj.wait.assert_called_once_with()
+ mock_getenv.assert_called_once_with('DEBUG')
+ # mock_bar.assert_called_once_with(1)
+ self.assertEqual(expected, result)
+
+ @patch('sys.exit')
+ @patch('subprocess.Popen')
+ @patch('subprocess.PIPE')
+ @patch('subprocess.STDOUT')
+ @patch('os.getenv')
+ @patch('dovetail.utils.dovetail_utils.exec_log')
+ @patch('dovetail.utils.dovetail_utils.show_progress_bar')
+ def test_exec_cmd_error(self, mock_bar, mock_log, mock_getenv, mock_stdout,
+ mock_pipe, mock_open, mock_exit):
+ logger = Mock()
+ cmd = 'cmd'
+ verbose = True
+ subprocess_obj = Mock()
+ cmd_output = 'line'
+ mock_open.return_value = subprocess_obj
+ pip_obj = Mock()
+ stdout_obj = Mock()
+ mock_pipe.return_value = pip_obj
+ mock_stdout.return_value = stdout_obj
+ subp_stdout = Mock()
+ subprocess_obj.stdout = subp_stdout
+ subprocess_obj.wait.return_value = 1
+ subp_stdout.readline.side_effect = [cmd_output.encode()]
+
+ dovetail_utils.exec_cmd(
+ cmd, logger=logger, exit_on_error=True, info=False,
+ exec_msg_on=True, err_msg='', verbose=verbose,
+ progress_bar=True)
+
+ log_calls = [
+ call(verbose, logger, "Executing command: '%s'" % cmd, 'debug'),
+ call(verbose, logger, cmd_output, 'debug', True),
+ call(verbose, logger, "The command '%s' failed." % cmd, 'error')]
+ mock_log.assert_has_calls(log_calls)
+ mock_open.assert_called_once_with(cmd, shell=True, stdout=mock_pipe,
+ stderr=mock_stdout)
+ subp_stdout.readline.assert_has_calls([call(), call()])
+ subp_stdout.close.assert_called_once_with()
+ subprocess_obj.wait.assert_called_once_with()
+ mock_getenv.assert_called_once_with('DEBUG')
+ # mock_bar.assert_called_once_with(1)
+ mock_exit.assert_called_once_with(1)
+
+ @patch('os.path', autospec=True)
+ def test_get_openstack_info_no_openrc(self, mock_path):
+ logger = Mock()
+ config_dir = 'config_dir'
+ env_file = 'env_file'
+ dovetail_utils.dt_cfg.dovetail_config = {
+ 'config_dir': config_dir, 'env_file': env_file}
+ mock_path.join.side_effect = ['openrc']
+ mock_path.isfile.return_value = False
+ dovetail_utils.get_openstack_info(logger)
+
+ mock_path.join.assert_called_once_with(config_dir, env_file)
+ mock_path.isfile.assert_called_once_with('openrc')
+ logger.error.assert_called_once_with('File openrc does not exist.')
+
+ @patch('dovetail.utils.dovetail_utils.source_env')
+ @patch('dovetail.utils.dovetail_utils.get_hosts_info')
+ @patch('dovetail.utils.dovetail_utils.get_openstack_endpoint')
+ @patch('dovetail.utils.dovetail_utils.get_hardware_info')
+ @patch('os.path', autospec=True)
+ def test_get_openstack_info(self, mock_path, mock_hardware, mock_endpoint,
+ mock_host, mock_env):
+ logger = Mock()
+ config_dir = 'config_dir'
+ env_file = 'env_file'
+ dovetail_utils.dt_cfg.dovetail_config = {
+ 'config_dir': config_dir, 'env_file': env_file}
+ mock_path.join.side_effect = ['openrc']
+ mock_path.isfile.return_value = True
+ dovetail_utils.get_openstack_info(logger)
+
+ mock_path.join.assert_called_once_with(config_dir, env_file)
+ mock_path.isfile.assert_called_once_with('openrc')
+ mock_env.assert_called_once()
+ mock_host.assert_called_once()
+ mock_endpoint.assert_called_once()
+ mock_hardware.assert_called_once()
+
+ @patch('json.dumps')
+ @patch('dovetail.utils.dovetail_utils.requests')
+ @patch('os.getenv')
+ def test_push_results_to_db(self, mock_getenv, mock_requests, mock_dumps):
+ logger = Mock()
+ case_name = 'case_name'
+ details = {'criteria': 'PASS'}
+ start_date = 'start_date'
+ stop_date = 'stop_date'
+ mock_getenv.side_effect = [
+ 'url', 'installer', 'scenario', 'pod_name', 'build_tag', 'version']
+ post_req = Mock()
+ post_req.raise_for_status.return_value = None
+ mock_requests.post.return_value = post_req
+ mock_dumps.return_value = {"project_name": "dovetail"}
+
+ dovetail_utils.push_results_to_db(
+ case_name, details, start_date, stop_date, logger)
+
+ mock_requests.post.assert_called_once_with(
+ 'url',
+ data={"project_name": "dovetail"},
+ headers={"Content-Type": "application/json"})
+ logger.debug.assert_called_once_with(
+ "The results were successfully pushed to DB.")
+
+ @patch('json.dumps')
+ @patch('dovetail.utils.dovetail_utils.requests')
+ @patch('os.getenv')
+ def test_push_results_to_db_exception(self, mock_getenv, mock_requests,
+ mock_dumps):
+ logger = Mock()
+ case_name = 'case_name'
+ details = {'criteria': 'PASS'}
+ start_date = 'start_date'
+ stop_date = 'stop_date'
+ mock_getenv.side_effect = [
+ 'url', 'installer', 'scenario', 'pod_name', 'build_tag', 'version']
+ post_req = Mock()
+ post_req.raise_for_status.side_effect = Exception()
+ mock_requests.post.return_value = post_req
+ mock_dumps.return_value = {"project_name": "dovetail"}
+ dovetail_utils.push_results_to_db(
+ case_name, details, start_date, stop_date, logger)
+
+ logger.debug.assert_not_called()
+ logger.exception.assert_called_once_with(
+ "The results cannot be pushed to DB.")
+
+ def test_get_mount_list_error_mount(self):
+ project_cfg = {'mounts': ['aaa']}
+ res, msg = dovetail_utils.get_mount_list(project_cfg)
+ self.assertEqual(None, res)
+ self.assertEqual('Error mount aaa.', msg)
+
+ def test_get_mount_list_keyerror_exception(self):
+ project_cfg = {'mounts': ['aaa=a,bbb=b', '']}
+ res, msg = dovetail_utils.get_mount_list(project_cfg)
+ self.assertEqual(None, res)
+ self.assertEqual("'target'", str(msg))
+
+ def test_get_mount_list(self):
+ project_cfg = {'mounts': ['target=a,source=b', '']}
+ res, msg = dovetail_utils.get_mount_list(project_cfg)
+ expected = [{'Source': 'b', 'Type': 'bind', 'ReadOnly': False,
+ 'Target': 'a'}]
+ self.assertEqual(expected, res)
+ self.assertEqual('Successfully to get mount list.', msg)
diff --git a/dovetail/tests/unit/utils/test_openstack_utils.py b/dovetail/tests/unit/utils/test_openstack_utils.py
new file mode 100644
index 00000000..73583838
--- /dev/null
+++ b/dovetail/tests/unit/utils/test_openstack_utils.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import unittest
+
+from mock import patch
+import munch
+import os_client_config
+import shade
+
+import dovetail.utils.openstack_utils as os_dovetail_utils
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class OpenStackUtilsTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.patcher1 = patch.object(shade,
+ 'OperatorCloud', autospec=True)
+ self.patcher2 = patch.object(os_client_config,
+ 'get_config', autospec=True)
+ self.cloud = self.patcher1.start().return_value
+ self.os_client_config = self.patcher2.start().return_value
+ self.os_dovetail = os_dovetail_utils.OS_Utils()
+
+ def tearDown(self):
+ self.patcher1.stop()
+ self.patcher2.stop()
+
+ def test_search_endpoints(self):
+ endpoint = munch.Munch({u'region_id': u'RegionOne',
+ u'url': u'http://127.0.0.1:8977/',
+ u'region': u'RegionOne',
+ u'enabled': True,
+ u'interface': u'public',
+ u'service_id': u'123456',
+ u'id': u'123456'})
+ endpoints = [endpoint]
+ self.cloud.search_endpoints.return_value = endpoints
+
+ expected = (True, endpoints)
+ result = self.os_dovetail.search_endpoints()
+
+ self.assertEqual(expected, result)
+
+ def test_search_endpoints_raised_exception(self):
+ errorMSG = 'Exception was raised'
+ exception = shade.exc.OpenStackCloudException(errorMSG)
+ self.cloud.search_endpoints.side_effect = exception
+
+ expected = (False, errorMSG)
+ result = self.os_dovetail.search_endpoints()
+
+ self.assertEqual(expected, result)
+
+ def test_search_services(self):
+ service = munch.Munch({'description': u'OpenStack Identity Service',
+ 'service_type': u'identity',
+ 'type': u'identity',
+ 'enabled': True,
+ 'id': u'1bd26028c8714f3bb726126dc1ea62fc',
+ 'name': u'keystone'})
+ services = [service]
+ self.cloud.search_services.return_value = services
+
+ expected = (True, services)
+ result = self.os_dovetail.search_services()
+
+ self.assertEqual(expected, result)
+
+ def test_search_services_raised_exception(self):
+ errorMSG = 'Exception was raised'
+ exception = shade.exc.OpenStackCloudException(errorMSG)
+ self.cloud.search_services.side_effect = exception
+
+ expected = (False, errorMSG)
+ result = self.os_dovetail.search_services()
+
+ self.assertEqual(expected, result)