diff options
Diffstat (limited to 'yardstick')
25 files changed, 1117 insertions, 76 deletions
diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py index 85ae14b1d..30170832a 100644 --- a/yardstick/benchmark/contexts/standalone/model.py +++ b/yardstick/benchmark/contexts/standalone/model.py @@ -35,7 +35,7 @@ LOG = logging.getLogger(__name__) VM_TEMPLATE = """ <domain type="kvm"> - <name>{vm_name}</name> + <name>{vm_name}</name> <uuid>{random_uuid}</uuid> <memory unit="MB">{memory}</memory> <currentMemory unit="MB">{memory}</currentMemory> @@ -80,7 +80,13 @@ VM_TEMPLATE = """ <source bridge="br-int" /> <model type='virtio'/> </interface> - </devices> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + </devices> </domain> """ WAIT_FOR_BOOT = 30 @@ -212,9 +218,8 @@ class Libvirt(object): mac.set('address', vf_mac) source = ET.SubElement(interface, 'source') - addr = ET.SubElement(source, 'address') pci_address = PciAddress(vf_pci.strip()) - cls._add_interface_address(addr, pci_address) + cls._add_interface_address(source, pci_address) pci_vm_address = PciAddress(vm_pci.strip()) cls._add_interface_address(interface, pci_vm_address) @@ -287,7 +292,8 @@ class StandaloneContextHelper(object): super(StandaloneContextHelper, self).__init__() @staticmethod - def install_req_libs(connection, extra_pkgs=[]): + def install_req_libs(connection, extra_pkgs=None): + extra_pkgs = extra_pkgs or [] pkgs = ["qemu-kvm", "libvirt-bin", "bridge-utils", "numactl", "fping"] pkgs.extend(extra_pkgs) cmd_template = "dpkg-query -W --showformat='${Status}\\n' \"%s\"|grep 'ok installed'" diff --git a/yardstick/benchmark/scenarios/lib/create_volume.py b/yardstick/benchmark/scenarios/lib/create_volume.py index c7086d0ef..df523a5ec 100644 --- a/yardstick/benchmark/scenarios/lib/create_volume.py +++ b/yardstick/benchmark/scenarios/lib/create_volume.py @@ -44,22 +44,21 @@ class CreateVolume(base.Scenario): self.setup_done = True - def run(self, result): + def run(self): """execute the test""" if not self.setup_done: self.setup() - if self.image_name: - self.image_id = op_utils.get_image_id(self.glance_client, - self.image_name) + self.image_id = op_utils.get_image_id(self.glance_client, + self.image_name) volume = op_utils.create_volume(self.cinder_client, self.volume_name, self.volume_size, self.image_id) status = volume.status while(status == 'creating' or status == 'downloading'): - LOG.info("Volume status is: %s" % status) + LOG.info("Volume status is: %s", status) time.sleep(5) volume = op_utils.get_volume_by_name(self.volume_name) status = volume.status diff --git a/yardstick/benchmark/scenarios/parser/parser.py b/yardstick/benchmark/scenarios/parser/parser.py index eb16833e5..5b2b49c2c 100644 --- a/yardstick/benchmark/scenarios/parser/parser.py +++ b/yardstick/benchmark/scenarios/parser/parser.py @@ -6,13 +6,13 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -from __future__ import print_function -from __future__ import absolute_import + import pkg_resources import logging import subprocess from yardstick.benchmark.scenarios import base + LOG = logging.getLogger(__name__) @@ -63,7 +63,7 @@ class Parser(base.Scenario): p = subprocess.Popen(cmd1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.communicate() - print("yangtotosca finished") + LOG.info("yangtotosca finished") result['yangtotosca'] = "success" if p.returncode == 0 else "fail" diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index 82e20bec7..8604e900f 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -13,27 +13,22 @@ # License for the specific language governing permissions and limitations # under the License. -# yardstick comment: this is a modified copy of rally/rally/common/utils.py - -from __future__ import absolute_import -from __future__ import print_function - +import collections +from contextlib import closing import datetime import errno +import importlib +import ipaddress import logging import os +import random +import socket import subprocess import sys -import collections -import socket -import random -import ipaddress -from contextlib import closing import six from flask import jsonify from six.moves import configparser -from oslo_utils import importutils from oslo_serialization import jsonutils import yardstick @@ -70,27 +65,28 @@ def itersubclasses(cls, _seen=None): def import_modules_from_package(package): - """Import modules from package and append into sys.modules + """Import modules given a package name :param: package - Full package name. For example: rally.deploy.engines """ yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__)) - path = os.path.join(yardstick_root, *package.split(".")) + path = os.path.join(yardstick_root, *package.split('.')) for root, _, files in os.walk(path): - matches = (filename for filename in files if filename.endswith(".py") and - not filename.startswith("__")) - new_package = os.path.relpath(root, yardstick_root).replace(os.sep, ".") + matches = (filename for filename in files if filename.endswith('.py') + and not filename.startswith('__')) + new_package = os.path.relpath(root, yardstick_root).replace(os.sep, + '.') module_names = set( - ("{}.{}".format(new_package, filename.rsplit(".py", 1)[0]) for filename in matches)) - # find modules which haven't already been imported + '{}.{}'.format(new_package, filename.rsplit('.py', 1)[0]) + for filename in matches) + # Find modules which haven't already been imported missing_modules = module_names.difference(sys.modules) - logger.debug("importing %s", missing_modules) - # we have already checked for already imported modules, so we don't need to check again + logger.debug('Importing modules: %s', missing_modules) for module_name in missing_modules: try: - sys.modules[module_name] = importutils.import_module(module_name) + importlib.import_module(module_name) except (ImportError, SyntaxError): - logger.exception("unable to import %s", module_name) + logger.exception('Unable to import module %s', module_name) def makedirs(d): diff --git a/yardstick/network_services/collector/subscriber.py b/yardstick/network_services/collector/subscriber.py index 4dc5a796e..7e18302eb 100644 --- a/yardstick/network_services/collector/subscriber.py +++ b/yardstick/network_services/collector/subscriber.py @@ -62,12 +62,13 @@ class Collector(object): # Result example: # {"VNF1: { "tput" : [1000, 999] }, "VNF2": { "latency": 100 }} LOG.debug("collect KPI for %s", node_name) - if resource.check_if_sa_running("collectd")[0] != 0: + if resource.check_if_system_agent_running("collectd")[0] != 0: continue try: results[node_name] = {"core": resource.amqp_collect_nfvi_kpi()} LOG.debug("%s collect KPIs %s", node_name, results[node_name]['core']) - except Exception: - LOG.exception("") + # NOTE(elfoley): catch a more specific error + except Exception as exc: # pylint: disable=broad-except + LOG.exception(exc) return results diff --git a/yardstick/network_services/nfvi/resource.py b/yardstick/network_services/nfvi/resource.py index adf4d8ae6..dc5c46a86 100644 --- a/yardstick/network_services/nfvi/resource.py +++ b/yardstick/network_services/nfvi/resource.py @@ -13,20 +13,16 @@ # limitations under the License. """ Resource collection definitions """ -from __future__ import absolute_import -from __future__ import print_function - -import logging -from itertools import chain - import errno -import jinja2 +from itertools import chain +import logging +import multiprocessing import os import os.path import re -import multiprocessing -import pkg_resources +import jinja2 +import pkg_resources from oslo_config import cfg from oslo_utils.encodeutils import safe_decode @@ -92,7 +88,7 @@ class ResourceProfile(object): return cls(node, plugins=plugins, interval=interval, timeout=timeout) - def check_if_sa_running(self, process): + def check_if_system_agent_running(self, process): """ verify if system agent is running """ try: err, pid, _ = self.connection.execute("pgrep -f %s" % process) @@ -101,7 +97,7 @@ class ResourceProfile(object): except OSError as e: if e.errno in {errno.ECONNRESET}: # if we can't connect to check, then we won't be able to connect to stop it - LOG.exception("can't connect to host to check collectd status") + LOG.exception("Can't connect to host to check %s status", process) return 1, None raise @@ -327,7 +323,7 @@ class ResourceProfile(object): self.amqp_client.terminate() LOG.debug("Check if %s is running", agent) - status, pid = self.check_if_sa_running(agent) + status, pid = self.check_if_system_agent_running(agent) LOG.debug("status %s pid %s", status, pid) if status != 0: return diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py index 5eeb6c889..fbaaa0ca8 100644 --- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py +++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py @@ -13,38 +13,34 @@ # limitations under the License. """ Base class implementation for generic vnf implementation """ -from __future__ import absolute_import - -import posixpath -import time +from collections import Mapping import logging +from multiprocessing import Queue, Value, Process import os +import posixpath import re -import subprocess -from collections import Mapping -from multiprocessing import Queue, Value, Process - from six.moves import cStringIO +import subprocess +import time +from trex_stl_lib.trex_stl_client import LoggerApi +from trex_stl_lib.trex_stl_client import STLClient +from trex_stl_lib.trex_stl_exceptions import STLError from yardstick.benchmark.contexts.base import Context from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file from yardstick.common import exceptions as y_exceptions from yardstick.common.process import check_if_process_failed +from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper from yardstick.network_services.helpers.samplevnf_helper import PortPairs from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig -from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper from yardstick.network_services.nfvi.resource import ResourceProfile +from yardstick.network_services.utils import get_nsb_option from yardstick.network_services.vnf_generic.vnf.base import GenericVNF -from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen -from yardstick.network_services.utils import get_nsb_option - -from trex_stl_lib.trex_stl_client import STLClient -from trex_stl_lib.trex_stl_client import LoggerApi -from trex_stl_lib.trex_stl_exceptions import STLError - +from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper from yardstick.ssh import AutoConnectSSH + DPDK_VERSION = "dpdk-16.07" LOG = logging.getLogger(__name__) @@ -346,7 +342,7 @@ class ResourceHelper(object): def _collect_resource_kpi(self): result = {} - status = self.resource.check_if_sa_running("collectd")[0] + status = self.resource.check_if_system_agent_running("collectd")[0] if status == 0: result = self.resource.amqp_collect_nfvi_kpi() diff --git a/yardstick/tests/functional/common/__init__.py b/yardstick/tests/functional/common/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/functional/common/__init__.py diff --git a/yardstick/tests/functional/common/fake_module/__init__.py b/yardstick/tests/functional/common/fake_module/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/functional/common/fake_module/__init__.py diff --git a/yardstick/tests/functional/common/fake_module/fake_library.py b/yardstick/tests/functional/common/fake_module/fake_library.py new file mode 100644 index 000000000..28c7dc694 --- /dev/null +++ b/yardstick/tests/functional/common/fake_module/fake_library.py @@ -0,0 +1,17 @@ +# Copyright (c) 2018 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +class FakeClassToBeImported(object): + pass diff --git a/yardstick/tests/functional/common/test_utils.py b/yardstick/tests/functional/common/test_utils.py new file mode 100644 index 000000000..b5333bbde --- /dev/null +++ b/yardstick/tests/functional/common/test_utils.py @@ -0,0 +1,34 @@ +# Copyright (c) 2018 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import sys + +from yardstick.common import utils + + +class ImportModulesFromPackageTestCase(unittest.TestCase): + + def test_import_package(self): + module_name = 'yardstick.tests.functional.common.fake_module' + library_name = 'fake_library' + class_name = 'FakeClassToBeImported' + self.assertNotIn(module_name, sys.modules) + + utils.import_modules_from_package(module_name) + self.assertIn(module_name, sys.modules) + module_obj = sys.modules[module_name] + library_obj = getattr(module_obj, library_name) + class_obj = getattr(library_obj, class_name) + self.assertEqual(class_name, class_obj().__class__.__name__) diff --git a/yardstick/tests/unit/apiserver/resources/test_env_action.py b/yardstick/tests/unit/apiserver/resources/test_env_action.py index b7bfe294d..cf646a29c 100644 --- a/yardstick/tests/unit/apiserver/resources/test_env_action.py +++ b/yardstick/tests/unit/apiserver/resources/test_env_action.py @@ -32,7 +32,7 @@ class EnvTestCase(APITestCase): time.sleep(0) - self.assertTrue(u'status' in resp) + self.assertIn(u'status', resp) def main(): diff --git a/yardstick/tests/unit/common/test_utils.py b/yardstick/tests/unit/common/test_utils.py index 452b93a56..033bb0243 100644 --- a/yardstick/tests/unit/common/test_utils.py +++ b/yardstick/tests/unit/common/test_utils.py @@ -7,12 +7,9 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -# Unittest for yardstick.common.utils - -from __future__ import absolute_import - from copy import deepcopy import errno +import importlib import ipaddress from itertools import product, chain import mock @@ -60,8 +57,8 @@ class ImportModulesFromPackageTestCase(unittest.TestCase): utils.import_modules_from_package('foo.bar') @mock.patch('yardstick.common.utils.os.walk') - @mock.patch('yardstick.common.utils.importutils') - def test_import_modules_from_package(self, mock_importutils, mock_walk): + @mock.patch.object(importlib, 'import_module') + def test_import_modules_from_package(self, mock_import_module, mock_walk): yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__)) mock_walk.return_value = ([ @@ -69,7 +66,7 @@ class ImportModulesFromPackageTestCase(unittest.TestCase): ]) utils.import_modules_from_package('foo.bar') - mock_importutils.import_module.assert_called_with('bar.baz') + mock_import_module.assert_called_once_with('bar.baz') class GetParaFromYaml(unittest.TestCase): diff --git a/yardstick/tests/unit/common/test_yaml_loader.py b/yardstick/tests/unit/common/test_yaml_loader.py index 90cbb8157..6c2beb422 100644 --- a/yardstick/tests/unit/common/test_yaml_loader.py +++ b/yardstick/tests/unit/common/test_yaml_loader.py @@ -22,7 +22,7 @@ class TemplateFormatTestCase(unittest.TestCase): def test_parse_to_value_exception(self): - self.assertEquals(yaml_loader.yaml_load("string"), u"string") + self.assertEqual(yaml_loader.yaml_load("string"), u"string") def main(): diff --git a/yardstick/tests/unit/dispatcher/__init__.py b/yardstick/tests/unit/dispatcher/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/dispatcher/__init__.py diff --git a/yardstick/tests/unit/dispatcher/test_influxdb.py b/yardstick/tests/unit/dispatcher/test_influxdb.py new file mode 100644 index 000000000..bca94e385 --- /dev/null +++ b/yardstick/tests/unit/dispatcher/test_influxdb.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd 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 +############################################################################## + +# Unittest for yardstick.dispatcher.influxdb + +import mock +import unittest + +from yardstick.dispatcher.influxdb import InfluxdbDispatcher +from yardstick import _init_logging + + +_init_logging() + + +class InfluxdbDispatcherTestCase(unittest.TestCase): + + def setUp(self): + self.data1 = { + "runner_id": 8921, + "context_cfg": { + "host": { + "ip": "10.229.43.154", + "key_filename": + "/root/yardstick/yardstick/resources/files" + "/yardstick_key", + "name": "kvm.LF", + "user": "root" + }, + "target": { + "ipaddr": "10.229.44.134" + } + }, + "scenario_cfg": { + "runner": { + "interval": 1, + "object": "yardstick.benchmark.scenarios.networking.ping" + ".Ping", + "output_filename": "/tmp/yardstick.out", + "runner_id": 8921, + "duration": 10, + "type": "Duration" + }, + "host": "kvm.LF", + "type": "Ping", + "target": "10.229.44.134", + "sla": { + "action": "monitor", + "max_rtt": 10 + }, + "tc": "ping", + "task_id": "ea958583-c91e-461a-af14-2a7f9d7f79e7" + } + } + self.data2 = { + "benchmark": { + "timestamp": "1451478117.883505", + "errors": "", + "data": { + "rtt": 0.613 + }, + "sequence": 1 + }, + "runner_id": 8921 + } + + self.yardstick_conf = {'dispatcher_influxdb': {}} + + @mock.patch('yardstick.dispatcher.influxdb.requests') + def test_record_result_data(self, mock_requests): + type(mock_requests.post.return_value).status_code = 204 + influxdb = InfluxdbDispatcher(self.yardstick_conf) + data = { + 'status': 1, + 'result': { + 'criteria': 'PASS', + 'info': { + }, + 'task_id': 'b9e2bbc2-dfd8-410d-8c24-07771e9f7979', + 'testcases': { + } + } + } + self.assertEqual(influxdb.flush_result_data(data), 0) + + def test__get_nano_timestamp(self): + influxdb = InfluxdbDispatcher(self.yardstick_conf) + results = {'timestamp': '1451461248.925574'} + self.assertEqual(influxdb._get_nano_timestamp(results), + '1451461248925574144') + + @mock.patch('yardstick.dispatcher.influxdb.time') + def test__get_nano_timestamp_except(self, mock_time): + results = {} + influxdb = InfluxdbDispatcher(self.yardstick_conf) + mock_time.time.return_value = 1451461248.925574 + self.assertEqual(influxdb._get_nano_timestamp(results), + '1451461248925574144') + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py b/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py new file mode 100644 index 000000000..641e97fae --- /dev/null +++ b/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py @@ -0,0 +1,63 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 +############################################################################## +# Unittest for yardstick.dispatcher.influxdb_line_protocol + +# yardstick comment: this file is a modified copy of +# influxdb-python/influxdb/tests/test_line_protocol.py + +import unittest +from third_party.influxdb.influxdb_line_protocol import make_lines + + +class TestLineProtocol(unittest.TestCase): + + def test_make_lines(self): + data = { + "tags": { + "empty_tag": "", + "none_tag": None, + "integer_tag": 2, + "string_tag": "hello" + }, + "points": [ + { + "measurement": "test", + "fields": { + "string_val": "hello!", + "int_val": 1, + "float_val": 1.1, + "none_field": None, + "bool_val": True, + } + } + ] + } + + self.assertEqual( + make_lines(data), + 'test,integer_tag=2,string_tag=hello ' + 'bool_val=True,float_val=1.1,int_val=1i,string_val="hello!"\n' + ) + + def test_string_val_newline(self): + data = { + "points": [ + { + "measurement": "m1", + "fields": { + "multi_line": "line1\nline1\nline3" + } + } + ] + } + + self.assertEqual( + make_lines(data), + 'm1 multi_line="line1\\nline1\\nline3"\n' + ) diff --git a/yardstick/tests/unit/orchestrator/__init__.py b/yardstick/tests/unit/orchestrator/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/orchestrator/__init__.py diff --git a/yardstick/tests/unit/orchestrator/test_heat.py b/yardstick/tests/unit/orchestrator/test_heat.py new file mode 100644 index 000000000..faf70cdbc --- /dev/null +++ b/yardstick/tests/unit/orchestrator/test_heat.py @@ -0,0 +1,486 @@ +#!/usr/bin/env python + +############################################################################## +# Copyright (c) 2017 Intel Corporation +# +# 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 +############################################################################## + +# Unittest for yardstick.benchmark.orchestrator.heat +from contextlib import contextmanager +from itertools import count +from tempfile import NamedTemporaryFile +import time +import uuid + +import mock +import unittest + +from yardstick.benchmark.contexts import node +from yardstick.orchestrator import heat + + +TARGET_MODULE = 'yardstick.orchestrator.heat' + + +def mock_patch_target_module(inner_import): + return mock.patch('.'.join([TARGET_MODULE, inner_import])) + + +@contextmanager +def timer(): + start = time.time() + data = {'start': start} + try: + yield data + finally: + data['end'] = end = time.time() + data['delta'] = end - start + + +def index_value_iter(index, index_value, base_value=None): + for current_index in count(): + if current_index == index: + yield index_value + else: + yield base_value + + +def get_error_message(error): + try: + # py2 + return error.message + except AttributeError: + # py3 + return next((arg for arg in error.args if isinstance(arg, str)), None) + + +class HeatContextTestCase(unittest.TestCase): + + def test_get_short_key_uuid(self): + u = uuid.uuid4() + k = heat.get_short_key_uuid(u) + self.assertEqual(heat.HEAT_KEY_UUID_LENGTH, len(k)) + self.assertIn(k, str(u)) + + +class HeatTemplateTestCase(unittest.TestCase): + + def setUp(self): + self.template = heat.HeatTemplate('test') + + def test_add_tenant_network(self): + self.template.add_network('some-network') + + self.assertEqual( + self.template.resources['some-network']['type'], + 'OS::Neutron::Net') + + def test_add_provider_network(self): + self.template.add_network('some-network', 'physnet2', 'sriov') + + self.assertEqual( + self.template.resources['some-network']['type'], + 'OS::Neutron::ProviderNet') + self.assertEqual( + self.template.resources['some-network']['properties']['physical_network'], + 'physnet2') + + def test_add_subnet(self): + netattrs = {'cidr': '10.0.0.0/24', + 'provider': None, 'external_network': 'ext_net'} + self.template.add_subnet( + 'some-subnet', "some-network", netattrs['cidr']) + + self.assertEqual( + self.template.resources['some-subnet']['type'], + 'OS::Neutron::Subnet') + self.assertEqual( + self.template.resources['some-subnet']['properties']['cidr'], + '10.0.0.0/24') + + def test_add_router(self): + self.template.add_router('some-router', 'ext-net', 'some-subnet') + + self.assertEqual( + self.template.resources['some-router']['type'], + 'OS::Neutron::Router') + self.assertIn( + 'some-subnet', + self.template.resources['some-router']['depends_on']) + + def test_add_router_interface(self): + self.template.add_router_interface( + 'some-router-if', 'some-router', 'some-subnet') + + self.assertEqual( + self.template.resources['some-router-if']['type'], + 'OS::Neutron::RouterInterface') + self.assertIn( + 'some-subnet', + self.template.resources['some-router-if']['depends_on']) + + def test_add_servergroup(self): + self.template.add_servergroup('some-server-group', 'anti-affinity') + + self.assertEqual( + self.template.resources['some-server-group']['type'], + 'OS::Nova::ServerGroup') + self.assertEqual( + self.template.resources['some-server-group']['properties']['policies'], + ['anti-affinity']) + + def test__add_resources_to_template_raw(self): + test_context = node.NodeContext() + test_context.name = 'foo' + test_context.template_file = '/tmp/some-heat-file' + test_context.heat_parameters = {'image': 'cirros'} + test_context.key_filename = "/tmp/1234" + test_context.keypair_name = "foo-key" + test_context.secgroup_name = "foo-secgroup" + test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b" + heat_object = heat.HeatObject() + + heat_stack = heat.HeatStack("tmpStack") + self.assertTrue(heat_stack.stacks_exist()) + + test_context.tmpfile = NamedTemporaryFile(delete=True, mode='w+t') + test_context.tmpfile.write("heat_template_version: 2015-04-30") + test_context.tmpfile.flush() + test_context.tmpfile.seek(0) + heat_template = heat.HeatTemplate(heat_object) + heat_template.resources = {} + + heat_template.add_network("network1") + heat_template.add_network("network2") + heat_template.add_security_group("sec_group1") + heat_template.add_security_group("sec_group2") + heat_template.add_subnet("subnet1", "network1", "cidr1") + heat_template.add_subnet("subnet2", "network2", "cidr2") + heat_template.add_router("router1", "gw1", "subnet1") + heat_template.add_router_interface("router_if1", "router1", "subnet1") + heat_template.add_port("port1", "network1", "subnet1", "normal") + heat_template.add_port( + "port2", + "network2", + "subnet2", + "normal", + sec_group_id="sec_group1", + provider="not-sriov") + heat_template.add_port( + "port3", + "network2", + "subnet2", + "normal", + sec_group_id="sec_group1", + provider="sriov") + heat_template.add_floating_ip( + "floating_ip1", "network1", "port1", "router_if1") + heat_template.add_floating_ip( + "floating_ip2", "network2", "port2", "router_if2", "foo-secgroup") + heat_template.add_floating_ip_association( + "floating_ip1_association", "floating_ip1", "port1") + heat_template.add_servergroup("server_grp2", "affinity") + heat_template.add_servergroup("server_grp3", "anti-affinity") + heat_template.add_security_group("security_group") + heat_template.add_server( + name="server1", image="image1", flavor="flavor1", flavors=[]) + heat_template.add_server_group( + name="servergroup", policies=["policy1", "policy2"]) + heat_template.add_server_group(name="servergroup", policies="policy1") + heat_template.add_server( + name="server2", + image="image1", + flavor="flavor1", + flavors=[], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_server( + name="server2", + image="image1", + flavor="flavor1", + flavors=[ + "flavor1", + "flavor2"], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_server( + name="server2", + image="image1", + flavor="flavor1", + flavors=[ + "flavor3", + "flavor4"], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_flavor( + name="flavor1", + vcpus=1, + ram=2048, + disk=1, + extra_specs={ + "cat": 1, + "dog": 2}) + heat_template.add_flavor(name=None, vcpus=1, ram=2048) + heat_template.add_server( + name="server1", + image="image1", + flavor="flavor1", + flavors=[], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_network("network1") + + heat_template.add_flavor("test") + self.assertEqual( + heat_template.resources['test']['type'], 'OS::Nova::Flavor') + + @mock_patch_target_module('op_utils') + @mock_patch_target_module('heatclient') + def test_create_negative(self, mock_heat_client_class, mock_op_utils): + self.template.HEAT_WAIT_LOOP_INTERVAL = 0 + mock_heat_client = mock_heat_client_class() # get the constructed mock + + # populate attributes of the constructed mock + mock_heat_client.stacks.get().stack_status_reason = 'the reason' + + expected_status_calls = 0 + expected_constructor_calls = 1 # above, to get the instance + expected_create_calls = 0 + expected_op_utils_usage = 0 + + with mock.patch.object(self.template, 'status', return_value=None) as mock_status: + # block with timeout hit + timeout = 0 + with self.assertRaises(RuntimeError) as raised, timer(): + self.template.create(block=True, timeout=timeout) + + # ensure op_utils was used + expected_op_utils_usage += 1 + self.assertEqual( + mock_op_utils.get_session.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_heat_api_version.call_count, + expected_op_utils_usage) + + # ensure the constructor and instance were used + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) + + # ensure that the status was used + self.assertGreater(mock_status.call_count, expected_status_calls) + expected_status_calls = mock_status.call_count # synchronize the value + + # ensure the expected exception was raised + error_message = get_error_message(raised.exception) + self.assertIn('timeout', error_message) + self.assertNotIn('the reason', error_message) + + # block with create failed + timeout = 10 + mock_status.side_effect = iter([None, None, u'CREATE_FAILED']) + with self.assertRaises(RuntimeError) as raised, timer(): + self.template.create(block=True, timeout=timeout) + + # ensure the existing heat_client was used and op_utils was used + # again + self.assertEqual( + mock_op_utils.get_session.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_heat_api_version.call_count, + expected_op_utils_usage) + + # ensure the constructor was not used but the instance was used + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) + + # ensure that the status was used three times + expected_status_calls += 3 + self.assertEqual(mock_status.call_count, expected_status_calls) + + # NOTE(elfoley): This needs to be split into multiple tests. + # The lines where the template is reset should serve as a guide for where + # to split. + @mock_patch_target_module('op_utils') + @mock_patch_target_module('heatclient') + def test_create(self, mock_heat_client_class, mock_op_utils): + self.template.HEAT_WAIT_LOOP_INTERVAL = 0.2 + mock_heat_client = mock_heat_client_class() + + # populate attributes of the constructed mock + mock_heat_client.stacks.get().outputs = [ + {'output_key': 'key1', 'output_value': 'value1'}, + {'output_key': 'key2', 'output_value': 'value2'}, + {'output_key': 'key3', 'output_value': 'value3'}, + ] + expected_outputs = { # pylint: disable=unused-variable + 'key1': 'value1', + 'key2': 'value2', + 'key3': 'value3', + } + + expected_status_calls = 0 + expected_constructor_calls = 1 # above, to get the instance + expected_create_calls = 0 + expected_op_utils_usage = 0 + + with mock.patch.object(self.template, 'status') as mock_status: + self.template.name = 'no block test' + mock_status.return_value = None + + # no block + self.assertIsInstance(self.template.create( + block=False, timeout=2), heat.HeatStack) + + # ensure op_utils was used + expected_op_utils_usage += 1 + self.assertEqual( + mock_op_utils.get_session.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_heat_api_version.call_count, + expected_op_utils_usage) + + # ensure the constructor and instance were used + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) + + # ensure that the status was not used + self.assertEqual(mock_status.call_count, expected_status_calls) + + # ensure no outputs because this requires blocking + self.assertEqual(self.template.outputs, {}) + + # block with immediate complete + self.template.name = 'block, immediate complete test' + + mock_status.return_value = self.template.HEAT_CREATE_COMPLETE_STATUS + self.assertIsInstance(self.template.create( + block=True, timeout=2), heat.HeatStack) + + # ensure existing instance was re-used and op_utils was not used + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) + + # ensure status was checked once + expected_status_calls += 1 + self.assertEqual(mock_status.call_count, expected_status_calls) + + # reset template outputs + self.template.outputs = None + + # block with delayed complete + self.template.name = 'block, delayed complete test' + + success_index = 2 + mock_status.side_effect = index_value_iter( + success_index, self.template.HEAT_CREATE_COMPLETE_STATUS) + self.assertIsInstance(self.template.create( + block=True, timeout=2), heat.HeatStack) + + # ensure existing instance was re-used and op_utils was not used + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) + + # ensure status was checked three more times + expected_status_calls += 1 + success_index + self.assertEqual(mock_status.call_count, expected_status_calls) + + +class HeatStackTestCase(unittest.TestCase): + + def test_delete_calls__delete_multiple_times(self): + stack = heat.HeatStack('test') + stack.uuid = 1 + with mock.patch.object(stack, "_delete") as delete_mock: + stack.delete() + # call once and then call again if uuid is not none + self.assertGreater(delete_mock.call_count, 1) + + def test_delete_all_calls_delete(self): + # we must patch the object before we create an instance + # so we can override delete() in all the instances + with mock.patch.object(heat.HeatStack, "delete") as delete_mock: + stack = heat.HeatStack('test') + stack.uuid = 1 + stack.delete_all() + self.assertGreater(delete_mock.call_count, 0) diff --git a/yardstick/tests/unit/orchestrator/test_kubernetes.py b/yardstick/tests/unit/orchestrator/test_kubernetes.py new file mode 100644 index 000000000..33fa1dca6 --- /dev/null +++ b/yardstick/tests/unit/orchestrator/test_kubernetes.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +############################################################################## +# Copyright (c) 2017 Intel Corporation +# +# 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 +############################################################################## + +# Unittest for yardstick.benchmark.orchestrator.heat +import unittest +import mock + +from yardstick.orchestrator.kubernetes import KubernetesObject +from yardstick.orchestrator.kubernetes import KubernetesTemplate + + +class GetTemplateTestCase(unittest.TestCase): + + def test_get_template(self): + output_t = { + "apiVersion": "v1", + "kind": "ReplicationController", + "metadata": { + "name": "host-k8s-86096c30" + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "labels": { + "app": "host-k8s-86096c30" + } + }, + "spec": { + "containers": [ + { + "args": [ + "-c", + "chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \ +service ssh restart;while true ; do sleep 10000; done" + ], + "command": [ + "/bin/bash" + ], + "image": "openretriever/yardstick", + "name": "host-k8s-86096c30-container", + "volumeMounts": [ + { + "mountPath": "/root/.ssh/", + "name": "k8s-86096c30-key" + } + ] + } + ], + "volumes": [ + { + "configMap": { + "name": "k8s-86096c30-key" + }, + "name": "k8s-86096c30-key" + } + ], + "nodeSelector": { + "kubernetes.io/hostname": "node-01" + } + } + } + } + } + input_s = { + 'command': '/bin/bash', + 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \ +service ssh restart;while true ; do sleep 10000; done'], + 'ssh_key': 'k8s-86096c30-key', + 'nodeSelector': {'kubernetes.io/hostname': 'node-01'} + } + name = 'host-k8s-86096c30' + output_r = KubernetesObject(name, **input_s).get_template() + self.assertEqual(output_r, output_t) + + +class GetRcPodsTestCase(unittest.TestCase): + + @mock.patch('yardstick.orchestrator.kubernetes.k8s_utils.get_pod_list') + def test_get_rc_pods(self, mock_get_pod_list): + servers = { + 'host': { + 'image': 'openretriever/yardstick', + 'command': '/bin/bash', + 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \ +service ssh restart;while true ; do sleep 10000; done'] + }, + 'target': { + 'image': 'openretriever/yardstick', + 'command': '/bin/bash', + 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \ +service ssh restart;while true ; do sleep 10000; done'] + } + } + k8s_template = KubernetesTemplate('k8s-86096c30', servers) + mock_get_pod_list.return_value.items = [] + pods = k8s_template.get_rc_pods() + self.assertEqual(pods, []) + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/yardstick/tests/unit/test_cmd/__init__.py b/yardstick/tests/unit/test_cmd/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/test_cmd/__init__.py diff --git a/yardstick/tests/unit/test_cmd/commands/__init__.py b/yardstick/tests/unit/test_cmd/commands/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/test_cmd/commands/__init__.py diff --git a/yardstick/tests/unit/test_cmd/commands/test_env.py b/yardstick/tests/unit/test_cmd/commands/test_env.py new file mode 100644 index 000000000..13c3ed44a --- /dev/null +++ b/yardstick/tests/unit/test_cmd/commands/test_env.py @@ -0,0 +1,73 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +from __future__ import absolute_import +import unittest +import mock +import uuid + +from yardstick.cmd.commands.env import EnvCommand + + +class EnvCommandTestCase(unittest.TestCase): + + @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task') + @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status') + def test_do_influxdb(self, check_status_mock, start_async_task_mock): + env = EnvCommand() + env.do_influxdb({}) + self.assertTrue(start_async_task_mock.called) + self.assertTrue(check_status_mock.called) + + @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task') + @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status') + def test_do_grafana(self, check_status_mock, start_async_task_mock): + env = EnvCommand() + env.do_grafana({}) + self.assertTrue(start_async_task_mock.called) + self.assertTrue(check_status_mock.called) + + @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task') + @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status') + def test_do_prepare(self, check_status_mock, start_async_task_mock): + env = EnvCommand() + env.do_prepare({}) + self.assertTrue(start_async_task_mock.called) + self.assertTrue(check_status_mock.called) + + @mock.patch('yardstick.cmd.commands.env.HttpClient.post') + def test_start_async_task(self, post_mock): + data = {'action': 'create_grafana'} + EnvCommand()._start_async_task(data) + self.assertTrue(post_mock.called) + + @mock.patch('yardstick.cmd.commands.env.HttpClient.get') + @mock.patch('yardstick.cmd.commands.env.EnvCommand._print_status') + def test_check_status(self, print_mock, get_mock): + # pylint: disable=unused-argument + # NOTE(ralonsoh): the pylint exception must be removed. The mocked + # command call must be tested. + task_id = str(uuid.uuid4()) + get_mock.return_value = {'status': 2, 'result': 'error'} + status = EnvCommand()._check_status(task_id, 'hello world') + self.assertEqual(status, 2) + + def test_print_status(self): + try: + EnvCommand()._print_status('hello', 'word') + except Exception as e: # pylint: disable=broad-except + # NOTE(ralonsoh): try to reduce the scope of this exception. + self.assertIsInstance(e, IndexError) + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/yardstick/tests/unit/test_cmd/commands/test_testcase.py b/yardstick/tests/unit/test_cmd/commands/test_testcase.py new file mode 100644 index 000000000..7ef157c19 --- /dev/null +++ b/yardstick/tests/unit/test_cmd/commands/test_testcase.py @@ -0,0 +1,29 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 yardstick.cmd.commands.testcase import TestcaseCommands + + +class TestcaseCommandsUT(unittest.TestCase): + @patch('yardstick.cmd.commands.testcase.TestcaseCommands._format_print') + @patch('yardstick.cmd.commands.client') + def test_do_list(self, mock_client, mock_print): + mock_client.get.return_value = {'result': []} + TestcaseCommands().do_list({}) + self.assertTrue(mock_print.called) + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/yardstick/tests/unit/test_cmd/test_NSBperf.py b/yardstick/tests/unit/test_cmd/test_NSBperf.py new file mode 100644 index 000000000..483e82a13 --- /dev/null +++ b/yardstick/tests/unit/test_cmd/test_NSBperf.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +# Copyright (c) 2016-2017 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from __future__ import absolute_import +import unittest +import mock +import subprocess +import os + +from yardstick.cmd.NSBperf import YardstickNSCli +from yardstick.cmd import NSBperf + + +@mock.patch('six.moves.input', return_value='0') +class TestHandler(unittest.TestCase): + + def test_handler(self, *args): + subprocess.call = mock.Mock(return_value=0) + self.assertRaises(SystemExit, NSBperf.sigint_handler) + + +class TestYardstickNSCli(unittest.TestCase): + def test___init__(self): + yardstick_ns_cli = YardstickNSCli() + self.assertIsNotNone(yardstick_ns_cli) + + def test_generate_final_report(self): + yardstick_ns_cli = YardstickNSCli() + test_case = "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml" + if os.path.isfile("/tmp/yardstick.out"): + os.remove('/tmp/yardstick.out') + self.assertIsNone(yardstick_ns_cli.generate_final_report(test_case)) + + def test_generate_kpi_results(self): + yardstick_ns_cli = YardstickNSCli() + tkey = "cpu" + tgen = {"cpu": {"ipc": 0}} + self.assertIsNone(yardstick_ns_cli.generate_kpi_results(tkey, tgen)) + + def test_generate_nfvi_results(self): + yardstick_ns_cli = YardstickNSCli() + nfvi = {"collect_stats": {"cpu": {"ipc": 0, "Hz": 2.6}}} + self.assertIsNone(yardstick_ns_cli.generate_nfvi_results(nfvi)) + + def test_handle_list_options(self): + yardstick_ns_cli = YardstickNSCli() + CLI_PATH = os.path.dirname(os.path.realpath(__file__)) + repo_dir = CLI_PATH + "/../../../" + test_path = os.path.join(repo_dir, "../samples/vnf_samples/nsut/") + args = {"list_vnfs": True, "list": False} + self.assertRaises(SystemExit, yardstick_ns_cli.handle_list_options, + args, test_path) + args = {"list_vnfs": False, "list": True} + self.assertRaises(SystemExit, + yardstick_ns_cli.handle_list_options, + args, test_path) + + def test_main(self): + yardstick_ns_cli = YardstickNSCli() + yardstick_ns_cli.parse_arguments = mock.Mock(return_value=0) + yardstick_ns_cli.handle_list_options = mock.Mock(return_value=0) + yardstick_ns_cli.terminate_if_less_options = mock.Mock(return_value=0) + yardstick_ns_cli.run_test = mock.Mock(return_value=0) + self.assertIsNone(yardstick_ns_cli.main()) + + def test_parse_arguments(self): + yardstick_ns_cli = YardstickNSCli() + self.assertRaises(SystemExit, yardstick_ns_cli.parse_arguments) + + def test_run_test(self): + cur_dir = os.getcwd() + CLI_PATH = os.path.dirname(os.path.realpath(__file__)) + YARDSTICK_REPOS_DIR = os.path.join(CLI_PATH + "/../../") + test_path = os.path.join(YARDSTICK_REPOS_DIR, + "../samples/vnf_samples/nsut/") + yardstick_ns_cli = YardstickNSCli() + subprocess.check_output = mock.Mock(return_value=0) + args = {"vnf": "vpe", + "test": "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml"} + self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path)) + os.chdir(cur_dir) + args = {"vnf": "vpe1"} + self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path)) + os.chdir(cur_dir) + args = {"vnf": "vpe", + "test": "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml."} + self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path)) + os.chdir(cur_dir) + args = [] + self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path)) + os.chdir(cur_dir) + + def test_terminate_if_less_options(self): + yardstick_ns_cli = YardstickNSCli() + args = {"vnf": False} + self.assertRaises(SystemExit, + yardstick_ns_cli.terminate_if_less_options, args) + + def test_validate_input(self): + yardstick_ns_cli = YardstickNSCli() + self.assertEqual(1, yardstick_ns_cli.validate_input("", 4)) + NSBperf.input = lambda _: 'yes' + self.assertEqual(1, yardstick_ns_cli.validate_input(5, 4)) + subprocess.call = mock.Mock(return_value=0) + self.assertEqual(0, yardstick_ns_cli.validate_input(2, 4)) + subprocess.call = mock.Mock(return_value=0) |