diff options
Diffstat (limited to 'components/pm-subscription-handler/tests')
5 files changed, 320 insertions, 10 deletions
diff --git a/components/pm-subscription-handler/tests/data/create_subscription_request.json b/components/pm-subscription-handler/tests/data/create_subscription_request.json index bc089a9a..74c09374 100644 --- a/components/pm-subscription-handler/tests/data/create_subscription_request.json +++ b/components/pm-subscription-handler/tests/data/create_subscription_request.json @@ -10,7 +10,8 @@ ], "modelInvariantIDs": [ "8lk4578-d396-4efb-af02-6b83499b12f8", - "687kj45-d396-4efb-af02-6b83499b12f8" + "687kj45-d396-4efb-af02-6b83499b12f8", + "597b524-d396-4efb-af02-6b83499b12f8" ], "modelVersionIDs": [ diff --git a/components/pm-subscription-handler/tests/services/test_measurement_group_service.py b/components/pm-subscription-handler/tests/services/test_measurement_group_service.py index f656513e..1dbe84a9 100644 --- a/components/pm-subscription-handler/tests/services/test_measurement_group_service.py +++ b/components/pm-subscription-handler/tests/services/test_measurement_group_service.py @@ -358,3 +358,48 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): self.assertEqual(meas_grp.subscription_name, 'sub') self.assertEqual(meas_grp.measurement_group_name, 'MG2') self.assertEqual(meas_grp.administrative_state, 'LOCKING') + + def test_filter_nf_to_meas_grp_for_delete(self): + sub = create_subscription_data('sub') + db.session.add(sub) + nf = NetworkFunction(nf_name='pnf_test2') + nf_service.save_nf(nf) + measurement_group_service.apply_nf_status_to_measurement_group( + "pnf_test2", "MG2", SubNfState.PENDING_DELETE.value) + db.session.commit() + measurement_group_service.filter_nf_to_meas_grp( + "pnf_test2", "MG2", SubNfState.DELETED.value) + measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( + NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2', + NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none()) + self.assertIsNone(measurement_grp_rel) + network_function = (NetworkFunctionModel.query.filter( + NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none()) + self.assertIsNone(network_function) + meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2') + self.assertEqual(meas_grp.subscription_name, 'sub') + self.assertEqual(meas_grp.measurement_group_name, 'MG2') + self.assertEqual(meas_grp.administrative_state, 'UNLOCKED') + + def test_filter_nf_to_meas_grp_for_create(self): + sub = create_subscription_data('sub') + db.session.add(sub) + nf = NetworkFunction(nf_name='pnf_test2') + nf_service.save_nf(nf) + measurement_group_service.apply_nf_status_to_measurement_group( + "pnf_test2", "MG2", SubNfState.PENDING_CREATE.value) + db.session.commit() + measurement_group_service.filter_nf_to_meas_grp( + "pnf_test2", "MG2", SubNfState.CREATED.value) + measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( + NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2', + NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none()) + self.assertIsNotNone(measurement_grp_rel) + self.assertEqual(measurement_grp_rel.nf_measure_grp_status, 'CREATED') + network_function = (NetworkFunctionModel.query.filter( + NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none()) + self.assertIsNotNone(network_function) + meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2') + self.assertEqual(meas_grp.subscription_name, 'sub') + self.assertEqual(meas_grp.measurement_group_name, 'MG2') + self.assertEqual(meas_grp.administrative_state, 'UNLOCKED') diff --git a/components/pm-subscription-handler/tests/services/test_subscription_service.py b/components/pm-subscription-handler/tests/services/test_subscription_service.py index 807806f8..a0f3297c 100644 --- a/components/pm-subscription-handler/tests/services/test_subscription_service.py +++ b/components/pm-subscription-handler/tests/services/test_subscription_service.py @@ -21,13 +21,14 @@ import os from unittest.mock import patch, MagicMock from mod.api.db_models import SubscriptionModel, MeasurementGroupModel, \ NfMeasureGroupRelationalModel, NetworkFunctionModel, NfSubRelationalModel, \ - convert_db_string_to_list + convert_db_string_to_list, NetworkFunctionFilterModel from mod.network_function import NetworkFunctionFilter from mod.subscription import SubNfState -from mod import aai_client -from mod.api.custom_exception import DuplicateDataException, InvalidDataException +from mod import aai_client, db +from mod.api.custom_exception import DuplicateDataException, InvalidDataException, \ + DataConflictException from mod.pmsh_config import AppConfig -from tests.base_setup import BaseClassSetup +from tests.base_setup import BaseClassSetup, create_subscription_data from mod.api.services import subscription_service, nf_service, measurement_group_service from tests.base_setup import create_multiple_subscription_data @@ -184,11 +185,10 @@ class SubscriptionServiceTestCase(BaseClassSetup): 'msrmt_grp_name', 'UNLOCKED', 15, 'pm.xml', [], []) measurement2 = self.create_measurement_grp(measurement_grp, 'meas2', 'UNLOCKED') - measurement3 = self.create_measurement_grp(measurement_grp, 'meas3', 'LOCKED') - measurement_grps = [measurement_grp, measurement2, measurement3] + unlocked_msgs = [measurement_grp, measurement2] mock_filter_call.return_value = NetworkFunctionFilter(**subscription["nfFilter"]) filtered_nfs = nf_service.capture_filtered_nfs(subscription["subscriptionName"]) - subscription_service.apply_measurement_grp_to_nfs(filtered_nfs, measurement_grps) + subscription_service.apply_measurement_grp_to_nfs(filtered_nfs, unlocked_msgs) # 2 measurement group with 2 nfs each contribute 4 calls self.assertEqual(mock_apply_nf.call_count, 4) @@ -377,3 +377,168 @@ class SubscriptionServiceTestCase(BaseClassSetup): def test_get_subscriptions_list_empty(self): subs = subscription_service.get_subscriptions_list() self.assertEqual(subs, []) + + @patch('mod.api.services.nf_service.save_nf_filter_update') + @patch('mod.api.services.subscription_service.is_duplicate_filter', + MagicMock(return_value=False)) + @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None)) + @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None)) + @patch.object(aai_client, '_get_all_aai_nf_data') + @patch.object(aai_client, 'get_aai_model_data') + @patch.object(NetworkFunctionFilter, 'get_network_function_filter') + def test_update_filter(self, mock_filter_call, mock_model_aai, mock_aai, mock_update_filter): + mock_aai.return_value = json.loads(self.aai_response_data) + mock_model_aai.return_value = json.loads(self.good_model_info) + mock_update_filter.return_value = None + subscription = self.create_test_subs('sub_01', 'msg_01') + subscription = json.loads(subscription)['subscription'] + nf_filter = subscription['nfFilter'] + mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter) + subscription_service.create_subscription(subscription) + subscription_service.update_filter('sub_01', nf_filter) + self.assertTrue(mock_update_filter.called) + + @patch('mod.api.services.nf_service.save_nf_filter_update') + @patch('mod.api.services.subscription_service.is_duplicate_filter', + MagicMock(return_value=False)) + @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None)) + @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None)) + @patch.object(aai_client, '_get_all_aai_nf_data') + @patch.object(aai_client, 'get_aai_model_data') + @patch.object(NetworkFunctionFilter, 'get_network_function_filter') + def test_update_filter_with_new_del_nfs(self, mock_filter_call, mock_model_aai, mock_aai, + mock_update_filter): + mock_aai.return_value = json.loads(self.aai_response_data) + mock_model_aai.return_value = json.loads(self.good_model_info) + mock_update_filter.return_value = None + subscription = self.create_test_subs('sub_01', 'msg_01') + subscription = json.loads(subscription)['subscription'] + nf_filter = subscription['nfFilter'] + mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter) + subscription_service.create_subscription(subscription) + # Check existing network functions + meas_group_nfs = db.session.query(NfMeasureGroupRelationalModel).filter( + NfMeasureGroupRelationalModel.measurement_grp_name == 'msg_01') \ + .all() + self.assertEqual(len(meas_group_nfs), 2) + self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201') + self.assertEqual(meas_group_nfs[0].nf_measure_grp_status, + SubNfState.PENDING_CREATE.value) + self.assertEqual(meas_group_nfs[1].nf_name, 'pnf_33_ericsson') + self.assertEqual(meas_group_nfs[1].nf_measure_grp_status, + SubNfState.PENDING_CREATE.value) + meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01') + self.assertEqual(meas_grp.administrative_state, 'UNLOCKED') + # Creating test data for update filter function + aai_response = self.aai_response_data.replace('pnf201', 'xnf111') + mock_aai.return_value = json.loads(aai_response) + nf_filter['nfNames'] = ["^vnf.*", "^xnf.*"] + mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter) + subscription_service.update_filter('sub_01', nf_filter) + self.assertTrue(mock_update_filter.called) + # Check updated network functions after filter change + meas_group_nfs = db.session.query(NfMeasureGroupRelationalModel).filter( + NfMeasureGroupRelationalModel.measurement_grp_name == 'msg_01') \ + .all() + self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201') + self.assertEqual(meas_group_nfs[0].nf_measure_grp_status, + SubNfState.PENDING_DELETE.value) + self.assertEqual(meas_group_nfs[1].nf_name, 'pnf_33_ericsson') + self.assertEqual(meas_group_nfs[1].nf_measure_grp_status, + SubNfState.PENDING_DELETE.value) + self.assertEqual(meas_group_nfs[2].nf_name, 'xnf111') + self.assertEqual(meas_group_nfs[2].nf_measure_grp_status, + SubNfState.PENDING_CREATE.value) + meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01') + self.assertEqual(meas_grp.administrative_state, 'FILTERING') + + def test_update_filter_locking(self): + sub = create_subscription_data('sub') + sub.measurement_groups[1].administrative_state = 'LOCKING' + db.session.add(sub) + try: + subscription_service.update_filter('sub', json.loads('{"nfNames": "^pnf.*"}')) + except DataConflictException as conflictEx: + self.assertEqual(conflictEx.args[0], + 'Cannot update filter as subscription: sub is under transitioning' + ' state for the following measurement groups: [subscription_name:' + ' sub, measurement_group_name: MG2, administrative_state: LOCKING,' + ' file_based_gp: 15, file_location: /pm/pm.xml, measurement_type: ' + '[{ "measurementType": "countera" }, { "measurementType": ' + '"counterb" }], managed_object_dns_basic: [{ "DN":"dna"},' + '{"DN":"dnb"}]]') + + def test_update_filter_filtering(self): + sub = create_subscription_data('sub') + sub.measurement_groups[1].administrative_state = 'FILTERING' + db.session.add(sub) + try: + subscription_service.update_filter('sub', json.loads('{"nfNames": "^pnf.*"}')) + except DataConflictException as conflictEx: + self.assertEqual(conflictEx.args[0], + 'Cannot update filter as subscription: sub is under transitioning' + ' state for the following measurement groups: [subscription_name:' + ' sub, measurement_group_name: MG2, administrative_state: FILTERING,' + ' file_based_gp: 15, file_location: /pm/pm.xml, measurement_type: [' + '{ "measurementType": "countera" }, { "measurementType": "counterb" ' + '}], managed_object_dns_basic: [{ "DN":"dna"},{"DN":"dnb"}]]') + + def test_update_filter_invalid_request(self): + try: + subscription_service.update_filter("sub3", json.loads('{"nfNames": "^pnf.*"}')) + except InvalidDataException as invalidEx: + self.assertEqual(invalidEx.args[0], + "Requested subscription is not available with sub name: sub3 " + "for nf filter update") + + @patch('mod.api.services.nf_service.save_nf_filter_update') + @patch('mod.api.services.subscription_service.is_duplicate_filter', + MagicMock(return_value=True)) + @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None)) + @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None)) + @patch.object(aai_client, '_get_all_aai_nf_data') + @patch.object(aai_client, 'get_aai_model_data') + @patch.object(NetworkFunctionFilter, 'get_network_function_filter') + def test_update_filter_invalid_duplicate_request(self, mock_filter_call, mock_model_aai, + mock_aai, mock_update_filter): + try: + mock_aai.return_value = json.loads(self.aai_response_data) + mock_model_aai.return_value = json.loads(self.good_model_info) + mock_update_filter.return_value = None + subscription = self.create_test_subs('sub_01', 'msg_01') + subscription = json.loads(subscription)['subscription'] + nf_filter = subscription['nfFilter'] + mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter) + subscription_service.create_subscription(subscription) + subscription_service.update_filter("sub_01", json.loads('{"nfNames": "^pnf.*"}')) + except InvalidDataException as invalidEx: + self.assertEqual(invalidEx.args[0], + "Duplicate nf filter update requested for subscription " + "with sub name: sub_01") + + def test_is_duplicate_filter_true(self): + subscription = self.create_test_subs('sub_01', 'msg_01') + subscription = json.loads(subscription)['subscription'] + nf_filter = subscription['nfFilter'] + db_network_filter = NetworkFunctionFilterModel('sub_01', + '{^pnf.*,^vnf.*}', + '{8lk4578-d396-4efb-af02-6b83499b12f8,' + '687kj45-d396-4efb-af02-6b83499b12f8,' + '597b524-d396-4efb-af02-6b83499b12f8}', + '{e80a6ae3-cafd-4d24-850d-e14c084a5ca9}', + '{PNF102}') + similar = subscription_service.is_duplicate_filter(nf_filter, db_network_filter) + self.assertTrue(similar) + + def test_is_duplicate_filter_false(self): + subscription = self.create_test_subs('sub_01', 'msg_01') + subscription = json.loads(subscription)['subscription'] + nf_filter = subscription['nfFilter'] + db_network_filter = NetworkFunctionFilterModel('sub_01', + '{^pnf.*,^vnf.*}', + '{8lk4578-d396-4efb-af02-6b83499b12f8,' + '687kj45-d396-4efb-af02-6b83499b12f8}', + '{e80a6ae3-cafd-4d24-850d-e14c084a5ca9}', + '{PNF102}') + similar = subscription_service.is_duplicate_filter(nf_filter, db_network_filter) + self.assertFalse(similar) diff --git a/components/pm-subscription-handler/tests/test_controller.py b/components/pm-subscription-handler/tests/test_controller.py index 42c52c09..7b0a8b19 100755 --- a/components/pm-subscription-handler/tests/test_controller.py +++ b/components/pm-subscription-handler/tests/test_controller.py @@ -23,7 +23,7 @@ from http import HTTPStatus from mod import aai_client, db from mod.api.controller import status, post_subscription, get_subscription_by_name, \ get_subscriptions, get_meas_group_with_nfs, delete_subscription_by_name, update_admin_state, \ - delete_meas_group_by_name + delete_meas_group_by_name, put_nf_filter from mod.api.services.measurement_group_service import query_meas_group_by_name from tests.base_setup import BaseClassSetup from mod.api.custom_exception import InvalidDataException, DataConflictException @@ -366,3 +366,33 @@ class ControllerTestCase(BaseClassSetup): self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value) self.assertEqual(error, 'Update admin status request was not processed for sub name: sub4 ' 'and meas group name: MG2 due to Exception : Server Error') + + @patch('mod.api.services.subscription_service.update_filter', MagicMock(return_value=None)) + def test_put_nf_filter(self): + response = put_nf_filter('sub1', json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}')) + self.assertEqual(response[0], 'Successfully updated network function Filter') + self.assertEqual(response[1], HTTPStatus.OK.value) + + @patch('mod.api.services.subscription_service.update_filter', + MagicMock(side_effect=InvalidDataException('Bad request'))) + def test_put_nf_filter_api_invalid_data_exception(self): + error, status_code = put_nf_filter('sub1', + json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}')) + self.assertEqual(status_code, HTTPStatus.BAD_REQUEST.value) + self.assertEqual(error, 'Bad request') + + @patch('mod.api.services.subscription_service.update_filter', + MagicMock(side_effect=DataConflictException('Data conflict'))) + def test_put_nf_filter_api_data_conflict_exception(self): + error, status_code = put_nf_filter('sub1', + json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}')) + self.assertEqual(status_code, HTTPStatus.CONFLICT.value) + self.assertEqual(error, 'Data conflict') + + @patch('mod.api.services.subscription_service.update_filter', + MagicMock(side_effect=Exception('Server Error'))) + def test_put_nf_filter_api_exception(self): + error, status_code = put_nf_filter('sub1', json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}')) + self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value) + self.assertEqual(error, 'Update nf filter request was not processed for sub name: sub1 ' + 'due to Exception : Server Error') diff --git a/components/pm-subscription-handler/tests/test_policy_response_handler.py b/components/pm-subscription-handler/tests/test_policy_response_handler.py index 3e6abf94..d5ae5ce1 100644 --- a/components/pm-subscription-handler/tests/test_policy_response_handler.py +++ b/components/pm-subscription-handler/tests/test_policy_response_handler.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. +# Copyright (C) 2019-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ from unittest.mock import patch, MagicMock from mod import db +from mod.api.services import measurement_group_service from mod.network_function import NetworkFunction from mod.policy_response_handler import PolicyResponseHandler, policy_response_handle_functions from mod.subscription import AdministrativeState, SubNfState @@ -100,6 +101,40 @@ class PolicyResponseHandlerTest(BaseClassSetup): status=SubNfState.CREATED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') + def test_handle_response_unlocked_success_filtering(self, mock_update_sub_nf): + with patch.dict(policy_response_handle_functions, + {AdministrativeState.UNLOCKED.value: {'success': mock_update_sub_nf}}): + sub = create_subscription_data('sub') + db.session.add(sub) + measurement_group_service.apply_nf_status_to_measurement_group( + self.nf.nf_name, "MG2", SubNfState.PENDING_CREATE.value) + db.session.commit() + self.policy_response_handler._handle_response( + 'MG2', + AdministrativeState.FILTERING.value, + self.nf.nf_name, 'success') + mock_update_sub_nf.assert_called_with( + measurement_group_name='MG2', + status=SubNfState.CREATED.value, nf_name=self.nf.nf_name) + + @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') + def test_handle_response_locking_success_filtering(self, mock_update_sub_nf): + with patch.dict(policy_response_handle_functions, + {AdministrativeState.LOCKING.value: {'success': mock_update_sub_nf}}): + sub = create_subscription_data('sub') + db.session.add(sub) + measurement_group_service.apply_nf_status_to_measurement_group( + self.nf.nf_name, "MG2", SubNfState.PENDING_DELETE.value) + db.session.commit() + self.policy_response_handler._handle_response( + 'MG2', + AdministrativeState.FILTERING.value, + self.nf.nf_name, 'success') + mock_update_sub_nf.assert_called_with( + measurement_group_name='MG2', + status=SubNfState.DELETED.value, nf_name=self.nf.nf_name) + + @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_unlocked_failed(self, mock_update_sub_nf): with patch.dict(policy_response_handle_functions, {AdministrativeState.UNLOCKED.value: {'failed': mock_update_sub_nf}}): @@ -111,6 +146,40 @@ class PolicyResponseHandlerTest(BaseClassSetup): measurement_group_name='msr_grp_name', status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name) + @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') + def test_handle_response_create_failed_filtering(self, mock_update_sub_nf): + with patch.dict(policy_response_handle_functions, + {AdministrativeState.UNLOCKED.value: {'failed': mock_update_sub_nf}}): + sub = create_subscription_data('sub') + db.session.add(sub) + measurement_group_service.apply_nf_status_to_measurement_group( + self.nf.nf_name, "MG2", SubNfState.PENDING_CREATE.value) + db.session.commit() + self.policy_response_handler._handle_response( + 'MG2', + AdministrativeState.FILTERING.value, + self.nf.nf_name, 'failed') + mock_update_sub_nf.assert_called_with( + measurement_group_name='MG2', + status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name) + + @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') + def test_handle_response_delete_failed_filtering(self, mock_update_sub_nf): + with patch.dict(policy_response_handle_functions, + {AdministrativeState.LOCKING.value: {'failed': mock_update_sub_nf}}): + sub = create_subscription_data('sub') + db.session.add(sub) + measurement_group_service.apply_nf_status_to_measurement_group( + self.nf.nf_name, "MG2", SubNfState.PENDING_DELETE.value) + db.session.commit() + self.policy_response_handler._handle_response( + 'MG2', + AdministrativeState.FILTERING.value, + self.nf.nf_name, 'failed') + mock_update_sub_nf.assert_called_with( + measurement_group_name='MG2', + status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) + def test_handle_response_exception(self): self.assertRaises(Exception, self.policy_response_handler._handle_response, 'sub1', 'wrong_state', 'nf1', 'wrong_message') |