diff options
Diffstat (limited to 'vnftest')
20 files changed, 783 insertions, 287 deletions
diff --git a/vnftest/cmd/NSBperf.py b/vnftest/cmd/NSBperf.py deleted file mode 100755 index 40a157b..0000000 --- a/vnftest/cmd/NSBperf.py +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# Copyright 2018 EuropeanSoftwareMarketingLtd. -# =================================================================== -# Licensed under the ApacheLicense, Version2.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 -# -# 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 -############################################################################## -# vnftest comment: this is a modified copy of -# yardstick/cmd/NSBperf.py - -"""NSBPERF main script. -""" - -from __future__ import absolute_import -from __future__ import print_function -import os -import argparse -import json -import subprocess -import signal -from oslo_serialization import jsonutils - -from six.moves import input - -CLI_PATH = os.path.dirname(os.path.realpath(__file__)) -REPO_PATH = os.path.abspath(os.path.join(CLI_PATH, os.pardir)) - - -def sigint_handler(*args, **kwargs): - """ Capture ctrl+c and exit cli """ - subprocess.call(["pkill", "-9", "vnftest"]) - raise SystemExit(1) - - -class VnftestNSCli(object): - """ This class handles vnftest network serivce testing """ - - def __init__(self): - super(VnftestNSCli, self).__init__() - - @classmethod - def validate_input(cls, choice, choice_len): - """ Validate user inputs """ - if not str(choice): - return 1 - - choice = int(choice) - if not 1 <= choice <= choice_len: - print("\nInvalid wrong choice...") - input("Press Enter to continue...") - return 1 - subprocess.call(['clear']) - return 0 - - @classmethod - def parse_arguments(cls): - """ - Parse command line arguments. - """ - parser = \ - argparse.ArgumentParser( - prog=__file__, - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument('--version', action='version', - version='%(prog)s 0.1') - parser.add_argument('--list', '--list-tests', action='store_true', - help='list all tests and exit') - parser.add_argument('--list-vnfs', action='store_true', - help='list all system vnfs and exit') - - group = parser.add_argument_group('test selection options') - group.add_argument('--vnf', help='vnf to use') - group.add_argument('--test', help='test in use') - - args = vars(parser.parse_args()) - - return args - - @classmethod - def generate_kpi_results(cls, tkey, tgen): - """ Generate report for vnf & traffic generator kpis """ - if tgen: - print("\n%s stats" % tkey) - print("----------------------------") - for key, value in tgen.items(): - if key != "collect_stats": - print(json.dumps({key: value}, indent=2)) - - @classmethod - def generate_nfvi_results(cls, nfvi): - """ Generate report for vnf & traffic generator kpis """ - if nfvi: - nfvi_kpi = {k: v for k, v in nfvi.items() if k == 'collect_stats'} - if nfvi_kpi: - print("\nNFVi stats") - print("----------------------------") - for key, value in nfvi_kpi.items(): - print(json.dumps({key: value}, indent=2)) - - def generate_final_report(self, test_case): - """ Function will check if partial test results are available - and generates final report in rst format. - """ - - tc_name = os.path.splitext(test_case)[0] - report_caption = '{}\n{} ({})\n{}\n\n'.format( - '================================================================', - 'Performance report for', tc_name.upper(), - '================================================================') - print(report_caption) - if os.path.isfile("/tmp/vnftest.out"): - lines = [] - with open("/tmp/vnftest.out") as infile: - lines = jsonutils.load(infile) - - if lines: - lines = \ - lines['result']["testcases"][tc_name]["tc_data"] - tc_res = lines.pop(len(lines) - 1) - for key, value in tc_res["data"].items(): - self.generate_kpi_results(key, value) - self.generate_nfvi_results(value) - - @classmethod - def handle_list_options(cls, args, test_path): - """ Process --list cli arguments if needed - - :param args: A dictionary with all CLI arguments - """ - if args['list_vnfs']: - vnfs = os.listdir(test_path) - print("VNF :") - print("================") - for index, vnf in enumerate(vnfs, 1): - print((' %-2s %s' % ('%s:' % str(index), vnf))) - raise SystemExit(0) - - if args['list']: - vnfs = os.listdir(test_path) - - print("Available Tests:") - print("*****************") - for vnf in vnfs: - testcases = os.listdir(test_path + vnf) - print(("VNF :(%s)" % vnf)) - print("================") - test_cases = [tc for tc in testcases if "tc_" in tc and "template" not in tc] - - print("\tBareMetal Testcase:") - print("\t===================") - for testcase in [tc for tc in test_cases if "baremetal" in tc]: - print("\t%s" % testcase) - - print(os.linesep) - print("\tStandalone Virtualization Testcase:") - print("\t===================================") - for testcase in [tc for tc in test_cases if "ovs" in tc or "sriov" in tc]: - print("\t%s" % testcase) - - print(os.linesep) - print("\tOpenstack Testcase:") - print("\t===================") - for testcase in [tc for tc in test_cases if "heat" in tc]: - print("\t%s" % testcase) - print(os.linesep) - raise SystemExit(0) - - @classmethod - def terminate_if_less_options(cls, args): - """ terminate cli if cmdline options is invalid """ - if not (args["vnf"] and args["test"]): - print("CLI needs option, make sure to pass vnf, test") - print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>") - raise SystemExit(1) - - def run_test(self, args, test_path): - """ run requested test """ - try: - vnf = args.get("vnf", "") - test = args.get("test", "") - - vnf_dir = test_path + os.sep + vnf - if not os.path.exists(vnf_dir): - raise ValueError("'%s', vnf not supported." % vnf) - - testcases = [tc for tc in os.listdir(vnf_dir) if "tc" in tc] - subtest = set([test]).issubset(testcases) - if not subtest: - raise ValueError("'%s', testcase not supported." % test) - - os.chdir(vnf_dir) - # fixme: Use REST APIs to initiate testcases - subprocess.check_output(["vnftest", "--debug", - "task", "start", test]) - self.generate_final_report(test) - except (IOError, ValueError): - print("Value/I/O error...") - except BaseException: - print("Test failed. Please verify test inputs & re-run the test..") - print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>") - - def main(self): - """Main function. - """ - test_path = os.path.join(REPO_PATH, "../samples/vnf_samples/nsut/") - os.chdir(os.path.join(REPO_PATH, "../")) - args = self.parse_arguments() - - # if required, handle list-* operations - self.handle_list_options(args, test_path) - - # check for input params - self.terminate_if_less_options(args) - - # run test - self.run_test(args, test_path) - -if __name__ == "__main__": - signal.signal(signal.SIGINT, sigint_handler) - NS_CLI = VnftestNSCli() - NS_CLI.main() diff --git a/vnftest/core/report.py b/vnftest/core/report.py index bb791dc..b8f8bb7 100644 --- a/vnftest/core/report.py +++ b/vnftest/core/report.py @@ -18,14 +18,14 @@ from __future__ import absolute_import from __future__ import print_function -import ast +# import ast import re import uuid from django.conf import settings from django.template import Context from django.template import Template -from oslo_utils import encodeutils +# from oslo_utils import encodeutils from oslo_utils import uuidutils from vnftest.common import constants as consts @@ -37,8 +37,6 @@ settings.configure() class Report(object): """Report commands. - - Set of commands to manage benchmark tasks. """ def __init__(self): @@ -83,39 +81,39 @@ class Report(object): """Start report generation.""" self._validate(args.yaml_name[0], args.task_id[0]) - self.db_fieldkeys = self._get_fieldkeys() + # self.db_fieldkeys = self._get_fieldkeys() - self.db_task = self._get_tasks() + # self.db_task = self._get_tasks() - field_keys = [] + # field_keys = [] temp_series = [] table_vals = {} - field_keys = [encodeutils.to_utf8(field['fieldKey']) - for field in self.db_fieldkeys] - - for key in field_keys: - self.Timestamp = [] - series = {} - values = [] - for task in self.db_task: - task_time = encodeutils.to_utf8(task['time']) - if not isinstance(task_time, str): - task_time = str(task_time, 'utf8') - key = str(key, 'utf8') - task_time = task_time[11:] - head, sep, tail = task_time.partition('.') - task_time = head + "." + tail[:6] - self.Timestamp.append(task_time) - if isinstance(task[key], float) is True: - values.append(task[key]) - else: - values.append(ast.literal_eval(task[key])) - table_vals['Timestamp'] = self.Timestamp - table_vals[key] = values - series['name'] = key - series['data'] = values - temp_series.append(series) + # field_keys = [encodeutils.to_utf8(field['fieldKey']) + # for field in self.db_fieldkeys] + + # for key in field_keys: + # self.Timestamp = [] + # series = {} + # values = [] + # for task in self.db_task: + # task_time = encodeutils.to_utf8(task['time']) + # if not isinstance(task_time, str): + # task_time = str(task_time, 'utf8') + # key = str(key, 'utf8') + # task_time = task_time[11:] + # head, sep, tail = task_time.partition('.') + # task_time = head + "." + tail[:6] + # self.Timestamp.append(task_time) + # if isinstance(task[key], float) is True: + # values.append(task[key]) + # else: + # values.append(ast.literal_eval(task[key])) + # table_vals['Timestamp'] = self.Timestamp + # table_vals[key] = values + # series['name'] = key + # series['data'] = values + # temp_series.append(series) Template_html = Template(template) Context_html = Context({"series": temp_series, diff --git a/vnftest/core/task.py b/vnftest/core/task.py index a2963a5..8ce897b 100644 --- a/vnftest/core/task.py +++ b/vnftest/core/task.py @@ -258,7 +258,8 @@ class Task(object): # pragma: no cover def _run(self, steps, run_in_parallel, output_file): """Deploys context and calls runners""" - self.context.deploy() + if self.context: + self.context.deploy() background_runners = [] result = [] @@ -547,31 +548,6 @@ def _is_background_step(step): return False -def parse_nodes_with_context(step_cfg): - """parse the 'nodes' fields in step """ - # ensure consistency in node instantiation order - return OrderedDict((nodename, Context.get_server(step_cfg["nodes"][nodename])) - for nodename in sorted(step_cfg["nodes"])) - - -def get_networks_from_nodes(nodes): - """parse the 'nodes' fields in step """ - networks = {} - for node in nodes.values(): - if not node: - continue - interfaces = node.get('interfaces', {}) - for interface in interfaces.values(): - # vld_id is network_name - network_name = interface.get('network_name') - if not network_name: - continue - network = Context.get_network(network_name) - if network: - networks[network['name']] = network - return networks - - def runner_join(runner, background_runners, outputs, result): """join (wait for) a runner, exit process at runner failure :param background_runners: diff --git a/vnftest/resources/__init__.py b/vnftest/resources/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vnftest/resources/__init__.py diff --git a/vnftest/resources/scripts/install/sample.bash b/vnftest/resources/scripts/install/sample.bash new file mode 100644 index 0000000..de1af20 --- /dev/null +++ b/vnftest/resources/scripts/install/sample.bash @@ -0,0 +1,25 @@ +#!/bin/bash + +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/resources/scripts/install/sample.bash + +# Sample plugin installation script + +set -e + +cat > test.sh <<EOF +echo "{\"Test Output\": \"Hello world!\"}" +EOF diff --git a/vnftest/resources/scripts/remove/sample.bash b/vnftest/resources/scripts/remove/sample.bash new file mode 100644 index 0000000..576d9a7 --- /dev/null +++ b/vnftest/resources/scripts/remove/sample.bash @@ -0,0 +1,21 @@ +#!/bin/bash + +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/resources/scripts/remove/sample.bash + +set -e + +rm test.sh diff --git a/vnftest/steps/dummy/dummy.py b/vnftest/steps/dummy/dummy.py index 650fdb4..53a5dae 100644 --- a/vnftest/steps/dummy/dummy.py +++ b/vnftest/steps/dummy/dummy.py @@ -35,7 +35,6 @@ class Dummy(base.Step): self.setup_done = True def run(self, result): - """execute the benchmark""" if not self.setup_done: self.setup() diff --git a/vnftest/tests/__init__.py b/vnftest/tests/__init__.py new file mode 100644 index 0000000..061e263 --- /dev/null +++ b/vnftest/tests/__init__.py @@ -0,0 +1,77 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/__init__.py + +import mock + + +STL_MOCKS = { + 'trex_stl_lib': mock.MagicMock(), + 'trex_stl_lib.base64': mock.MagicMock(), + 'trex_stl_lib.binascii': mock.MagicMock(), + 'trex_stl_lib.collections': mock.MagicMock(), + 'trex_stl_lib.copy': mock.MagicMock(), + 'trex_stl_lib.datetime': mock.MagicMock(), + 'trex_stl_lib.functools': mock.MagicMock(), + 'trex_stl_lib.imp': mock.MagicMock(), + 'trex_stl_lib.inspect': mock.MagicMock(), + 'trex_stl_lib.json': mock.MagicMock(), + 'trex_stl_lib.linecache': mock.MagicMock(), + 'trex_stl_lib.math': mock.MagicMock(), + 'trex_stl_lib.os': mock.MagicMock(), + 'trex_stl_lib.platform': mock.MagicMock(), + 'trex_stl_lib.pprint': mock.MagicMock(), + 'trex_stl_lib.random': mock.MagicMock(), + 'trex_stl_lib.re': mock.MagicMock(), + 'trex_stl_lib.scapy': mock.MagicMock(), + 'trex_stl_lib.socket': mock.MagicMock(), + 'trex_stl_lib.string': mock.MagicMock(), + 'trex_stl_lib.struct': mock.MagicMock(), + 'trex_stl_lib.sys': mock.MagicMock(), + 'trex_stl_lib.threading': mock.MagicMock(), + 'trex_stl_lib.time': mock.MagicMock(), + 'trex_stl_lib.traceback': mock.MagicMock(), + 'trex_stl_lib.trex_stl_async_client': mock.MagicMock(), + 'trex_stl_lib.trex_stl_client': mock.MagicMock(), + 'trex_stl_lib.trex_stl_exceptions': mock.MagicMock(), + 'trex_stl_lib.trex_stl_ext': mock.MagicMock(), + 'trex_stl_lib.trex_stl_jsonrpc_client': mock.MagicMock(), + 'trex_stl_lib.trex_stl_packet_builder_interface': mock.MagicMock(), + 'trex_stl_lib.trex_stl_packet_builder_scapy': mock.MagicMock(), + 'trex_stl_lib.trex_stl_port': mock.MagicMock(), + 'trex_stl_lib.trex_stl_stats': mock.MagicMock(), + 'trex_stl_lib.trex_stl_streams': mock.MagicMock(), + 'trex_stl_lib.trex_stl_types': mock.MagicMock(), + 'trex_stl_lib.types': mock.MagicMock(), + 'trex_stl_lib.utils': mock.MagicMock(), + 'trex_stl_lib.utils.argparse': mock.MagicMock(), + 'trex_stl_lib.utils.collections': mock.MagicMock(), + 'trex_stl_lib.utils.common': mock.MagicMock(), + 'trex_stl_lib.utils.json': mock.MagicMock(), + 'trex_stl_lib.utils.os': mock.MagicMock(), + 'trex_stl_lib.utils.parsing_opts': mock.MagicMock(), + 'trex_stl_lib.utils.pwd': mock.MagicMock(), + 'trex_stl_lib.utils.random': mock.MagicMock(), + 'trex_stl_lib.utils.re': mock.MagicMock(), + 'trex_stl_lib.utils.string': mock.MagicMock(), + 'trex_stl_lib.utils.sys': mock.MagicMock(), + 'trex_stl_lib.utils.text_opts': mock.MagicMock(), + 'trex_stl_lib.utils.text_tables': mock.MagicMock(), + 'trex_stl_lib.utils.texttable': mock.MagicMock(), + 'trex_stl_lib.warnings': mock.MagicMock(), + 'trex_stl_lib.yaml': mock.MagicMock(), + 'trex_stl_lib.zlib': mock.MagicMock(), + 'trex_stl_lib.zmq': mock.MagicMock(), +} diff --git a/vnftest/tests/fixture.py b/vnftest/tests/fixture.py new file mode 100644 index 0000000..ef19cfd --- /dev/null +++ b/vnftest/tests/fixture.py @@ -0,0 +1,48 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/fixture.py + +import fixtures +import mock +import six + +from vnftest.common import task_template + + +class PluginParserFixture(fixtures.Fixture): + """PluginParser fixture. + + This class is intended to be used as a fixture within unit tests and + therefore consumers must register it using useFixture() within their + unit test class. + """ + + def __init__(self, rendered_plugin): + super(PluginParserFixture, self).__init__() + self._rendered_plugin = rendered_plugin + + def _setUp(self): + self.addCleanup(self._restore) + self._mock_tasktemplate_render = mock.patch.object( + task_template.TaskTemplate, 'render') + self.mock_tasktemplate_render = self._mock_tasktemplate_render.start() + self.mock_tasktemplate_render.return_value = self._rendered_plugin + self._mock_open = mock.patch.object(six.moves.builtins, 'open', create=True) + self.mock_open = self._mock_open.start() + self.mock_open.side_effect = mock.mock_open() + + def _restore(self): + self._mock_tasktemplate_render.stop() + self._mock_open.stop() diff --git a/vnftest/tests/unit/core/__init__.py b/vnftest/tests/unit/core/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vnftest/tests/unit/core/__init__.py diff --git a/vnftest/tests/unit/core/no_constraint_no_args_step_sample.yaml b/vnftest/tests/unit/core/no_constraint_no_args_step_sample.yaml new file mode 100644 index 0000000..4272d70 --- /dev/null +++ b/vnftest/tests/unit/core/no_constraint_no_args_step_sample.yaml @@ -0,0 +1,28 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/no_constraint_no_args_scenario_sample.yaml + +--- + +schema: "vnftest:suite:0.1" + +name: "suite_1" +test_cases_dir: "tests/onap/test_cases/" +test_cases: +- + file_name: onap_vnftest_tc001.yaml +- + file_name: onap_vnftest_tc002.yaml + diff --git a/vnftest/tests/unit/core/no_constraint_with_args_step_sample.yaml b/vnftest/tests/unit/core/no_constraint_with_args_step_sample.yaml new file mode 100644 index 0000000..3667230 --- /dev/null +++ b/vnftest/tests/unit/core/no_constraint_with_args_step_sample.yaml @@ -0,0 +1,30 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/no_constraint_with_args_scenario_sample.yaml + +--- + +schema: "vnftest:suite:0.1" + +name: "suite_1" +test_cases_dir: "tests/onap/test_cases/" +test_cases: +- + file_name: onap_vnftest_tc001.yaml +- + file_name: onap_vnftest_tc002.yaml + task_args: + huawei-pod1: '{"host": "node1.LF","target": "node2.LF"}' + diff --git a/vnftest/tests/unit/core/test_plugin.py b/vnftest/tests/unit/core/test_plugin.py new file mode 100644 index 0000000..6f1bff8 --- /dev/null +++ b/vnftest/tests/unit/core/test_plugin.py @@ -0,0 +1,149 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/test_plugin.py + +import copy +import os +import pkg_resources + +import mock +import testtools + +from vnftest import ssh +from vnftest.core import plugin +from vnftest.tests import fixture + + +class PluginTestCase(testtools.TestCase): + + FILE = """ +schema: "vnftest:plugin:0.1" + +plugins: + name: sample + +deployment: + ip: 10.1.0.50 + user: root + password: root +""" + + NAME = 'sample' + DEPLOYMENT = {'ip': '10.1.0.50', 'user': 'root', 'password': 'root'} + + def setUp(self): + super(PluginTestCase, self).setUp() + self.plugin_parser = plugin.PluginParser(mock.Mock()) + self.plugin = plugin.Plugin() + self.useFixture(fixture.PluginParserFixture(PluginTestCase.FILE)) + + self._mock_ssh_from_node = mock.patch.object(ssh.SSH, 'from_node') + self.mock_ssh_from_node = self._mock_ssh_from_node.start() + self.mock_ssh_obj = mock.Mock() + self.mock_ssh_from_node.return_value = self.mock_ssh_obj + self.mock_ssh_obj.wait = mock.Mock() + self.mock_ssh_obj._put_file_shell = mock.Mock() + + self.addCleanup(self._cleanup) + + def _cleanup(self): + self._mock_ssh_from_node.stop() + + def test_install(self): + args = mock.Mock() + args.input_file = [mock.Mock()] + with mock.patch.object(self.plugin, '_install_setup') as \ + mock_install, \ + mock.patch.object(self.plugin, '_run') as mock_run: + self.plugin.install(args) + mock_install.assert_called_once_with(PluginTestCase.NAME, + PluginTestCase.DEPLOYMENT) + mock_run.assert_called_once_with(PluginTestCase.NAME) + + def test_remove(self): + args = mock.Mock() + args.input_file = [mock.Mock()] + with mock.patch.object(self.plugin, '_remove_setup') as \ + mock_remove, \ + mock.patch.object(self.plugin, '_run') as mock_run: + self.plugin.remove(args) + mock_remove.assert_called_once_with(PluginTestCase.NAME, + PluginTestCase.DEPLOYMENT) + mock_run.assert_called_once_with(PluginTestCase.NAME) + + @mock.patch.object(pkg_resources, 'resource_filename', + return_value='script') + def test__install_setup(self, mock_resource_filename): + plugin_name = 'plugin_name' + self.plugin._install_setup(plugin_name, PluginTestCase.DEPLOYMENT) + mock_resource_filename.assert_called_once_with( + 'vnftest.resources', 'scripts/install/' + plugin_name + '.bash') + self.mock_ssh_from_node.assert_called_once_with( + PluginTestCase.DEPLOYMENT) + self.mock_ssh_obj.wait.assert_called_once_with(timeout=600) + self.mock_ssh_obj._put_file_shell.assert_called_once_with( + 'script', '~/{0}.sh'.format(plugin_name)) + + @mock.patch.object(pkg_resources, 'resource_filename', + return_value='script') + @mock.patch.object(os, 'environ', return_value='1.2.3.4') + def test__install_setup_with_ip_local(self, mock_os_environ, + mock_resource_filename): + plugin_name = 'plugin_name' + deployment = copy.deepcopy(PluginTestCase.DEPLOYMENT) + deployment['ip'] = 'local' + self.plugin._install_setup(plugin_name, deployment) + mock_os_environ.__getitem__.assert_called_once_with('JUMP_HOST_IP') + mock_resource_filename.assert_called_once_with( + 'vnftest.resources', + 'scripts/install/' + plugin_name + '.bash') + self.mock_ssh_from_node.assert_called_once_with( + deployment, overrides={'ip': os.environ["JUMP_HOST_IP"]}) + self.mock_ssh_obj.wait.assert_called_once_with(timeout=600) + self.mock_ssh_obj._put_file_shell.assert_called_once_with( + 'script', '~/{0}.sh'.format(plugin_name)) + + @mock.patch.object(pkg_resources, 'resource_filename', + return_value='script') + def test__remove_setup(self, mock_resource_filename): + plugin_name = 'plugin_name' + self.plugin._remove_setup(plugin_name, PluginTestCase.DEPLOYMENT) + mock_resource_filename.assert_called_once_with( + 'vnftest.resources', + 'scripts/remove/' + plugin_name + '.bash') + self.mock_ssh_from_node.assert_called_once_with( + PluginTestCase.DEPLOYMENT) + self.mock_ssh_obj.wait.assert_called_once_with(timeout=600) + self.mock_ssh_obj._put_file_shell.assert_called_once_with( + 'script', '~/{0}.sh'.format(plugin_name)) + + @mock.patch.object(pkg_resources, 'resource_filename', + return_value='script') + @mock.patch.object(os, 'environ', return_value='1.2.3.4') + def test__remove_setup_with_ip_local(self, mock_os_environ, + mock_resource_filename): + plugin_name = 'plugin_name' + deployment = copy.deepcopy(PluginTestCase.DEPLOYMENT) + deployment['ip'] = 'local' + self.plugin._remove_setup(plugin_name, deployment) + mock_os_environ.__getitem__.assert_called_once_with('JUMP_HOST_IP') + mock_resource_filename.assert_called_once_with( + 'vnftest.resources', + 'scripts/remove/' + plugin_name + '.bash') + self.mock_ssh_from_node.assert_called_once_with( + deployment, overrides={'ip': os.environ["JUMP_HOST_IP"]}) + self.mock_ssh_obj.wait.assert_called_once_with(timeout=600) + self.mock_ssh_obj._put_file_shell.mock_os_environ( + 'script', '~/{0}.sh'.format(plugin_name)) diff --git a/vnftest/tests/unit/core/test_report.py b/vnftest/tests/unit/core/test_report.py new file mode 100644 index 0000000..0bb17e3 --- /dev/null +++ b/vnftest/tests/unit/core/test_report.py @@ -0,0 +1,59 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/test_report.py + +from __future__ import print_function + +from __future__ import absolute_import + +import unittest +import uuid + +try: + from unittest import mock +except ImportError: + import mock + +from vnftest.core import report +from vnftest.cmd.commands import change_osloobj_to_paras + +FAKE_YAML_NAME = 'fake_name' +FAKE_TASK_ID = str(uuid.uuid4()) +DUMMY_TASK_ID = 'aaaaaa-aaaaaaaa-aaaaaaaaaa-aaaaaa' + + +class ReportTestCase(unittest.TestCase): + + def setUp(self): + super(ReportTestCase, self).setUp() + self.param = change_osloobj_to_paras({}) + self.param.yaml_name = [FAKE_YAML_NAME] + self.param.task_id = [FAKE_TASK_ID] + self.rep = report.Report() + + @mock.patch('vnftest.core.report.Report._validate') + def test_generate_success(self, mock_valid): + self.rep.generate(self.param) + mock_valid.assert_called_once_with(FAKE_YAML_NAME, FAKE_TASK_ID) + + # pylint: disable=deprecated-method + def test_invalid_yaml_name(self): + self.assertRaisesRegexp(ValueError, "yaml*", self.rep._validate, + 'F@KE_NAME', FAKE_TASK_ID) + + # pylint: disable=deprecated-method + def test_invalid_task_id(self): + self.assertRaisesRegexp(ValueError, "task*", self.rep._validate, + FAKE_YAML_NAME, DUMMY_TASK_ID) diff --git a/vnftest/tests/unit/core/test_task.py b/vnftest/tests/unit/core/test_task.py new file mode 100644 index 0000000..b136960 --- /dev/null +++ b/vnftest/tests/unit/core/test_task.py @@ -0,0 +1,150 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/test_task.py + +import unittest + +import mock +import os + +from vnftest.common import constants as consts +from vnftest.core import task + + +class TaskTestCase(unittest.TestCase): + + def test_set_dispatchers(self): + t = task.Task() + output_config = {"DEFAULT": {"dispatcher": "file, http"}} + t._set_dispatchers(output_config) + self.assertEqual(output_config, output_config) + + @mock.patch.object(task, 'DispatcherBase') + def test__do_output(self, mock_dispatcher): + t = task.Task() + output_config = {"DEFAULT": {"dispatcher": "file, http"}} + + dispatcher1 = mock.MagicMock() + dispatcher1.__dispatcher_type__ = 'file' + + dispatcher2 = mock.MagicMock() + dispatcher2.__dispatcher_type__ = 'http' + + mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1, + dispatcher2]) + self.assertIsNone(t._do_output(output_config, {})) + + @mock.patch.object(task, 'Context') + @mock.patch.object(task, 'base_runner') + def test_run(self, mock_base_runner, *args): + step = { + 'runner': { + 'duration': 60, + 'interval': 1, + 'type': 'Duration' + }, + 'type': 'Dummy' + } + + t = task.Task() + runner = mock.Mock() + runner.join.return_value = 0 + runner.get_output.return_value = {} + runner.get_result.return_value = [] + mock_base_runner.Runner.get.return_value = runner + t._run([step], False, "vnftest.out") + self.assertTrue(runner.run.called) + + def test_parse_suite_no_constraint_no_args(self): + SAMPLE_step_PATH = "no_constraint_no_args_step_sample.yaml" + t = task.TaskParser(self._get_file_abspath(SAMPLE_step_PATH)) + with mock.patch.object(os, 'environ', + new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}): + task_files, task_args, task_args_fnames = t.parse_suite() + + self.assertEqual(task_files[0], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc001.yaml')) + self.assertEqual(task_files[1], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc002.yaml')) + self.assertIsNone(task_args[0]) + self.assertIsNone(task_args[1]) + self.assertIsNone(task_args_fnames[0]) + self.assertIsNone(task_args_fnames[1]) + + def test_parse_suite_no_constraint_with_args(self): + SAMPLE_step_PATH = "no_constraint_with_args_step_sample.yaml" + t = task.TaskParser(self._get_file_abspath(SAMPLE_step_PATH)) + with mock.patch.object(os, 'environ', + new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}): + task_files, task_args, task_args_fnames = t.parse_suite() + + self.assertEqual(task_files[0], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc001.yaml')) + self.assertEqual(task_files[1], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc002.yaml')) + self.assertIsNone(task_args[0]) + self.assertEqual(task_args[1], + '{"host": "node1.LF","target": "node2.LF"}') + self.assertIsNone(task_args_fnames[0]) + self.assertIsNone(task_args_fnames[1]) + + def test_parse_suite_with_constraint_no_args(self): + SAMPLE_step_PATH = "with_constraint_no_args_step_sample.yaml" + t = task.TaskParser(self._get_file_abspath(SAMPLE_step_PATH)) + with mock.patch.object(os, 'environ', + new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}): + task_files, task_args, task_args_fnames = t.parse_suite() + self.assertEqual(task_files[0], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc001.yaml')) + self.assertEqual(task_files[1], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc002.yaml')) + self.assertIsNone(task_args[0]) + self.assertIsNone(task_args[1]) + self.assertIsNone(task_args_fnames[0]) + self.assertIsNone(task_args_fnames[1]) + + def test_parse_suite_with_constraint_with_args(self): + SAMPLE_step_PATH = "with_constraint_with_args_step_sample.yaml" + t = task.TaskParser(self._get_file_abspath(SAMPLE_step_PATH)) + with mock.patch('os.environ', + new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}): + task_files, task_args, task_args_fnames = t.parse_suite() + + self.assertEqual(task_files[0], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc001.yaml')) + self.assertEqual(task_files[1], self.change_to_abspath( + 'tests/onap/test_cases/onap_vnftest_tc002.yaml')) + self.assertIsNone(task_args[0]) + self.assertEqual(task_args[1], + '{"host": "node1.LF","target": "node2.LF"}') + self.assertIsNone(task_args_fnames[0]) + self.assertIsNone(task_args_fnames[1]) + + @mock.patch('six.moves.builtins.open', side_effect=mock.mock_open()) + @mock.patch.object(task, 'utils') + @mock.patch('logging.root') + def test_set_log(self, mock_logging_root, *args): + task_obj = task.Task() + task_obj.task_id = 'task_id' + task_obj._set_log() + mock_logging_root.addHandler.assert_called() + + def _get_file_abspath(self, filename): + curr_path = os.path.dirname(os.path.abspath(__file__)) + file_path = os.path.join(curr_path, filename) + return file_path + + def change_to_abspath(self, filepath): + return os.path.join(consts.VNFTEST_ROOT_PATH, filepath) diff --git a/vnftest/tests/unit/core/test_testcase.py b/vnftest/tests/unit/core/test_testcase.py new file mode 100644 index 0000000..0ba4873 --- /dev/null +++ b/vnftest/tests/unit/core/test_testcase.py @@ -0,0 +1,40 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/test_testcase.py + +from __future__ import absolute_import +import unittest + +from vnftest.core import testcase + + +class Arg(object): + + def __init__(self): + self.casename = ('onap_vnftest_tc001',) + + +class TestcaseUT(unittest.TestCase): + + def test_list_all(self): + t = testcase.Testcase() + result = t.list_all("") + self.assertIsInstance(result, list) + + def test_show(self): + t = testcase.Testcase() + casename = Arg() + result = t.show(casename) + self.assertTrue(result) diff --git a/vnftest/tests/unit/core/with_constraint_no_args_step_sample.yaml b/vnftest/tests/unit/core/with_constraint_no_args_step_sample.yaml new file mode 100644 index 0000000..f9524fb --- /dev/null +++ b/vnftest/tests/unit/core/with_constraint_no_args_step_sample.yaml @@ -0,0 +1,31 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/with_constraint_no_args_scenario_sample.yaml + +--- + +schema: "vnftest:suite:0.1" + +name: "suite_1" +test_cases_dir: "tests/onap/test_cases/" +test_cases: +- + file_name: onap_vnftest_tc001.yaml +- + file_name: onap_vnftest_tc002.yaml + constraint: + installer: compass + pod: huawei-pod1 + diff --git a/vnftest/tests/unit/core/with_constraint_with_args_step_sample.yaml b/vnftest/tests/unit/core/with_constraint_with_args_step_sample.yaml new file mode 100644 index 0000000..53c8390 --- /dev/null +++ b/vnftest/tests/unit/core/with_constraint_with_args_step_sample.yaml @@ -0,0 +1,33 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## +# vnftest comment: this is a modified copy of +# yardstick/tests/unit/benchmark/core/with_constraint_with_args_scenario_sample.yaml + +--- + +schema: "vnftest:suite:0.1" + +name: "suite_1" +test_cases_dir: "tests/onap/test_cases/" +test_cases: +- + file_name: onap_vnftest_tc001.yaml +- + file_name: onap_vnftest_tc002.yaml + constraint: + installer: compass + pod: huawei-pod1 + task_args: + huawei-pod1: '{"host": "node1.LF","target": "node2.LF"}' + diff --git a/vnftest/tests/unit/onap/__init__.py b/vnftest/tests/unit/onap/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vnftest/tests/unit/onap/__init__.py diff --git a/vnftest/tests/unit/onap/test_onap_api_call.py b/vnftest/tests/unit/onap/test_onap_api_call.py new file mode 100644 index 0000000..2b6d79d --- /dev/null +++ b/vnftest/tests/unit/onap/test_onap_api_call.py @@ -0,0 +1,60 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 mock +import testtools + +from vnftest.contexts.base import Context +from vnftest.core import task +from vnftest.onap.onap_api_call import OnapApiCall + + +class OnapApiCallTestCase(testtools.TestCase): + + step = { + 'type': 'OnapApiCall', + 'options': { + 'file': "dummy.yaml", + 'input': + [{ + 'parameter_name': "input1", + 'value': "value1" + }], + 'output': + [{ + 'parameter_name': "output1", + 'value': "[value]" + }]}, + 'sla': { + 'action': 'assert', + 'value': "{output1}", + 'equals': "output1", + 'retries': 5, + 'interval': 5} + } + NAME = 'sample' + + def setUp(self): + super(OnapApiCallTestCase, self).setUp() + + @mock.patch('vnftest.onap.onap_api_call.OnapApiCall.execute_operation_impl') + def test_run(self, mock_execute_operation): + mock_execute_operation.return_value = {'body': {'value': 'output1'}} + t = task.Task() + context_cfg = {} + context = Context.get("CSAR") + context.init(context_cfg) + t.context = context + output = t._run([OnapApiCallTestCase.step], False, "vnftest.out") + self.assertEquals(output[0]['data']['output1'], 'output1') |