From 032ff22ef20b59950a8b5fae8d2ba6d03e93ac93 Mon Sep 17 00:00:00 2001 From: Wojciech Sliwka Date: Wed, 10 Jul 2019 13:48:52 +0200 Subject: Opensourcing new version of Simulator Additional info in README.md Issue-ID: INT-1134 Signed-off-by: Wojciech Sliwka Change-Id: I06d41fd3f361b7a451b30b702882810e4136a129 --- .../pnfsimulator/simulator-cli/tests/__init__.py | 19 ++ .../tests/resources/notification.json | 15 ++ .../simulator-cli/tests/test_netconf_simulator.py | 165 +++++++++++++ .../simulator-cli/tests/test_pnf_simulator.py | 270 +++++++++++++++++++++ .../simulator-cli/tests/test_tailf_client.py | 47 ++++ 5 files changed, 516 insertions(+) create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/__init__.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/resources/notification.json create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/test_netconf_simulator.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/test_pnf_simulator.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/test_tailf_client.py (limited to 'test/mocks/pnfsimulator/simulator-cli/tests') diff --git a/test/mocks/pnfsimulator/simulator-cli/tests/__init__.py b/test/mocks/pnfsimulator/simulator-cli/tests/__init__.py new file mode 100644 index 000000000..aa8b4f995 --- /dev/null +++ b/test/mocks/pnfsimulator/simulator-cli/tests/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/test/mocks/pnfsimulator/simulator-cli/tests/resources/notification.json b/test/mocks/pnfsimulator/simulator-cli/tests/resources/notification.json new file mode 100644 index 000000000..bdba8ae59 --- /dev/null +++ b/test/mocks/pnfsimulator/simulator-cli/tests/resources/notification.json @@ -0,0 +1,15 @@ +{ + "commonEventHeader": { + "domain": "notification", + "eventName": "#RandomString(20)", + "version": "4.0.1" + }, + "notificationFields": { + "arrayOfNamedHashMap": [{ + "name": "A20161221.1031-1041.bin.gz", + "hashMap": { + "fileformatType": "org.3GPP.32.435#measCollec" + } + }] + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/simulator-cli/tests/test_netconf_simulator.py b/test/mocks/pnfsimulator/simulator-cli/tests/test_netconf_simulator.py new file mode 100644 index 000000000..46ce84623 --- /dev/null +++ b/test/mocks/pnfsimulator/simulator-cli/tests/test_netconf_simulator.py @@ -0,0 +1,165 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import logging +import unittest +import os +from mock import patch + +from cli.netconf_simulator import create_argument_parser, NetconfSimulatorClient + + +class TestArgumentParser(unittest.TestCase): + + def test_should_properly_parse_edit_config_with_all_params(self): + parser = create_argument_parser() + args = parser.parse_args( + ['edit-config', '--address', '127.0.0.1', '--config', 'sample_path', + "--verbose"] + ) + + self.assertEqual(args.address, '127.0.0.1') + self.assertEqual(args.config, 'sample_path') + self.assertTrue(args.verbose) + + def test_should_properly_parse_load_yang_model(self): + parser = create_argument_parser() + + args = parser.parse_args( + ['load-model', '--address', '127.0.0.1', '--module-name', + 'sample_name', '--yang-model', 'sample_model', '--config', + 'sample_config', + "--verbose"] + ) + + self.assertEqual(args.address, '127.0.0.1') + self.assertEqual(args.config, 'sample_config') + self.assertEqual(args.yang_model, 'sample_model') + self.assertEqual(args.module_name, 'sample_name') + self.assertTrue(args.verbose) + + def test_should_properly_parse_delete_yang_model(self): + parser = create_argument_parser() + + args = parser.parse_args( + ['delete-model', '--address', '127.0.0.1', '--model-name', + 'sample_name', "--verbose"] + ) + + self.assertEqual(args.address, '127.0.0.1') + self.assertEqual(args.model_name, 'sample_name') + self.assertTrue(args.verbose) + + def test_should_properly_parse_get_config(self): + parser = create_argument_parser() + args = parser.parse_args( + ['get-config', '--address', '127.0.0.1', '--verbose'] + ) + + self.assertEqual(args.address, '127.0.0.1') + self.assertTrue(args.verbose) + + +class TestNetconfSimulatorClient(unittest.TestCase): + + @classmethod + def setUpClass(cls): + with open("example", "w+") as f: + f.write("sampleContent") + + @classmethod + def tearDownClass(cls): + os.remove("example") + + @patch('cli.netconf_simulator.requests') + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_properly_get_config(self, logger, requests): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + client.get_config() + + requests.get.assert_called_with('http://localhost:8080/netconf/get') + + @patch('cli.netconf_simulator.requests') + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_properly_get_config_for_given_module(self, logger, requests): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + client.get_config("module", "container") + + requests.get.assert_called_with('http://localhost:8080/netconf/get/module/container') + + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_raise_exception_when_module_is_present_and_container_is_absent(self, logger): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + with self.assertRaises(AttributeError) as context: + client.get_config(module_name="test") + + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_raise_exception_when_module_is_absent_and_container_is_present(self, logger): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + with self.assertRaises(AttributeError) as context: + client.get_config(container="test") + + @patch('cli.netconf_simulator.requests') + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_properly_load_yang_model(self, logger, requests): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + client.load_yang_model('sample_module_name', 'example', 'example') + + requests.post.assert_called() + + @patch('cli.netconf_simulator.requests') + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_properly_delete_yang_model(self, logger, requests): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + client.delete_yang_model('sample_model_name') + + requests.delete.assert_called() + + @patch('cli.netconf_simulator.requests') + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_properly_edit_config(self, logger, requests): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + client.edit_config('example') + + requests.post.assert_called() + + @patch('cli.netconf_simulator.requests') + @patch('cli.netconf_simulator.NetconfSimulatorClient._configure_logger') + def test_should_properly_run_less_like_mode(self, logger, requests): + client = NetconfSimulatorClient('localhost') + client.logger = logging.getLogger() + + client.less_like_func(100) + + requests.get.assert_called_with( + params={"offset": 100}, url="http://localhost:8080/store/less") diff --git a/test/mocks/pnfsimulator/simulator-cli/tests/test_pnf_simulator.py b/test/mocks/pnfsimulator/simulator-cli/tests/test_pnf_simulator.py new file mode 100644 index 000000000..50f220038 --- /dev/null +++ b/test/mocks/pnfsimulator/simulator-cli/tests/test_pnf_simulator.py @@ -0,0 +1,270 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import json +import os +import unittest +from http.client import HTTPResponse, HTTPConnection +from unittest import mock +from unittest.mock import patch, Mock + +from cli.pnf_simulator import SimulatorClient, FullEventRequest, Messages +from cli.pnf_simulator import create_argument_parser, SimulatorParams, PersistedEventRequest + + +class TestArgumentParser(unittest.TestCase): + + def test_should_properly_parse_send_template_action_with_all_params(self): + parser = create_argument_parser() + + result = parser.parse_args( + ['send', 'template', '--address', '127.0.0.1', "--name", 'sample_template', '--patch', '"{}"', '--repeats', '2', + "--interval", '5', '--verbose', '--ves_server_url', 'sample_url']) + + self.assertEqual(result.address, '127.0.0.1') + self.assertEqual(result.name, "sample_template") + self.assertEqual(result.patch, "\"{}\"") + self.assertEqual(result.repeats, 2) + self.assertEqual(result.interval, 5) + self.assertEqual(result.ves_server_url, 'sample_url') + self.assertTrue(result.verbose) + + def test_should_properly_parse_send_event_action_with_all_params(self): + parser = create_argument_parser() + + result = parser.parse_args( + ['send', 'event', '--address', '127.0.0.1', "--filepath", 'sample_filepath.json', '--verbose', '--ves_server_url', 'sample_url']) + + self.assertEqual(result.address, '127.0.0.1') + self.assertEqual(result.filepath, "sample_filepath.json") + self.assertEqual(result.ves_server_url, 'sample_url') + self.assertTrue(result.verbose) + + def test_should_properly_parse_configure_action_with_all_params(self): + parser = create_argument_parser() + result = parser.parse_args( + ['configure', '--address', '127.0.0.1', "--verbose", '--ves-server-url', 'sample_url'] + ) + + self.assertEqual(result.address, '127.0.0.1') + self.assertTrue(result.verbose) + self.assertEqual(result.ves_server_url, 'sample_url') + + def test_should_properly_parse_get_config_action_with_all_params(self): + parser = create_argument_parser() + result = parser.parse_args( + ['get-config', '--address', '127.0.0.1', '--verbose'] + ) + + self.assertEqual(result.address, '127.0.0.1') + self.assertTrue(result.verbose) + + def test_should_not_parse_arguments_when_mandatory_params_are_missing_for_template(self): + parser = create_argument_parser() + + with self.assertRaises(SystemExit) as context: + parser.parse_args(['send', 'template']) + self.assertTrue('the following arguments are required: --address, --name' in context.exception) + + def test_should_not_parse_arguments_when_mandatory_params_are_missing_for_event(self): + parser = create_argument_parser() + + with self.assertRaises(SystemExit) as context: + parser.parse_args(['send', 'event']) + self.assertTrue('the following arguments are required: --address, --filepath' in context.exception) + + def test_should_not_parse_arguments_when_mandatory_template_params_are_missing(self): + parser = create_argument_parser() + + with self.assertRaises(SystemExit) as context: + parser.parse_args(['template']) + self.assertTrue('one of the arguments --list --get-content is required' in context.exception) + + def test_should_not_parse_template_action_with_all_params(self): + parser = create_argument_parser() + with self.assertRaises(SystemExit) as context: + parser.parse_args( + ['template', '--address', '127.0.0.1', "--list", '--get-content', 'sample'] + ) + self.assertTrue('argument --get-content: not allowed with argument --list' in context.exception) + + def test_should_properly_parse_template_action_with_list_param(self): + parser = create_argument_parser() + result = parser.parse_args( + ['template', '--address', '127.0.0.1', "--list"] + ) + + self.assertTrue(result.list) + self.assertEqual(result.address, '127.0.0.1') + self.assertFalse(result.verbose) + + def test_should_properly_parse_template_action_with_get_content_param(self): + parser = create_argument_parser() + result = parser.parse_args( + ['template', '--address', '127.0.0.1', "--get-content", "sample"] + ) + + self.assertTrue(result.get_content) + self.assertEqual(result.address, '127.0.0.1') + self.assertFalse(result.verbose) + + def test_should_not_parse_template_action_with_empty_get_content_param(self): + parser = create_argument_parser() + with self.assertRaises(SystemExit) as context: + parser.parse_args( + ['template', '--address', '127.0.0.1', "--list", '--get-content'] + ) + self.assertTrue('argument --get-content: expected one argument' in context.exception) + + def test_should_not_parse_template_action_when_only_override_is_given(self): + parser = create_argument_parser() + with self.assertRaises(SystemExit) as context: + parser.parse_args( + ['template', '--address', '127.0.0.1', "--override"] + ) + self.assertTrue(Messages.OVERRIDE_VALID_ONLY_WITH_UPLOAD in context.exception) + + def test_should_parse_template_action_with_upload(self): + parser = create_argument_parser() + result = parser.parse_args( + ['template', '--address', '127.0.0.1', "--upload", "resources/notification.json"] + ) + + self.assertFalse(result.override) + self.assertEqual(result.upload, 'resources/notification.json') + + def test_should_parse_template_action_with_upload_and_override(self): + parser = create_argument_parser() + result = parser.parse_args( + ['template', '--address', '127.0.0.1', "--upload", "resources/notification.json", "--override"] + ) + + self.assertTrue(result.override) + self.assertEqual(result.upload, 'resources/notification.json') + + + def test_should_properly_parse_filter_templates_action_with_all_params(self): + parser = create_argument_parser() + + result = parser.parse_args( + ['filter', '--address', '127.0.0.1', '--criteria', '"{}"', '--verbose']) + + self.assertEqual(result.address, '127.0.0.1') + self.assertEqual(result.criteria, "\"{}\"") + self.assertTrue(result.verbose) + +class TestSimulatorClient(unittest.TestCase): + + @patch('cli.pnf_simulator.http.client.HTTPConnection') + def test_should_properly_send_event(self, http_connection): + request = self._create_request() + mocked_connection = Mock(HTTPConnection) + http_connection.return_value = mocked_connection + mocked_response = Mock(HTTPResponse) + mocked_connection.getresponse.return_value = mocked_response + mocked_response.status = '200' + mocked_response.headers = {} + + client = SimulatorClient('localhost') + client.send_event(request) + + mocked_connection.close.assert_called_with() + mocked_connection.request.assert_called_with('POST', '/simulator/start', + body=mock.ANY, + headers={'Content-Type': 'application/json'}) + + @patch('cli.pnf_simulator.http.client.HTTPConnection') + def test_should_properly_send_one_time_event(self, http_connection): + event_abs_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)),"resources/notification.json") + request = self._create_one_time_request(event_abs_filepath) + mocked_connection = Mock(HTTPConnection) + http_connection.return_value = mocked_connection + mocked_response = Mock(HTTPResponse) + mocked_connection.getresponse.return_value = mocked_response + mocked_response.status = '202' + mocked_response.headers = {} + + client = SimulatorClient('localhost') + client.send_one_time_event(request) + + mocked_connection.close.assert_called_with() + mocked_connection.request.assert_called_with('POST', '/simulator/event', + body=mock.ANY, + headers={'Content-Type': 'application/json'}) + + @patch('cli.pnf_simulator.http.client.HTTPConnection') + def test_should_properly_update_configuration(self, http_connection): + mocked_connection = Mock(HTTPConnection) + http_connection.return_value = mocked_connection + mocked_response = Mock(HTTPResponse) + mocked_connection.getresponse.return_value = mocked_response + mocked_response.status = '200' + mocked_response.headers = {} + + client = SimulatorClient('localhost') + client.edit_configuration("sample_url") + + mocked_connection.close.assert_called_with() + mocked_connection.request.assert_called_with('PUT', '/simulator/config', + body=json.dumps({"vesServerUrl": "sample_url"}), + headers={'Content-Type': 'application/json'}) + + @patch('cli.pnf_simulator.http.client.HTTPConnection') + def test_should_properly_retrieve_configuration(self, http_connection): + mocked_connection = Mock(HTTPConnection) + http_connection.return_value = mocked_connection + mocked_response = Mock(HTTPResponse) + mocked_connection.getresponse.return_value = mocked_response + mocked_response.status = '200' + mocked_response.headers = {} + + client = SimulatorClient('localhost') + client.get_configuration() + mocked_connection.close.assert_called_with() + mocked_connection.request.assert_called_with('GET', '/simulator/config') + + + @patch('cli.pnf_simulator.http.client.HTTPConnection') + def test_should_properly_trigger_filter_template_action(self, http_connection): + request = '{"sampleSearchString": "sampleSearchValue"}' + mocked_connection = Mock(HTTPConnection) + http_connection.return_value = mocked_connection + mocked_response = Mock(HTTPResponse) + mocked_connection.getresponse.return_value = mocked_response + mocked_response.status = '200' + mocked_response.headers = {} + + client = SimulatorClient('localhost') + client.search_for_templates(request) + + mocked_connection.close.assert_called_with() + mocked_connection.request.assert_called_with('POST', '/template/search', + body=json.dumps({"searchExpr": {"sampleSearchString": "sampleSearchValue"}}), + headers={'Content-Type': 'application/json'}) + + + @classmethod + def _create_request(cls): + return PersistedEventRequest(SimulatorParams(), 'sample_template') + + @classmethod + def _create_one_time_request(cls, event_filepath): + with open(event_filepath) as json_event: + event_body = json.load(json_event) + return FullEventRequest(event_body, 'sample_url') diff --git a/test/mocks/pnfsimulator/simulator-cli/tests/test_tailf_client.py b/test/mocks/pnfsimulator/simulator-cli/tests/test_tailf_client.py new file mode 100644 index 000000000..da8bd624e --- /dev/null +++ b/test/mocks/pnfsimulator/simulator-cli/tests/test_tailf_client.py @@ -0,0 +1,47 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import unittest +import asynctest + +from cli.client.tailf_client import TailfClient + + +class TestTailfClient(unittest.TestCase): + + def __init__(self, methodName='runTest'): + super().__init__(methodName) + self._client = TailfClient('ws://localhost:9999') + + @asynctest.mock.patch('cli.client.tailf_client.websockets') + def test_should_connect_to_server_and_receive_message(self, websockets_mock): + recv_mock = asynctest.CoroutineMock(side_effect=self.interrupt) + aenter_mock = asynctest.MagicMock() + connection_mock = asynctest.MagicMock() + websockets_mock.connect.return_value = aenter_mock + aenter_mock.__aenter__.return_value = connection_mock + connection_mock.recv = recv_mock + + self._client.tailf_messages() + + recv_mock.assert_awaited_once() + + def interrupt(self): + self._client._is_running = False + return 'test' -- cgit 1.2.3-korg