diff options
Diffstat (limited to 'functest')
-rwxr-xr-x | functest/ci/testcases.yaml | 80 | ||||
-rw-r--r-- | functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt | 32 | ||||
-rw-r--r-- | functest/opnfv_tests/vnf/ims/clearwater_ims_base.py | 3 | ||||
-rw-r--r-- | functest/tests/unit/ci/test_prepare_env.py | 111 | ||||
-rw-r--r-- | functest/tests/unit/ci/test_run_tests.py | 84 | ||||
-rw-r--r-- | functest/tests/unit/ci/test_tier_handler.py | 9 | ||||
-rw-r--r-- | functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py | 222 | ||||
-rw-r--r-- | functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py | 51 | ||||
-rw-r--r-- | functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py | 34 | ||||
-rw-r--r-- | functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py | 55 | ||||
-rw-r--r-- | functest/tests/unit/utils/test_functest_logger.py | 48 | ||||
-rw-r--r-- | functest/tests/unit/utils/test_openstack_tacker.py | 92 | ||||
-rw-r--r-- | functest/tests/unit/utils/test_openstack_utils.py | 55 | ||||
-rw-r--r-- | functest/utils/openstack_utils.py | 34 |
14 files changed, 823 insertions, 87 deletions
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index 1c33b996..23b214bb 100755 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -102,7 +102,7 @@ tiers: name: tempest_smoke_serial criteria: 'success_rate == 100%' blocking: false - clean_flag: false + clean_flag: true description: >- This test case runs the smoke subset of the OpenStack Tempest suite. The list of test cases is generated by @@ -134,7 +134,7 @@ tiers: name: refstack_defcore criteria: 'success_rate == 100%' blocking: false - clean_flag: false + clean_flag: true description: >- This test case runs a sub group of tests of the OpenStack Defcore testcases by using refstack client. @@ -306,19 +306,7 @@ tiers: run: module: 'functest.opnfv_tests.features.security_scan' class: 'SecurityScan' -# - -# name: copper -# criteria: 'status == "PASS"' -# blocking: false -# clean_flag: true -# description: >- -# Test suite for policy management based on OpenStack Congress -# dependencies: -# installer: '(apex)|(joid)' -# scenario: '^((?!fdio|lxd).)*$' -# run: -# module: 'functest.opnfv_tests.features.copper' -# class: 'Copper' + - name: multisite criteria: 'success_rate == 100%' @@ -416,30 +404,30 @@ tiers: - name: components order: 3 - ci_loop: 'daily' + ci_loop: 'weekly' description : >- Extensive testing of OpenStack API. testcases: -# - -# name: tempest_full_parallel -# criteria: 'success_rate >= 80%' -# blocking: false -# clean_flag: false -# description: >- -# The list of test cases is generated by -# Tempest automatically and depends on the parameters of -# the OpenStack deplopyment. -# dependencies: -# installer: '^((?!netvirt).)*$' -# scenario: '' -# run: -# module: 'functest.opnfv_tests.openstack.tempest.tempest' -# class: 'TempestFullParallel' + - + name: tempest_full_parallel + criteria: 'success_rate >= 80%' + blocking: false + clean_flag: true + description: >- + The list of test cases is generated by + Tempest automatically and depends on the parameters of + the OpenStack deplopyment. + dependencies: + installer: '^((?!netvirt).)*$' + scenario: '' + run: + module: 'functest.opnfv_tests.openstack.tempest.tempest' + class: 'TempestFullParallel' - name: tempest_custom criteria: 'success_rate == 100%' blocking: false - clean_flag: false + clean_flag: true description: >- The test case allows running a customized list of tempest test cases defined in a file under @@ -452,20 +440,20 @@ tiers: run: module: 'functest.opnfv_tests.openstack.tempest.tempest' class: 'TempestCustom' -# - -# name: rally_full -# criteria: 'success_rate >= 90%' -# blocking: false -# clean_flag: false -# description: >- -# This test case runs the full suite of scenarios of the OpenStack -# Rally suite using several threads and iterations. -# dependencies: -# installer: '^((?!netvirt).)*$' -# scenario: '' -# run: -# module: 'functest.opnfv_tests.openstack.rally.rally' -# class: 'RallyFull' + - + name: rally_full + criteria: 'success_rate >= 90%' + blocking: false + clean_flag: false + description: >- + This test case runs the full suite of scenarios of the OpenStack + Rally suite using several threads and iterations. + dependencies: + installer: '^((?!netvirt).)*$' + scenario: '' + run: + module: 'functest.opnfv_tests.openstack.rally.rally' + class: 'RallyFull' - name: vnf diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt index 43edabc1..0da92cd8 100644 --- a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt @@ -27,11 +27,7 @@ scenarios: - os-onos-nofeature-ha - os-onos-nofeature-noha - - os-onos-sfc-ha - - os-onos-sfc-noha installers: - - fuel - - apex - compass tests: - tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard @@ -41,22 +37,6 @@ - tempest.scenario.test_volume_boot_pattern.TestVolumeBootPatternV2.test_volume_boot_pattern - - scenarios: - - os-onos-nofeature-ha - - os-onos-nofeature-noha - - os-onos-sfc-ha - - os-onos-sfc-noha - installers: - - joid - tests: - - tempest.api.object_storage - - tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard - - tempest.scenario.test_network_basic_ops.TestNetworkBasicOps.test_network_basic_ops - - tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops - - tempest.scenario.test_volume_boot_pattern.TestVolumeBootPattern.test_volume_boot_pattern - - tempest.scenario.test_volume_boot_pattern.TestVolumeBootPatternV2.test_volume_boot_pattern - -- # https://bugs.launchpad.net/tempest/+bug/1577632 scenarios: - os-odl_l2-nofeature-ha @@ -71,3 +51,15 @@ - fuel tests: - tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops + + + # https://bugs.opendaylight.org/show_bug.cgi?id=5586 + scenarios: + - os-odl-bgpvpn-ha + - os-odl-gluon-noha + - os-odl_l2-bgpvpn-ha + installers: + - apex + - fuel + tests: + - tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard diff --git a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py index f21ce3f9..2fc5449c 100644 --- a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py +++ b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py @@ -46,8 +46,7 @@ class ClearwaterOnBoardingBase(vnf_base.VnfOnBoardingBase): rq = requests.post(account_url, data=params) output_dict['login'] = params if rq.status_code != 201 and rq.status_code != 409: - raise Exception("Unable to create an account for number" - " provision: %s" % rq.json()['reason']) + raise Exception("Unable to create an account for number provision") self.logger.info('Account is created on Ellis: %s', params) session_url = 'http://{0}/session'.format(ellis_ip) diff --git a/functest/tests/unit/ci/test_prepare_env.py b/functest/tests/unit/ci/test_prepare_env.py index 540501ff..714dd13c 100644 --- a/functest/tests/unit/ci/test_prepare_env.py +++ b/functest/tests/unit/ci/test_prepare_env.py @@ -20,6 +20,9 @@ class PrepareEnvTesting(unittest.TestCase): logging.disable(logging.CRITICAL) + def setUp(self): + self.prepare_envparser = prepare_env.PrepareEnvParser() + @mock.patch('functest.ci.prepare_env.logger.info') def test_print_separator(self, mock_logger_info): str = "==============================================" @@ -81,7 +84,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_scenario(self, mock_logger_warn, mock_logger_info): - CONST.DEPLOY_SCENARIO = mock.Mock() + CONST.DEPLOY_SCENARIO = 'test_scenario' prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -134,6 +137,47 @@ class PrepareEnvTesting(unittest.TestCase): mock_logger_info.assert_any_call(test_utils. SubstrMatch(" IS_CI_RUN=")) + def test_get_deployment_handler_missing_const_vars(self): + with mock.patch('functest.ci.prepare_env.' + 'factory.Factory.get_handler') as m: + CONST.INSTALLER_IP = None + prepare_env.get_deployment_handler() + self.assertFalse(m.called) + + CONST.INSTALLER_TYPE = None + prepare_env.get_deployment_handler() + self.assertFalse(m.called) + + @mock.patch('functest.ci.prepare_env.logger.debug') + def test_get_deployment_handler_missing_print_deploy_info(self, + mock_debug): + with mock.patch('functest.ci.prepare_env.' + 'factory.Factory.get_handler') as m, \ + mock.patch('functest.ci.prepare_env.' + 'ft_utils.get_parameter_from_yaml', + side_effect=ValueError): + CONST.INSTALLER_IP = 'test_ip' + CONST.INSTALLER_TYPE = 'test_inst_type' + opnfv_constants.INSTALLERS = ['test_inst_type'] + prepare_env.get_deployment_handler() + msg = ('Printing deployment info is not supported for ' + 'test_inst_type') + mock_debug.assert_any_call(msg) + self.assertFalse(m.called) + + @mock.patch('functest.ci.prepare_env.logger.debug') + def test_get_deployment_handler_exception(self, mock_debug): + with mock.patch('functest.ci.prepare_env.' + 'factory.Factory.get_handler', + side_effect=Exception), \ + mock.patch('functest.ci.prepare_env.' + 'ft_utils.get_parameter_from_yaml'): + CONST.INSTALLER_IP = 'test_ip' + CONST.INSTALLER_TYPE = 'test_inst_type' + opnfv_constants.INSTALLERS = ['test_inst_type'] + prepare_env.get_deployment_handler() + self.assertTrue(mock_debug.called) + @mock.patch('functest.ci.prepare_env.logger.info') @mock.patch('functest.ci.prepare_env.logger.debug') def test_create_directories_missing_dir(self, mock_logger_debug, @@ -228,6 +272,36 @@ class PrepareEnvTesting(unittest.TestCase): prepare_env.source_rc_file() + @mock.patch('functest.ci.prepare_env.logger.debug') + def test_patch_file(self, mock_logger_debug): + with mock.patch("__builtin__.open", mock.mock_open()), \ + mock.patch('functest.ci.prepare_env.yaml.safe_load', + return_value={'test_scenario': {'tkey': 'tvalue'}}), \ + mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml', + return_value={'tkey1': 'tvalue1'}), \ + mock.patch('functest.ci.prepare_env.os.remove') as m, \ + mock.patch('functest.ci.prepare_env.yaml.dump'): + CONST.DEPLOY_SCENARIO = 'test_scenario' + prepare_env.patch_file('test_file') + self.assertTrue(m.called) + + @mock.patch('functest.ci.prepare_env.logger.info') + def test_verify_deployment_error(self, mock_logger_error): + mock_popen = mock.Mock() + attrs = {'poll.return_value': None, + 'stdout.readline.return_value': 'ERROR'} + mock_popen.configure_mock(**attrs) + + with mock.patch('functest.ci.prepare_env.print_separator') as m, \ + mock.patch('functest.ci.prepare_env.subprocess.Popen', + return_value=mock_popen), \ + self.assertRaises(Exception) as context: + prepare_env.verify_deployment() + self.assertTrue(m.called) + msg = "Problem while running 'check_os.sh'." + mock_logger_error.assert_called_once_with('ERROR') + self.assertTrue(msg in context) + def _get_rally_creds(self): return {"type": "ExistingCloud", "admin": {"username": 'test_user_name', @@ -271,6 +345,33 @@ class PrepareEnvTesting(unittest.TestCase): "Rally plugins.") mock_exec.assert_any_call(cmd, error_msg=error_msg) + @mock.patch('functest.ci.prepare_env.logger.debug') + def test_install_tempest(self, mock_logger_debug): + mock_popen = mock.Mock() + attrs = {'poll.return_value': None, + 'stdout.readline.return_value': '0'} + mock_popen.configure_mock(**attrs) + + CONST.tempest_deployment_name = 'test_dep_name' + with mock.patch('functest.ci.prepare_env.' + 'ft_utils.execute_command_raise', + side_effect=Exception), \ + mock.patch('functest.ci.prepare_env.subprocess.Popen', + return_value=mock_popen), \ + self.assertRaises(Exception): + prepare_env.install_tempest() + mock_logger_debug.assert_any_call("Tempest test_dep_name" + " does not exist") + + def test_create_flavor(self): + with mock.patch('functest.ci.prepare_env.' + 'os_utils.get_or_create_flavor', + return_value=('test_', None)), \ + self.assertRaises(Exception) as context: + prepare_env.create_flavor() + msg = 'Failed to create flavor' + self.assertTrue(msg in context) + @mock.patch('functest.ci.prepare_env.sys.exit') @mock.patch('functest.ci.prepare_env.logger.error') def test_check_environment_missing_file(self, mock_logger_error, @@ -299,6 +400,7 @@ class PrepareEnvTesting(unittest.TestCase): mock_logger_info.assert_any_call("Functest environment" " is installed.") + @mock.patch('functest.ci.prepare_env.print_deployment_info') @mock.patch('functest.ci.prepare_env.check_environment') @mock.patch('functest.ci.prepare_env.create_flavor') @mock.patch('functest.ci.prepare_env.install_tempest') @@ -307,19 +409,21 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.patch_config_file') @mock.patch('functest.ci.prepare_env.source_rc_file') @mock.patch('functest.ci.prepare_env.create_directories') + @mock.patch('functest.ci.prepare_env.get_deployment_handler') @mock.patch('functest.ci.prepare_env.check_env_variables') @mock.patch('functest.ci.prepare_env.logger.info') - def test_main_start(self, mock_logger_info, mock_env_var, + def test_main_start(self, mock_logger_info, mock_env_var, mock_dep_handler, mock_create_dir, mock_source_rc, mock_patch_config, mock_verify_depl, mock_install_rally, mock_install_temp, mock_create_flavor, - mock_check_env): + mock_check_env, mock_print_info): with mock.patch("__builtin__.open", mock.mock_open()) as m: args = {'action': 'start'} self.assertEqual(prepare_env.main(**args), 0) mock_logger_info.assert_any_call("######### Preparing Functest " "environment #########\n") self.assertTrue(mock_env_var.called) + self.assertTrue(mock_dep_handler.called) self.assertTrue(mock_create_dir.called) self.assertTrue(mock_source_rc.called) self.assertTrue(mock_patch_config.called) @@ -329,6 +433,7 @@ class PrepareEnvTesting(unittest.TestCase): self.assertTrue(mock_create_flavor.called) m.assert_called_once_with(CONST.env_active, "w") self.assertTrue(mock_check_env.called) + self.assertTrue(mock_print_info.called) @mock.patch('functest.ci.prepare_env.check_environment') def test_main_check(self, mock_check_env): diff --git a/functest/tests/unit/ci/test_run_tests.py b/functest/tests/unit/ci/test_run_tests.py index 02140610..7d02b1af 100644 --- a/functest/tests/unit/ci/test_run_tests.py +++ b/functest/tests/unit/ci/test_run_tests.py @@ -37,6 +37,9 @@ class RunTestsTesting(unittest.TestCase): attrs = {'get_tiers.return_value': [self.tier]} self.tiers.configure_mock(**attrs) + self.run_tests_parser = run_tests.RunTestsParser() + self.global_variables = run_tests.GlobalVariables() + @mock.patch('functest.ci.run_tests.logger.info') def test_print_separator(self, mock_logger_info): run_tests.print_separator(self.sep) @@ -121,8 +124,8 @@ class RunTestsTesting(unittest.TestCase): def test_run_tests_import_test_class_exception(self): mock_test = mock.Mock() - args = {'get_name': 'test_name', - 'needs_clean': False} + args = {'get_name.return_value': 'test_name', + 'needs_clean.return_value': False} mock_test.configure_mock(**args) with mock.patch('functest.ci.run_tests.print_separator'),\ mock.patch('functest.ci.run_tests.source_rc_file'), \ @@ -133,6 +136,28 @@ class RunTestsTesting(unittest.TestCase): msg = "Cannot import the class for the test case." self.assertTrue(msg in context) + def test_run_tests_default(self): + mock_test = mock.Mock() + args = {'get_name.return_value': 'test_name', + 'needs_clean.return_value': True} + mock_test.configure_mock(**args) + test_run_dict = {'module': 'test_module', + 'class': mock.Mock, + 'args': 'test_args'} + with mock.patch('functest.ci.run_tests.print_separator'),\ + mock.patch('functest.ci.run_tests.source_rc_file'), \ + mock.patch('functest.ci.run_tests.generate_os_snapshot'), \ + mock.patch('functest.ci.run_tests.cleanup'), \ + mock.patch('functest.ci.run_tests.update_test_info'), \ + mock.patch('functest.ci.run_tests.get_run_dict', + return_value=test_run_dict), \ + mock.patch('functest.ci.run_tests.generate_report.main'), \ + self.assertRaises(run_tests.BlockingTestFailed) as context: + run_tests.GlobalVariables.CLEAN_FLAG = True + run_tests.run_test(mock_test, 'tier_name') + msg = 'The test case test_name failed and is blocking' + self.assertTrue(msg in context) + @mock.patch('functest.ci.run_tests.logger.info') def test_run_tier_default(self, mock_logger_info): with mock.patch('functest.ci.run_tests.print_separator'), \ @@ -187,6 +212,61 @@ class RunTestsTesting(unittest.TestCase): self.assertEqual(run_tests.main(**kwargs), run_tests.Result.EX_ERROR) + def test_main_default(self): + kwargs = {'test': 'test_name', 'noclean': True, 'report': True} + mock_obj = mock.Mock() + args = {'get_tier.return_value': True, + 'get_test.return_value': False} + mock_obj.configure_mock(**args) + with mock.patch('functest.ci.run_tests.tb.TierBuilder', + return_value=mock_obj), \ + mock.patch('functest.ci.run_tests.source_rc_file'), \ + mock.patch('functest.ci.run_tests.generate_report.init'), \ + mock.patch('functest.ci.run_tests.run_tier') as m: + self.assertEqual(run_tests.main(**kwargs), + run_tests.Result.EX_OK) + self.assertTrue(m.called) + + mock_obj = mock.Mock() + args = {'get_tier.return_value': False, + 'get_test.return_value': True} + mock_obj.configure_mock(**args) + with mock.patch('functest.ci.run_tests.tb.TierBuilder', + return_value=mock_obj), \ + mock.patch('functest.ci.run_tests.source_rc_file'), \ + mock.patch('functest.ci.run_tests.generate_report.init'), \ + mock.patch('functest.ci.run_tests.run_test') as m: + self.assertEqual(run_tests.main(**kwargs), + run_tests.Result.EX_OK) + self.assertTrue(m.called) + + kwargs = {'test': 'all', 'noclean': True, 'report': True} + mock_obj = mock.Mock() + args = {'get_tier.return_value': False, + 'get_test.return_value': False} + mock_obj.configure_mock(**args) + with mock.patch('functest.ci.run_tests.tb.TierBuilder', + return_value=mock_obj), \ + mock.patch('functest.ci.run_tests.source_rc_file'), \ + mock.patch('functest.ci.run_tests.generate_report.init'), \ + mock.patch('functest.ci.run_tests.run_all') as m: + self.assertEqual(run_tests.main(**kwargs), + run_tests.Result.EX_OK) + self.assertTrue(m.called) + + kwargs = {'test': 'any', 'noclean': True, 'report': True} + mock_obj = mock.Mock() + args = {'get_tier.return_value': False, + 'get_test.return_value': False} + mock_obj.configure_mock(**args) + with mock.patch('functest.ci.run_tests.tb.TierBuilder', + return_value=mock_obj), \ + mock.patch('functest.ci.run_tests.source_rc_file'), \ + mock.patch('functest.ci.run_tests.generate_report.init'), \ + mock.patch('functest.ci.run_tests.logger.debug') as m: + self.assertEqual(run_tests.main(**kwargs), + run_tests.Result.EX_ERROR) + self.assertTrue(m.called) if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/ci/test_tier_handler.py b/functest/tests/unit/ci/test_tier_handler.py index 01d99d7e..21df4098 100644 --- a/functest/tests/unit/ci/test_tier_handler.py +++ b/functest/tests/unit/ci/test_tier_handler.py @@ -41,6 +41,15 @@ class TierHandlerTesting(unittest.TestCase): self.dependency = tier_handler.Dependency('test_installer', 'test_scenario') + self.testcase.str = self.testcase.__str__() + self.dependency.str = self.dependency.__str__() + self.tier.str = self.tier.__str__() + + def test_split_text(self): + test_str = 'this is for testing' + self.assertEqual(tier_handler.split_text(test_str, 10), + ['this is ', 'for ', 'testing ']) + def test_add_test(self): self.tier.add_test(self.test) self.assertEqual(self.tier.tests_array, diff --git a/functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py b/functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py index caf21925..8ca5cc5b 100644 --- a/functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py +++ b/functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py @@ -37,7 +37,6 @@ class OSTempestConfUtilsTesting(unittest.TestCase): self.assertTrue(msg in context) def test_create_tempest_resources_missing_image(self): - CONST.tempest_use_custom_images = 'test_image' with mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.' 'os_utils.get_keystone_client', return_value=mock.Mock()), \ @@ -54,13 +53,18 @@ class OSTempestConfUtilsTesting(unittest.TestCase): 'os_utils.get_or_create_image', return_value=(mock.Mock(), None)), \ self.assertRaises(Exception) as context: + + CONST.tempest_use_custom_images = True conf_utils.create_tempest_resources() msg = 'Failed to create image' self.assertTrue(msg in context) + CONST.tempest_use_custom_images = False + conf_utils.create_tempest_resources(use_custom_images=True) + msg = 'Failed to create image' + self.assertTrue(msg in context) + def test_create_tempest_resources_missing_flavor(self): - CONST.tempest_use_custom_images = 'test_image' - CONST.tempest_use_custom_flavors = 'test_flavour' with mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.' 'os_utils.get_keystone_client', return_value=mock.Mock()), \ @@ -80,10 +84,18 @@ class OSTempestConfUtilsTesting(unittest.TestCase): 'os_utils.get_or_create_flavor', return_value=(mock.Mock(), None)), \ self.assertRaises(Exception) as context: + CONST.tempest_use_custom_images = True + CONST.tempest_use_custom_flavors = True conf_utils.create_tempest_resources() msg = 'Failed to create flavor' self.assertTrue(msg in context) + CONST.tempest_use_custom_images = True + CONST.tempest_use_custom_flavors = False + conf_utils.create_tempest_resources(use_custom_flavors=False) + msg = 'Failed to create flavor' + self.assertTrue(msg in context) + def test_get_verifier_id_missing_verifier(self): CONST.tempest_deployment_name = 'test_deploy_name' with mock.patch('functest.opnfv_tests.openstack.tempest.' @@ -153,6 +165,210 @@ class OSTempestConfUtilsTesting(unittest.TestCase): self.assertTrue(m1.called) self.assertTrue(m2.called) + def test_get_repo_tag_default(self): + mock_popen = mock.Mock() + attrs = {'stdout.readline.return_value': 'test_tag'} + mock_popen.configure_mock(**attrs) + + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.subprocess.Popen', + return_value=mock_popen): + self.assertEqual(conf_utils.get_repo_tag('test_repo'), + 'test_tag') + + def test_backup_tempest_config_default(self): + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.path.exists', + return_value=False), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.makedirs') as m1, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.shutil.copyfile') as m2: + conf_utils.backup_tempest_config('test_conf_file') + self.assertTrue(m1.called) + self.assertTrue(m2.called) + + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.path.exists', + return_value=True), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.shutil.copyfile') as m2: + conf_utils.backup_tempest_config('test_conf_file') + self.assertTrue(m2.called) + + def test_configure_tempest_default(self): + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_verifier', + return_value='test_conf_file'), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_tempest_update_params') as m1, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_tempest_multisite_params') as m2: + conf_utils.configure_tempest('test_dep_dir', + MODE='feature_multisite') + self.assertTrue(m1.called) + self.assertTrue(m2.called) + + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_verifier', + return_value='test_conf_file'), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_tempest_update_params') as m1: + conf_utils.configure_tempest('test_dep_dir') + self.assertTrue(m1.called) + self.assertTrue(m2.called) + + def test_configure_tempest_defcore_default(self): + img_flavor_dict = {'image_id': 'test_image_id', + 'flavor_id': 'test_flavor_id', + 'image_id_alt': 'test_image_alt_id', + 'flavor_id_alt': 'test_flavor_alt_id'} + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_verifier', + return_value='test_conf_file'), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.configure_tempest_update_params'), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'set') as mset, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'read') as mread, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'write') as mwrite, \ + mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.shutil.copyfile'): + CONST.dir_functest_test = 'test_dir' + CONST.refstack_tempest_conf_path = 'test_path' + conf_utils.configure_tempest_defcore('test_dep_dir', + img_flavor_dict) + mset.assert_any_call('compute', 'image_ref', 'test_image_id') + mset.assert_any_call('compute', 'image_ref_alt', + 'test_image_alt_id') + mset.assert_any_call('compute', 'flavor_ref', 'test_flavor_id') + mset.assert_any_call('compute', 'flavor_ref_alt', + 'test_flavor_alt_id') + self.assertTrue(mread.called) + self.assertTrue(mwrite.called) + + def _test_missing_param(self, params, image_id, flavor_id): + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'set') as mset, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'read') as mread, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'write') as mwrite, \ + mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.backup_tempest_config'): + CONST.dir_functest_test = 'test_dir' + CONST.OS_ENDPOINT_TYPE = None + conf_utils.\ + configure_tempest_update_params('test_conf_file', + IMAGE_ID=image_id, + FLAVOR_ID=flavor_id) + mset.assert_any_call(params[0], params[1], params[2]) + self.assertTrue(mread.called) + self.assertTrue(mwrite.called) + + def test_configure_tempest_update_params_missing_image_id(self): + CONST.tempest_use_custom_images = True + self._test_missing_param(('compute', 'image_ref', + 'test_image_id'), 'test_image_id', + None) + + def test_configure_tempest_update_params_missing_image_id_alt(self): + CONST.tempest_use_custom_images = True + conf_utils.IMAGE_ID_ALT = 'test_image_id_alt' + self._test_missing_param(('compute', 'image_ref_alt', + 'test_image_id_alt'), None, None) + + def test_configure_tempest_update_params_missing_flavor_id(self): + CONST.tempest_use_custom_flavors = True + self._test_missing_param(('compute', 'flavor_ref', + 'test_flavor_id'), None, + 'test_flavor_id') + + def test_configure_tempest_update_params_missing_flavor_id_alt(self): + CONST.tempest_use_custom_flavors = True + conf_utils.FLAVOR_ID_ALT = 'test_flavor_id_alt' + self._test_missing_param(('compute', 'flavor_ref_alt', + 'test_flavor_id_alt'), None, + None) + + def test_configure_verifier_missing_temp_conf_file(self): + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.path.isfile', + return_value=False), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ft_utils.execute_command') as mexe, \ + self.assertRaises(Exception) as context: + conf_utils.configure_verifier('test_dep_dir') + mexe.assert_any_call("rally verify configure-verifier") + msg = ("Tempest configuration file 'test_dep_dir/tempest.conf'" + " NOT found.") + self.assertTrue(msg in context) + + def test_configure_verifier_default(self): + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.path.isfile', + return_value=True), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ft_utils.execute_command') as mexe: + self.assertEqual(conf_utils.configure_verifier('test_dep_dir'), + 'test_dep_dir/tempest.conf') + mexe.assert_any_call("rally verify configure-verifier " + "--reconfigure") + + def test_configure_tempest_multisite_params_without_fuel(self): + conf_utils.CI_INSTALLER_TYPE = 'not_fuel' + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os_utils.get_endpoint', + return_value='kingbird_endpoint_url'), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'set') as mset, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'read') as mread, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'add_section') as msection, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ConfigParser.RawConfigParser.' + 'write') as mwrite, \ + mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.backup_tempest_config'): + + conf_utils.configure_tempest_multisite_params('test_conf_file') + msection.assert_any_call("kingbird") + mset.assert_any_call('service_available', 'kingbird', 'true') + mset.assert_any_call('kingbird', 'endpoint_type', 'publicURL') + mset.assert_any_call('kingbird', 'TIME_TO_SYNC', '120') + mset.assert_any_call('kingbird', 'endpoint_url', + 'kingbird_endpoint_url') + self.assertTrue(mread.called) + self.assertTrue(mwrite.called) + + def test_install_verifier_ext_default(self): + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.get_repo_tag', + return_value='test_tag'), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.ft_utils.' + 'execute_command_raise') as mexe: + conf_utils.install_verifier_ext('test_path') + cmd = ("rally verify add-verifier-ext --source test_path " + "--version test_tag") + error_msg = ("Problem while adding verifier extension from" + " test_path") + mexe.assert_called_once_with(cmd, error_msg=error_msg) if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py b/functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py index 398c53bf..34031b40 100644 --- a/functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py +++ b/functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py @@ -13,6 +13,7 @@ import mock from functest.core import testcase from functest.opnfv_tests.openstack.tempest import tempest from functest.opnfv_tests.openstack.tempest import conf_utils +from functest.utils.constants import CONST class OSTempestTesting(unittest.TestCase): @@ -33,6 +34,14 @@ class OSTempestTesting(unittest.TestCase): 'conf_utils.get_verifier_deployment_dir', return_value='test_verifier_deploy_dir'): self.tempestcommon = tempest.TempestCommon() + self.tempestsmoke_serial = tempest.TempestSmokeSerial() + self.tempestsmoke_parallel = tempest.TempestSmokeParallel() + self.tempestfull_parallel = tempest.TempestFullParallel() + with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' + 'conf_utils.install_verifier_ext'): + self.tempestmultisite = tempest.TempestMultisite() + self.tempestcustom = tempest.TempestCustom() + self.tempestdefcore = tempest.TempestDefcore() @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.logger.debug') def test_generate_test_list_defcore_mode(self, mock_logger_debug): @@ -100,6 +109,48 @@ class OSTempestTesting(unittest.TestCase): with self.assertRaises(Exception): self.tempestcommon.parse_verifier_result() + def test_apply_tempest_blacklist_no_blacklist(self): + with mock.patch('__builtin__.open', mock.mock_open()) as m, \ + mock.patch.object(self.tempestcommon, 'read_file', + return_value=['test1', 'test2']): + conf_utils.TEMPEST_BLACKLIST = Exception + CONST.INSTALLER_TYPE = 'installer_type' + CONST.DEPLOY_SCENARIO = 'deploy_scenario' + self.tempestcommon.apply_tempest_blacklist() + obj = m() + obj.write.assert_any_call('test1\n') + obj.write.assert_any_call('test2\n') + + def test_apply_tempest_blacklist_default(self): + item_dict = {'scenarios': ['deploy_scenario'], + 'installers': ['installer_type'], + 'tests': ['test2']} + with mock.patch('__builtin__.open', mock.mock_open()) as m, \ + mock.patch.object(self.tempestcommon, 'read_file', + return_value=['test1', 'test2']), \ + mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' + 'yaml.safe_load', return_value=item_dict): + CONST.INSTALLER_TYPE = 'installer_type' + CONST.DEPLOY_SCENARIO = 'deploy_scenario' + self.tempestcommon.apply_tempest_blacklist() + obj = m() + obj.write.assert_any_call('test1\n') + self.assertFalse(obj.write.assert_any_call('test2\n')) + + @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.logger.info') + def test_run_verifier_tests_default(self, mock_logger_info): + with mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('__builtin__.iter', return_value=['\} tempest\.']), \ + mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' + 'subprocess.Popen'): + conf_utils.TEMPEST_LIST = 'test_tempest_list' + cmd_line = ("rally verify start --load-list " + "test_tempest_list --detailed") + self.tempestcommon.run_verifier_tests() + mock_logger_info. \ + assert_any_call("Starting Tempest test suite: '%s'." + % cmd_line) + @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.logger.info') def test_parse_verifier_result_default(self, mock_logger_info): self.tempestcommon.VERIFICATION_ID = 'test_uuid' diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py b/functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py index 527f12e5..18bebfdf 100644 --- a/functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py +++ b/functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py @@ -39,16 +39,48 @@ class ClearwaterTesting(unittest.TestCase): with mock.patch.object(self.clearwater.orchestrator, 'download_upload_and_deploy_blueprint', return_value=''): - self.clearwater.deploy_vnf(self.bp), + self.clearwater.deploy_vnf(self.bp) self.assertEqual(self.clearwater.deploy, True) def test_undeploy_vnf_deployment_passed(self): with mock.patch.object(self.clearwater.orchestrator, 'undeploy_deployment'): self.clearwater.deploy = True + self.clearwater.undeploy_vnf() + self.assertEqual(self.clearwater.deploy, False) + + def test_undeploy_vnf_deployment_with_undeploy(self): + with mock.patch.object(self.clearwater.orchestrator, + 'undeploy_deployment') as m: + self.clearwater.deploy = False + self.clearwater.undeploy_vnf(), + self.assertEqual(self.clearwater.deploy, False) + self.assertFalse(m.called) + + self.clearwater.orchestrator = None + self.clearwater.deploy = True + self.clearwater.undeploy_vnf(), + self.assertEqual(self.clearwater.deploy, True) + + self.clearwater.deploy = False self.clearwater.undeploy_vnf(), self.assertEqual(self.clearwater.deploy, False) + def test_set_methods(self): + self.clearwater.set_orchestrator(self.orchestrator) + self.assertTrue(self.clearwater.orchestrator, self.orchestrator) + self.clearwater.set_flavor_id('test_flavor_id') + self.assertTrue(self.clearwater.config['flavor_id'], 'test_flavor_id') + self.clearwater.set_image_id('test_image_id') + self.assertTrue(self.clearwater.config['image_id'], 'test_image_id') + self.clearwater.set_agent_user('test_user') + self.assertTrue(self.clearwater.config['agent_user'], 'test_user') + self.clearwater.set_external_network_name('test_network') + self.assertTrue(self.clearwater.config['external_network_name'], + 'test_network') + self.clearwater.set_public_domain('test_domain') + self.assertTrue(self.clearwater.config['public_domain'], + 'test_domain') if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py b/functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py index 620b0216..bf6d483f 100644 --- a/functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py +++ b/functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py @@ -6,6 +6,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 import logging +import subprocess32 as subprocess import unittest import mock @@ -117,6 +118,60 @@ class ImsVnfTesting(unittest.TestCase): 'dest'), True) + def test_execute_command_failed(self): + with mock.patch('__builtin__.open', + mock.mock_open(read_data='test_data\n')): + subprocess.call = mock.create_autospec(subprocess.call, + return_value=0) + mock_log = mock.Mock() + cmd = 'test_cmd -e test_env bash_script' + ret = orchestrator_cloudify.execute_command(cmd, mock_log, + timeout=100) + self.assertEqual(ret, False) + + def test_execute_command_default(self): + with mock.patch('__builtin__.open', + mock.mock_open(read_data='test_data\n')): + subprocess.call = mock. \ + create_autospec(subprocess.call, + return_value=subprocess.TimeoutExpired) + mock_log = mock.Mock() + cmd = 'test_cmd -e test_env bash_script' + ret = orchestrator_cloudify.execute_command(cmd, mock_log, + timeout=100) + self.assertEqual(ret, ['test_data\n']) + + def test_set_methods(self): + self.orchestrator.set_credentials('test_username', 'test_password', + 'test_tenant_name', 'test_auth_url') + self.assertTrue(self.orchestrator.config['keystone_username'], + 'test_username') + self.assertTrue(self.orchestrator.config['keystone_password'], + 'test_password') + self.assertTrue(self.orchestrator.config['keystone_url'], + 'test_auth_url') + self.assertTrue(self.orchestrator.config['keystone_tenant_name'], + 'test_tenant_name') + self.orchestrator.set_flavor_id('test_flavor_id') + self.assertTrue(self.orchestrator.config['flavor_id'], + 'test_flavor_id') + self.orchestrator.set_image_id('test_image_id') + self.assertTrue(self.orchestrator.config['image_id'], 'test_image_id') + self.orchestrator.set_external_network_name('test_network') + self.assertTrue(self.orchestrator.config['external_network_name'], + 'test_network') + self.orchestrator.set_ssh_user('test_user') + self.assertTrue(self.orchestrator.config['ssh_user'], + 'test_user') + self.orchestrator.set_nova_url('test_nova_url') + self.assertTrue(self.orchestrator.config['nova_url'], + 'test_nova_url') + self.orchestrator.set_neutron_url('test_neutron_url') + self.assertTrue(self.orchestrator.config['neutron_url'], + 'test_neutron_url') + self.orchestrator.set_nameservers(['test_subnet']) + self.assertTrue(self.orchestrator.config['dns_subnet_1'], + 'test_subnet') if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_functest_logger.py b/functest/tests/unit/utils/test_functest_logger.py new file mode 100644 index 00000000..42e41a14 --- /dev/null +++ b/functest/tests/unit/utils/test_functest_logger.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# 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 logging +import unittest + +import mock + +from functest.utils import functest_logger +from functest.utils.constants import CONST + + +class OSUtilsLogger(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + with mock.patch('__builtin__.open', mock.mock_open()): + with mock.patch('functest.utils.functest_logger.os.path.exists', + return_value=True), \ + mock.patch('functest.utils.functest_logger.' + 'json.load'), \ + mock.patch('functest.utils.functest_logger.' + 'logging.config.dictConfig') as m: + self.logger = functest_logger.Logger('os_utils') + self.assertTrue(m.called) + with mock.patch('functest.utils.functest_logger.os.path.exists', + return_value=False), \ + mock.patch('functest.utils.functest_logger.' + 'logging.basicConfig') as m: + self.logger = functest_logger.Logger('os_utils') + self.assertTrue(m.called) + + def test_is_debug_false(self): + CONST.CI_DEBUG = False + self.assertFalse(self.logger.is_debug()) + + def test_is_debug_true(self): + CONST.CI_DEBUG = "True" + self.assertTrue(self.logger.is_debug()) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_openstack_tacker.py b/functest/tests/unit/utils/test_openstack_tacker.py index dc717258..37d77a18 100644 --- a/functest/tests/unit/utils/test_openstack_tacker.py +++ b/functest/tests/unit/utils/test_openstack_tacker.py @@ -6,9 +6,11 @@ # http://www.apache.org/licenses/LICENSE-2.0 import logging -import mock import unittest +import mock +from tackerclient.v1_0 import client as tackerclient + from functest.utils import openstack_tacker from functest.tests.unit import test_utils @@ -56,6 +58,13 @@ class OSTackerTesting(unittest.TestCase): } return cred_dict + def test_get_tacker_client(self): + with mock.patch('functest.utils.openstack_tacker.' + 'os_utils.get_session'): + tackerclient.Client = mock.Mock + ret = openstack_tacker.get_tacker_client() + self.assertTrue(isinstance(ret, mock.Mock)) + def test_get_id_from_name(self): with mock.patch.object(self.tacker_client, 'get', return_value=self.getresponse): @@ -183,8 +192,16 @@ class OSTackerTesting(unittest.TestCase): vnfd_name=self.vnfd) self.assertEqual(resp, self.vnfd) - # TODO: Exception('You need to provide an VNFD' - # 'id or name') AssertionError + def test_delete_vnfd_missing_vnfd_name(self): + with mock.patch('functest.utils.openstack_tacker.get_vnfd_id', + return_value=self.vnfd), \ + self.assertRaises(Exception) as context: + resp = openstack_tacker.delete_vnfd(self.tacker_client, + vnfd_id=None, + vnfd_name=None) + self.assertIsNone(resp) + msg = 'You need to provide VNFD id or VNFD name' + self.assertTrue(msg in context) @mock.patch('functest.utils.openstack_tacker.logger.error') def test_delete_vnfd_exception(self, mock_logger_error): @@ -253,7 +270,47 @@ class OSTackerTesting(unittest.TestCase): "client")) self.assertIsNone(resp) - # TODO: wait_for_vnf + def test_wait_for_vnf_vnf_retrieval_failed(self): + with mock.patch('functest.utils.openstack_tacker.get_vnf', + return_value=None), \ + self.assertRaises(Exception) as context: + openstack_tacker.wait_for_vnf(self.tacker_client, + vnf_id='vnf_id', + vnf_name='vnf_name') + msg = ("Could not retrieve VNF - id='vnf_id', " + "name='vnf_name'") + self.assertTrue(msg in context) + with mock.patch('functest.utils.openstack_tacker.get_vnf', + side_effect=Exception): + ret = openstack_tacker.wait_for_vnf(self.tacker_client, + vnf_id='vnf_id', + vnf_name='vnf_name') + self.assertEqual(ret, None) + + def test_wait_for_vnf_vnf_status_error(self): + vnf = {'id': 'vnf_id', + 'status': 'ERROR'} + with mock.patch('functest.utils.openstack_tacker.get_vnf', + return_value=vnf), \ + self.assertRaises(Exception) as context: + openstack_tacker.wait_for_vnf(self.tacker_client, + vnf_id='vnf_id', + vnf_name='vnf_name') + msg = ('Error when booting vnf vnf_id') + self.assertTrue(msg in context) + + def test_wait_for_vnf_vnf_timeout(self): + vnf = {'id': 'vnf_id', + 'status': 'PENDING_CREATE'} + with mock.patch('functest.utils.openstack_tacker.get_vnf', + return_value=vnf), \ + self.assertRaises(Exception) as context: + openstack_tacker.wait_for_vnf(self.tacker_client, + vnf_id='vnf_id', + vnf_name='vnf_name', + timeout=2) + msg = ('Timeout when booting vnf vnf_id') + self.assertTrue(msg in context) def test_delete_vnf(self): with mock.patch('functest.utils.openstack_tacker.get_vnf_id', @@ -265,8 +322,13 @@ class OSTackerTesting(unittest.TestCase): vnf_name=self.vnf) self.assertEqual(resp, self.vnf) - # TODO: Exception('You need to provide an VNF' - # 'classifier id or name') AssertionError + def test_delete_vnf_missing_vnf_name(self): + with self.assertRaises(Exception) as context: + openstack_tacker.delete_vnf(self.tacker_client, + vnf_id=None, + vnf_name=None) + msg = 'You need to provide a VNF id or name' + self.assertTrue(msg in context) @mock.patch('functest.utils.openstack_tacker.logger.error') def test_delete_vnf_exception(self, mock_logger_error): @@ -345,8 +407,13 @@ class OSTackerTesting(unittest.TestCase): sfc_name=self.sfc) self.assertEqual(resp, self.sfc) - # TODO: Exception('You need to provide an SFC' - # 'id or name') AssertionError + def test_delete_sfc_missing_sfc_name(self): + with self.assertRaises(Exception) as context: + openstack_tacker.delete_sfc(self.tacker_client, + sfc_id=None, + sfc_name=None) + msg = 'You need to provide an SFC id or name' + self.assertTrue(msg in context) @mock.patch('functest.utils.openstack_tacker.logger.error') def test_delete_sfc_exception(self, mock_logger_error): @@ -431,8 +498,13 @@ class OSTackerTesting(unittest.TestCase): sfc_clf_name=cl) self.assertEqual(resp, cl) - # TODO: Exception('You need to provide an SFC' - # 'classifier id or name') AssertionError + def test_delete_sfc_classifier_missing_sfc_name(self): + with self.assertRaises(Exception) as context: + openstack_tacker.delete_vnf(self.tacker_client, + sfc_clf_id=None, + sfc_clf_name=None) + msg = 'You need to provide an SFCclassifier id or name' + self.assertTrue(msg in context) @mock.patch('functest.utils.openstack_tacker.logger.error') def test_delete_sfc_classifier_exception(self, mock_logger_error): diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py index 673ad5e2..7f3995d0 100644 --- a/functest/tests/unit/utils/test_openstack_utils.py +++ b/functest/tests/unit/utils/test_openstack_utils.py @@ -229,6 +229,12 @@ class OSUtilsTesting(unittest.TestCase): self.sec_group = {'id': 'sec_group_id', 'name': 'test_sec_group'} + self.sec_group_rule = {'id': 'sec_group_rule_id', + 'direction': 'direction', + 'protocol': 'protocol', + 'port_range_max': 'port_max', + 'security_group_id': self.sec_group['id'], + 'port_range_min': 'port_min'} self.neutron_floatingip = {'id': 'fip_id', 'floating_ip_address': 'test_ip'} self.neutron_client = mock.Mock() @@ -260,6 +266,9 @@ class OSUtilsTesting(unittest.TestCase): 'show_bgpvpn.return_value': self.mock_return, 'list_security_groups.return_value': {'security_groups': [self.sec_group]}, + 'list_security_group_rules.' + 'return_value': {'security_group_rules': + [self.sec_group_rule]}, 'create_security_group_rule.return_value': mock.Mock(), 'create_security_group.return_value': {'security_group': self.sec_group}, @@ -1247,6 +1256,52 @@ class OSUtilsTesting(unittest.TestCase): 'test_sec_group'), 'sec_group_id') + def test_get_security_group_rules_default(self): + self.assertEqual(openstack_utils. + get_security_group_rules(self.neutron_client, + self.sec_group['id']), + [self.sec_group_rule]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_security_group_rules_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_security_group_rules(Exception, + 'sec_group_id'), + None) + self.assertTrue(mock_logger_error.called) + + def test_check_security_group_rules_not_exists(self): + self.assertEqual(openstack_utils. + check_security_group_rules(self.neutron_client, + 'sec_group_id_2', + 'direction', + 'protocol', + 'port_min', + 'port_max'), + True) + + def test_check_security_group_rules_exists(self): + self.assertEqual(openstack_utils. + check_security_group_rules(self.neutron_client, + self.sec_group['id'], + 'direction', + 'protocol', + 'port_min', + 'port_max'), + False) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_check_security_group_rules_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + check_security_group_rules(Exception, + 'sec_group_id', + 'direction', + 'protocol', + 'port_max', + 'port_min'), + None) + self.assertTrue(mock_logger_error.called) + def test_create_security_group_default(self): self.assertEqual(openstack_utils. create_security_group(self.neutron_client, diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index ffc870f6..4663f7ba 100644 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -1054,6 +1054,40 @@ def create_secgroup_rule(neutron_client, sg_id, direction, protocol, return False +def get_security_group_rules(neutron_client, sg_id): + try: + security_rules = neutron_client.list_security_group_rules()[ + 'security_group_rules'] + security_rules = [rule for rule in security_rules + if rule["security_group_id"] == sg_id] + return security_rules + except Exception, e: + logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:" + " %s" % e) + return None + + +def check_security_group_rules(neutron_client, sg_id, direction, protocol, + port_min=None, port_max=None): + try: + security_rules = get_security_group_rules(neutron_client, sg_id) + security_rules = [rule for rule in security_rules + if (rule["direction"].lower() == direction + and rule["protocol"].lower() == protocol + and rule["port_range_min"] == port_min + and rule["port_range_max"] == port_max)] + if len(security_rules) == 0: + return True + else: + return False + except Exception, e: + logger.error("Error [check_security_group_rules(" + " neutron_client, sg_id, direction," + " protocol, port_min=None, port_max=None)]: " + "%s" % e) + return None + + def create_security_group_full(neutron_client, sg_name, sg_description): sg_id = get_security_group_id(neutron_client, sg_name) |